From 0bb6a820f00a8548ff49397fa4bd9e8b690510ab Mon Sep 17 00:00:00 2001 From: PoffyZhang <99775271@qq.com> Date: Thu, 11 Apr 2024 16:12:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B9=89=E4=B9=8C=E5=85=AC=E8=B7=AF=20?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 34 +- ningda-generator/pom.xml | 34 + .../generator/config/GeneratorCodeConfig.java | 66 + ningda-yw-api/pom.xml | 309 ++ .../src/main/java/com/ningdatech/carapi/App.java | 32 + .../carapi/analysis/common/DangerLevelEnum.java | 72 + .../controller/AnalysisEvalDataViewController.java | 77 + .../controller/IndustryStandardsController.java | 61 + .../controller/InsuranceRiskEvalController.java | 114 + .../controller/SecurityAnalysisEvalController.java | 73 + .../controller/WarnAnalysisController.java | 50 + .../carapi/analysis/entity/IndustryStandards.java | 54 + .../analysis/entity/SecurityManageGrade.java | 62 + .../analysis/entity/SecurityManageResultEval.java | 77 + .../carapi/analysis/entity/SecurityRiskEval.java | 80 + .../entity/SecuritySystemBuildingEval.java | 74 + .../analysis/entity/VehicleAccidentEval.java | 77 + .../analysis/entity/VehicleOverSpeedEval.java | 77 + .../carapi/analysis/entity/VehicleServiceLife.java | 69 + .../analysis/entity/VehicleViolationEval.java | 77 + .../carapi/analysis/entity/WarnAnalysisCar.java | 80 + .../analysis/entity/WarnAnalysisCompany.java | 71 + .../carapi/analysis/entity/WarnAnalysisDriver.java | 79 + .../entity/dto/CompanyWarnStatisticsDto.java | 22 + .../analysis/entity/dto/OutDangerImportDto.java | 64 + .../entity/dto/VehicleAccidentImportDto.java | 70 + .../entity/dto/VehicleOverSpeedImportDto.java | 70 + .../entity/dto/VehicleViolationImportDto.java | 71 + .../analysis/entity/enumeration/DangerLevel.java | 40 + .../entity/enumeration/IndustryStandardsType.java | 43 + .../entity/enumeration/InsuranceDangerLevel.java | 31 + .../entity/req/IndustryStandardsListReq.java | 36 + .../entity/req/IndustryStandardsSaveReq.java | 34 + .../entity/req/SecurityManageGradeListReq.java | 27 + .../entity/req/SecurityRiskEvalListReq.java | 55 + .../entity/req/SecurityRiskEvalSaveReq.java | 78 + .../req/SecuritySystemBuildingEvalSaveReq.java | 70 + .../entity/req/VehicleAccidentEvalModReq.java | 41 + .../entity/req/VehicleOverSpeedEvalModReq.java | 41 + .../entity/req/VehicleServiceLifeListReq.java | 42 + .../entity/req/VehicleViolationEvalModReq.java | 41 + .../analysis/entity/req/WarnAnalysisListReq.java | 42 + .../entity/vo/CompanyWarnStatisticsVo.java | 39 + .../entity/vo/IndustryStandardsListVo.java | 32 + .../analysis/entity/vo/SecurityManageGradeVo.java | 40 + .../entity/vo/SecurityManageResultEvalListVo.java | 66 + .../analysis/entity/vo/SecurityRiskEvalListVo.java | 53 + .../vo/SecuritySystemBuildingEvalListVo.java | 47 + .../entity/vo/VehicleAccidentEvalListVo.java | 55 + .../entity/vo/VehicleOverSpeedEvalListVo.java | 55 + .../entity/vo/VehicleServiceLifeListVo.java | 60 + .../entity/vo/VehicleViolationEvalListVo.java | 59 + .../analysis/entity/vo/WarnAnalysisByCarVo.java | 58 + .../entity/vo/WarnAnalysisByCompanyVo.java | 54 + .../analysis/entity/vo/WarnAnalysisByDriverVo.java | 59 + .../manage/AnalysisEvalDataViewManage.java | 190 ++ .../analysis/manage/IndustryStandardsManage.java | 132 + .../analysis/manage/InsuranceRiskEvalManage.java | 568 ++++ .../manage/SecurityAnalysisEvalManage.java | 245 ++ .../carapi/analysis/manage/WarnAnalysisManage.java | 149 + .../analysis/mapper/IndustryStandardsMapper.java | 18 + .../analysis/mapper/IndustryStandardsMapper.xml | 9 + .../analysis/mapper/NdInsureOutDangerVOMapper.java | 7 + .../analysis/mapper/NdInsureOutDangerVOMapper.xml | 7 + .../analysis/mapper/SecurityManageGradeMapper.java | 16 + .../analysis/mapper/SecurityManageGradeMapper.xml | 5 + .../mapper/SecurityManageResultEvalMapper.java | 16 + .../mapper/SecurityManageResultEvalMapper.xml | 5 + .../analysis/mapper/SecurityRiskEvalMapper.java | 16 + .../analysis/mapper/SecurityRiskEvalMapper.xml | 5 + .../mapper/SecuritySystemBuildingEvalMapper.java | 16 + .../mapper/SecuritySystemBuildingEvalMapper.xml | 5 + .../analysis/mapper/VehicleAccidentEvalMapper.java | 16 + .../analysis/mapper/VehicleAccidentEvalMapper.xml | 5 + .../mapper/VehicleOverSpeedEvalMapper.java | 16 + .../analysis/mapper/VehicleOverSpeedEvalMapper.xml | 5 + .../analysis/mapper/VehicleServiceLifeMapper.java | 16 + .../analysis/mapper/VehicleServiceLifeMapper.xml | 5 + .../mapper/VehicleViolationEvalMapper.java | 16 + .../analysis/mapper/VehicleViolationEvalMapper.xml | 5 + .../analysis/mapper/WarnAnalysisCarMapper.java | 28 + .../analysis/mapper/WarnAnalysisCarMapper.xml | 162 + .../analysis/mapper/WarnAnalysisCompanyMapper.java | 23 + .../analysis/mapper/WarnAnalysisCompanyMapper.xml | 95 + .../analysis/mapper/WarnAnalysisDriverMapper.java | 23 + .../analysis/mapper/WarnAnalysisDriverMapper.xml | 87 + .../service/IIndustryStandardsService.java | 19 + .../service/INdInsureOutDangerVOService.java | 7 + .../service/ISecurityManageGradeService.java | 16 + .../service/ISecurityManageResultEvalService.java | 16 + .../analysis/service/ISecurityRiskEvalService.java | 16 + .../ISecuritySystemBuildingEvalService.java | 16 + .../service/IVehicleAccidentEvalService.java | 16 + .../service/IVehicleOverSpeedEvalService.java | 16 + .../service/IVehicleServiceLifeService.java | 16 + .../service/IVehicleViolationEvalService.java | 16 + .../analysis/service/IWarnAnalysisCarService.java | 25 + .../service/IWarnAnalysisCompanyService.java | 23 + .../service/IWarnAnalysisDriverService.java | 22 + .../service/impl/IndustryStandardsServiceImpl.java | 30 + .../impl/NdInsureOutDangerVOServiceImpl.java | 16 + .../impl/SecurityManageGradeServiceImpl.java | 20 + .../impl/SecurityManageResultEvalServiceImpl.java | 20 + .../service/impl/SecurityRiskEvalServiceImpl.java | 20 + .../SecuritySystemBuildingEvalServiceImpl.java | 20 + .../impl/VehicleAccidentEvalServiceImpl.java | 20 + .../impl/VehicleOverSpeedEvalServiceImpl.java | 20 + .../impl/VehicleServiceLifeServiceImpl.java | 20 + .../impl/VehicleViolationEvalServiceImpl.java | 20 + .../service/impl/WarnAnalysisCarServiceImpl.java | 46 + .../impl/WarnAnalysisCompanyServiceImpl.java | 36 + .../impl/WarnAnalysisDriverServiceImpl.java | 36 + .../carapi/archives/aop/AuditVehicle.java | 17 + .../carapi/archives/aop/AuditVehicleAspect.java | 64 + .../archives/assembler/QuestionAssembler.java | 48 + .../archives/controller/ArchivesController.java | 131 + .../controller/ExaminationPaperController.java | 75 + .../controller/PaperQuestionController.java | 67 + .../carapi/archives/entity/ExamPaper.java | 66 + .../carapi/archives/entity/ExamPaperQuestion.java | 50 + .../carapi/archives/entity/PaperQuestion.java | 67 + .../carapi/archives/enums/ApproveStateEnum.java | 54 + .../carapi/archives/enums/AuditStateEnum.java | 70 + .../carapi/archives/enums/CertOperTypeEnum.java | 54 + .../archives/enums/DriverRelationConstant.java | 14 + .../enums/ExamPaperQualifiedScoreConstant.java | 20 + .../carapi/archives/enums/IsRandomEnum.java | 65 + .../archives/enums/PaperQuestionStatusEnum.java | 24 + .../carapi/archives/manage/ArchivesManage.java | 246 ++ .../archives/manage/ExaminationPaperManage.java | 458 +++ .../archives/manage/PaperQuestionManage.java | 215 ++ .../carapi/archives/mapper/ExamPaperMapper.java | 16 + .../carapi/archives/mapper/ExamPaperMapper.xml | 5 + .../archives/mapper/ExamPaperQuestionMapper.java | 16 + .../archives/mapper/ExamPaperQuestionMapper.xml | 5 + .../archives/mapper/NdPaperQuestionMapper.java | 16 + .../archives/mapper/NdPaperQuestionMapper.xml | 5 + .../carapi/archives/model/ExamRuleInfo.java | 28 + .../model/JudgmentalQuestionTextContent.java | 20 + .../model/MultipleChoiceQuestionTextContent.java | 25 + .../model/ShortAnswerQuestionTextContent.java | 19 + .../model/SingleChoiceQuestionTextContent.java | 25 + .../archives/model/po/ReqExamPaperListPO.java | 22 + .../carapi/archives/model/po/ReqExamRulePO.java | 17 + .../archives/model/po/ReqQuestionListPO.java | 24 + .../archives/model/po/ReqSaveExamPaperPO.java | 46 + .../archives/model/po/ReqSaveExamRulePO.java | 27 + .../archives/model/po/ReqSaveNewQuestionPO.java | 40 + .../archives/model/vo/ResExamPaperListVO.java | 33 + .../carapi/archives/model/vo/ResExamPaperVO.java | 34 + .../carapi/archives/model/vo/ResExamRuleVO.java | 24 + .../archives/model/vo/ResQuestionDetailVO.java | 36 + .../archives/model/vo/ResQuestionListVO.java | 32 + .../service/IExamPaperQuestionService.java | 16 + .../carapi/archives/service/IExamPaperService.java | 16 + .../archives/service/IPaperQuestionService.java | 16 + .../service/impl/ExamPaperQuestionServiceImpl.java | 20 + .../service/impl/ExamPaperServiceImpl.java | 20 + .../service/impl/NdIPaperQuestionServiceImpl.java | 20 + .../datascreen/contants/DigitalCockpitContant.java | 20 + .../controller/DigitalCockpitController.java | 166 + .../VehicleManageDataScreenController.java | 76 + .../datascreen/manage/DigitalCockpitManage.java | 659 ++++ .../datascreen/mapper/VehicleStatisticsMapper.java | 78 + .../datascreen/mapper/VehicleStatisticsMapper.xml | 542 +++ .../car/datascreen/model/dto/DataScreenParam.java | 47 + .../model/po/InsureDistributionStatisticsPO.java | 21 + .../model/po/OnlineVehicleRegionsPO.java | 34 + .../datascreen/model/po/OnlineVehicleTimesPO.java | 37 + .../model/po/OperatorDistributionStatisticsPO.java | 21 + .../datascreen/model/po/OverspeedStatisticsPO.java | 21 + .../model/po/RegionDistributionStatisticsPO.java | 24 + .../datascreen/model/po/VehicleStatusTimePO.java | 24 + .../model/po/VehicleTypeStatisticsPO.java | 22 + .../model/po/VehicleUsefulLifeStatisticsPO.java | 21 + .../model/po/YearVehicleStatisticsPO.java | 21 + .../model/vo/InsureDistributionStatisticsVO.java | 29 + .../model/vo/OperatorDistributionStatisticsVO.java | 26 + .../model/vo/RegionDistributionStatisticsVO.java | 24 + .../datascreen/model/vo/StatisticsCenterVO.java | 39 + .../model/vo/VehicleTypeStatisticsVO.java | 30 + .../model/vo/VehicleUsefulLifeStatisticsVO.java | 25 + .../model/vo/YearVehicleStatisticsVO.java | 21 + .../service/VehicleStatisticsService.java | 43 + .../service/impl/VehicleStatisticsServiceImpl.java | 378 +++ .../controller/VehicleEquipmentController.java | 110 + .../converter/VehicleEquipmentConverter.java | 46 + .../equipment/manage/VehicleEquipmentManage.java | 510 +++ .../equipment/mapper/DataAccessDevicesMapper.java | 16 + .../equipment/mapper/DataAccessDevicesMapper.xml | 5 + .../mapper/NdVehicleEquipmentChannelsMapper.java | 16 + .../mapper/NdVehicleEquipmentChannelsMapper.xml | 5 + .../mapper/NdVehicleEquipmentInfoMapper.java | 20 + .../mapper/NdVehicleEquipmentInfoMapper.xml | 31 + .../mapper/NdVehicleEquipmentJoinMapper.java | 29 + .../equipment/mapper/VehicleEquipmentNoMapper.java | 16 + .../equipment/mapper/VehicleEquipmentNoMapper.xml | 5 + .../car/equipment/model/DataAccessDevices.java | 115 + .../model/NdVehicleEquipmentChannels.java | 52 + .../equipment/model/NdVehicleEquipmentInfo.java | 143 + .../equipment/model/NdVehicleEquipmentJoin.java | 145 + .../car/equipment/model/VehicleEquipmentNo.java | 59 + .../model/dto/EquipmentChannelsSaveDTO.java | 52 + .../car/equipment/model/dto/EquipmentSaveDTO.java | 80 + .../equipment/model/dto/EquipmentUpdateDTO.java | 81 + .../equipment/model/dto/VehicleEquipmentDTO.java | 119 + .../model/dto/VehicleEquipmentPageQuery.java | 64 + .../model/dto/VehicleEquipmentQueryDTO.java | 93 + .../car/equipment/model/res/SipApiResponse.java | 24 + .../car/equipment/model/res/SipEquipmentRes.java | 56 + .../equipment/model/vo/NdVehicleEquipmentVO.java | 115 + .../car/equipment/model/vo/VehicleEquipmentVO.java | 121 + .../service/IDataAccessDevicesService.java | 16 + .../INdVehicleEquipmentChannelsService.java | 16 + .../service/INdVehicleEquipmentInfoService.java | 30 + .../service/INdVehicleEquipmentJoinService.java | 20 + .../service/IVehicleEquipmentNoService.java | 16 + .../service/impl/DataAccessDevicesServiceImpl.java | 20 + .../NdVehicleEquipmentChannelsServiceImpl.java | 20 + .../impl/NdVehicleEquipmentInfoServiceImpl.java | 185 + .../impl/NdVehicleEquipmentJoinServiceImpl.java | 35 + .../impl/VehicleEquipmentNoServiceImpl.java | 20 + .../controller/StatusMonitorController.java | 70 + .../carapi/car/monitor/entity/AlarmDataLoad.java | 75 + .../car/monitor/entity/DataAccessAlarmWarn.java | 94 + .../monitor/entity/DataAccessAlarmWarnFile.java | 43 + .../car/monitor/entity/SecurityMonitorJoin.java | 47 + .../car/monitor/entity/VehicleSecurityMonitor.java | 95 + .../car/monitor/manage/StatusMonitorManage.java | 186 + .../car/monitor/mapper/AlarmDataLoadMapper.java | 16 + .../car/monitor/mapper/AlarmDataLoadMapper.xml | 5 + .../mapper/DataAccessAlarmWarnFileMapper.java | 16 + .../mapper/DataAccessAlarmWarnFileMapper.xml | 5 + .../monitor/mapper/DataAccessAlarmWarnMapper.java | 16 + .../monitor/mapper/DataAccessAlarmWarnMapper.xml | 5 + .../monitor/mapper/SecurityMonitorJoinMapper.java | 46 + .../mapper/VehicleSecurityMonitorMapper.java | 16 + .../mapper/VehicleSecurityMonitorMapper.xml | 5 + .../car/monitor/model/dto/AlarmDataLoadDTO.java | 86 + .../monitor/model/dto/LoadMonitorPageParamDTO.java | 30 + .../model/dto/SecurityMonitorExportDTO.java | 50 + .../model/dto/SecurityMonitorPageParamDTO.java | 36 + .../car/monitor/model/vo/AlarmDataLoadVO.java | 70 + .../car/monitor/model/vo/SecurityMonitorVO.java | 106 + .../carapi/car/monitor/mqtt/MqttReceiveConfig.java | 93 + .../car/monitor/service/IAlarmDataLoadService.java | 16 + .../service/IDataAccessAlarmWarnFileService.java | 16 + .../service/IDataAccessAlarmWarnService.java | 16 + .../service/IVehicleSecurityMonitorService.java | 16 + .../monitor/service/SecurityMonitorService.java | 13 + .../service/impl/AlarmDataLoadServiceImpl.java | 20 + .../impl/DataAccessAlarmWarnFileServiceImpl.java | 20 + .../impl/DataAccessAlarmWarnServiceImpl.java | 20 + .../service/impl/SecurityMonitorServiceImpl.java | 27 + .../impl/VehicleSecurityMonitorServiceImpl.java | 20 + .../car/position/contants/PositionContant.java | 42 + .../controller/PositionMonitorController.java | 54 + .../car/position/entity/VehiclePositionInfo.java | 100 + .../car/position/manage/PositionMonitorManage.java | 398 +++ .../position/mapper/VehiclePositionInfoMapper.java | 21 + .../position/mapper/VehiclePositionInfoMapper.xml | 19 + .../carapi/car/position/model/po/ReqDataPO.java | 35 + .../position/model/po/ReqRealTimeMonitorPO.java | 23 + .../po/ReqRealTimeMonitorVehicleGisDetailPO.java | 21 + .../car/position/model/po/ReqTrajectoryDataPO.java | 35 + .../carapi/car/position/model/vo/DeviceVO.java | 31 + .../model/vo/ResRealTimeMonitorStatisticsVO.java | 28 + .../vo/ResRealTimeMonitorVehicleGisDetailVO.java | 92 + .../vo/ResRealTimeMonitorVehicleGisListVO.java | 103 + .../car/position/model/vo/ResTrajectoryDataVO.java | 92 + .../service/IVehiclePositionInfoService.java | 21 + .../impl/VehiclePositionInfoServiceImpl.java | 31 + .../car/rpt/controller/RptDailyController.java | 119 + .../car/rpt/controller/RptMonthController.java | 99 + .../car/rpt/controller/RptOtherController.java | 173 + .../car/rpt/controller/RptTendaysController.java | 84 + .../entity/RptDailyOperatorVehiclesLaunchRate.java | 58 + .../car/rpt/entity/RptDailyOverspeedCompany.java | 64 + .../entity/RptDailyOverspeedSpecialVehicles.java | 67 + ...RptDailySpecialVehiclesCompanyLaunchRate60.java | 64 + .../entity/RptDailySpecialVehiclesLaunchRate.java | 58 + .../entity/RptDailySpecialVehiclesOverspeed.java | 48 + .../car/rpt/entity/RptMonthOverspeedCompany.java | 64 + .../entity/RptMonthOverspeedSpecialCompany.java | 67 + .../entity/RptMonthOverspeedSpecialVehicles.java | 58 + .../car/rpt/entity/RptMonthSpecialOffline.java | 63 + .../car/rpt/entity/RptOtherAlarmCleanVehicles.java | 91 + .../entity/RptOtherAlarmCleanVehiclesAnalysis.java | 118 + .../rpt/entity/RptOtherCrossDomainVehicles.java | 103 + .../RptOtherCrossDomainVehiclesAnalysis.java | 142 + .../car/rpt/entity/RptOtherOnlineVehicles.java | 79 + .../rpt/entity/RptOtherOnlineVehiclesAnalysis.java | 94 + .../car/rpt/entity/RptOtherSpecialOverspeed.java | 76 + .../car/rpt/entity/RptOtherSpecialTrips.java | 57 + .../car/rpt/entity/RptOtherTerminalInstall.java | 94 + .../rpt/entity/RptTendaysSpecialOfflineWeek.java | 57 + .../entity/RptTendaysSpecialOverspeedCompany.java | 64 + .../entity/RptTendaysSpecialOverspeedVehicles.java | 67 + .../carapi/car/rpt/manage/RptDailyManage.java | 192 ++ .../carapi/car/rpt/manage/RptMonthManage.java | 239 ++ .../carapi/car/rpt/manage/RptOtherManage.java | 389 +++ .../carapi/car/rpt/manage/RptTendaysManage.java | 158 + .../RptDailyOperatorVehiclesLaunchRateMapper.java | 22 + .../RptDailyOperatorVehiclesLaunchRateMapper.xml | 39 + .../rpt/mapper/RptDailyOverspeedCompanyMapper.java | 22 + .../rpt/mapper/RptDailyOverspeedCompanyMapper.xml | 58 + .../RptDailyOverspeedSpecialVehiclesMapper.java | 22 + .../RptDailyOverspeedSpecialVehiclesMapper.xml | 62 + ...lySpecialVehiclesCompanyLaunchRate60Mapper.java | 22 + ...ilySpecialVehiclesCompanyLaunchRate60Mapper.xml | 72 + .../RptDailySpecialVehiclesLaunchRateMapper.java | 22 + .../RptDailySpecialVehiclesLaunchRateMapper.xml | 73 + .../RptDailySpecialVehiclesOverspeedMapper.java | 22 + .../RptDailySpecialVehiclesOverspeedMapper.xml | 23 + .../rpt/mapper/RptMonthOverspeedCompanyMapper.java | 22 + .../rpt/mapper/RptMonthOverspeedCompanyMapper.xml | 72 + .../RptMonthOverspeedSpecialCompanyMapper.java | 22 + .../RptMonthOverspeedSpecialCompanyMapper.xml | 70 + .../RptMonthOverspeedSpecialVehiclesMapper.java | 24 + .../RptMonthOverspeedSpecialVehiclesMapper.xml | 56 + .../rpt/mapper/RptMonthSpecialOfflineMapper.java | 23 + .../rpt/mapper/RptMonthSpecialOfflineMapper.xml | 86 + .../RptOtherAlarmCleanVehiclesAnalysisMapper.java | 16 + .../RptOtherAlarmCleanVehiclesAnalysisMapper.xml | 5 + .../mapper/RptOtherAlarmCleanVehiclesMapper.java | 22 + .../mapper/RptOtherAlarmCleanVehiclesMapper.xml | 61 + .../RptOtherCrossDomainVehiclesAnalysisMapper.java | 16 + .../RptOtherCrossDomainVehiclesAnalysisMapper.xml | 5 + .../mapper/RptOtherCrossDomainVehiclesMapper.java | 26 + .../mapper/RptOtherCrossDomainVehiclesMapper.xml | 103 + .../RptOtherOnlineVehiclesAnalysisMapper.java | 16 + .../RptOtherOnlineVehiclesAnalysisMapper.xml | 5 + .../rpt/mapper/RptOtherOnlineVehiclesMapper.java | 25 + .../rpt/mapper/RptOtherOnlineVehiclesMapper.xml | 11 + .../rpt/mapper/RptOtherSpecialOverspeedMapper.java | 25 + .../rpt/mapper/RptOtherSpecialOverspeedMapper.xml | 119 + .../car/rpt/mapper/RptOtherSpecialTripsMapper.java | 16 + .../car/rpt/mapper/RptOtherSpecialTripsMapper.xml | 5 + .../rpt/mapper/RptOtherTerminalInstallMapper.java | 16 + .../rpt/mapper/RptOtherTerminalInstallMapper.xml | 5 + .../mapper/RptTendaysSpecialOfflineWeekMapper.java | 25 + .../mapper/RptTendaysSpecialOfflineWeekMapper.xml | 107 + .../RptTendaysSpecialOverspeedCompanyMapper.java | 22 + .../RptTendaysSpecialOverspeedCompanyMapper.xml | 49 + .../RptTendaysSpecialOverspeedVehiclesMapper.java | 22 + .../RptTendaysSpecialOverspeedVehiclesMapper.xml | 52 + ...RptDailyOperatorVehiclesLaunchRateParamDTO.java | 27 + .../dto/RptDailyOverspeedCompanyParamDTO.java | 31 + .../RptDailyOverspeedSpecialVehiclesParamDTO.java | 34 + ...lySpecialVehiclesCompanyLaunchRateParamDTO.java | 36 + .../RptDailySpecialVehiclesLaunchRateParamDTO.java | 43 + .../RptDailySpecialVehiclesOverspeedParamDTO.java | 25 + .../dto/RptMonthOverspeedCompanyParamDTO.java | 40 + .../model/dto/RptMonthSpecialOfflineParamDTO.java | 36 + .../RptMonthSpecialOverspeedCompanyParamDTO.java | 43 + .../RptMonthSpecialOverspeedVehiclesParamDTO.java | 45 + .../carapi/car/rpt/model/dto/RptOtherParamDTO.java | 85 + .../dto/RptTendaysOfflineWeekSpecialParamDTO.java | 39 + .../RptTendaysOverspeedSpecialCompanyParamDTO.java | 49 + ...RptTendaysOverspeedSpecialVehiclesParamDTO.java | 48 + .../po/RptDailyOperatorVehiclesLaunchRatePO.java | 65 + .../rpt/model/po/RptDailyOverspeedCompanyPO.java | 61 + .../po/RptDailyOverspeedSpecialVehiclesPO.java | 77 + ...tDailySpecialVehiclesCompanyLaunchRate60PO.java | 73 + .../po/RptDailySpecialVehiclesLaunchRatePO.java | 73 + .../po/RptDailySpecialVehiclesOverspeedPO.java | 52 + .../rpt/model/po/RptMonthOverspeedCompanyPO.java | 55 + .../po/RptMonthOverspeedSpecialVehiclesPO.java | 12 + .../car/rpt/model/po/RptMonthSpecialOfflinePO.java | 73 + .../po/RptMonthSpecialVehiclesOverspeedPO.java | 58 + .../rpt/model/po/RptOtherAlarmCleanVehiclesPO.java | 109 + .../model/po/RptOtherCrossDomainVehiclesPO.java | 125 + .../car/rpt/model/po/RptOtherOnlineVehiclesPO.java | 93 + .../rpt/model/po/RptOtherSpecialOverspeedPO.java | 89 + .../model/po/RptTendaysSpecialOfflineWeekPO.java | 64 + .../po/RptTendaysSpecialOverspeedCompanyPO.java | 60 + .../po/RptTendaysSpecialOverspeedVehiclesPO.java | 77 + .../vo/RptDailyOperatorVehiclesLaunchRateVO.java | 65 + .../rpt/model/vo/RptDailyOverspeedCompanyVO.java | 73 + .../vo/RptDailyOverspeedSpecialVehiclesVO.java | 77 + ...tDailySpecialVehiclesCompanyLaunchRate60VO.java | 73 + .../vo/RptDailySpecialVehiclesLaunchRateVO.java | 73 + .../vo/RptDailySpecialVehiclesOverspeedVO.java | 52 + .../rpt/model/vo/RptMonthOverspeedCompanyVO.java | 73 + .../vo/RptMonthOverspeedSpecialCompanyVO.java | 81 + .../vo/RptMonthOverspeedSpecialVehiclesVO.java | 65 + .../car/rpt/model/vo/RptMonthSpecialOfflineVO.java | 74 + .../vo/RptOtherAlarmCleanVehiclesAnalysisVO.java | 145 + .../rpt/model/vo/RptOtherAlarmCleanVehiclesVO.java | 109 + .../car/rpt/model/vo/RptOtherCompanyTripsVO.java | 64 + .../vo/RptOtherCrossDomainVehiclesAnalysisVO.java | 177 + .../model/vo/RptOtherCrossDomainVehiclesVO.java | 125 + .../model/vo/RptOtherOnlineVehiclesAnalysisVO.java | 113 + .../car/rpt/model/vo/RptOtherOnlineVehiclesVO.java | 93 + .../rpt/model/vo/RptOtherSpecialOverspeedVO.java | 89 + .../car/rpt/model/vo/RptOtherSpecialTripsVO.java | 56 + .../rpt/model/vo/RptOtherTerminalInstallVO.java | 113 + .../model/vo/RptTendaysSpecialOfflineWeekVO.java | 64 + .../vo/RptTendaysSpecialOverspeedCompanyVO.java | 73 + .../vo/RptTendaysSpecialOverspeedVehiclesVO.java | 77 + ...IRptDailyOperatorVehiclesLaunchRateService.java | 21 + .../service/IRptDailyOverspeedCompanyService.java | 21 + .../IRptDailyOverspeedSpecialVehiclesService.java | 21 + ...ySpecialVehiclesCompanyLaunchRate60Service.java | 21 + .../IRptDailySpecialVehiclesLaunchRateService.java | 21 + .../IRptDailySpecialVehiclesOverspeedService.java | 21 + .../service/IRptMonthOverspeedCompanyService.java | 22 + .../IRptMonthOverspeedSpecialCompanyService.java | 21 + .../IRptMonthOverspeedSpecialVehiclesService.java | 23 + .../service/IRptMonthSpecialOfflineService.java | 22 + ...IRptOtherAlarmCleanVehiclesAnalysisService.java | 16 + .../IRptOtherAlarmCleanVehiclesService.java | 20 + ...RptOtherCrossDomainVehiclesAnalysisService.java | 16 + .../IRptOtherCrossDomainVehiclesService.java | 24 + .../IRptOtherOnlineVehiclesAnalysisService.java | 16 + .../service/IRptOtherOnlineVehiclesService.java | 24 + .../service/IRptOtherSpecialOverspeedService.java | 24 + .../rpt/service/IRptOtherSpecialTripsService.java | 16 + .../service/IRptOtherTerminalInstallService.java | 16 + .../IRptTendaysSpecialOfflineWeekService.java | 24 + .../IRptTendaysSpecialOverspeedCompanyService.java | 21 + ...IRptTendaysSpecialOverspeedVehiclesService.java | 21 + ...DailyOperatorVehiclesLaunchRateServiceImpl.java | 34 + .../impl/RptDailyOverspeedCompanyServiceImpl.java | 34 + ...ptDailyOverspeedSpecialVehiclesServiceImpl.java | 34 + ...cialVehiclesCompanyLaunchRate60ServiceImpl.java | 36 + ...tDailySpecialVehiclesLaunchRateServiceImpl.java | 42 + ...ptDailySpecialVehiclesOverspeedServiceImpl.java | 34 + .../impl/RptMonthOverspeedCompanyServiceImpl.java | 34 + ...RptMonthOverspeedSpecialCompanyServiceImpl.java | 32 + ...ptMonthOverspeedSpecialVehiclesServiceImpl.java | 34 + .../impl/RptMonthSpecialOfflineServiceImpl.java | 35 + ...OtherAlarmCleanVehiclesAnalysisServiceImpl.java | 20 + .../RptOtherAlarmCleanVehiclesServiceImpl.java | 36 + ...therCrossDomainVehiclesAnalysisServiceImpl.java | 20 + .../RptOtherCrossDomainVehiclesServiceImpl.java | 48 + .../RptOtherOnlineVehiclesAnalysisServiceImpl.java | 20 + .../impl/RptOtherOnlineVehiclesServiceImpl.java | 41 + .../impl/RptOtherSpecialOverspeedServiceImpl.java | 41 + .../impl/RptOtherSpecialTripsServiceImpl.java | 20 + .../impl/RptOtherTerminalInstallServiceImpl.java | 20 + .../RptTendaysSpecialOfflineWeekServiceImpl.java | 41 + ...tTendaysSpecialOverspeedCompanyServiceImpl.java | 34 + ...TendaysSpecialOverspeedVehiclesServiceImpl.java | 34 + .../trips/controller/VehicleTripsController.java | 54 + .../carapi/car/trips/entity/VehicleTrips.java | 99 + .../carapi/car/trips/entity/VehicleTripsCity.java | 42 + .../car/trips/entity/VehicleTripsCompany.java | 37 + .../car/trips/manage/VehicleTripsManage.java | 117 + .../car/trips/mapper/VehicleTripsCityMapper.java | 29 + .../car/trips/mapper/VehicleTripsCityMapper.xml | 110 + .../car/trips/mapper/VehicleTripsMapper.java | 16 + .../carapi/car/trips/mapper/VehicleTripsMapper.xml | 6 + .../trips/model/dto/VehicleTripsCityExportDTO.java | 35 + .../car/trips/model/dto/VehicleTripsParamDTO.java | 55 + .../car/trips/model/vo/VehicleTripsCityVO.java | 34 + .../car/trips/model/vo/VehicleTripsCompanyVO.java | 34 + .../trips/service/IVehicleTripsCityService.java | 28 + .../car/trips/service/IVehicleTripsService.java | 16 + .../service/impl/VehicleTripsServiceCityImpl.java | 48 + .../service/impl/VehicleTripsServiceImpl.java | 20 + .../car/vehicle/contants/VehicleContant.java | 10 + .../car/vehicle/controller/VehicleController.java | 150 + .../carapi/car/vehicle/manage/VehicleManage.java | 804 +++++ .../vehicle/mapper/VehicleBaseInfoJoinMapper.java | 79 + .../car/vehicle/mapper/VehicleBaseInfoMapper.java | 43 + .../car/vehicle/mapper/VehicleBaseInfoMapper.xml | 123 + .../car/vehicle/model/NdVehicleBaseInfo.java | 211 ++ .../car/vehicle/model/NdVehicleBaseInfoJoin.java | 226 ++ .../model/dto/VehicleArchivesPageQuery.java | 95 + .../vehicle/model/dto/VehicleArchivesQueryDTO.java | 166 + .../car/vehicle/model/dto/VehicleAuditDTO.java | 43 + .../vehicle/model/dto/VehicleAuditPageQuery.java | 57 + .../vehicle/model/dto/VehicleBaseExportDTO.java | 201 ++ .../car/vehicle/model/dto/VehicleSaveDTO.java | 132 + .../car/vehicle/model/dto/VehicleUpdateDTO.java | 132 + .../car/vehicle/model/dto/VehicleViolationDTO.java | 37 + .../car/vehicle/model/po/VehicleCompanyPO.java | 62 + .../carapi/car/vehicle/model/vo/VehicleBaseVO.java | 172 + .../car/vehicle/model/vo/VehicleCarPlateVO.java | 39 + .../service/IVehicleBaseInfoJoinService.java | 40 + .../vehicle/service/IVehicleBaseInfoService.java | 49 + .../impl/VehicleBaseInfoJoinServiceImpl.java | 104 + .../service/impl/VehicleBaseInfoServiceImpl.java | 415 +++ .../carapi/car/vehicle/utils/VinUtils.java | 95 + .../video/controller/VideoMonitorController.java | 76 + .../car/video/manage/VideoMonitorManage.java | 246 ++ .../car/video/model/dto/PlaybackVideoParamDTO.java | 39 + .../model/dto/PlaybackVideoStartParamDTO.java | 40 + .../carapi/car/video/model/vo/PlaybackVideoVO.java | 35 + .../common/aop/BuildChildrenRegionEntity.java | 19 + .../aop/BuildChildrenRegionEntityAspect.java | 76 + .../common/aop/BuildChildrenRegionWrapper.java | 21 + .../aop/BuildChildrenRegionWrapperAspect.java | 63 + .../com/ningdatech/carapi/common/base/BaseDTO.java | 40 + .../ningdatech/carapi/common/base/BaseEntity.java | 29 + .../ningdatech/carapi/common/base/BaseMapper.java | 37 + .../carapi/common/config/BeanConfig.java | 109 + .../ningdatech/carapi/common/config/WebConfig.java | 31 + .../carapi/common/constant/AlarmLevelEnum.java | 55 + .../carapi/common/constant/AlarmTypeEnum.java | 89 + .../constant/ApprovedMotorcycleTypeEnum.java | 35 + .../carapi/common/constant/BgTypeEnum.java | 107 + .../carapi/common/constant/CarStatusEnum.java | 76 + .../carapi/common/constant/CommonConstant.java | 18 + .../carapi/common/constant/CompanyTypeEnum.java | 59 + .../carapi/common/constant/DeletedEnum.java | 55 + .../common/constant/DriverLicenseTypeEnum.java | 23 + .../common/constant/DriverVehicleTypeEnum.java | 108 + .../common/constant/EducationDegreeEnum.java | 44 + .../carapi/common/constant/EducationEnum.java | 73 + .../carapi/common/constant/GPSDataEnum.java | 37 + .../carapi/common/constant/GenderEnum.java | 72 + .../carapi/common/constant/InsureCompanyEnum.java | 95 + .../carapi/common/constant/MissCertEnum.java | 60 + .../carapi/common/constant/UserRoleTypeEnum.java | 58 + .../common/constant/VehicleEquipFuncEnum.java | 19 + .../common/constant/VehicleLimitSpeedEnum.java | 70 + .../carapi/common/constant/VehicleMovingEnum.java | 60 + .../carapi/common/constant/VehicleStatusEnum.java | 80 + .../carapi/common/constant/VehicleTypeEnum.java | 121 + .../carapi/common/constant/ViolationTypeEnum.java | 75 + .../carapi/common/contants/DefValConstants.java | 111 + .../carapi/common/contants/IrsConst.java | 18 + .../carapi/common/exception/AppErrorCode.java | 20 + .../carapi/common/filter/SqlInjectFilter.java | 112 + .../common/handler/GlobalExceptionHandler.java | 62 + .../common/handler/GlobalResponseHandler.java | 76 + .../carapi/common/helper/UserInfoHelper.java | 146 + .../interceptor/DataPermissionInterceptor.java | 71 + .../carapi/common/model/DataChartVo.java | 42 + .../carapi/common/model/FileBasicInfo.java | 27 + .../ningdatech/carapi/common/model/GroupByDto.java | 20 + .../carapi/common/model/KeyValueDTO.java | 20 + .../ningdatech/carapi/common/model/MapDataVO.java | 39 + .../carapi/common/model/RegionContainsBO.java | 24 + .../carapi/common/model/po/MapDataPO.java | 47 + .../ningdatech/carapi/common/util/BizUtils.java | 34 + .../ningdatech/carapi/common/util/CodeUtil.java | 394 +++ .../carapi/common/util/ExcelDownUtil.java | 68 + .../carapi/common/util/ExcelExportStyle.java | 79 + .../ningdatech/carapi/common/util/OssUtils.java | 120 + .../com/ningdatech/carapi/common/util/QrCoder.java | 103 + .../ningdatech/carapi/common/util/SignUtil.java | 67 + .../controller/CompanyArchivesController.java | 155 + .../controller/CompanyLargeScreenController.java | 53 + .../controller/NdCompanyBlackListController.java | 36 + .../NdCompanyCreditDeductController.java | 54 + .../NdCompanyCreditInsideController.java | 58 + .../controller/NdCompanyCreditLevelController.java | 29 + .../NdCompanyCreditRewardController.java | 56 + .../NdCompanyProductManageController.java | 30 + .../NdCompanyQualityManageController.java | 59 + .../NdCompanySecurityProductDutyController.java | 109 + .../NdCompanySecurityProductExecuteController.java | 79 + ...ompanySecurityProductRegulationsController.java | 80 + .../carapi/company/entity/CompanyBasicCredit.java | 71 + .../carapi/company/entity/CompanyCertificate.java | 57 + .../carapi/company/entity/CompanyCommonCredit.java | 57 + .../carapi/company/entity/CompanyEmployees.java | 77 + .../company/entity/CompanySecurityCommitment.java | 54 + .../company/entity/CompanySecurityGovernment.java | 54 + .../entity/CompanySecurityProductExecute.java | 57 + .../entity/CompanySecurityProductRegulation.java | 66 + .../company/entity/CompanyVehicleNotGetOn.java | 58 + .../carapi/company/entity/NdCompanyBlackList.java | 91 + .../company/entity/NdCompanyCreditDeduct.java | 90 + .../company/entity/NdCompanyCreditInside.java | 105 + .../company/entity/NdCompanyCreditLevel.java | 88 + .../company/entity/NdCompanyCreditReward.java | 90 + .../company/entity/NdCompanyProductManage.java | 95 + .../company/entity/NdCompanyQualityManage.java | 82 + .../entity/NdCompanySecurityProductDuty.java | 80 + .../entity/NdCompanySecurityProductExecute.java | 72 + .../NdCompanySecurityProductRegulations.java | 77 + .../carapi/company/entity/dto/CompanyAuditDTO.java | 40 + .../company/entity/dto/CompanyAuditPageQuery.java | 43 + .../dto/CompanyCreditBlackListPageParam.java | 28 + .../entity/dto/CompanyCreditDeductPageParam.java | 27 + .../entity/dto/CompanyCreditInsidePageParam.java | 34 + .../entity/dto/CompanyCreditLevelPageParam.java | 29 + .../entity/dto/CompanyCreditRewardPageParam.java | 29 + .../company/entity/dto/CompanyListParamDTO.java | 41 + .../entity/dto/CompanySecurityCommitmentParam.java | 37 + .../dto/CompanySecurityProductExecuteParam.java | 31 + .../dto/CompanySecurityProductRegulationParam.java | 42 + .../entity/dto/ReqCompanyArchivesDetailsDTO.java | 21 + .../company/entity/dto/ReqNotGetOnCarDTO.java | 36 + .../company/entity/dto/ReqQualityManageDTO.java | 31 + .../entity/dto/ReqSecurityProductDutyDTO.java | 41 + .../entity/dto/ReqSecurityProductExecuteDTO.java | 33 + .../dto/ReqSecurityProductRegulationsDTO.java | 36 + .../company/entity/dto/ResCompanyArchivesDTO.java | 43 + .../entity/dto/ResCompanyArchivesDetailsDTO.java | 38 + .../entity/dto/ResCompanyBasicCreditDTO.java | 29 + .../entity/dto/ResCompanyBasicCreditDetailDTO.java | 30 + .../entity/dto/ResCompanyBlackDetailListDTO.java | 33 + .../company/entity/dto/ResCompanyBlackListDTO.java | 17 + .../entity/dto/ResCompanyCommonCreditDTO.java | 23 + .../entity/dto/ResCompanyEmployeesCountDTO.java | 18 + .../company/entity/dto/ResCompanyTotalDTO.java | 32 + .../entity/dto/ResNotGetOnCarRecordDTO.java | 38 + .../company/entity/dto/ResProductManageDTO.java | 23 + .../company/entity/dto/ResQualityManageDTO.java | 33 + .../entity/dto/ResSecurityProductDutyDTO.java | 40 + .../entity/dto/ResSecurityProductExecuteDTO.java | 33 + .../dto/ResSecurityProductRegulationsDTO.java | 33 + .../company/entity/dto/UploadCommitmentDTO.java | 32 + .../company/entity/dto/UploadExecutionDTO.java | 30 + .../company/entity/dto/UploadGovernmentDTO.java | 32 + .../company/entity/dto/UploadRegulationDTO.java | 39 + .../carapi/company/entity/po/CompanyProductPO.java | 27 + .../carapi/company/entity/po/CompanyQualityPO.java | 27 + .../entity/po/CompanySecurityProductDutyPO.java | 33 + .../entity/po/CompanySecurityProductExecutePO.java | 27 + .../po/CompanySecurityProductRegulationPO.java | 29 + .../entity/po/CompanyVehicleNotGetOnPO.java | 22 + .../company/entity/po/ResCompanyTotalPO.java | 26 + .../carapi/company/entity/vo/ComSecProExeVO.java | 45 + .../carapi/company/entity/vo/ComSecProRegVO.java | 57 + .../company/entity/vo/CompanyEmployeesVO.java | 74 + .../entity/vo/CompanySecurityCommitmentVO.java | 54 + .../entity/vo/CompanySecurityGovernmentVO.java | 54 + .../enumeration/CompanyBlackListTypeEnum.java | 80 + .../enumeration/CompanyCreditLevelEnum.java | 56 + .../company/enumeration/CompanyTypeEnum.java | 58 + .../company/enumeration/ProductCompanyType.java | 57 + .../enumeration/SecurityProductFileType.java | 51 + .../SecurityProductRegulationFileType.java | 53 + .../company/manage/CompanySecurityManage.java | 431 +++ .../company/mapper/CompanyBasicCreditMapper.java | 16 + .../company/mapper/CompanyBasicCreditMapper.xml | 5 + .../company/mapper/CompanyCertificateMapper.java | 16 + .../company/mapper/CompanyCertificateMapper.xml | 5 + .../company/mapper/CompanyCommonCreditMapper.java | 16 + .../company/mapper/CompanyCommonCreditMapper.xml | 5 + .../company/mapper/CompanyEmployeesMapper.java | 21 + .../company/mapper/CompanyEmployeesMapper.xml | 21 + .../CompanySecurityProductExecuteFileMapper.java | 17 + .../CompanySecurityProductExecuteFileMapper.xml | 8 + ...ompanySecurityProductRegulationsFileMapper.java | 16 + ...CompanySecurityProductRegulationsFileMapper.xml | 5 + .../mapper/CompanyVehicleNotGetOnMapper.java | 27 + .../mapper/CompanyVehicleNotGetOnMapper.xml | 38 + .../company/mapper/NdCompanyBlackListMapper.java | 39 + .../company/mapper/NdCompanyBlackListMapper.xml | 42 + .../mapper/NdCompanyCreditDeductMapper.java | 16 + .../company/mapper/NdCompanyCreditDeductMapper.xml | 5 + .../mapper/NdCompanyCreditInsideMapper.java | 16 + .../company/mapper/NdCompanyCreditInsideMapper.xml | 5 + .../company/mapper/NdCompanyCreditLevelMapper.java | 16 + .../company/mapper/NdCompanyCreditLevelMapper.xml | 5 + .../mapper/NdCompanyCreditRewardMapper.java | 16 + .../company/mapper/NdCompanyCreditRewardMapper.xml | 5 + .../mapper/NdCompanyProductManageMapper.java | 27 + .../mapper/NdCompanyProductManageMapper.xml | 35 + .../mapper/NdCompanyQualityManageMapper.java | 32 + .../mapper/NdCompanyQualityManageMapper.xml | 63 + .../mapper/NdCompanySecurityCommitmentMapper.java | 16 + .../mapper/NdCompanySecurityCommitmentMapper.xml | 6 + .../mapper/NdCompanySecurityGovernmentMapper.java | 16 + .../mapper/NdCompanySecurityGovernmentMapper.xml | 6 + .../mapper/NdCompanySecurityProductDutyMapper.java | 28 + .../mapper/NdCompanySecurityProductDutyMapper.xml | 44 + .../NdCompanySecurityProductExecuteMapper.java | 28 + .../NdCompanySecurityProductExecuteMapper.xml | 34 + .../NdCompanySecurityProductRegulationsMapper.java | 28 + .../NdCompanySecurityProductRegulationsMapper.xml | 40 + .../company/service/ICompanyArchivesService.java | 103 + .../service/ICompanyBasicCreditService.java | 16 + .../service/ICompanyCertificateService.java | 18 + .../service/ICompanyCommonCreditService.java | 18 + .../company/service/ICompanyEmployeesService.java | 20 + .../service/ICompanyLargeScreenService.java | 25 + .../service/ICompanySecurityCommitmentService.java | 22 + .../service/ICompanySecurityGovernmentService.java | 26 + .../ICompanySecurityProductExecuteFileService.java | 28 + ...mpanySecurityProductRegulationsFileService.java | 26 + .../service/ICompanyVehicleNotGetOnService.java | 31 + .../service/INdCompanyBlackListService.java | 37 + .../service/INdCompanyCreditDeductService.java | 27 + .../service/INdCompanyCreditInsideService.java | 25 + .../service/INdCompanyCreditLevelService.java | 25 + .../service/INdCompanyCreditRewardService.java | 27 + .../service/INdCompanyProductManageService.java | 28 + .../service/INdCompanyQualityManageService.java | 30 + .../INdCompanySecurityProductDutyService.java | 30 + .../INdCompanySecurityProductExecuteService.java | 30 + ...NdCompanySecurityProductRegulationsService.java | 30 + .../impl/CompanyBasicCreditServiceImpl.java | 20 + .../impl/CompanyCertificateServiceImpl.java | 38 + .../impl/CompanyCommonCreditServiceImpl.java | 39 + .../service/impl/CompanyEmployeesServiceImpl.java | 31 + .../impl/CompanyLargeScreenServiceImpl.java | 140 + ...mpanySecurityProductExecuteFileServiceImpl.java | 52 + ...ySecurityProductRegulationsFileServiceImpl.java | 45 + .../impl/CompanyVehicleNotGetOnServiceImpl.java | 47 + .../service/impl/ICompanyArchivesServiceImpl.java | 810 +++++ .../impl/NdCompanyBlackListServiceImpl.java | 83 + .../impl/NdCompanyCreditDeductServiceImpl.java | 76 + .../impl/NdCompanyCreditInsideServiceImpl.java | 78 + .../impl/NdCompanyCreditLevelServiceImpl.java | 53 + .../impl/NdCompanyCreditRewardServiceImpl.java | 75 + .../impl/NdCompanyProductManageServiceImpl.java | 41 + .../impl/NdCompanyQualityManageServiceImpl.java | 95 + .../NdCompanySecurityCommitmentServiceImpl.java | 38 + .../NdCompanySecurityGovernmentServiceImpl.java | 47 + .../NdCompanySecurityProductDutyServiceImpl.java | 46 + ...NdCompanySecurityProductExecuteServiceImpl.java | 41 + ...mpanySecurityProductRegulationsServiceImpl.java | 40 + .../carapi/datascope/aop/LambdaDataScope.java | 22 + .../datascope/aop/LambdaDataScopeAspect.java | 89 + .../carapi/datascope/aop/XmlDataScope.java | 24 + .../carapi/datascope/aop/XmlDataScopeAspect.java | 101 + .../datascope/contants/DataScopeColumnConst.java | 17 + .../carapi/datascope/contants/DataScopeEnum.java | 55 + .../contants/LambdaDataScopeTypeEnum.java | 48 + .../carapi/datascope/model/DataScopeDto.java | 29 + .../carapi/datascope/model/DataScopeEntity.java | 23 + .../datascope/provider/DataScopeContext.java | 38 + .../datascope/provider/DataScopeProvider.java | 26 + .../provider/impl/AllDataScopeProviderImpl.java | 38 + .../impl/SelfChildRegionDataScopeProviderImpl.java | 48 + .../impl/SelfCompanyDataScopeProviderImpl.java | 52 + .../impl/SelfRegionDataScopeProviderImpl.java | 53 + .../carapi/driver/assembler/TrainingAssembler.java | 97 + .../driver/call/RestTemplateToInterface.java | 68 + .../carapi/driver/constant/ApplicantTypeEnum.java | 62 + .../carapi/driver/constant/ArticleTypeEnum.java | 18 + .../constant/CurrentUserOrganizationEnum.java | 19 + .../DriverAbnormalBehaviorAppendixTypeEnum.java | 38 + .../DriverAbnormalBehaviorOverseeEnum.java | 44 + .../DriverAbnormalBehaviorProcessingEnum.java | 44 + .../carapi/driver/constant/DriverAgeRangeEnum.java | 53 + ...rContinuingEducationRegistrationStatusEnum.java | 18 + .../driver/constant/DriverJobChangeStatusEnum.java | 15 + .../driver/constant/DriverMaterialAuditStatus.java | 44 + .../constant/DriverRegistrationStatusEnum.java | 21 + .../DriverReplacementRegistrationStatusEnum.java | 21 + .../carapi/driver/constant/DriverStatusEnum.java | 24 + .../constant/DrivingExperienceRangeEnum.java | 38 + .../carapi/driver/constant/ExamQualifiedEnum.java | 16 + .../carapi/driver/constant/ExamTypeEnum.java | 23 + .../driver/constant/ExaminationStatusEnum.java | 19 + .../carapi/driver/constant/MaterialStatusEnum.java | 18 + .../carapi/driver/constant/MaterialTypeEnum.java | 30 + .../carapi/driver/constant/QuestionTypeEnum.java | 28 + .../carapi/driver/constant/ScoreOperateType.java | 15 + .../driver/constant/StarManageDisplayTypeEnum.java | 17 + .../carapi/driver/constant/TrainingModeEnum.java | 21 + .../constant/TrainingRegistrationFlagEnum.java | 53 + .../constant/TrainingRegistrationTypeEnum.java | 26 + .../carapi/driver/constant/TrainingStatusEnum.java | 20 + .../carapi/driver/constant/TrainingTypeEnum.java | 24 + .../carapi/driver/constant/UserCanLoginEnum.java | 56 + .../carapi/driver/constants/DriverConstant.java | 19 + .../driver/controller/ArticleInfoController.java | 43 + .../controller/BehaviourManageController.java | 87 + .../driver/controller/CertificateController.java | 50 + .../controller/DriverArchivesController.java | 188 + .../controller/DriverBlackListController.java | 42 + .../controller/DriverManageDataViewController.java | 61 + .../controller/DriverScoreInfoController.java | 20 + .../controller/DriverScoreRecordController.java | 60 + .../driver/controller/ExamRecordController.java | 40 + .../driver/controller/StarManageController.java | 57 + .../controller/TrainingMaterialController.java | 60 + .../controller/TrainingOrganizationController.java | 127 + .../carapi/driver/entity/ArticleInfo.java | 56 + .../entity/BehaviorAnalysisProcessingMode.java | 28 + .../driver/entity/BehaviourAnalysisExportDTO.java | 98 + .../carapi/driver/entity/Certificate.java | 97 + .../entity/DriverAbnormalBehaviorAnalysis.java | 139 + .../DriverAbnormalBehaviorAnalysisNoticeDTO.java | 39 + .../DriverAbnormalBehaviorAnalysisOverseeDTO.java | 33 + ...DriverAbnormalBehaviorAnalysisPageParamDTO.java | 55 + .../driver/entity/DriverArchivesDataImportDTO.java | 61 + .../carapi/driver/entity/DriverBlackList.java | 86 + .../carapi/driver/entity/DriverInfo.java | 147 + .../carapi/driver/entity/DriverScoreInfo.java | 45 + .../carapi/driver/entity/DriverScoreRecord.java | 52 + .../driver/entity/DriverTrainingMaterials.java | 39 + .../carapi/driver/entity/DriverWorkRecordInfo.java | 131 + .../carapi/driver/entity/ExamRecord.java | 53 + .../carapi/driver/entity/ExamRecordDetail.java | 69 + .../driver/entity/OverseeInterfaceCallDTO.java | 42 + .../carapi/driver/entity/RegionStarDTO.java | 23 + .../carapi/driver/entity/StarManage.java | 71 + .../carapi/driver/entity/TrainingBonusRecord.java | 59 + .../carapi/driver/entity/TrainingMaterial.java | 64 + .../carapi/driver/entity/TrainingOrganization.java | 113 + .../entity/TrainingOrganizationMaterial.java | 46 + .../driver/entity/TrainingOrganizationTrainer.java | 82 + .../driver/entity/TrainingRegistrationReview.java | 84 + .../driver/helper/DriverBehaviorScoreHelper.java | 55 + .../carapi/driver/helper/DriverInfoHelper.java | 75 + .../helper/RegistrationAvailableCheckHelper.java | 75 + .../carapi/driver/manage/ArticleInfoManage.java | 70 + .../driver/manage/BehaviourAnalysisManage.java | 257 ++ .../carapi/driver/manage/CertificateManage.java | 154 + .../carapi/driver/manage/DriverArchivesManage.java | 2204 ++++++++++++ .../driver/manage/DriverBlackListManage.java | 169 + .../driver/manage/DriverManageDataViewManage.java | 126 + .../driver/manage/DriverScoreRecordManage.java | 161 + .../carapi/driver/manage/DriverStarManage.java | 269 ++ .../carapi/driver/manage/ExamRecordManage.java | 101 + .../driver/manage/TrainingBonusRecordManage.java | 16 + .../driver/manage/TrainingMaterialManage.java | 241 ++ .../driver/manage/TrainingOrganizationManage.java | 1582 +++++++++ .../carapi/driver/mapper/ArticleInfoMapper.java | 16 + .../carapi/driver/mapper/ArticleInfoMapper.xml | 5 + .../BehaviorAnalysisProcessingModeMapper.java | 7 + .../BehaviorAnalysisProcessingModeMapper.xml | 7 + .../driver/mapper/BehaviourAnalysisMapper.java | 56 + .../driver/mapper/BehaviourAnalysisMapper.xml | 34 + .../carapi/driver/mapper/CertificateMapper.java | 16 + .../carapi/driver/mapper/CertificateMapper.xml | 5 + .../driver/mapper/DriverBlackListMapper.java | 16 + .../carapi/driver/mapper/DriverBlackListMapper.xml | 5 + .../carapi/driver/mapper/DriverInfoMapper.java | 52 + .../carapi/driver/mapper/DriverInfoMapper.xml | 95 + .../driver/mapper/DriverScoreInfoMapper.java | 16 + .../carapi/driver/mapper/DriverScoreInfoMapper.xml | 5 + .../driver/mapper/DriverScoreRecordMapper.java | 16 + .../driver/mapper/DriverScoreRecordMapper.xml | 5 + .../driver/mapper/DriverWorkRecordInfoMapper.java | 7 + .../driver/mapper/ExamRecordDetailMapper.java | 16 + .../driver/mapper/ExamRecordDetailMapper.xml | 5 + .../carapi/driver/mapper/ExamRecordMapper.java | 16 + .../carapi/driver/mapper/ExamRecordMapper.xml | 5 + .../mapper/NdTrainingOrganizationMapper.java | 16 + .../driver/mapper/NdTrainingOrganizationMapper.xml | 5 + .../carapi/driver/mapper/StarManageMapper.java | 23 + .../carapi/driver/mapper/StarManageMapper.xml | 62 + .../driver/mapper/TrainingBonusRecordMapper.java | 16 + .../driver/mapper/TrainingBonusRecordMapper.xml | 5 + .../driver/mapper/TrainingMaterialMapper.java | 16 + .../driver/mapper/TrainingMaterialMapper.xml | 5 + .../mapper/TrainingOrganizationMaterialMapper.java | 16 + .../mapper/TrainingOrganizationMaterialMapper.xml | 5 + .../mapper/TrainingOrganizationTrainerMapper.java | 16 + .../mapper/TrainingOrganizationTrainerMapper.xml | 5 + .../mapper/TrainingRegistrationReviewMapper.java | 16 + .../mapper/TrainingRegistrationReviewMapper.xml | 4 + .../driver/model/DriverArchivesExportDTO.java | 46 + .../model/JudgmentalQuestionInfoTextContent.java | 18 + .../MultipleChoiceQuestionInfoTextContent.java | 22 + .../model/SingleChoiceQuestionInfoTextContent.java | 23 + .../carapi/driver/model/StarManageDisplayInfo.java | 25 + .../carapi/driver/model/TrainingBasicInfo.java | 77 + .../carapi/driver/model/TrainingExamPaperInfo.java | 29 + .../carapi/driver/model/TrainingMaterialInfo.java | 43 + .../driver/model/TrainingMaterialOverviewInfo.java | 69 + .../carapi/driver/model/TrainingTrainersInfo.java | 37 + .../carapi/driver/model/bo/CodingRuleBO.java | 19 + .../driver/model/dto/DriverBasicInfoDTO.java | 114 + .../driver/model/dto/TrainerInfoExportDTO.java | 132 + .../carapi/driver/model/po/AlarmWarnFilePO.java | 26 + .../carapi/driver/model/po/AuditInfo.java | 34 + .../driver/model/po/ReqAddDriverArchivesPO.java | 103 + .../driver/model/po/ReqArchivalInfoSearchPO.java | 46 + .../driver/model/po/ReqArticleInfoListPO.java | 30 + .../carapi/driver/model/po/ReqChangedJobPO.java | 24 + .../carapi/driver/model/po/ReqCompanyStarPO.java | 24 + .../driver/model/po/ReqCreateTrainingOrgPO.java | 43 + .../model/po/ReqCurrentUserOrganizationPO.java | 26 + .../model/po/ReqDriverBlackListSearchPO.java | 30 + .../driver/model/po/ReqDriverInReviewingPO.java | 43 + .../driver/model/po/ReqDriverInductionPO.java | 82 + .../driver/model/po/ReqDriverStarListPO.java | 29 + .../driver/model/po/ReqDriverTrainingListPO.java | 18 + .../po/ReqDriverTrainingPreliminaryTrialPO.java | 44 + .../po/ReqDriverTrainingRegistrationListPO.java | 45 + .../model/po/ReqDriverTrainingRegistrationPO.java | 93 + .../model/po/ReqGetArchivalInfoReviewDetailPO.java | 34 + .../driver/model/po/ReqListExamRecordPO.java | 37 + .../carapi/driver/model/po/ReqMakeUpExamPO.java | 24 + .../carapi/driver/model/po/ReqRegionStarPO.java | 18 + .../driver/model/po/ReqSaveTrainingMaterialPO.java | 44 + .../carapi/driver/model/po/ReqScoreBonusPO.java | 37 + .../carapi/driver/model/po/ReqScoreListPO.java | 22 + .../carapi/driver/model/po/ReqSetExamTimePO.java | 38 + .../carapi/driver/model/po/ReqTrainerExportPO.java | 21 + .../driver/model/po/ReqTrainingMaterialListPO.java | 24 + .../model/po/ReqTrainingOrganizationListPO.java | 42 + .../po/ReqTrainingOrganizationStatusModifyPO.java | 29 + .../driver/model/po/ReqUploadCertificatePO.java | 57 + .../driver/model/po/ReqUploadExamResultPO.java | 28 + .../driver/model/query/ArchivalInfoListQuery.java | 19 + .../model/query/TrainingOrgTrainersQuery.java | 31 + .../driver/model/vo/BehaviourAnalysisVO.java | 82 + .../vo/DriverAbnormalBehaviorAnalysisDetailVO.java | 53 + .../driver/model/vo/DriverDailyAlarmEvent.java | 38 + .../model/vo/OrganizationTrainingTrainersInfo.java | 55 + .../driver/model/vo/ResArchivalInfoDetailVO.java | 126 + .../model/vo/ResArchivalInfoSearchListVO.java | 68 + .../driver/model/vo/ResArticleInfoListVO.java | 32 + .../carapi/driver/model/vo/ResCertificateVO.java | 79 + .../driver/model/vo/ResCompanyStarListVO.java | 27 + .../driver/model/vo/ResCreateTrainingOrgVO.java | 20 + .../model/vo/ResCurrentUserOrganizationVO.java | 21 + .../driver/model/vo/ResDriverBlackListVO.java | 52 + .../model/vo/ResDriverScoreRecordListVO.java | 39 + .../driver/model/vo/ResDriverStarListVO.java | 53 + .../driver/model/vo/ResDriverTrainingListVO.java | 51 + .../vo/ResDriverTrainingRegistrationListVO.java | 70 + .../driver/model/vo/ResListExamRecordVO.java | 60 + .../carapi/driver/model/vo/ResRegionStarVO.java | 25 + .../driver/model/vo/ResSaveTrainingMaterialVO.java | 17 + .../driver/model/vo/ResTrainingMaterialListVO.java | 51 + .../driver/model/vo/ResTrainingMaterialVO.java | 44 + .../driver/model/vo/ResTrainingOrgTrainerVO.java | 41 + .../model/vo/ResTrainingOrganizationDetailVO.java | 31 + .../model/vo/ResTrainingOrganizationListVO.java | 91 + .../carapi/driver/model/vo/StarManageDisplay.java | 26 + .../carapi/driver/service/IArticleInfoService.java | 16 + .../IBehaviorAnalysisProcessingModeService.java | 11 + .../driver/service/IBehaviourAnalysisService.java | 33 + .../carapi/driver/service/ICertificateService.java | 17 + .../driver/service/IDriverBlackListService.java | 16 + .../carapi/driver/service/IDriverInfoService.java | 53 + .../driver/service/IDriverScoreInfoService.java | 16 + .../driver/service/IDriverScoreRecordService.java | 16 + .../driver/service/IDriverWorkRecordService.java | 8 + .../driver/service/IExamRecordDetailService.java | 16 + .../carapi/driver/service/IExamRecordService.java | 16 + .../carapi/driver/service/IStarManageService.java | 22 + .../service/ITrainingBonusRecordService.java | 16 + .../driver/service/ITrainingMaterialService.java | 16 + .../ITrainingOrganizationMaterialService.java | 16 + .../service/ITrainingOrganizationService.java | 16 + .../ITrainingOrganizationTrainerService.java | 16 + .../ITrainingRegistrationReviewService.java | 16 + .../service/impl/ArticleInfoServiceImpl.java | 20 + .../BehaviorAnalysisProcessingModeServiceImpl.java | 17 + .../service/impl/BehaviourAnalysisServiceImpl.java | 112 + .../service/impl/CertificateServiceImpl.java | 20 + .../service/impl/DriverBlackListServiceImpl.java | 20 + .../driver/service/impl/DriverInfoServiceImpl.java | 93 + .../service/impl/DriverScoreInfoServiceImpl.java | 20 + .../service/impl/DriverScoreRecordServiceImpl.java | 20 + .../service/impl/DriverWorkRecordServiceImpl.java | 16 + .../service/impl/ExamRecordDetailServiceImpl.java | 20 + .../driver/service/impl/ExamRecordServiceImpl.java | 20 + .../driver/service/impl/StarManageServiceImpl.java | 45 + .../impl/TrainingBonusRecordServiceImpl.java | 20 + .../service/impl/TrainingMaterialServiceImpl.java | 20 + .../TrainingOrganizationMaterialServiceImpl.java | 20 + .../impl/TrainingOrganizationServiceImpl.java | 20 + .../TrainingOrganizationTrainerServiceImpl.java | 20 + .../TrainingRegistrationReviewServiceImpl.java | 22 + .../carapi/homepage/constant/HomepageConstant.java | 20 + .../homepage/controller/AiWorkbenchController.java | 79 + .../dto/HomepageAbnormalBehaviorPageParamDTO.java | 42 + .../entity/dto/HomepageVehicleAuditPageQuery.java | 39 + .../homepage/entity/model/MyCacheHashKey.java | 33 + .../carapi/homepage/entity/model/OnlineNumCnt.java | 16 + .../entity/po/DriverAbnormalBehaviorNumPO.java | 27 + .../carapi/homepage/entity/po/VehicleNumPO.java | 20 + .../vo/HomepageDriverAbnormalBehaviorVo.java | 40 + .../carapi/homepage/entity/vo/HomepageVo.java | 33 + .../carapi/homepage/manage/HomepageManage.java | 284 ++ .../carapi/homepage/mapper/HomepageMapper.java | 16 + .../carapi/homepage/mapper/HomepageMapper.xml | 88 + .../carapi/homepage/service/IHomepageService.java | 25 + .../homepage/service/impl/HomepageServiceImpl.java | 146 + .../industry/contants/CertificateContant.java | 52 + .../controller/DataQualityMonitorController.java | 95 + .../industry/controller/DataScreenController.java | 74 + .../DriverTrainingCertificateController.java | 96 + .../LabAcceptanceCertificateController.java | 77 + .../controller/LabWorkerCertificateController.java | 86 + ...ortarEnterpriseFilingCertificateController.java | 80 + .../OperatorAssessmentSystemController.java | 45 + .../controller/PassportManageController.java | 93 + .../industry/controller/PurchaseOilController.java | 55 + .../controller/PurchaseRawMaterialController.java | 56 + .../controller/PurchaseVehicleController.java | 54 + .../controller/PurchaseWheelController.java | 59 + .../ReadyMixedMortarIndustryManageController.java | 75 + .../controller/RegistrationRecordController.java | 73 + ...tyEquipmentInstallUseCertificateController.java | 77 + ...ntInstallUseCertificateOperationController.java | 68 + .../VehicleAnnualInspectionReviewController.java | 84 + .../entity/DataQualityMonitorDynamics.java | 59 + .../industry/entity/DataQualityMonitorGps.java | 106 + .../industry/entity/DataQualityMonitorStatic.java | 66 + .../entity/DriverTrainingCertificateJoin.java | 60 + .../entity/DriverTrainingCertificateOper.java | 84 + .../entity/DriverTrainingCertificateOperJoin.java | 84 + .../industry/entity/LabAcceptanceCertificate.java | 77 + .../entity/LabAcceptanceCertificateChange.java | 87 + .../industry/entity/LabWorkerCertificate.java | 84 + .../entity/LabWorkerCertificateChange.java | 90 + .../entity/MortarEnterpriseFilingCertificate.java | 77 + .../MortarEnterpriseFilingCertificateChange.java | 88 + .../industry/entity/OperatorIndexScoreInfo.java | 41 + .../carapi/industry/entity/OperatorScoreInfo.java | 78 + .../carapi/industry/entity/PassportInfo.java | 65 + .../carapi/industry/entity/PurchaseOil.java | 74 + .../industry/entity/PurchaseRawMaterial.java | 82 + .../carapi/industry/entity/PurchaseVehicle.java | 73 + .../carapi/industry/entity/PurchaseWheel.java | 74 + .../entity/ReadyMixedMortarIndustryManage.java | 72 + .../carapi/industry/entity/RegistrationRecord.java | 75 + .../SafetyEquipmentInstallUseCertificate.java | 75 + ...etyEquipmentInstallUseCertificateOperation.java | 95 + .../entity/VehicleAnnualInspectionReview.java | 56 + .../industry/enums/AbnormalDataTypeEnum.java | 62 + .../carapi/industry/enums/AddTypeEnum.java | 51 + .../industry/enums/DataQualityMonitorGpsEnum.java | 107 + .../enums/LabWorkerCertificateTypeEnum.java | 40 + .../enums/OperatorAssessmentIndexEnum.java | 100 + .../carapi/industry/enums/QuarterEnum.java | 50 + .../manage/AnnualInspectionReviewManage.java | 240 ++ .../industry/manage/DataQualityMonitorManage.java | 304 ++ .../carapi/industry/manage/DataScreenManage.java | 98 + .../manage/DriverTrainingCertificateManage.java | 359 ++ .../manage/LabAcceptanceCertificateManage.java | 298 ++ .../manage/LabWorkerCertificateManage.java | 309 ++ .../MortarEnterpriseFilingCertificateManage.java | 225 ++ .../industry/manage/OperatorAssessmentManage.java | 246 ++ .../carapi/industry/manage/PassportManage.java | 181 + .../carapi/industry/manage/PurchaseOilManage.java | 75 + .../industry/manage/PurchaseRawMaterialManage.java | 87 + .../industry/manage/PurchaseVehicleManage.java | 83 + .../industry/manage/PurchaseWheelManage.java | 83 + .../industry/manage/ReadyMixedMortarManage.java | 189 ++ .../industry/manage/RegistrationRecordManage.java | 169 + ...ipmentInstallUseCertificateOperationManage.java | 134 + ...SafetyEquipmentIntallUserCertificateManage.java | 173 + .../mapper/DataQualityMonitorDynamicsMapper.java | 16 + .../mapper/DataQualityMonitorDynamicsMapper.xml | 5 + .../mapper/DataQualityMonitorGpsMapper.java | 16 + .../mapper/DataQualityMonitorGpsMapper.xml | 5 + .../mapper/DataQualityMonitorStaticMapper.java | 16 + .../mapper/DataQualityMonitorStaticMapper.xml | 5 + .../carapi/industry/mapper/DataScreenMapper.java | 18 + .../carapi/industry/mapper/DataScreenMapper.xml | 159 + .../DriverTrainingCertificateJoinMapper.java | 32 + .../mapper/DriverTrainingCertificateJoinMapper.xml | 5 + .../DriverTrainingCertificateOperJoinMapper.java | 33 + .../DriverTrainingCertificateOperMapper.java | 16 + .../mapper/DriverTrainingCertificateOperMapper.xml | 5 + .../LabAcceptanceCertificateChangeMapper.java | 16 + .../LabAcceptanceCertificateChangeMapper.xml | 5 + .../mapper/LabAcceptanceCertificateMapper.java | 16 + .../mapper/LabAcceptanceCertificateMapper.xml | 5 + .../mapper/LabWorkerCertificateChangeMapper.java | 16 + .../mapper/LabWorkerCertificateChangeMapper.xml | 5 + .../mapper/LabWorkerCertificateMapper.java | 16 + .../industry/mapper/LabWorkerCertificateMapper.xml | 5 + ...tarEnterpriseFilingCertificateChangeMapper.java | 16 + ...rtarEnterpriseFilingCertificateChangeMapper.xml | 5 + .../MortarEnterpriseFilingCertificateMapper.java | 16 + .../MortarEnterpriseFilingCertificateMapper.xml | 5 + .../mapper/OperatorIndexScoreInfoMapper.java | 16 + .../mapper/OperatorIndexScoreInfoMapper.xml | 5 + .../carapi/industry/mapper/PassportInfoMapper.java | 16 + .../carapi/industry/mapper/PassportInfoMapper.xml | 5 + .../carapi/industry/mapper/PurchaseOilMapper.java | 16 + .../carapi/industry/mapper/PurchaseOilMapper.xml | 5 + .../industry/mapper/PurchaseRawMaterialMapper.java | 16 + .../industry/mapper/PurchaseRawMaterialMapper.xml | 5 + .../industry/mapper/PurchaseVehicleMapper.java | 16 + .../industry/mapper/PurchaseVehicleMapper.xml | 5 + .../industry/mapper/PurchaseWheelMapper.java | 16 + .../carapi/industry/mapper/PurchaseWheelMapper.xml | 5 + .../ReadyMixedMortarIndustryManageMapper.java | 16 + .../ReadyMixedMortarIndustryManageMapper.xml | 5 + .../industry/mapper/RegistrationRecordMapper.java | 16 + .../industry/mapper/RegistrationRecordMapper.xml | 5 + ...SafetyEquipmentInstallUseCertificateMapper.java | 16 + .../SafetyEquipmentInstallUseCertificateMapper.xml | 5 + ...ipmentInstallUseCertificateOperationMapper.java | 16 + ...uipmentInstallUseCertificateOperationMapper.xml | 5 + .../VehicleAnnualInspectionReviewMapper.java | 16 + .../mapper/VehicleAnnualInspectionReviewMapper.xml | 5 + .../dto/DataQualityMonitorDynamicsExportDTO.java | 65 + .../DataQualityMonitorDynamicsPageParamDTO.java | 42 + .../model/dto/DataQualityMonitorGpsExportDTO.java | 67 + .../dto/DataQualityMonitorGpsPageParamDTO.java | 49 + .../dto/DataQualityMonitorStaticExportDTO.java | 65 + .../dto/DataQualityMonitorStaticPageParamDTO.java | 42 + .../dto/DriverTrainingCertificateExportDTO.java | 47 + .../dto/DriverTrainingCertificatePageParamDTO.java | 49 + .../dto/DriverTrainingCertificateUpdateDTO.java | 72 + .../model/dto/InspectionReviewSaveDTO.java | 47 + .../model/dto/InspectionReviewUpdateDTO.java | 52 + .../dto/LabAcceptanceCertificateExportDto.java | 45 + .../dto/LabAcceptanceCertificateImportDto.java | 57 + .../model/dto/LabWorkerCertificateExportDto.java | 49 + .../model/dto/LabWorkerCertificateImportDto.java | 57 + .../dto/MortarEnterpriseFilingCertificateDTO.java | 82 + ...MortarEnterpriseFilingCertificateExportDto.java | 45 + .../industry/model/dto/OperatorAssessmentDTO.java | 33 + .../dto/OperatorsAssessmentDetailsExportDTO.java | 34 + .../industry/model/dto/PassportExportDTO.java | 44 + .../industry/model/dto/PassportPageParamDTO.java | 44 + .../carapi/industry/model/dto/PassportSaveDTO.java | 56 + .../industry/model/dto/PassportUpdateDTO.java | 61 + .../dto/ReadyMixedMortarIndustryManageSaveDTO.java | 44 + .../ReadyMixedMortarIndustryManageUpdateDTO.java | 47 + .../industry/model/dto/ReadyMixedPageParamDTO.java | 31 + .../model/dto/RegistrationRecordPageParamDTO.java | 45 + .../model/dto/RegistrationRecordSaveDTO.java | 70 + .../model/dto/RegistrationRecordUpdateDTO.java | 71 + .../industry/model/dto/ReviewPageParamDTO.java | 45 + .../model/dto/SafetyEqInsUseCertExportDTO.java | 41 + .../model/dto/UseCertOperatePageParamDTO.java | 43 + .../model/dto/UseCertOperateUpdateDTO.java | 87 + .../industry/model/dto/UseCertPageParamDTO.java | 46 + .../carapi/industry/model/dto/UseCertSaveDTO.java | 56 + .../industry/model/dto/UseCertUpdateDTO.java | 73 + .../dto/VehicleAnnualInspectionExportDTO.java | 38 + .../carapi/industry/model/po/CeriticatePO.java | 18 + .../model/req/LabAcceptanceCertificateListReq.java | 36 + .../model/req/LabAcceptanceCertificateReq.java | 91 + .../model/req/LabWorkerCertificateAuditReq.java | 30 + .../model/req/LabWorkerCertificateListReq.java | 66 + .../model/req/LabWorkerCertificateReq.java | 92 + .../carapi/industry/model/req/PurchaseListReq.java | 34 + .../industry/model/req/PurchaseOilListReq.java | 22 + .../model/req/PurchaseRawMaterialListReq.java | 25 + .../industry/model/req/PurchaseVehicleListReq.java | 22 + .../industry/model/req/PurchaseWheelListReq.java | 22 + .../model/vo/DataQualityMonitorDynamicsVO.java | 54 + .../industry/model/vo/DataQualityMonitorGpsVO.java | 101 + .../model/vo/DataQualityMonitorStaticVO.java | 54 + .../model/vo/DriverTrainingCertificateOperVO.java | 84 + .../model/vo/DriverTrainingCertificateVO.java | 120 + .../vo/LabAcceptanceCertificateChangeListVo.java | 89 + .../model/vo/LabAcceptanceCertificateListVo.java | 72 + .../model/vo/LabWorkerCertificateChangeListVo.java | 93 + .../model/vo/LabWorkerCertificateListVo.java | 86 + .../MortarEnterpriseFilingCertificateChangeVO.java | 61 + .../vo/MortarEnterpriseFilingCertificateVO.java | 68 + .../industry/model/vo/OperatorScoreDetailVO.java | 89 + .../carapi/industry/model/vo/PassportVO.java | 73 + .../industry/model/vo/PurchaseOilListVo.java | 73 + .../model/vo/PurchaseRawMaterialListVo.java | 80 + .../industry/model/vo/PurchaseVehicleListVo.java | 71 + .../industry/model/vo/PurchaseWheelListVo.java | 71 + .../model/vo/ReadyMixedMortarIndustryManageVO.java | 84 + .../industry/model/vo/RegistrationRecordVO.java | 72 + ...yEquipmentInstallUseCertificateOperationVO.java | 87 + .../vo/SafetyEquipmentInstallUseCertificateVO.java | 88 + ...VehicleAnnualInspectionReviewApplicationVO.java | 69 + .../model/vo/VehicleAnnualInspectionReviewVO.java | 77 + .../carapi/industry/service/DataScreenService.java | 19 + .../IDataQualityMonitorDynamicsService.java | 16 + .../service/IDataQualityMonitorGpsService.java | 16 + .../service/IDataQualityMonitorStaticService.java | 16 + .../IDriverTrainingCertificateJoinService.java | 22 + .../IDriverTrainingCertificateOperJoinService.java | 22 + .../IDriverTrainingCertificateOperService.java | 16 + .../ILabAcceptanceCertificateChangeService.java | 16 + .../service/ILabAcceptanceCertificateService.java | 18 + .../ILabWorkerCertificateChangeService.java | 16 + .../service/ILabWorkerCertificateService.java | 21 + ...arEnterpriseFilingCertificateChangeService.java | 16 + .../IMortarEnterpriseFilingCertificateService.java | 18 + .../service/IOperatorIndexScoreInfoService.java | 16 + .../industry/service/IPassportInfoService.java | 16 + .../industry/service/IPurchaseOilService.java | 16 + .../service/IPurchaseRawMaterialService.java | 16 + .../industry/service/IPurchaseVehicleService.java | 16 + .../industry/service/IPurchaseWheelService.java | 16 + .../IReadyMixedMortarIndustryManageService.java | 21 + .../service/IRegistrationRecordService.java | 16 + ...pmentInstallUseCertificateOperationService.java | 16 + ...afetyEquipmentInstallUseCertificateService.java | 16 + .../IVehicleAnnualInspectionReviewService.java | 16 + .../DataQualityMonitorDynamicsServiceImpl.java | 20 + .../impl/DataQualityMonitorGpsServiceImpl.java | 20 + .../impl/DataQualityMonitorStaticServiceImpl.java | 20 + .../service/impl/DataScreenServiceImpl.java | 58 + .../DriverTrainingCertificateJoinServiceImpl.java | 35 + ...iverTrainingCertificateOperJoinServiceImpl.java | 38 + .../DriverTrainingCertificateOperServiceImpl.java | 20 + .../LabAcceptanceCertificateChangeServiceImpl.java | 20 + .../impl/LabAcceptanceCertificateServiceImpl.java | 53 + .../LabWorkerCertificateChangeServiceImpl.java | 20 + .../impl/LabWorkerCertificateServiceImpl.java | 83 + ...terpriseFilingCertificateChangeServiceImpl.java | 20 + ...rtarEnterpriseFilingCertificateServiceImpl.java | 53 + .../impl/OperatorIndexScoreInfoServiceImpl.java | 20 + .../service/impl/PassportInfoServiceImpl.java | 20 + .../service/impl/PurchaseOilServiceImpl.java | 20 + .../impl/PurchaseRawMaterialServiceImpl.java | 20 + .../service/impl/PurchaseVehicleServiceImpl.java | 20 + .../service/impl/PurchaseWheelServiceImpl.java | 20 + .../ReadyMixedMortarIndustryManageServiceImpl.java | 33 + .../impl/RegistrationRecordServiceImpl.java | 20 + ...tInstallUseCertificateOperationServiceImpl.java | 20 + ...yEquipmentInstallUseCertificateServiceImpl.java | 20 + .../VehicleAnnualInspectionReviewServiceImpl.java | 20 + .../carapi/irs/constant/SmsConstant.java | 12 + .../carapi/irs/controller/AccidentController.java | 49 + .../irs/controller/AccidentQueryController.java | 71 + .../carapi/irs/controller/IrsController.java | 38 + .../IrsDriversLicensePullController.java | 59 + .../carapi/irs/controller/SmsController.java | 48 + .../controller/VehicleIllegalQueryController.java | 64 + .../carapi/irs/entity/DriversLicenseRaw.java | 51 + .../carapi/irs/manage/DataInitManage.java | 1408 ++++++++ .../carapi/irs/manage/IrsDriversLicenseManage.java | 284 ++ .../ningdatech/carapi/irs/manage/SmsManage.java | 28 + .../carapi/irs/mapper/DriversLicenseMapper.java | 16 + .../carapi/irs/mapper/DriversLicenseMapper.xml | 5 + .../carapi/irs/mapper/IrsTempCarplateMapper.java | 16 + .../carapi/irs/mapper/IrsTempCarplateMapper.xml | 5 + .../irs/mapper/VehicleAccidentIrsDataMapper.java | 16 + .../irs/mapper/VehicleAccidentIrsDataMapper.xml | 5 + .../irs/mapper/VehicleViolationIrsDataMapper.java | 16 + .../irs/mapper/VehicleViolationIrsDataMapper.xml | 5 + .../carapi/irs/model/dto/irs/DriverLicenseDTO.java | 81 + .../irs/model/dto/irs/DrivingLicenseDTO.java | 153 + .../carapi/irs/model/dto/irs/ResponseDataDTO.java | 32 + .../carapi/irs/model/entity/IrsTempCarplate.java | 35 + .../irs/model/entity/VehicleAccidentIrsData.java | 98 + .../irs/model/entity/VehicleViolationIrsData.java | 57 + .../service/AbstractLicenseGetByIrsService.java | 77 + .../carapi/irs/service/AccidentService.java | 24 + .../ningdatech/carapi/irs/service/CarService.java | 25 + .../carapi/irs/service/DriverService.java | 32 + .../carapi/irs/service/FilePreviewService.java | 13 + .../irs/service/IDriversLicenseRawService.java | 16 + .../irs/service/IIrsTempCarplateService.java | 16 + .../service/IVehicleAccidentIrsDataService.java | 16 + .../service/IVehicleViolationIrsDataService.java | 16 + .../irs/service/PullLicenseByIrsService.java | 49 + .../carapi/irs/service/RefreshKeyService.java | 15 + .../ningdatech/carapi/irs/service/SmsService.java | 12 + .../irs/service/impl/AccidentServieImpl.java | 806 +++++ .../carapi/irs/service/impl/CarServiceImpl.java | 239 ++ .../carapi/irs/service/impl/DriverServiceImpl.java | 234 ++ .../service/impl/DriversLicenseImplRawService.java | 24 + .../irs/service/impl/FilePreviewServiceImpl.java | 56 + .../service/impl/IrsTempCarplateServiceImpl.java | 20 + .../impl/PullDriverLicenseByIrsServiceImpl.java | 185 + .../impl/PullDrivingLicenseByIrsServiceImpl.java | 185 + .../carapi/irs/service/impl/RefreshServieImpl.java | 232 ++ .../carapi/irs/service/impl/SmsServieImpl.java | 240 ++ .../impl/VehicleAccidentIrsDataServiceImpl.java | 20 + .../impl/VehicleViolationIrsDataServiceImpl.java | 20 + .../carapi/irs/task/MyAccidentQueryTask.java | 569 ++++ .../carapi/irs/task/MyDrivingLicenseQueryTask.java | 219 ++ .../carapi/irs/task/MyVehicleIllegalQueryTask.java | 512 +++ .../carapi/irs/task/MyVehicleLicenseQueryTask.java | 275 ++ .../com/ningdatech/carapi/irs/utils/HttpUtil.java | 215 ++ .../com/ningdatech/carapi/irs/utils/Md5Utils.java | 44 + .../carapi/log/constant/LogBackupConstant.java | 15 + .../carapi/log/controller/LogBackupController.java | 36 + .../log/controller/OpenApiLogBackupController.java | 37 + .../carapi/log/manage/LogBackupManage.java | 43 + .../ningdatech/carapi/log/manage/LogManage.java | 67 + .../ningdatech/carapi/log/task/LogBackupTask.java | 52 + .../com/ningdatech/carapi/open/aop/TaskLock.java | 44 + .../ningdatech/carapi/open/aop/TaskLockAspect.java | 88 + .../carapi/open/contants/AlarmContant.java | 19 + ...OpenApiAbnormalBehaviorAlarmDataController.java | 46 + .../controller/OpenApiCarPositionController.java | 55 + .../OpenApiCompanyArchivesController.java | 58 + .../OpenApiDriverArchivesController.java | 104 + .../controller/OpenApiEquipmentController.java | 44 + .../open/controller/OpenApiOssController.java | 34 + .../open/controller/OpenApiRedisController.java | 56 + .../open/controller/OpenApiRegionController.java | 42 + .../OpenApiSecurityAdvisoryController.java | 34 + .../OpenApiTrainingOrganizationController.java | 37 + ...OpenApiUserLoginVerificationCodeController.java | 40 + .../OpenApiVehicleArchivesController.java | 126 + .../open/controller/OpenApiVehicleController.java | 46 + .../OpenApiVehicleEquipmentController.java | 54 + .../carapi/open/irs/contants/SmsContant.java | 24 + .../carapi/open/irs/service/SmsService.java | 13 + .../open/irs/service/impl/SmsServiceImpl.java | 25 + .../carapi/open/manage/AlarmDataManage.java | 122 + .../carapi/open/manage/OpenCarPositionManage.java | 343 ++ .../open/manage/OpenSecurityAdvisoryManage.java | 162 + .../carapi/open/manage/UserLoginManage.java | 127 + .../carapi/open/model/OpenApiTestReq.java | 26 + .../carapi/open/model/dto/AlarmDataPictureDTO.java | 144 + .../carapi/open/model/dto/AlarmDataVideoDTO.java | 169 + .../carapi/open/model/dto/UserLoginDTO.java | 40 + .../open/model/po/ReqRealTimeCapPositionPO.java | 27 + .../open/model/vo/CompanySecurityInfoVO.java | 63 + .../carapi/qrcode/controller/QrcodeController.java | 58 + .../carapi/qrcode/entity/NdVehicleGetOn.java | 90 + .../carapi/qrcode/manage/QrcodeManage.java | 144 + .../carapi/qrcode/mapper/VehicleGetOnMapper.java | 20 + .../carapi/qrcode/mapper/VehicleGetOnMapper.xml | 17 + .../carapi/qrcode/model/dto/GetOnVehicleDTO.java | 47 + .../qrcode/model/dto/VehicleGetOnPageQuery.java | 83 + .../carapi/qrcode/model/vo/GetOnVehicleVO.java | 71 + .../carapi/qrcode/service/VehicleGetOnService.java | 17 + .../service/impl/VehicleGetOnServiceImpl.java | 29 + .../report/constant/DataUploadAuditStatusEnum.java | 72 + .../report/constant/DataUploadAuditTypeEnum.java | 62 + .../carapi/report/constant/QueryTypeEnum.java | 62 + .../carapi/report/constant/UploadDataTypeEnum.java | 92 + .../carapi/report/constants/ReportConstant.java | 47 + .../BulkCementDirectSystemController.java | 89 + .../BulkCementLogFacStaAnnualReportController.java | 64 + .../BulkCementSupplyBulletinController.java | 55 + ...BulkCementThreeCityUsageBulletinController.java | 63 + .../BulkCementTransferBulletinController.java | 64 + .../ConcreteSupplyBulletinController.java | 62 + .../MaterialLogEquipStaAnnualReportController.java | 64 + .../controller/MortarSupplyBulletinController.java | 62 + ...rohibitedAreasBulkCementSalesUseController.java | 56 + .../manage/BulkCementDirectSystemManage.java | 3585 ++++++++++++++++++++ .../report/manage/BulkCementLogFacStaManage.java | 461 +++ .../manage/BulkCementSupplyBulletinManage.java | 402 +++ .../BulkCementThreeCityUsageBulletinManage.java | 414 +++ .../manage/BulkCementTransferBulletinManage.java | 405 +++ .../manage/ConcreteSupplyBulletinManage.java | 417 +++ .../report/manage/MaterialLogEquipStaManage.java | 478 +++ .../report/manage/MortarSupplyBulletinManage.java | 473 +++ ...NonProhibitedAreasBulkCementSalesUseManage.java | 381 +++ ...ulkCementDirectReportSystemAuditInfoMapper.java | 16 + ...BulkCementDirectReportSystemAuditInfoMapper.xml | 5 + ...kCementDirectReportSystemAuditRecordMapper.java | 16 + ...lkCementDirectReportSystemAuditRecordMapper.xml | 5 + ...ementDirectReportSystemDataRelevanceMapper.java | 16 + ...CementDirectReportSystemDataRelevanceMapper.xml | 5 + .../BulkCementDirectReportSystemIndexMapper.java | 16 + .../BulkCementDirectReportSystemIndexMapper.xml | 5 + ...mentDirectReportSystemUniversalIndexMapper.java | 16 + ...ementDirectReportSystemUniversalIndexMapper.xml | 5 + ...ogisticFacilityStatisticAnnualReportMapper.java | 16 + ...LogisticFacilityStatisticAnnualReportMapper.xml | 5 + .../mapper/BulkCementSupplyBulletinMapper.java | 16 + .../mapper/BulkCementSupplyBulletinMapper.xml | 5 + .../BulkCementThreeCityUsageBulletinMapper.java | 16 + .../BulkCementThreeCityUsageBulletinMapper.xml | 5 + .../mapper/BulkCementTransferBulletinMapper.java | 16 + .../mapper/BulkCementTransferBulletinMapper.xml | 5 + .../mapper/ConcreteSupplyBulletinMapper.java | 16 + .../report/mapper/ConcreteSupplyBulletinMapper.xml | 5 + ...gisticEquipmentStatisticAnnualReportMapper.java | 16 + ...ogisticEquipmentStatisticAnnualReportMapper.xml | 5 + .../report/mapper/MortarSupplyBulletinMapper.java | 16 + .../report/mapper/MortarSupplyBulletinMapper.xml | 5 + ...NonProhibitedAreasBulkCementSalesUseMapper.java | 16 + .../NonProhibitedAreasBulkCementSalesUseMapper.xml | 5 + .../dto/BulkCementLogFacStaQueryDataExportDTO.java | 69 + .../dto/BulkCementSupplyQueryDataExportDTO.java | 46 + ...BulkCementThreeCityUsageQueryDataExportDTO.java | 51 + .../dto/BulkCementTransferQueryDataExportDTO.java | 45 + .../dto/ConcreteSupplyQueryDataExportDTO.java | 55 + .../dto/MaterialLogEquipStaQueryDataExportDTO.java | 66 + .../model/dto/MortarSupplyQueryDataExportDTO.java | 142 + .../model/dto/NonProAreasQueryDataExportDTO.java | 77 + .../dto/ReqBulkCementLogFacStaDataUploadDTO.java | 78 + .../dto/ReqMaterialLogEquipStaDataUploadDTO.java | 79 + .../BulkCementDirectReportSystemAuditInfo.java | 62 + .../BulkCementDirectReportSystemAuditRecord.java | 70 + .../BulkCementDirectReportSystemDataRelevance.java | 85 + .../entity/BulkCementDirectReportSystemIndex.java | 56 + ...BulkCementDirectReportSystemUniversalIndex.java | 66 + ...ementLogisticFacilityStatisticAnnualReport.java | 108 + .../model/entity/BulkCementSupplyBulletin.java | 99 + .../entity/BulkCementThreeCityUsageBulletin.java | 102 + .../model/entity/BulkCementTransferBulletin.java | 96 + .../model/entity/ConcreteSupplyBulletin.java | 105 + ...rialLogisticEquipmentStatisticAnnualReport.java | 105 + .../report/model/entity/MortarSupplyBulletin.java | 129 + .../NonProhibitedAreasBulkCementSalesUse.java | 114 + .../po/ReqBulkCementLogFacStaDataUploadPO.java | 45 + .../model/po/ReqBulkCementSupplyDataUploadPO.java | 59 + .../ReqBulkCementThreeCityUsageDataUploadPO.java | 71 + .../po/ReqBulkCementTransferDataUploadPO.java | 65 + .../model/po/ReqConcreteSupplyDataUploadPO.java | 74 + .../carapi/report/model/po/ReqDataAuditPO.java | 40 + .../report/model/po/ReqDataQueryModifyPO.java | 31 + .../report/model/po/ReqDataUploadDetailPO.java | 24 + .../report/model/po/ReqDataUploadListPO.java | 59 + .../po/ReqMaterialLogEquipStaDataUploadPO.java | 60 + .../model/po/ReqMortarSupplyDataUploadPO.java | 98 + .../po/ReqNonProhibitedAreasDataUploadPO.java | 78 + .../ResBulkCementLogFacStaDataQueryDetailVO.java | 36 + .../vo/ResBulkCementLogFacStaDataQueryVO.java | 39 + .../ResBulkCementLogFacStaDataUploadDetailVO.java | 116 + .../vo/ResBulkCementLogFacStaRelatedDataVO.java | 25 + .../vo/ResBulkCementSupplyDataQueryDetailVO.java | 35 + .../vo/ResBulkCementSupplyDataUploadDetailVO.java | 103 + ...sBulkCementThreeCityUsageDataQueryDetailVO.java | 35 + ...BulkCementThreeCityUsageDataUploadDetailVO.java | 110 + .../vo/ResBulkCementTransferDataQueryDetailVO.java | 38 + .../ResBulkCementTransferDataUploadDetailVO.java | 88 + .../vo/ResConcreteSupplyDataQueryDetailVO.java | 38 + .../vo/ResConcreteSupplyDataUploadDetailVO.java | 113 + .../model/vo/ResConcreteSupplyRelatedDataVO.java | 28 + .../report/model/vo/ResDataQueryDetailVO.java | 48 + .../carapi/report/model/vo/ResDataQueryListVO.java | 62 + .../report/model/vo/ResDataUploadDetailVO.java | 65 + .../report/model/vo/ResDataUploadListVO.java | 65 + .../ResMaterialLogEquipStaDataQueryDetailVO.java | 37 + .../vo/ResMaterialLogEquipStaDataQueryVO.java | 39 + .../ResMaterialLogEquipStaDataUploadDetailVO.java | 111 + .../vo/ResMaterialLogEquipStaRelatedDataVO.java | 25 + .../model/vo/ResMortarSupplyDataQueryDetailVO.java | 35 + .../vo/ResMortarSupplyDataUploadDetailVO.java | 159 + .../model/vo/ResMortarSupplyRelatedDataVO.java | 31 + .../vo/ResNonProhibitedAreasDataQueryDetailVO.java | 38 + .../ResNonProhibitedAreasDataUploadDetailVO.java | 132 + ...lkCementDirectReportSystemAuditInfoService.java | 16 + ...CementDirectReportSystemAuditRecordService.java | 16 + ...mentDirectReportSystemDataRelevanceService.java | 16 + .../IBulkCementDirectReportSystemIndexService.java | 16 + ...entDirectReportSystemUniversalIndexService.java | 16 + ...gisticFacilityStatisticAnnualReportService.java | 16 + .../service/IBulkCementSupplyBulletinService.java | 16 + .../IBulkCementThreeCityUsageBulletinService.java | 16 + .../IBulkCementTransferBulletinService.java | 16 + .../service/IConcreteSupplyBulletinService.java | 16 + ...isticEquipmentStatisticAnnualReportService.java | 16 + .../service/IMortarSupplyBulletinService.java | 16 + ...onProhibitedAreasBulkCementSalesUseService.java | 16 + ...mentDirectReportSystemAuditInfoServiceImpl.java | 20 + ...ntDirectReportSystemAuditRecordServiceImpl.java | 20 + ...DirectReportSystemDataRelevanceServiceImpl.java | 20 + ...lkCementDirectReportSystemIndexServiceImpl.java | 20 + ...irectReportSystemUniversalIndexServiceImpl.java | 20 + ...icFacilityStatisticAnnualReportServiceImpl.java | 20 + .../impl/BulkCementSupplyBulletinServiceImpl.java | 20 + ...ulkCementThreeCityUsageBulletinServiceImpl.java | 20 + .../BulkCementTransferBulletinServiceImpl.java | 20 + .../impl/ConcreteSupplyBulletinServiceImpl.java | 20 + ...cEquipmentStatisticAnnualReportServiceImpl.java | 20 + .../impl/MortarSupplyBulletinServiceImpl.java | 20 + ...ohibitedAreasBulkCementSalesUseServiceImpl.java | 20 + .../carapi/safe/constant/AccidentTypeEnum.java | 44 + .../carapi/safe/constant/SecurityContant.java | 13 + .../safe/constant/VehicleAccidentReportEnum.java | 43 + .../constant/VehicleAccidentReportStatusEnum.java | 44 + .../safe/controller/LawEnforcementController.java | 49 + .../controller/NdVehicleAccidentController.java | 105 + .../safe/controller/NdVehicleInsureController.java | 77 + .../controller/NdVehicleOverspeedController.java | 56 + .../controller/NdVehicleViolationController.java | 42 + .../controller/SecurityAdvisoryController.java | 57 + .../safe/controller/SecurityHonestyController.java | 47 + .../SecurityManageDataScreenController.java | 87 + .../carapi/safe/entity/AlarmDataPicture.java | 159 + .../carapi/safe/entity/AlarmDataVideo.java | 182 + .../carapi/safe/entity/NdInsureInfo.java | 110 + .../carapi/safe/entity/NdInsureOutDanger.java | 138 + .../safe/entity/NdInsureOutDangerAnalysis.java | 94 + .../safe/entity/NdLawCertificateVerification.java | 149 + .../carapi/safe/entity/NdLawEquipmentInstall.java | 142 + .../carapi/safe/entity/NdSafetyCommitment.java | 127 + .../carapi/safe/entity/NdSafetyCredit.java | 155 + .../carapi/safe/entity/NdSecurityAdvisory.java | 100 + .../safe/entity/NdSecurityNoticeSaveReq.java | 33 + .../carapi/safe/entity/NdVehicleAccident.java | 149 + .../safe/entity/NdVehicleAccidentAnalysis.java | 92 + .../carapi/safe/entity/NdVehicleAccidentDead.java | 131 + .../safe/entity/NdVehicleOverspeedCompany.java | 98 + .../safe/entity/NdVehicleOverspeedVehicle.java | 107 + .../safe/entity/NdVehicleOverspeedWaysection.java | 121 + .../carapi/safe/entity/NdVehicleViolation.java | 181 + .../carapi/safe/entity/VehicleAccidentReport.java | 112 + .../carapi/safe/entity/VehicleOverspeedInfo.java | 100 + .../carapi/safe/manage/LawEnforcementManage.java | 109 + .../carapi/safe/manage/SecurityAdvisoryManage.java | 119 + .../carapi/safe/manage/SecurityHonestyManage.java | 163 + .../carapi/safe/manage/VehicleAccidentManage.java | 665 ++++ .../carapi/safe/manage/VehicleInsureManage.java | 415 +++ .../carapi/safe/manage/VehicleOverspeedManage.java | 189 ++ .../carapi/safe/manage/VehicleViolationManage.java | 188 + .../carapi/safe/mapper/AlarmDataPictureMapper.java | 25 + .../carapi/safe/mapper/AlarmDataPictureMapper.xml | 50 + .../carapi/safe/mapper/AlarmDataVideoMapper.java | 23 + .../carapi/safe/mapper/AlarmDataVideoMapper.xml | 56 + .../carapi/safe/mapper/NdInsureInfoMapper.java | 16 + .../mapper/NdInsureOutDangerAnalysisMapper.java | 22 + .../mapper/NdInsureOutDangerAnalysisMapper.xml | 45 + .../safe/mapper/NdInsureOutDangerMapper.java | 22 + .../carapi/safe/mapper/NdInsureOutDangerMapper.xml | 5 + .../mapper/NdLawCertificateVerificationMapper.java | 16 + .../safe/mapper/NdLawEquipmentInstallMapper.java | 16 + .../safe/mapper/NdSafetyCommitmentMapper.java | 16 + .../carapi/safe/mapper/NdSafetyCreditMapper.java | 16 + .../safe/mapper/NdSecurityAdvisoryMapper.java | 17 + .../safe/mapper/NdSecurityAdvisoryMapper.xml | 9 + .../mapper/NdVehicleAccidentAnalysisMapper.java | 22 + .../mapper/NdVehicleAccidentAnalysisMapper.xml | 102 + .../safe/mapper/NdVehicleAccidentDeadMapper.java | 22 + .../safe/mapper/NdVehicleAccidentDeadMapper.xml | 7 + .../safe/mapper/NdVehicleAccidentMapper.java | 16 + .../mapper/NdVehicleOverspeedCompanyMapper.java | 19 + .../mapper/NdVehicleOverspeedCompanyMapper.xml | 7 + .../mapper/NdVehicleOverspeedVehicleMapper.java | 16 + .../mapper/NdVehicleOverspeedWaysectionMapper.java | 16 + .../safe/mapper/NdVehicleViolationMapper.java | 16 + .../mapper/SecurityManageDataScreenMapper.java | 26 + .../safe/mapper/SecurityManageDataScreenMapper.xml | 174 + .../safe/mapper/VehicleAccidentReportMapper.java | 16 + .../safe/mapper/VehicleAccidentReportMapper.xml | 5 + .../safe/mapper/VehicleOverspeedInfoMapper.java | 38 + .../safe/mapper/VehicleOverspeedInfoMapper.xml | 174 + .../carapi/safe/model/dto/AccidentAuditDTO.java | 35 + .../carapi/safe/model/dto/AccidentPageQuery.java | 95 + .../carapi/safe/model/dto/InsurePageQuery.java | 103 + .../safe/model/dto/LawEnforcementPageQuery.java | 73 + .../safe/model/dto/LongitudeLatitudeDTO.java | 25 + .../safe/model/dto/NdInsureOutDangerImportDTO.java | 117 + .../safe/model/dto/NdVehicleAccidentDTO.java | 118 + .../carapi/safe/model/dto/OverspeedPageQuery.java | 87 + .../safe/model/dto/SecurityAdvisoryPageQuery.java | 44 + .../safe/model/dto/SecurityHonestyPageQuery.java | 43 + .../safe/model/dto/VehicleAccidentReportDTO.java | 62 + .../model/dto/VehicleAccidentReportQueryDTO.java | 92 + .../carapi/safe/model/dto/ViolationPageQuery.java | 91 + .../safe/model/po/NdInsureOutDangerAnalysisPO.java | 83 + .../model/po/NdVehicleOverspeedWaysectionPO.java | 105 + .../carapi/safe/model/po/OutDangerAnalysisPO.java | 33 + .../carapi/safe/model/po/OutDangerCityPO.java | 35 + .../safe/model/po/OutDangerPeriodTimePO.java | 50 + .../carapi/safe/model/po/OverspeedAnalysisPO.java | 23 + .../carapi/safe/model/po/OverspeedTimesPO.java | 20 + .../safe/model/po/VehicleOverspeedCompanyPO.java | 104 + .../safe/model/po/VehicleOverspeedVehiclePO.java | 104 + .../model/vo/LawCertificateVerificationVO.java | 128 + .../safe/model/vo/LawEquipmentInstallVO.java | 122 + .../carapi/safe/model/vo/NdInsureInfoVO.java | 89 + .../safe/model/vo/NdInsureOutDangerAnalysisVO.java | 74 + .../carapi/safe/model/vo/NdInsureOutDangerVO.java | 122 + .../carapi/safe/model/vo/NdSafetyCommitmentVO.java | 113 + .../carapi/safe/model/vo/NdSafetyCreditVO.java | 137 + .../carapi/safe/model/vo/NdSecurityAdvisoryVO.java | 80 + .../safe/model/vo/NdVehicleAccidentAnalysisVO.java | 82 + .../safe/model/vo/NdVehicleAccidentDeadVO.java | 119 + .../safe/model/vo/NdVehicleAccidentReportVO.java | 113 + .../carapi/safe/model/vo/NdVehicleAccidentVO.java | 160 + .../safe/model/vo/NdVehicleOverspeedCompanyVO.java | 99 + .../safe/model/vo/NdVehicleOverspeedVehicleVO.java | 100 + .../model/vo/NdVehicleOverspeedWaysectionVO.java | 116 + .../carapi/safe/model/vo/NdVehicleViolationVO.java | 165 + .../safe/service/IAlarmDataPictureService.java | 20 + .../safe/service/IAlarmDataVideoService.java | 19 + .../carapi/safe/service/INdInsureInfoService.java | 20 + .../service/INdInsureOutDangerAnalysisService.java | 21 + .../safe/service/INdInsureOutDangerService.java | 25 + .../INdLawCertificateVerificationService.java | 16 + .../service/INdLawEquipmentInstallService.java | 16 + .../safe/service/INdSafetyCommitmentService.java | 16 + .../safe/service/INdSafetyCreditService.java | 16 + .../safe/service/INdSecurityAdvisoryService.java | 25 + .../service/INdVehicleAccidentAnalysisService.java | 24 + .../service/INdVehicleAccidentDeadService.java | 21 + .../safe/service/INdVehicleAccidentService.java | 17 + .../service/INdVehicleOverspeedCompanyService.java | 16 + .../service/INdVehicleOverspeedVehicleService.java | 16 + .../INdVehicleOverspeedWaysectionService.java | 16 + .../safe/service/INdVehicleViolationService.java | 23 + .../service/IVehicleAccidentReportService.java | 16 + .../safe/service/IVehicleOverspeedInfoService.java | 32 + .../service/SecurityManageDataScreenService.java | 35 + .../service/impl/AlarmDataPictureServiceImpl.java | 31 + .../service/impl/AlarmDataVideoServiceImpl.java | 30 + .../impl/NdAccidentServiceAnalysisImpl.java | 40 + .../service/impl/NdAccidentServiceDeadImpl.java | 29 + .../safe/service/impl/NdAccidentServiceImpl.java | 21 + .../safe/service/impl/NdInsureInfoServiceImpl.java | 38 + .../impl/NdInsureOutDangerAnalysisServiceImpl.java | 32 + .../service/impl/NdInsureOutDangerServiceImpl.java | 65 + .../NdLawCertificateVerificationServiceImpl.java | 21 + .../impl/NdLawEquipmentInstallServiceImpl.java | 21 + .../impl/NdSafetyCommitmentServiceImpl.java | 21 + .../service/impl/NdSafetyCreditServiceImpl.java | 21 + .../impl/NdSecurityAdvisoryServiceImpl.java | 47 + .../impl/NdVehicleOverspeedCompanyServiceImpl.java | 23 + .../impl/NdVehicleOverspeedVehicleServiceImpl.java | 21 + .../NdVehicleOverspeedWaysectionServiceImpl.java | 21 + .../impl/NdVehicleViolationServiceImpl.java | 57 + .../impl/SecurityManageDataScreenServiceImpl.java | 308 ++ .../impl/VehicleAccidentReportServiceImpl.java | 20 + .../impl/VehicleOverspeedInfoServiceImpl.java | 131 + .../ningdatech/carapi/safe/utils/InitDataUtil.java | 35 + .../carapi/scheduler/contants/TaskContant.java | 144 + .../scheduler/contants/VehicleTaskContant.java | 16 + .../carapi/scheduler/entity/GpsData.java | 33 + .../scheduler/entity/VehicleOnlineStatusDay.java | 74 + .../scheduler/entity/VehicleOnlineStatusHour.java | 74 + .../carapi/scheduler/enums/DataTypeEnum.java | 15 + .../carapi/scheduler/enums/OperatorTypeEnum.java | 22 + .../scheduler/mapper/OverSpeedGpsDataMapper.java | 37 + .../scheduler/mapper/OverSpeedGpsDataMapper.xml | 41 + .../mapper/VehicleOnlineStatusDayMapper.java | 35 + .../mapper/VehicleOnlineStatusDayMapper.xml | 94 + .../mapper/VehicleOnlineStatusHourMapper.java | 32 + .../mapper/VehicleOnlineStatusHourMapper.xml | 88 + .../scheduler/mapper/VehicleStatusMapper.java | 18 + .../scheduler/mapper/VehicleStatusMapper.xml | 21 + .../scheduler/model/dto/AccidentQueryDTO.java | 24 + .../scheduler/model/dto/GpsSpeedDataDTO.java | 19 + .../scheduler/model/dto/OverSpeedGpsDataDTO.java | 49 + .../scheduler/model/dto/VehicleStatusDTO.java | 28 + .../service/IVehicleOnlineStatusDayService.java | 31 + .../service/IVehicleOnlineStatusHourService.java | 27 + .../scheduler/service/OverSpeedGpsDataService.java | 37 + .../scheduler/service/VehicleStatusService.java | 10 + .../service/impl/OverSpeedGpsDataServiceImpl.java | 38 + .../impl/VehicleOnlineStatusDayServiceImpl.java | 84 + .../impl/VehicleOnlineStatusHourServiceImpl.java | 77 + .../service/impl/VehicleStatusServiceImpl.java | 35 + .../carapi/scheduler/util/DriverScoreUtils.java | 134 + .../ningdatech/carapi/scheduler/util/GpsUtils.java | 58 + .../carapi/scheduler/util/SplitListUtils.java | 74 + .../carapi/sys/contants/RegionContant.java | 20 + .../carapi/sys/contants/UserLoginConstant.java | 15 + .../sys/controller/CodingRuleController.java | 48 + .../carapi/sys/controller/CompanyController.java | 123 + .../controller/ImportTemplateDownController.java | 66 + .../carapi/sys/controller/MenuController.java | 116 + .../carapi/sys/controller/OperatorController.java | 106 + .../carapi/sys/controller/RegionController.java | 75 + .../carapi/sys/controller/RoleController.java | 141 + .../carapi/sys/controller/UserController.java | 85 + .../carapi/sys/convert/RegionConverter.java | 196 ++ .../carapi/sys/convert/UserAuthConverter.java | 48 + .../carapi/sys/convert/UserCompanyConverter.java | 47 + .../carapi/sys/convert/UserRoleConverter.java | 76 + .../carapi/sys/entity/BonusPointsRule.java | 18 + .../ningdatech/carapi/sys/entity/CodingRule.java | 61 + .../carapi/sys/entity/CodingRuleInfo.java | 30 + .../com/ningdatech/carapi/sys/entity/Company.java | 252 ++ .../ningdatech/carapi/sys/entity/CompanyJoin.java | 216 ++ .../ningdatech/carapi/sys/entity/CompanyType.java | 48 + .../carapi/sys/entity/CompanyTypeRelated.java | 41 + .../com/ningdatech/carapi/sys/entity/ExamRule.java | 53 + .../com/ningdatech/carapi/sys/entity/Menu.java | 88 + .../ningdatech/carapi/sys/entity/MetaApply.java | 83 + .../com/ningdatech/carapi/sys/entity/Operator.java | 61 + .../carapi/sys/entity/OperatorRegionHead.java | 83 + .../com/ningdatech/carapi/sys/entity/Region.java | 52 + .../com/ningdatech/carapi/sys/entity/Resource.java | 95 + .../com/ningdatech/carapi/sys/entity/Role.java | 69 + .../carapi/sys/entity/RoleAuthority.java | 76 + .../com/ningdatech/carapi/sys/entity/RoleMenu.java | 39 + .../carapi/sys/entity/ScoreDeductionRule.java | 18 + .../ningdatech/carapi/sys/entity/TreeEntity.java | 131 + .../com/ningdatech/carapi/sys/entity/UserRole.java | 63 + .../entity/constant/ImportTemplateConstant.java | 51 + .../carapi/sys/entity/dto/CascadeCodeDTO.java | 40 + .../carapi/sys/entity/dto/CascadeDTO.java | 36 + .../carapi/sys/entity/dto/CompanyDTO.java | 134 + .../carapi/sys/entity/dto/CompanyPageQuery.java | 62 + .../carapi/sys/entity/dto/CompanyQueryDTO.java | 146 + .../carapi/sys/entity/dto/CompanySaveDTO.java | 125 + .../carapi/sys/entity/dto/CompanyUpdateDTO.java | 131 + .../carapi/sys/entity/dto/GlobalUserPageDTO.java | 65 + .../carapi/sys/entity/dto/MenuQueryDTO.java | 99 + .../carapi/sys/entity/dto/MenuSaveDTO.java | 99 + .../carapi/sys/entity/dto/MenuUpdateDTO.java | 101 + .../carapi/sys/entity/dto/OperatorPageQuery.java | 37 + .../carapi/sys/entity/dto/OperatorQueryDTO.java | 57 + .../sys/entity/dto/OperatorRegionHeadSaveDTO.java | 46 + .../carapi/sys/entity/dto/OperatorSaveDTO.java | 50 + .../carapi/sys/entity/dto/OperatorUpdateDTO.java | 53 + .../carapi/sys/entity/dto/PageParamsDTO.java | 87 + .../carapi/sys/entity/dto/RegionDTO.java | 58 + .../carapi/sys/entity/dto/RegionInfo.java | 20 + .../carapi/sys/entity/dto/RegionMapKey.java | 39 + .../carapi/sys/entity/dto/RegionTreeDTO.java | 46 + .../carapi/sys/entity/dto/ResourceQueryDTO.java | 34 + .../carapi/sys/entity/dto/ResourceSaveDTO.java | 63 + .../carapi/sys/entity/dto/ResourceUpdateDTO.java | 68 + .../sys/entity/dto/RoleAuthoritySaveDTO.java | 53 + .../carapi/sys/entity/dto/RolePageQuery.java | 37 + .../carapi/sys/entity/dto/RoleQueryDTO.java | 49 + .../carapi/sys/entity/dto/RoleSaveDTO.java | 62 + .../carapi/sys/entity/dto/RoleUpdateDTO.java | 64 + .../carapi/sys/entity/dto/RoleUserSaveVO.java | 48 + .../carapi/sys/entity/dto/UserPageQuery.java | 57 + .../carapi/sys/entity/dto/UserQueryDTO.java | 132 + .../carapi/sys/entity/dto/UserRoleSaveDTO.java | 47 + .../carapi/sys/entity/dto/UserSaveDTO.java | 111 + .../carapi/sys/entity/dto/UserUpdateDTO.java | 113 + .../sys/entity/enumeration/AuthorizeType.java | 61 + .../sys/entity/enumeration/BooleanDisplayEnum.java | 33 + .../enumeration/CodingRuleBehaviorTypeEnum.java | 144 + .../entity/enumeration/CodingRuleVehicleType.java | 22 + .../sys/entity/enumeration/ImportTemplateEnum.java | 40 + .../sys/entity/enumeration/MenuTypeEnum.java | 57 + .../entity/enumeration/MetaApplyStatusEnum.java | 45 + .../sys/entity/enumeration/MetaApplyTypeEnum.java | 23 + .../carapi/sys/entity/enumeration/RoleEnum.java | 34 + .../entity/enumeration/RuleOperationTypeEnum.java | 17 + .../carapi/sys/entity/req/RegionDeleteReq.java | 29 + .../carapi/sys/entity/req/RegionTreeReq.java | 39 + .../carapi/sys/entity/req/ReqCodingRulePO.java | 24 + .../ningdatech/carapi/sys/entity/vo/CarInfoVO.java | 37 + .../com/ningdatech/carapi/sys/entity/vo/CarVO.java | 22 + .../carapi/sys/entity/vo/CompanyCarInfoVO.java | 32 + .../ningdatech/carapi/sys/entity/vo/CompanyVO.java | 162 + .../carapi/sys/entity/vo/EquipmentInfoVO.java | 33 + .../carapi/sys/entity/vo/MenuResourceTreeVO.java | 38 + .../carapi/sys/entity/vo/MenuRoleVO.java | 77 + .../ningdatech/carapi/sys/entity/vo/MenuVO.java | 71 + .../carapi/sys/entity/vo/OperatorVO.java | 62 + .../sys/entity/vo/RegionCompanyCarTreeVo.java | 50 + .../carapi/sys/entity/vo/RegionTreeCompanyVO.java | 119 + .../carapi/sys/entity/vo/RegionTreeVO.java | 60 + .../carapi/sys/entity/vo/ResCodingRuleVO.java | 24 + .../carapi/sys/entity/vo/RoleMenuVO.java | 31 + .../ningdatech/carapi/sys/entity/vo/RoleVO.java | 67 + .../ningdatech/carapi/sys/entity/vo/TreeVO.java | 103 + .../carapi/sys/entity/vo/UserInfoVO.java | 120 + .../carapi/sys/event/ImportDataEvent.java | 31 + .../carapi/sys/helper/CompaniesCacheHelper.java | 196 ++ .../carapi/sys/helper/OperatorsCacheHelper.java | 153 + .../carapi/sys/helper/RegionsCacheHelper.java | 439 +++ .../carapi/sys/helper/UserCacheHelper.java | 124 + .../carapi/sys/helper/VehiclesCacheHelper.java | 145 + .../carapi/sys/manage/CodingRuleManage.java | 135 + .../carapi/sys/manage/CompanyManage.java | 499 +++ .../ningdatech/carapi/sys/manage/MenuManage.java | 42 + .../carapi/sys/manage/OperatorManage.java | 125 + .../ningdatech/carapi/sys/manage/RegionManage.java | 663 ++++ .../ningdatech/carapi/sys/manage/RoleManage.java | 92 + .../ningdatech/carapi/sys/manage/UserManage.java | 354 ++ .../carapi/sys/mapper/CodingRuleMapper.java | 16 + .../carapi/sys/mapper/CodingRuleMapper.xml | 5 + .../carapi/sys/mapper/CompanyJoinMapper.java | 35 + .../carapi/sys/mapper/CompanyMapper.java | 32 + .../ningdatech/carapi/sys/mapper/CompanyMapper.xml | 106 + .../carapi/sys/mapper/CompanyTypeMapper.java | 18 + .../sys/mapper/CompanyTypeRelatedMapper.java | 18 + .../carapi/sys/mapper/ExamRuleMapper.java | 16 + .../carapi/sys/mapper/ExamRuleMapper.xml | 5 + .../ningdatech/carapi/sys/mapper/MenuMapper.java | 29 + .../ningdatech/carapi/sys/mapper/MenuMapper.xml | 68 + .../carapi/sys/mapper/MetaApplyMapper.java | 16 + .../carapi/sys/mapper/MetaApplyMapper.xml | 5 + .../carapi/sys/mapper/OperatorMapper.java | 18 + .../carapi/sys/mapper/OperatorMapper.xml | 5 + .../sys/mapper/OperatorRegionHeadMapper.java | 18 + .../carapi/sys/mapper/OperatorRegionHeadMapper.xml | 5 + .../carapi/sys/mapper/OperatorScoreInfoMapper.java | 16 + .../carapi/sys/mapper/OperatorScoreInfoMapper.xml | 5 + .../ningdatech/carapi/sys/mapper/RegionMapper.java | 16 + .../ningdatech/carapi/sys/mapper/RegionMapper.xml | 5 + .../carapi/sys/mapper/ResourceMapper.java | 44 + .../carapi/sys/mapper/ResourceMapper.xml | 57 + .../carapi/sys/mapper/RoleAuthorityMapper.java | 32 + .../carapi/sys/mapper/RoleAuthorityMapper.xml | 15 + .../ningdatech/carapi/sys/mapper/RoleMapper.java | 35 + .../ningdatech/carapi/sys/mapper/RoleMapper.xml | 47 + .../carapi/sys/mapper/RoleMenuMapper.java | 16 + .../carapi/sys/mapper/RoleMenuMapper.xml | 5 + .../carapi/sys/mapper/UserRoleMapper.java | 19 + .../carapi/sys/mapper/UserRoleMapper.xml | 6 + .../carapi/sys/service/CompanyJoinService.java | 24 + .../carapi/sys/service/CompanyService.java | 73 + .../sys/service/CompanyTypeRelatedService.java | 17 + .../carapi/sys/service/CompanyTypeService.java | 17 + .../carapi/sys/service/ICodingRuleService.java | 16 + .../carapi/sys/service/IExamRuleService.java | 16 + .../carapi/sys/service/IMetaApplyService.java | 16 + .../sys/service/IOperatorScoreInfoService.java | 16 + .../carapi/sys/service/IRegionService.java | 51 + .../carapi/sys/service/IRoleMenuService.java | 16 + .../ningdatech/carapi/sys/service/MenuService.java | 45 + .../sys/service/OperatorRegionHeadService.java | 41 + .../carapi/sys/service/OperatorService.java | 46 + .../carapi/sys/service/ResourceService.java | 58 + .../carapi/sys/service/RoleAuthorityService.java | 71 + .../ningdatech/carapi/sys/service/RoleService.java | 78 + .../carapi/sys/service/UserRoleService.java | 23 + .../sys/service/impl/CodingRuleServiceImpl.java | 20 + .../sys/service/impl/CompanyJoinServiceImpl.java | 47 + .../sys/service/impl/CompanyServiceImpl.java | 346 ++ .../impl/CompanyTypeRelatedServiceImpl.java | 23 + .../sys/service/impl/CompanyTypeServiceImpl.java | 23 + .../sys/service/impl/ExamRuleServiceImpl.java | 20 + .../carapi/sys/service/impl/MenuServiceImpl.java | 182 + .../sys/service/impl/MetaApplyServiceImpl.java | 20 + .../impl/OperatorRegionHeadServiceImpl.java | 84 + .../service/impl/OperatorScoreInfoServiceImpl.java | 20 + .../sys/service/impl/OperatorServiceImpl.java | 128 + .../carapi/sys/service/impl/RegionServiceImpl.java | 56 + .../sys/service/impl/ResourceServiceImpl.java | 85 + .../sys/service/impl/RoleAuthorityServiceImpl.java | 192 ++ .../sys/service/impl/RoleMenuServiceImpl.java | 20 + .../carapi/sys/service/impl/RoleServiceImpl.java | 207 ++ .../sys/service/impl/UserRoleServiceImpl.java | 48 + .../carapi/sys/utils/AuthCacheKeyUtils.java | 38 + .../carapi/sys/utils/DataScopeCacheFilterUtil.java | 55 + .../com/ningdatech/carapi/sys/utils/HttpUtils.java | 310 ++ .../com/ningdatech/carapi/sys/utils/TreeUtil.java | 318 ++ .../carapi/user/controller/UserAuthController.java | 95 + .../carapi/user/controller/UserInfoController.java | 38 + .../ningdatech/carapi/user/entity/NdUserAuth.java | 38 + .../ningdatech/carapi/user/entity/NdUserInfo.java | 128 + .../carapi/user/entity/NdUserInfoJoin.java | 148 + .../carapi/user/entity/ReqCreateAccountPO.java | 48 + .../carapi/user/manage/UserInfoManage.java | 113 + .../carapi/user/mapper/NdUserAuthMapper.java | 16 + .../carapi/user/mapper/NdUserAuthMapper.xml | 5 + .../carapi/user/mapper/NdUserInfoJoinMapper.java | 32 + .../carapi/user/mapper/NdUserInfoMapper.java | 28 + .../carapi/user/mapper/NdUserInfoMapper.xml | 5 + .../carapi/user/model/vo/NdUserInfoVO.java | 99 + .../carapi/user/model/vo/UserBasicInfoVO.java | 42 + .../carapi/user/security/auth/AuthProperties.java | 46 + .../security/auth/AuthenticationBeanConfig.java | 28 + .../user/security/auth/WebSecurityConfig.java | 66 + .../security/auth/config/RedisSessionConfig.java | 57 + .../user/security/auth/constant/AuthTypeEnum.java | 47 + .../auth/constant/SessionTimeConstant.java | 12 + .../security/auth/errorcode/AuthErrorCodeEnum.java | 36 + .../security/auth/facade/UserAuthLoginFacade.java | 55 + .../handler/DefaultExpiredSessionStrategy.java | 41 + .../auth/handler/DefaultLoginFailureHandler.java | 46 + .../auth/handler/DefaultLoginSuccessHandler.java | 38 + .../auth/handler/DefaultLogoutSuccessHandler.java | 28 + .../user/security/auth/model/UserInfoDetails.java | 69 + .../security/auth/model/dto/UserFullInfoDTO.java | 30 + .../PasswordLoginUserDetailServiceImpl.java | 68 + .../auth/password/UsernamePasswordAuthFilter.java | 87 + .../password/UsernamePasswordAuthProvider.java | 149 + .../UsernamePasswordAuthSecurityConfig.java | 84 + .../auth/password/UsernamePasswordAuthToken.java | 75 + .../carapi/user/service/INdUserAuthService.java | 16 + .../user/service/INdUserInfoJoinService.java | 24 + .../carapi/user/service/INdUserInfoService.java | 45 + .../user/service/impl/NdUserAuthServiceImpl.java | 20 + .../service/impl/NdUserInfoJoinServiceImpl.java | 59 + .../user/service/impl/NdUserInfoServiceImpl.java | 196 ++ .../ningdatech/carapi/user/util/LoginUserUtil.java | 17 + .../src/main/resources/application-dev.yml | 147 + .../src/main/resources/application-prod.yml | 175 + ningda-yw-api/src/main/resources/application.yml | 3 + .../src/main/resources/db/migration/V1.sql | 230 ++ .../main/resources/db/migration/meta_region.sql | 157 + .../src/main/resources/integration/zwdd-dev.yml | 15 + .../src/main/resources/integration/zwdd-prod.yml | 15 + .../src/main/resources/irs/车牌号.xlsx | Bin 0 -> 38096 bytes .../src/main/resources/logback-spring.xml | 68 + .../src/main/resources/security/auth-dev.yml | 45 + .../src/main/resources/security/auth-prod.yml | 44 + ...混砂浆物流装备统计年报表(空).xls | Bin 0 -> 23552 bytes ...、干混砂浆物流装备统计年报表.xls | Bin 0 -> 25600 bytes .../散装水泥供应量统计月报表(空).xls | Bin 0 -> 10326 bytes .../散装水泥供应量统计月报表.xls | Bin 0 -> 10658 bytes ...装水泥物流设施统计年报表(空).xls | Bin 0 -> 22528 bytes .../散装水泥物流设施统计年报表.xls | Bin 0 -> 23552 bytes ...散装水泥中转库进出量快报(空).xls | Bin 0 -> 10160 bytes ...江省散装水泥中转库进出量快报.xls | Bin 0 -> 10375 bytes ...舟山市散装水泥使用量快报(空).xls | Bin 0 -> 10280 bytes ...州、舟山市散装水泥使用量快报.xls | Bin 0 -> 10570 bytes .../template/车辆事故数据(空).xlsx | Bin 0 -> 9861 bytes .../resources/template/车辆事故数据.xlsx | Bin 0 -> 10070 bytes .../resources/template/运营商考核详情.docx | Bin 0 -> 11492 bytes ...泥销售使用情况统计年报表(空).xls | Bin 0 -> 22016 bytes ...装水泥销售使用情况统计年报表.xls | Bin 0 -> 23552 bytes ...物综合利用情况统计月报表(空).xls | Bin 0 -> 10505 bytes ...废弃物综合利用情况统计月报表.xls | Bin 0 -> 10802 bytes ...物综合利用情况统计月报表(空).xls | Bin 0 -> 23040 bytes ...废弃物综合利用情况统计月报表.xls | Bin 0 -> 25088 bytes .../test/java/com/ningdatech/carapi/AppTests.java | 19 + .../com/ningdatech/carapi/alarm/AlarmTest.java | 164 + .../com/ningdatech/carapi/car/HmacAuthUtil.java | 89 + .../java/com/ningdatech/carapi/car/RptTest.java | 109 + .../ningdatech/carapi/car/VehicleBaseInfoTest.java | 744 ++++ .../ningdatech/carapi/company/CompanyInfoTest.java | 268 ++ .../ningdatech/carapi/dataview/DataViewTest.java | 249 ++ .../carapi/driver/AddDriverAccountTest.java | 347 ++ .../carapi/driver/DriverDataImportTest.java | 864 +++++ .../carapi/driver/DriverStarDataImportTest.java | 70 + .../ningdatech/carapi/driver/SplitListUtils.java | 27 + .../ningdatech/carapi/loginbycode/AliSmsTest.java | 39 + .../carapi/loginbycode/config/Config.java | 35 + .../carapi/loginbycode/utils/AliSmsUtil.java | 106 + .../com/ningdatech/carapi/open/OpenApiTest.java | 294 ++ .../java/com/ningdatech/carapi/oss/OSSTest.java | 115 + .../com/ningdatech/carapi/oss/util/OssUtils.java | 126 + .../com/ningdatech/carapi/redis/RedisTest.java | 70 + .../com/ningdatech/carapi/report/ReportTest.java | 2977 ++++++++++++++++ .../carapi/safe/InsureOutdangerTest.java | 442 +++ .../ningdatech/carapi/schedule/VehicleStatus.java | 29 + .../java/com/ningdatech/carapi/sms/SendSms.java | 42 + .../sys/helper/RegionsCacheHelperTempTest.java | 44 + .../carapi/sys/helper/RegionsCacheHelperTest.java | 68 + .../com/ningdatech/carapi/user/UserInfoTest.java | 129 + .../com/ningdatech/carapi/user/UserLoginTest.java | 17 + .../com/ningdatech/carapi/utils/HttpUtils.java | 310 ++ .../carapi/vehicle/CompanyVehicleTest.java | 800 +++++ outInsure/保险出险数据.xlsx | Bin 0 -> 3798805 bytes pom.xml | 116 + 开发指南.md | 18 + 1896 files changed, 130730 insertions(+), 25 deletions(-) create mode 100644 ningda-generator/pom.xml create mode 100644 ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeConfig.java create mode 100644 ningda-yw-api/pom.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/App.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/common/DangerLevelEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/AnalysisEvalDataViewController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/IndustryStandardsController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/InsuranceRiskEvalController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/SecurityAnalysisEvalController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/WarnAnalysisController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/IndustryStandards.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageGrade.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageResultEval.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityRiskEval.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecuritySystemBuildingEval.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleAccidentEval.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleOverSpeedEval.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleServiceLife.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleViolationEval.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCar.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisDriver.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/CompanyWarnStatisticsDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/OutDangerImportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleAccidentImportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleOverSpeedImportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleViolationImportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/DangerLevel.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/IndustryStandardsType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/InsuranceDangerLevel.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsSaveReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityManageGradeListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalSaveReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecuritySystemBuildingEvalSaveReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleAccidentEvalModReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleOverSpeedEvalModReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleServiceLifeListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleViolationEvalModReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/WarnAnalysisListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/CompanyWarnStatisticsVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/IndustryStandardsListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageGradeVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageResultEvalListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityRiskEvalListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecuritySystemBuildingEvalListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleAccidentEvalListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleOverSpeedEvalListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleServiceLifeListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleViolationEvalListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCarVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCompanyVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByDriverVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/AnalysisEvalDataViewManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/IndustryStandardsManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/InsuranceRiskEvalManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/SecurityAnalysisEvalManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/WarnAnalysisManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IIndustryStandardsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/INdInsureOutDangerVOService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageGradeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageResultEvalService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityRiskEvalService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecuritySystemBuildingEvalService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleAccidentEvalService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleOverSpeedEvalService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleServiceLifeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleViolationEvalService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCarService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisDriverService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/IndustryStandardsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/NdInsureOutDangerVOServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageGradeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageResultEvalServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityRiskEvalServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecuritySystemBuildingEvalServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleAccidentEvalServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleOverSpeedEvalServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleServiceLifeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleViolationEvalServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCarServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisDriverServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicle.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicleAspect.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/assembler/QuestionAssembler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ArchivesController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ExaminationPaperController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/PaperQuestionController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaperQuestion.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/PaperQuestion.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ApproveStateEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/AuditStateEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/CertOperTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/DriverRelationConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ExamPaperQualifiedScoreConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/IsRandomEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/PaperQuestionStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ArchivesManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ExaminationPaperManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/PaperQuestionManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ExamRuleInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/JudgmentalQuestionTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/MultipleChoiceQuestionTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ShortAnswerQuestionTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/SingleChoiceQuestionTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamPaperListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamRulePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqQuestionListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamPaperPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamRulePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveNewQuestionPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamRuleVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperQuestionService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IPaperQuestionService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperQuestionServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/NdIPaperQuestionServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/contants/DigitalCockpitContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/DigitalCockpitController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/VehicleManageDataScreenController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/manage/DigitalCockpitManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/dto/DataScreenParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/InsureDistributionStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleRegionsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleTimesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OperatorDistributionStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OverspeedStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/RegionDistributionStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleStatusTimePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleTypeStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleUsefulLifeStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/YearVehicleStatisticsPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/InsureDistributionStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/OperatorDistributionStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/RegionDistributionStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/StatisticsCenterVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleTypeStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleUsefulLifeStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/YearVehicleStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/VehicleStatisticsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/impl/VehicleStatisticsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/controller/VehicleEquipmentController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/converter/VehicleEquipmentConverter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/manage/VehicleEquipmentManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/DataAccessDevices.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentChannels.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/VehicleEquipmentNo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentChannelsSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipApiResponse.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipEquipmentRes.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/NdVehicleEquipmentVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/VehicleEquipmentVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IDataAccessDevicesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentChannelsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentJoinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IVehicleEquipmentNoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/DataAccessDevicesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentChannelsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentJoinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/VehicleEquipmentNoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/controller/StatusMonitorController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/AlarmDataLoad.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarn.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarnFile.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/SecurityMonitorJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/VehicleSecurityMonitor.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/manage/StatusMonitorManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/SecurityMonitorJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/AlarmDataLoadDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/LoadMonitorPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/AlarmDataLoadVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/SecurityMonitorVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mqtt/MqttReceiveConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IAlarmDataLoadService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnFileService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IVehicleSecurityMonitorService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/SecurityMonitorService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/AlarmDataLoadServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnFileServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/SecurityMonitorServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/VehicleSecurityMonitorServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/contants/PositionContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/controller/PositionMonitorController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/entity/VehiclePositionInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/manage/PositionMonitorManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqDataPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorVehicleGisDetailPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqTrajectoryDataPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/DeviceVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorStatisticsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResTrajectoryDataVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/IVehiclePositionInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/impl/VehiclePositionInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptDailyController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptMonthController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptOtherController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptTendaysController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOperatorVehiclesLaunchRate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedSpecialVehicles.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesCompanyLaunchRate60.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesLaunchRate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesOverspeed.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialVehicles.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthSpecialOffline.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehicles.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehiclesAnalysis.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehicles.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehiclesAnalysis.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehicles.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehiclesAnalysis.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialOverspeed.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialTrips.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherTerminalInstall.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOfflineWeek.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedVehicles.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptDailyManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptMonthManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptOtherManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptTendaysManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOperatorVehiclesLaunchRateParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedCompanyParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedSpecialVehiclesParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesCompanyLaunchRateParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesLaunchRateParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesOverspeedParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthOverspeedCompanyParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOfflineParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedCompanyParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedVehiclesParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptOtherParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOfflineWeekSpecialParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialCompanyParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialVehiclesParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOperatorVehiclesLaunchRatePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedCompanyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedSpecialVehiclesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesCompanyLaunchRate60PO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesLaunchRatePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesOverspeedPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedCompanyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedSpecialVehiclesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialOfflinePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialVehiclesOverspeedPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherAlarmCleanVehiclesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherCrossDomainVehiclesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherOnlineVehiclesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherSpecialOverspeedPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOfflineWeekPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedCompanyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedVehiclesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOperatorVehiclesLaunchRateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedSpecialVehiclesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesCompanyLaunchRate60VO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesLaunchRateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesOverspeedVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialVehiclesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthSpecialOfflineVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesAnalysisVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCompanyTripsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesAnalysisVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesAnalysisVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialOverspeedVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialTripsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherTerminalInstallVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOfflineWeekVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedVehiclesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOperatorVehiclesLaunchRateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedCompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedSpecialVehiclesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesCompanyLaunchRate60Service.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesLaunchRateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesOverspeedService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedCompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialCompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialVehiclesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthSpecialOfflineService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesAnalysisService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesAnalysisService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesAnalysisService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialOverspeedService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialTripsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherTerminalInstallService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOfflineWeekService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedCompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedVehiclesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOperatorVehiclesLaunchRateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedCompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedSpecialVehiclesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesCompanyLaunchRate60ServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesLaunchRateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesOverspeedServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedCompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialCompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialVehiclesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthSpecialOfflineServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesAnalysisServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesAnalysisServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesAnalysisServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialOverspeedServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialTripsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherTerminalInstallServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOfflineWeekServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedCompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedVehiclesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/controller/VehicleTripsController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTrips.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCity.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/manage/VehicleTripsManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsCityExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCityVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsCityService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceCityImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/contants/VehicleContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/controller/VehicleController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/manage/VehicleManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfoJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleBaseExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleViolationDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/po/VehicleCompanyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleBaseVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleCarPlateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoJoinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoJoinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/utils/VinUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/controller/VideoMonitorController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/manage/VideoMonitorManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoStartParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/vo/PlaybackVideoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntity.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntityAspect.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapperAspect.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseEntity.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/BeanConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/WebConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmLevelEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ApprovedMotorcycleTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/BgTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CarStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CommonConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CompanyTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DeletedEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverLicenseTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverVehicleTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationDegreeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GPSDataEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GenderEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/InsureCompanyEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/MissCertEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/UserRoleTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleEquipFuncEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleLimitSpeedEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleMovingEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ViolationTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/DefValConstants.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/IrsConst.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/exception/AppErrorCode.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/filter/SqlInjectFilter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalExceptionHandler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalResponseHandler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/helper/UserInfoHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/interceptor/DataPermissionInterceptor.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/DataChartVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/FileBasicInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/GroupByDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/KeyValueDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/MapDataVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/RegionContainsBO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/po/MapDataPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/BizUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/CodeUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelDownUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelExportStyle.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/OssUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/QrCoder.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/SignUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyArchivesController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyLargeScreenController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyBlackListController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditDeductController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditInsideController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditLevelController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditRewardController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyProductManageController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyQualityManageController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductDutyController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductExecuteController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductRegulationsController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyBasicCredit.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCertificate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCommonCredit.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyEmployees.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityCommitment.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityGovernment.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductExecute.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductRegulation.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyVehicleNotGetOn.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyBlackList.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditDeduct.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditInside.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditLevel.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditReward.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyProductManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyQualityManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductDuty.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductExecute.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductRegulations.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditBlackListPageParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditDeductPageParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditInsidePageParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditLevelPageParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditRewardPageParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyListParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityCommitmentParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductExecuteParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductRegulationParam.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqCompanyArchivesDetailsDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqNotGetOnCarDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqQualityManageDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductDutyDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductExecuteDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductRegulationsDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDetailsDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDetailDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackDetailListDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackListDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyCommonCreditDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyEmployeesCountDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyTotalDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResNotGetOnCarRecordDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResProductManageDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResQualityManageDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductDutyDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductExecuteDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductRegulationsDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadCommitmentDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadExecutionDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadGovernmentDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadRegulationDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyProductPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyQualityPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductDutyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductExecutePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductRegulationPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyVehicleNotGetOnPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/ResCompanyTotalPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProExeVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProRegVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanyEmployeesVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityCommitmentVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityGovernmentVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyBlackListTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyCreditLevelEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/ProductCompanyType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductFileType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductRegulationFileType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/manage/CompanySecurityManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyArchivesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyBasicCreditService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCertificateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCommonCreditService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyEmployeesService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyLargeScreenService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityCommitmentService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityGovernmentService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductExecuteFileService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductRegulationsFileService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyVehicleNotGetOnService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyBlackListService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditDeductService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditInsideService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditLevelService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditRewardService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyProductManageService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyQualityManageService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductDutyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductExecuteService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductRegulationsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyBasicCreditServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCertificateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCommonCreditServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyEmployeesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyLargeScreenServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductExecuteFileServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductRegulationsFileServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyVehicleNotGetOnServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/ICompanyArchivesServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyBlackListServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditDeductServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditInsideServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditLevelServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditRewardServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyProductManageServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyQualityManageServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityCommitmentServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityGovernmentServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductDutyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductExecuteServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductRegulationsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScope.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScopeAspect.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScope.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScopeAspect.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeColumnConst.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/LambdaDataScopeTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeEntity.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeContext.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeProvider.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/AllDataScopeProviderImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfChildRegionDataScopeProviderImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfCompanyDataScopeProviderImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfRegionDataScopeProviderImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/assembler/TrainingAssembler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/call/RestTemplateToInterface.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ApplicantTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ArticleTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/CurrentUserOrganizationEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorAppendixTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorOverseeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorProcessingEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAgeRangeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverContinuingEducationRegistrationStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverJobChangeStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverMaterialAuditStatus.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverRegistrationStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverReplacementRegistrationStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DrivingExperienceRangeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamQualifiedEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExaminationStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/QuestionTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ScoreOperateType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/StarManageDisplayTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingModeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationFlagEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/UserCanLoginEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constants/DriverConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ArticleInfoController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/BehaviourManageController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/CertificateController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverArchivesController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverBlackListController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverManageDataViewController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreInfoController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreRecordController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ExamRecordController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/StarManageController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingMaterialController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingOrganizationController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ArticleInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviorAnalysisProcessingMode.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviourAnalysisExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/Certificate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysis.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisNoticeDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisOverseeDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverArchivesDataImportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverBlackList.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreRecord.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverTrainingMaterials.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverWorkRecordInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecord.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecordDetail.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/OverseeInterfaceCallDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/RegionStarDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/StarManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingBonusRecord.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingMaterial.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganization.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationMaterial.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationTrainer.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingRegistrationReview.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverBehaviorScoreHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverInfoHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/RegistrationAvailableCheckHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ArticleInfoManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/BehaviourAnalysisManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/CertificateManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverArchivesManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverBlackListManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverManageDataViewManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverScoreRecordManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverStarManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ExamRecordManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingBonusRecordManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingMaterialManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingOrganizationManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverWorkRecordInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/DriverArchivesExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/JudgmentalQuestionInfoTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/MultipleChoiceQuestionInfoTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/SingleChoiceQuestionInfoTextContent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/StarManageDisplayInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingBasicInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingExamPaperInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialOverviewInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingTrainersInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/bo/CodingRuleBO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/DriverBasicInfoDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/TrainerInfoExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AlarmWarnFilePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AuditInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqAddDriverArchivesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArchivalInfoSearchPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArticleInfoListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqChangedJobPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCompanyStarPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCreateTrainingOrgPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCurrentUserOrganizationPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverBlackListSearchPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInReviewingPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInductionPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverStarListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingPreliminaryTrialPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqGetArchivalInfoReviewDetailPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqListExamRecordPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqMakeUpExamPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqRegionStarPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSaveTrainingMaterialPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreBonusPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSetExamTimePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainerExportPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingMaterialListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationStatusModifyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadCertificatePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadExamResultPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/ArchivalInfoListQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/TrainingOrgTrainersQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/BehaviourAnalysisVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverAbnormalBehaviorAnalysisDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverDailyAlarmEvent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/OrganizationTrainingTrainersInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoSearchListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArticleInfoListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCertificateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCompanyStarListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCreateTrainingOrgVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCurrentUserOrganizationVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverBlackListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverScoreRecordListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverStarListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingRegistrationListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResListExamRecordVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResRegionStarVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResSaveTrainingMaterialVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrgTrainerVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/StarManageDisplay.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IArticleInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviorAnalysisProcessingModeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviourAnalysisService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ICertificateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverBlackListService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreRecordService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverWorkRecordService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordDetailService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IStarManageService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingBonusRecordService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingMaterialService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationMaterialService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationTrainerService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingRegistrationReviewService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ArticleInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviorAnalysisProcessingModeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviourAnalysisServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/CertificateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverBlackListServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreRecordServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverWorkRecordServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordDetailServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/StarManageServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingBonusRecordServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingMaterialServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationMaterialServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationTrainerServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingRegistrationReviewServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/constant/HomepageConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/controller/AiWorkbenchController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageAbnormalBehaviorPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageVehicleAuditPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/MyCacheHashKey.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/OnlineNumCnt.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/DriverAbnormalBehaviorNumPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/VehicleNumPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageDriverAbnormalBehaviorVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/manage/HomepageManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/IHomepageService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/impl/HomepageServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/contants/CertificateContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataQualityMonitorController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataScreenController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DriverTrainingCertificateController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabAcceptanceCertificateController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabWorkerCertificateController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/MortarEnterpriseFilingCertificateController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/OperatorAssessmentSystemController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PassportManageController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseOilController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseRawMaterialController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseVehicleController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseWheelController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/ReadyMixedMortarIndustryManageController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/RegistrationRecordController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateOperationController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/VehicleAnnualInspectionReviewController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorDynamics.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorGps.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorStatic.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOperJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificateChange.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificateChange.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificateChange.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorIndexScoreInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorScoreInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PassportInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseOil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseRawMaterial.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseVehicle.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseWheel.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/ReadyMixedMortarIndustryManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/RegistrationRecord.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificateOperation.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/VehicleAnnualInspectionReview.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AbnormalDataTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AddTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/DataQualityMonitorGpsEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/LabWorkerCertificateTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/OperatorAssessmentIndexEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/QuarterEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/AnnualInspectionReviewManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataQualityMonitorManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataScreenManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DriverTrainingCertificateManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabAcceptanceCertificateManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabWorkerCertificateManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/MortarEnterpriseFilingCertificateManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/OperatorAssessmentManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PassportManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseOilManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseRawMaterialManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseVehicleManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseWheelManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/ReadyMixedMortarManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/RegistrationRecordManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentInstallUseCertificateOperationManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentIntallUserCertificateManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificatePageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateExportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateImportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateExportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateImportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateExportDto.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorAssessmentDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorsAssessmentDetailsExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReviewPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/SafetyEqInsUseCertExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperatePageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperateUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertPageParamDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/VehicleAnnualInspectionExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/po/CeriticatePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateAuditReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseOilListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseRawMaterialListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseVehicleListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseWheelListReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorDynamicsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorGpsVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorStaticVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateOperVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateChangeListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateChangeListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateChangeVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/OperatorScoreDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PassportVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseOilListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseRawMaterialListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseVehicleListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseWheelListVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/ReadyMixedMortarIndustryManageVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/RegistrationRecordVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateOperationVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewApplicationVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/DataScreenService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorDynamicsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorGpsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorStaticService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateJoinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperJoinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateChangeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateChangeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateChangeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IOperatorIndexScoreInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPassportInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseOilService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseRawMaterialService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseVehicleService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseWheelService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IReadyMixedMortarIndustryManageService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IRegistrationRecordService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateOperationService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IVehicleAnnualInspectionReviewService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorDynamicsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorGpsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorStaticServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataScreenServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateJoinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperJoinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateChangeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateChangeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateChangeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/OperatorIndexScoreInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PassportInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseOilServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseRawMaterialServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseVehicleServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseWheelServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/ReadyMixedMortarIndustryManageServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/RegistrationRecordServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateOperationServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/VehicleAnnualInspectionReviewServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/constant/SmsConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentQueryController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsDriversLicensePullController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/SmsController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/VehicleIllegalQueryController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/entity/DriversLicenseRaw.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/DataInitManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/IrsDriversLicenseManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/SmsManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DriverLicenseDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DrivingLicenseDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/ResponseDataDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/IrsTempCarplate.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleAccidentIrsData.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleViolationIrsData.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AbstractLicenseGetByIrsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AccidentService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/CarService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/DriverService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/FilePreviewService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IDriversLicenseRawService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IIrsTempCarplateService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleAccidentIrsDataService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleViolationIrsDataService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/PullLicenseByIrsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/RefreshKeyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/SmsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/AccidentServieImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/CarServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriverServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriversLicenseImplRawService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/FilePreviewServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/IrsTempCarplateServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDriverLicenseByIrsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDrivingLicenseByIrsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/RefreshServieImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/SmsServieImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleAccidentIrsDataServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleViolationIrsDataServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyAccidentQueryTask.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyDrivingLicenseQueryTask.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleIllegalQueryTask.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleLicenseQueryTask.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/HttpUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/Md5Utils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/log/constant/LogBackupConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/LogBackupController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/OpenApiLogBackupController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogBackupManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/log/task/LogBackupTask.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLock.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLockAspect.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/contants/AlarmContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiAbnormalBehaviorAlarmDataController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCarPositionController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCompanyArchivesController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiDriverArchivesController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiEquipmentController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiOssController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRedisController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRegionController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiSecurityAdvisoryController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiTrainingOrganizationController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiUserLoginVerificationCodeController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleArchivesController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleEquipmentController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/contants/SmsContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/SmsService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/impl/SmsServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/AlarmDataManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenCarPositionManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenSecurityAdvisoryManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/UserLoginManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/OpenApiTestReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataPictureDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataVideoDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/UserLoginDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/po/ReqRealTimeCapPositionPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/vo/CompanySecurityInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/controller/QrcodeController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/entity/NdVehicleGetOn.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/manage/QrcodeManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/GetOnVehicleDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/VehicleGetOnPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/vo/GetOnVehicleVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/VehicleGetOnService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/impl/VehicleGetOnServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/QueryTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/UploadDataTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constants/ReportConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementDirectSystemController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementLogFacStaAnnualReportController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementSupplyBulletinController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementThreeCityUsageBulletinController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementTransferBulletinController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/ConcreteSupplyBulletinController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MaterialLogEquipStaAnnualReportController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MortarSupplyBulletinController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/NonProhibitedAreasBulkCementSalesUseController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementDirectSystemManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementLogFacStaManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementSupplyBulletinManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementThreeCityUsageBulletinManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementTransferBulletinManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/ConcreteSupplyBulletinManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MaterialLogEquipStaManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MortarSupplyBulletinManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/NonProhibitedAreasBulkCementSalesUseManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementLogFacStaQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementSupplyQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementThreeCityUsageQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementTransferQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ConcreteSupplyQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MaterialLogEquipStaQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MortarSupplyQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/NonProAreasQueryDataExportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqBulkCementLogFacStaDataUploadDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqMaterialLogEquipStaDataUploadDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditRecord.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemDataRelevance.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemIndex.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemUniversalIndex.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementLogisticFacilityStatisticAnnualReport.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementSupplyBulletin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementThreeCityUsageBulletin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementTransferBulletin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/ConcreteSupplyBulletin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MaterialLogisticEquipmentStatisticAnnualReport.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MortarSupplyBulletin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/NonProhibitedAreasBulkCementSalesUse.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementLogFacStaDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementSupplyDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementThreeCityUsageDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementTransferDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqConcreteSupplyDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataAuditPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataQueryModifyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadDetailPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadListPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMaterialLogEquipStaDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMortarSupplyDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqNonProhibitedAreasDataUploadPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaRelatedDataVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyRelatedDataVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadListVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaRelatedDataVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyRelatedDataVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataQueryDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataUploadDetailVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditRecordService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemDataRelevanceService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemIndexService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemUniversalIndexService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementLogisticFacilityStatisticAnnualReportService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementSupplyBulletinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementThreeCityUsageBulletinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementTransferBulletinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IConcreteSupplyBulletinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMaterialLogisticEquipmentStatisticAnnualReportService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMortarSupplyBulletinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/INonProhibitedAreasBulkCementSalesUseService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditRecordServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemDataRelevanceServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemIndexServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemUniversalIndexServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementLogisticFacilityStatisticAnnualReportServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementSupplyBulletinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementThreeCityUsageBulletinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementTransferBulletinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/ConcreteSupplyBulletinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MaterialLogisticEquipmentStatisticAnnualReportServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MortarSupplyBulletinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/NonProhibitedAreasBulkCementSalesUseServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/AccidentTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/SecurityContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/LawEnforcementController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleAccidentController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleInsureController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleOverspeedController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleViolationController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityAdvisoryController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityHonestyController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityManageDataScreenController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataPicture.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataVideo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDanger.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDangerAnalysis.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawCertificateVerification.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawEquipmentInstall.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCommitment.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCredit.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityAdvisory.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityNoticeSaveReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccident.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentAnalysis.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentDead.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedCompany.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedVehicle.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedWaysection.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleViolation.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleAccidentReport.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleOverspeedInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/LawEnforcementManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityAdvisoryManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityHonestyManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleAccidentManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleInsureManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleOverspeedManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleViolationManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawCertificateVerificationMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawEquipmentInstallMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCommitmentMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCreditMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedVehicleMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedWaysectionMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleViolationMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentAuditDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/InsurePageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LawEnforcementPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LongitudeLatitudeDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdInsureOutDangerImportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdVehicleAccidentDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/OverspeedPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityAdvisoryPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityHonestyPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/ViolationPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdInsureOutDangerAnalysisPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdVehicleOverspeedWaysectionPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerAnalysisPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerCityPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerPeriodTimePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedAnalysisPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedTimesPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedCompanyPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedVehiclePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawCertificateVerificationVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawEquipmentInstallVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerAnalysisVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCommitmentVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCreditVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSecurityAdvisoryVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentAnalysisVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentDeadVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentReportVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedVehicleVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedWaysectionVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleViolationVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataPictureService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataVideoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerAnalysisService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawCertificateVerificationService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawEquipmentInstallService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCommitmentService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCreditService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSecurityAdvisoryService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentAnalysisService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentDeadService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedCompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedVehicleService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedWaysectionService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleViolationService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleAccidentReportService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleOverspeedInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/SecurityManageDataScreenService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataPictureServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataVideoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceAnalysisImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceDeadImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerAnalysisServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawCertificateVerificationServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawEquipmentInstallServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCommitmentServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCreditServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSecurityAdvisoryServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedCompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedVehicleServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedWaysectionServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleViolationServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/SecurityManageDataScreenServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleAccidentReportServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleOverspeedInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/utils/InitDataUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/TaskContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/VehicleTaskContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/GpsData.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusDay.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusHour.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/DataTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/OperatorTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/AccidentQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/GpsSpeedDataDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/OverSpeedGpsDataDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/VehicleStatusDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusDayService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusHourService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/OverSpeedGpsDataService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/VehicleStatusService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/OverSpeedGpsDataServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusDayServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusHourServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleStatusServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/DriverScoreUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/GpsUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/SplitListUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/RegionContant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/UserLoginConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CodingRuleController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CompanyController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/ImportTemplateDownController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/MenuController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/OperatorController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RegionController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RoleController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/UserController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/RegionConverter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserAuthConverter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserCompanyConverter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserRoleConverter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/BonusPointsRule.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRule.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRuleInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Company.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyTypeRelated.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ExamRule.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Menu.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/MetaApply.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Operator.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/OperatorRegionHead.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Region.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Resource.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Role.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleAuthority.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleMenu.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ScoreDeductionRule.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/TreeEntity.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/UserRole.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/constant/ImportTemplateConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeCodeDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanySaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/GlobalUserPageDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorRegionHeadSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/PageParamsDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionMapKey.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionTreeDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleAuthoritySaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RolePageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUserSaveVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserPageQuery.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserQueryDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserRoleSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserSaveDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserUpdateDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/AuthorizeType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/BooleanDisplayEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleBehaviorTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleVehicleType.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/ImportTemplateEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MenuTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyStatusEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RoleEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RuleOperationTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionDeleteReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionTreeReq.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/ReqCodingRulePO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyCarInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/EquipmentInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuResourceTreeVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuRoleVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/OperatorVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionCompanyCarTreeVo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeCompanyVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/ResCodingRuleVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleMenuVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/TreeVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/UserInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/event/ImportDataEvent.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/CompaniesCacheHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/OperatorsCacheHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/UserCacheHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/VehiclesCacheHelper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CodingRuleManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CompanyManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/MenuManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/OperatorManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RegionManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RoleManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/UserManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeRelatedMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyJoinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeRelatedService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ICodingRuleService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IExamRuleService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IMetaApplyService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IOperatorScoreInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRegionService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRoleMenuService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/MenuService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorRegionHeadService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ResourceService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleAuthorityService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/UserRoleService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CodingRuleServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyJoinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeRelatedServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ExamRuleServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MenuServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MetaApplyServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorRegionHeadServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorScoreInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RegionServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ResourceServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleAuthorityServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleMenuServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/UserRoleServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/AuthCacheKeyUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/DataScopeCacheFilterUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/HttpUtils.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/TreeUtil.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserAuthController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserInfoController.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserAuth.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfo.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfoJoin.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/ReqCreateAccountPO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/manage/UserInfoManage.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoJoinMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.xml create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/NdUserInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/UserBasicInfoVO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthProperties.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthenticationBeanConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/WebSecurityConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/config/RedisSessionConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/AuthTypeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/SessionTimeConstant.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/errorcode/AuthErrorCodeEnum.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/facade/UserAuthLoginFacade.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultExpiredSessionStrategy.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginFailureHandler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginSuccessHandler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLogoutSuccessHandler.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/UserInfoDetails.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/dto/UserFullInfoDTO.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/PasswordLoginUserDetailServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthFilter.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthProvider.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthSecurityConfig.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthToken.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserAuthService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoJoinService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoService.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserAuthServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoJoinServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoServiceImpl.java create mode 100644 ningda-yw-api/src/main/java/com/ningdatech/carapi/user/util/LoginUserUtil.java create mode 100644 ningda-yw-api/src/main/resources/application-dev.yml create mode 100644 ningda-yw-api/src/main/resources/application-prod.yml create mode 100644 ningda-yw-api/src/main/resources/application.yml create mode 100644 ningda-yw-api/src/main/resources/db/migration/V1.sql create mode 100644 ningda-yw-api/src/main/resources/db/migration/meta_region.sql create mode 100644 ningda-yw-api/src/main/resources/integration/zwdd-dev.yml create mode 100644 ningda-yw-api/src/main/resources/integration/zwdd-prod.yml create mode 100644 ningda-yw-api/src/main/resources/irs/车牌号.xlsx create mode 100644 ningda-yw-api/src/main/resources/logback-spring.xml create mode 100644 ningda-yw-api/src/main/resources/security/auth-dev.yml create mode 100644 ningda-yw-api/src/main/resources/security/auth-prod.yml create mode 100644 ningda-yw-api/src/main/resources/template/散装水泥、预拌混凝土、干混砂浆物流装备统计年报表(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/散装水泥、预拌混凝土、干混砂浆物流装备统计年报表.xls create mode 100644 ningda-yw-api/src/main/resources/template/散装水泥供应量统计月报表(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/散装水泥供应量统计月报表.xls create mode 100644 ningda-yw-api/src/main/resources/template/散装水泥物流设施统计年报表(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/散装水泥物流设施统计年报表.xls create mode 100644 ningda-yw-api/src/main/resources/template/浙江省散装水泥中转库进出量快报(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/浙江省散装水泥中转库进出量快报.xls create mode 100644 ningda-yw-api/src/main/resources/template/温州、台州、舟山市散装水泥使用量快报(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/温州、台州、舟山市散装水泥使用量快报.xls create mode 100644 ningda-yw-api/src/main/resources/template/车辆事故数据(空).xlsx create mode 100644 ningda-yw-api/src/main/resources/template/车辆事故数据.xlsx create mode 100644 ningda-yw-api/src/main/resources/template/运营商考核详情.docx create mode 100644 ningda-yw-api/src/main/resources/template/非禁现区域散装水泥销售使用情况统计年报表(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/非禁现区域散装水泥销售使用情况统计年报表.xls create mode 100644 ningda-yw-api/src/main/resources/template/预拌混凝土生产及废弃物综合利用情况统计月报表(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/预拌混凝土生产及废弃物综合利用情况统计月报表.xls create mode 100644 ningda-yw-api/src/main/resources/template/预拌砂浆生产及废弃物综合利用情况统计月报表(空).xls create mode 100644 ningda-yw-api/src/main/resources/template/预拌砂浆生产及废弃物综合利用情况统计月报表.xls create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/AppTests.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/alarm/AlarmTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/car/HmacAuthUtil.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/car/RptTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/car/VehicleBaseInfoTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/company/CompanyInfoTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/dataview/DataViewTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/AddDriverAccountTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverDataImportTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverStarDataImportTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/SplitListUtils.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/AliSmsTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/config/Config.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/utils/AliSmsUtil.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/open/OpenApiTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/OSSTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/util/OssUtils.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/redis/RedisTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/report/ReportTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/safe/InsureOutdangerTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/schedule/VehicleStatus.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/sms/SendSms.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTempTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/user/UserInfoTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/user/UserLoginTest.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/utils/HttpUtils.java create mode 100644 ningda-yw-api/src/test/java/com/ningdatech/carapi/vehicle/CompanyVehicleTest.java create mode 100644 outInsure/保险出险数据.xlsx create mode 100644 pom.xml create mode 100644 开发指南.md diff --git a/.gitignore b/.gitignore index 84adb3f..eb97fdd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,9 @@ -# ---> Java -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - +### IDEA ### +*.iml +*/target/* +*/*.iml +/.gradle/ +*.pid +/LOG_PATH_IS_UNDEFINED/ +logs +/.idea/ diff --git a/ningda-generator/pom.xml b/ningda-generator/pom.xml new file mode 100644 index 0000000..07a6592 --- /dev/null +++ b/ningda-generator/pom.xml @@ -0,0 +1,34 @@ + + + + com.ningdatech + ningda-yw-road + 1.0.0 + + 4.0.0 + + ningda-generator + + + + com.baomidou + mybatis-plus-boot-starter + + + com.baomidou + mybatis-plus-generator + ${mybatis.plus.version} + + + org.freemarker + freemarker + + + + mysql + mysql-connector-java + + + diff --git a/ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeConfig.java b/ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeConfig.java new file mode 100644 index 0000000..4424e6e --- /dev/null +++ b/ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeConfig.java @@ -0,0 +1,66 @@ +package com.ningdatech.generator.config; + +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; + +import java.util.Collections; + +/** + * @description: 自动生成code代码 + * @author: liushuai + * @date: 2022/3/25 14:20 + */ +public class GeneratorCodeConfig { + + private static final String PATH_LXX = "/Users/LiuXinXin/IdeaProjects/car-manage/ningda-car-api/src/main/java"; + private static final String PATH_YYD = "/Users/wendy/coding/java/car-manage/ningda-car-api/src/main/java"; + private static final String PATH_LS = "/Users/qinxianyun/Documents/qin/ningdatech/secret-file-manage/ningda-api/src/main/java"; + private static final String PATH_ZPF = "D:\\ningda\\car-manage\\ningda-car-api\\src\\main\\java"; + private static final String PATH_CMM = "D:\\work\\shuiniche\\car-manage\\ningda-car-api\\src\\main\\java"; + + private static final String URL = "jdbc:mysql://47.98.125.47:3306/nd_cement_truck_dev?" + + "useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&" + + "useSSL=false&serverTimezone=Asia/Shanghai"; + private static final String USER_NAME = "root"; + private static final String PASSWORD = "NingdaKeji123!"; + + private static void generate(String author, String packageName, String path, String... tableNames) { + FastAutoGenerator.create(URL, USER_NAME, PASSWORD) + .globalConfig(builder -> { + // 设置作者 + builder.author(author) + // 开启 swagger 模式 + .enableSwagger() + // 覆盖已生成文件 + .fileOverride() + // 指定输出目录 + .outputDir(path); + }) + .packageConfig(builder -> { + // 设置父包名 + builder.parent("com.ningdatech") + // 设置父包模块名 + .moduleName("carapi." + packageName) + // 设置mapperXml生成路径 + .pathInfo(Collections.singletonMap(OutputFile.xml, + //设置自己的生成路径 + path + "/com/ningdatech/carapi/" + packageName + "/mapper")); + }) + .strategyConfig(builder -> { + builder.addTablePrefix("nd"); + // 设置需要生成的表名 + builder.addInclude(tableNames); + }) + // 使用Freemarker引擎模板,默认的是Velocity引擎模板 + .templateEngine(new FreemarkerTemplateEngine()) + .execute(); + } + + public static void main(String[] args) { + //generate("PoffyZhang", "car.monitor",PATH_ZPF, "nd_vehicle_security_monitor"); + //generate("WendyYang", "irs",PATH_YYD, "nd_drivers_license"); + generate("CMM", "test",PATH_CMM, "nd_vehicle_equipment_no"); + } + +} diff --git a/ningda-yw-api/pom.xml b/ningda-yw-api/pom.xml new file mode 100644 index 0000000..cf63d76 --- /dev/null +++ b/ningda-yw-api/pom.xml @@ -0,0 +1,309 @@ + + + 4.0.0 + + com.ningdatech + ningda-yw-road + 1.0.0 + + ningda-yw-api + 1.0.0 + + + + com.alibaba + easyexcel + + + org.apache.poi + poi + + + org.apache.poi + poi-ooxml + + + org.apache.poi + poi-ooxml-schemas + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.jxls + jxls-jexcel + 1.0.6 + + + com.ningdatech + nd-openapi-signature-starter + + + org.springframework.boot + spring-boot-starter-jdbc + + + + org.springframework.boot + spring-boot-devtools + true + true + + + com.ningdatech + nd-basic + 1.0.0 + + + org.slf4j + slf4j-log4j12 + + + + + + com.ningdatech + nd-swagger2-starter + + + org.slf4j + slf4j-log4j12 + + + + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-validation + + + io.krakens + java-grok + 0.1.9 + + + org.apache.httpcomponents + httpclient + + + + org.springframework.session + spring-session-data-redis + + + com.ningdatech + nd-cache-starter + 1.0.0 + + + org.slf4j + slf4j-log4j12 + + + + + + com.baomidou + mybatis-plus-boot-starter + + + org.apache.poi + poi + 4.1.2 + + + org.apache.poi + poi-ooxml + 4.1.2 + + + org.apache.tomcat.embed + tomcat-embed-core + + + com.ningdatech + nd-log-starter + 1.0.0 + + + com.ningdatech + nd-file-starter + 1.0.0 + + + + + + + org.springframework.boot + spring-boot-starter-integration + + + org.springframework.integration + spring-integration-stream + + + org.springframework.integration + spring-integration-mqtt + + + junit + junit + test + + + + org.springframework.boot + spring-boot-starter-data-redis + + + com.aliyun + aliyun-java-sdk-dysmsapi + 1.1.0 + + + nd-sms-send-starter + com.ningdatech + 1.0.0 + + + javax.persistence + javax.persistence-api + 2.2 + + + + + fr.opensagres.xdocreport + fr.opensagres.xdocreport.core + 2.0.2 + + + fr.opensagres.xdocreport + fr.opensagres.xdocreport.document + 2.0.2 + + + fr.opensagres.xdocreport + fr.opensagres.xdocreport.template + 2.0.2 + + + fr.opensagres.xdocreport + fr.opensagres.xdocreport.document.docx + 2.0.2 + + + fr.opensagres.xdocreport + fr.opensagres.xdocreport.template.freemarker + 2.0.2 + + + org.springframework + spring-test + + + + cn.afterturn + easypoi-base + + + + + + + + dev + + + dev + + + + test + + test + + + + pre + + pre + + + + prod + + prod + + + + + + + + src/main/resources + + **/* + + + + src/main/java + + **/*.xml + + + + src/main/lib + BOOT-INF/lib/ + + **/*.jar + + + + + src/main/resources + BOOT-INF/classes/ + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.12.RELEASE + + true + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/App.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/App.java new file mode 100644 index 0000000..69dba50 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/App.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.context.annotation.Import; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.ningdatech.basic.config.DefaultAsyncTaskConfig; + +/** + * @author liuxinxin + */ +@EnableAsync +@SpringBootApplication +@MapperScan(App.MAPPER_PACKAGES) +@EnableScheduling +@Import(DefaultAsyncTaskConfig.class) +@EnableTransactionManagement +@EnableAspectJAutoProxy(exposeProxy = true) +public class App { + + protected static final String MAPPER_PACKAGES = "com.ningdatech.carapi.**.mapper"; + + public static void main(String[] args) { + System.setProperty("druid.mysql.usePingMethod", "false"); + SpringApplication.run(App.class, args); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/common/DangerLevelEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/common/DangerLevelEnum.java new file mode 100644 index 0000000..536af96 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/common/DangerLevelEnum.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.analysis.common; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * @return + * @author CMM + * @since 2022/12/20 14:10 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "VehicleDangerLevelEnum", description = "车辆风险等级-枚举") +public enum DangerLevelEnum { + /** + * 风险等级 + */ + LOW_RISK(1, "红色预警"), + + INTERMEDIATE_RISK(2, "橙色预警"), + + SECONDARY_RISK(3,"黄色预警"), + + SENIOR_RISK(4,"蓝色预警"); + + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (DangerLevelEnum t : DangerLevelEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static Integer getCodeByDesc(String desc) { + if(StringUtils.isBlank(desc)){ + return null; + } + for (DangerLevelEnum t : DangerLevelEnum.values()) { + if (desc.equals(t.getDesc())) { + return t.code; + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/AnalysisEvalDataViewController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/AnalysisEvalDataViewController.java new file mode 100644 index 0000000..625f55c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/AnalysisEvalDataViewController.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.analysis.controller; + +import com.ningdatech.carapi.analysis.entity.enumeration.DangerLevel; +import com.ningdatech.carapi.analysis.entity.vo.CompanyWarnStatisticsVo; +import com.ningdatech.carapi.analysis.manage.AnalysisEvalDataViewManage; +import com.ningdatech.carapi.common.model.DataChartVo; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.common.util.CodeUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * AnalysisEvalDataViewController + *

+ * + * @author WendyYang + * @since 15:24 2022/10/25 + */ +@RestController +@RequiredArgsConstructor +@Api(tags = "分析评估-数据大屏") +@RequestMapping("/api/v1/analysis-eval/data-view") +public class AnalysisEvalDataViewController { + + private final AnalysisEvalDataViewManage analysisEvalDataViewManage; + + @GetMapping("/insuranceOrgStatistics/{regionId}") + @ApiOperation("保险机构车辆占比") + public List insuranceOrgStatistics(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return analysisEvalDataViewManage.insuranceOrgStatistics(regionId); + } + + @GetMapping("/companyWarnStatistics/{regionId}") + @ApiOperation("企业综合预警分析") + public List companyWarnStatistics(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return analysisEvalDataViewManage.companyWarnStatistics(regionId); + } + + @GetMapping("/companyWarnStatisticsByLevel") + @ApiOperation("企业红色预警") + public List companyWarnStatisticsByLevel(@RequestParam("regionId") Long regionId, + @RequestParam(value = "dangerLevel", required = false) Integer dangerLevel) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + // 默认查询最低等级预警即蓝色预警 + if (dangerLevel == null) { + dangerLevel = DangerLevel.BLUE.getCode(); + } + return analysisEvalDataViewManage.companyWarnStatisticsByLevel(regionId, dangerLevel); + } + + @GetMapping("/carWarnStatistics/{regionId}") + @ApiOperation("车辆综合预警分析") + public List carWarnStatistics(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return analysisEvalDataViewManage.carWarnStatistics(regionId); + } + + @GetMapping("/carWarnStatisticsByLevel") + @ApiOperation("车辆红色预警") + public List carWarnStatisticsByLevel(@RequestParam("regionId") Long regionId, + @RequestParam(value = "dangerLevel", required = false) Integer dangerLevel) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + // 默认查询红色预警 + if (dangerLevel == null) { + dangerLevel = DangerLevel.RED.getCode(); + } + return analysisEvalDataViewManage.carWarnStatisticsByLevel(regionId, dangerLevel); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/IndustryStandardsController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/IndustryStandardsController.java new file mode 100644 index 0000000..f0bf5fd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/IndustryStandardsController.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.analysis.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.analysis.entity.req.IndustryStandardsListReq; +import com.ningdatech.carapi.analysis.entity.req.IndustryStandardsSaveReq; +import com.ningdatech.carapi.analysis.entity.vo.IndustryStandardsListVo; +import com.ningdatech.carapi.analysis.manage.IndustryStandardsManage; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Api(tags = "分析评估-行业规范") +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/analysis-eval/industry-standards") +public class IndustryStandardsController { + + private final IndustryStandardsManage industryStandardsManage; + + @GetMapping("/list") + @ApiOperation("行业规范列表") + public PageVo industryStandardsList(@Valid IndustryStandardsListReq req) { + return industryStandardsManage.list(req); + } + + @PostMapping("/save") + @ApiOperation("新增行业规范") + public void save(@Valid @RequestBody IndustryStandardsSaveReq req) { + industryStandardsManage.save(req); + } + + @ApiOperation("增加下载次数") + @GetMapping("/incrementDownCount/{id}") + public void incrementDownCount(@PathVariable Long id) { + industryStandardsManage.incrementDownCount(id); + } + + @ApiOperation("删除行业标准文件") + @DeleteMapping("/delete-standards") + public void deleteStandardFile(@RequestParam Long id) { + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + industryStandardsManage.deleteStandardFile(id,roleId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/InsuranceRiskEvalController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/InsuranceRiskEvalController.java new file mode 100644 index 0000000..6ec224c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/InsuranceRiskEvalController.java @@ -0,0 +1,114 @@ +package com.ningdatech.carapi.analysis.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.analysis.entity.req.VehicleAccidentEvalModReq; +import com.ningdatech.carapi.analysis.entity.req.VehicleOverSpeedEvalModReq; +import com.ningdatech.carapi.analysis.entity.req.VehicleServiceLifeListReq; +import com.ningdatech.carapi.analysis.entity.req.VehicleViolationEvalModReq; +import com.ningdatech.carapi.analysis.entity.vo.VehicleAccidentEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.VehicleOverSpeedEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.VehicleServiceLifeListVo; +import com.ningdatech.carapi.analysis.entity.vo.VehicleViolationEvalListVo; +import com.ningdatech.carapi.analysis.manage.InsuranceRiskEvalManage; +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.Valid; + +/** + *

+ * 分析评估-保险风险评估 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Validated +@RestController +@RequiredArgsConstructor +@Api(tags = "分析评估-保险风险评估") +@RequestMapping("/api/v1/insurance-risk-eval") +public class InsuranceRiskEvalController { + + private final InsuranceRiskEvalManage insuranceRiskEvalManage; + + @ApiOperation("车辆使用年限列表") + @GetMapping("/vehicleServiceLifeList") + public PageVo vehicleServiceLifeList(@Valid VehicleServiceLifeListReq req) { + return insuranceRiskEvalManage.vehicleServiceLifeList(req); + } + + @ApiOperation("车辆违章情况列表") + @GetMapping("/vehicleViolationList") + public PageVo vehicleViolationList(@Valid VehicleServiceLifeListReq req) { + return insuranceRiskEvalManage.vehicleViolationEvalList(req); + } + + @ApiOperation("车辆出险情况列表") + @GetMapping("/vehicleAccidentList") + public PageVo vehicleAccidentList(@Valid VehicleServiceLifeListReq req) { + return insuranceRiskEvalManage.vehicleAccidentList(req); + } + + @ApiOperation("车辆超速情况列表") + @GetMapping("/vehicleOverSPeedList") + public PageVo vehicleOverSpeedList(@Valid VehicleServiceLifeListReq req) { + return insuranceRiskEvalManage.vehicleOverSpeedList(req); + } + + @ApiOperation("车辆违章情况修改") + @PutMapping("/modVehicleViolation") + @WebLog(value = "车辆违章情况修改", modular = "分析评估-保险风险评估") + public void modVehicleViolation(@Valid @RequestBody VehicleViolationEvalModReq req) { + insuranceRiskEvalManage.vehicleViolationEvalMod(req); + } + + @ApiOperation("车辆出险情况修改") + @PutMapping("/modVehicleAccident") + @WebLog(value = "车辆出险情况修改", modular = "分析评估-保险风险评估") + public void modVehicleAccident(@Valid @RequestBody VehicleAccidentEvalModReq req) { + insuranceRiskEvalManage.vehicleAccidentEvalMod(req); + } + + @ApiOperation("车辆超速情况修改") + @PutMapping("/modVehicleOverSpeed") + @WebLog(value = "车辆超速情况修改", modular = "分析评估-保险风险评估") + public void modVehicleOverSpeed(@Valid @RequestBody VehicleOverSpeedEvalModReq req) { + insuranceRiskEvalManage.vehicleOverSpeedEvalMod(req); + } + + @ApiOperation("车辆违章情况删除") + @DeleteMapping("/delVehicleViolation/{id}") + @WebLog(value = "车辆违章情况删除", modular = "分析评估-保险风险评估") + public void delVehicleViolation(@PathVariable Integer id) { + insuranceRiskEvalManage.vehicleViolationEvalDel(id); + } + + @ApiOperation("车辆超速情况删除") + @DeleteMapping("/delVehicleOverSpeed/{id}") + @WebLog(value = "车辆超速情况删除", modular = "分析评估-保险风险评估") + public void delVehicleOverSpeed(@PathVariable Integer id) { + insuranceRiskEvalManage.vehicleOverSpeedEvalDel(id); + } + + @ApiOperation("车辆出险情况删除") + @DeleteMapping("/delVehicleAccident/{id}") + @WebLog(value = "车辆出险情况删除", modular = "分析评估-保险风险评估") + public void delVehicleAccident(@PathVariable Integer id) { + insuranceRiskEvalManage.vehicleAccidentEvalDel(id); + } + + @ApiOperation("模版数据导入") + @PostMapping("/importTemplateData") + @WebLog(value = "模版数据导入", modular = "分析评估-保险风险评估") + public void importTemplateData(@RequestParam("template") ImportTemplateEnum template, MultipartFile file) { + insuranceRiskEvalManage.importTemplateData(template, file); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/SecurityAnalysisEvalController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/SecurityAnalysisEvalController.java new file mode 100644 index 0000000..5c78771 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/SecurityAnalysisEvalController.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.analysis.controller; + + +import com.ningdatech.basic.model.IdVo; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.analysis.entity.req.SecurityManageGradeListReq; +import com.ningdatech.carapi.analysis.entity.req.SecurityRiskEvalListReq; +import com.ningdatech.carapi.analysis.entity.req.SecurityRiskEvalSaveReq; +import com.ningdatech.carapi.analysis.entity.req.SecuritySystemBuildingEvalSaveReq; +import com.ningdatech.carapi.analysis.entity.vo.SecurityManageGradeVo; +import com.ningdatech.carapi.analysis.entity.vo.SecurityManageResultEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.SecurityRiskEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.SecuritySystemBuildingEvalListVo; +import com.ningdatech.carapi.analysis.manage.SecurityAnalysisEvalManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 安全管理综合评级 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-10-13 + */ +@RestController +@RequiredArgsConstructor +@Api(tags = "分析评估-安全分析评估") +@RequestMapping("/api/v1/security/analysis-eval") +public class SecurityAnalysisEvalController { + + private final SecurityAnalysisEvalManage securityAnalysisEvalManage; + + @GetMapping("/smg/list") + @ApiOperation("安全管理综合评级列表") + public PageVo listSecurityManageGrade(SecurityManageGradeListReq req) { + return securityAnalysisEvalManage.list(req); + } + + @GetMapping("/sre/list") + @ApiOperation("安全责任体系分析评估列表") + public PageVo listSecurityRiskEval(SecurityRiskEvalListReq req) { + return securityAnalysisEvalManage.list(req); + } + + @PostMapping("/sre/save") + @ApiOperation("新增安全责任体系分析评估") + public IdVo save(@Valid @RequestBody SecurityRiskEvalSaveReq req) { + return securityAnalysisEvalManage.save(req); + } + + @GetMapping("/ibe/list") + @ApiOperation("安全制度建设分析评估列表") + public PageVo listInstitutionBuildingEval(SecurityRiskEvalListReq req) { + return securityAnalysisEvalManage.listSystemBuildingEval(req); + } + + @PostMapping("/ibe/save") + @ApiOperation("保存安全制度建设分析评估") + public IdVo save(@Valid @RequestBody SecuritySystemBuildingEvalSaveReq req) { + return securityAnalysisEvalManage.save(req); + } + + @GetMapping("/smre/list") + @ApiOperation("安全管理结果分析评估列表") + public PageVo listSecurityManageResultEval(SecurityRiskEvalListReq req) { + return securityAnalysisEvalManage.listSecurityManageResultEval(req); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/WarnAnalysisController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/WarnAnalysisController.java new file mode 100644 index 0000000..1f52704 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/controller/WarnAnalysisController.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.analysis.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import com.ningdatech.carapi.analysis.entity.vo.WarnAnalysisByCarVo; +import com.ningdatech.carapi.analysis.entity.vo.WarnAnalysisByCompanyVo; +import com.ningdatech.carapi.analysis.entity.vo.WarnAnalysisByDriverVo; +import com.ningdatech.carapi.analysis.manage.WarnAnalysisManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 综合预警分析 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@RestController +@RequiredArgsConstructor +@Api(tags = "分析评估-预警分析") +@RequestMapping("/api/v1/warn-analysis") +public class WarnAnalysisController { + + private final WarnAnalysisManage warnAnalysisManage; + + @ApiOperation("车辆综合预警分析列表") + @GetMapping("/listCarWarnAnalysis") + public PageVo listWarnAnalysisCar(WarnAnalysisListReq req) { + return warnAnalysisManage.listCarWarnAnalysis(req); + } + + @ApiOperation("企业综合预警分析列表") + @GetMapping("/listCompanyWarnAnalysis") + public PageVo listWarnAnalysisCompany(WarnAnalysisListReq req) { + return warnAnalysisManage.listCompanyWarnAnalysis(req); + } + + @ApiOperation("驾驶员综合预警分析列表") + @GetMapping("/listDriverWarnAnalysis") + public PageVo listDriverWarnAnalysis(WarnAnalysisListReq req) { + return warnAnalysisManage.listDriverWarnAnalysis(req); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/IndustryStandards.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/IndustryStandards.java new file mode 100644 index 0000000..9c05069 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/IndustryStandards.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 行业标准 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@TableName("nd_industry_standards") +@ApiModel(value = "IndustryStandards对象", description = "") +public class IndustryStandards implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + private String name; + + @ApiModelProperty("标准类型") + private Integer type; + + @ApiModelProperty("文件ID") + private Long fileId; + + @ApiModelProperty("下载次数") + private Integer downCount; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageGrade.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageGrade.java new file mode 100644 index 0000000..48f9eb1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageGrade.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全管理综合评级 + *

+ * + * @author WendyYang + * @since 2022-10-13 + */ +@Data +@TableName("nd_security_manage_grade") +@ApiModel(value = "SecurityManageGrade对象", description = "安全管理综合评级") +public class SecurityManageGrade implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("安全评级") + private String securityLevel; + + @ApiModelProperty("综合得分") + private Integer score; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageResultEval.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageResultEval.java new file mode 100644 index 0000000..79e745c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityManageResultEval.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全制度建设分析评估 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@TableName("nd_security_manage_result_eval") +@ApiModel(value = "SecurityManageResultEval对象", description = "安全制度建设分析评估") +public class SecurityManageResultEval implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("综合得分") + private Integer totalScore; + + @ApiModelProperty("出现次数") + private Integer dangerCount; + + @ApiModelProperty("出险扣分") + private Integer dangerScore; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("死亡人数扣分") + private Integer deadScore; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("受伤人数扣分") + private Integer injuredScore; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityRiskEval.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityRiskEval.java new file mode 100644 index 0000000..167f8db --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecurityRiskEval.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全责任体系分析评估 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +@Data +@TableName("nd_security_risk_eval") +@ApiModel(value = "SecurityRiskEval对象", description = "安全责任体系分析评估") +public class SecurityRiskEval implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("综合得分") + private Integer totalScore; + + @ApiModelProperty("安全承诺得分") + private Integer promiseScore; + + @ApiModelProperty("安全责任得分") + private Integer riskScore; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("检查地址") + private String checkAddress; + + @ApiModelProperty("检查人") + private String checkUser; + + @ApiModelProperty("检查部门") + private String checkDept; + + @ApiModelProperty("检查内容") + private String checkContent; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecuritySystemBuildingEval.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecuritySystemBuildingEval.java new file mode 100644 index 0000000..1fd79dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/SecuritySystemBuildingEval.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全制度建设分析评估 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +@Data +@TableName("nd_security_system_building_eval") +@ApiModel(value = "SecuritySystemBuildingEval对象", description = "安全制度建设分析评估") +public class SecuritySystemBuildingEval implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("综合得分") + private Integer totalScore; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("检查地址") + private String checkAddress; + + @ApiModelProperty("检查人") + private String checkUser; + + @ApiModelProperty("检查部门") + private String checkDept; + + @ApiModelProperty("检查内容") + private String checkContent; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleAccidentEval.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleAccidentEval.java new file mode 100644 index 0000000..841eae9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleAccidentEval.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆事故情况评估 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +@Data +@TableName("nd_vehicle_accident_eval") +@ApiModel(value = "VehicleAccidentEval对象", description = "车辆事故情况评估") +public class VehicleAccidentEval implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("车辆ID") + private Long carId; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("行驶里程") + private Integer mileage; + + @ApiModelProperty("累计事故次数") + private Integer accidentCount; + + @ApiModelProperty("万公里事故次数") + private Integer avgAccidentCount; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleOverSpeedEval.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleOverSpeedEval.java new file mode 100644 index 0000000..e52dfd6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleOverSpeedEval.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆超速情况评估 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +@Data +@TableName("nd_vehicle_over_speed_eval") +@ApiModel(value = "VehicleOverSpeedEval对象", description = "车辆超速情况评估") +public class VehicleOverSpeedEval implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("车辆ID") + private Long carId; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("行驶里程") + private Integer mileage; + + @ApiModelProperty("累计超速次数") + private Integer overSpeedCount; + + @ApiModelProperty("万公里超速次数") + private Integer avgOverSpeedCount; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleServiceLife.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleServiceLife.java new file mode 100644 index 0000000..d8954c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleServiceLife.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 车辆使用年限 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@TableName("nd_vehicle_service_life") +@ApiModel(value = "VehicleServiceLife对象", description = "车辆使用年限") +public class VehicleServiceLife implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车辆ID") + private Long carId; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("购置时间") + private LocalDate buyTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleViolationEval.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleViolationEval.java new file mode 100644 index 0000000..e993b1d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/VehicleViolationEval.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆违章情况评估 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@TableName("nd_vehicle_violation_eval") +@ApiModel(value = "VehicleViolationEval对象", description = "车辆违章情况评估") +public class VehicleViolationEval implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("车辆ID") + private Long carId; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("行驶里程") + private Integer mileage; + + @ApiModelProperty("累计违章次数") + private Integer violationCount; + + @ApiModelProperty("万公里违章次数") + private Integer avgViolationCount; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCar.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCar.java new file mode 100644 index 0000000..27e5013 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCar.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆综合预警分析 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@TableName("nd_warn_analysis_car") +@ApiModel(value = "WarnAnalysisCar对象", description = "车辆综合预警分析") +public class WarnAnalysisCar implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("出现次数") + private Integer dangerCount; + + @ApiModelProperty("车辆风险分值") + private Integer dangerScore; + + @ApiModelProperty("车辆ID") + private Long carId; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("超速次数") + private Integer overSpeedCount; + + @ApiModelProperty("违章次数") + private Integer violationCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCompany.java new file mode 100644 index 0000000..8a2de0f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisCompany.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 企业综合预警分析 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@TableName("nd_warn_analysis_company") +@ApiModel(value = "WarnAnalysisCompany对象", description = "企业综合预警分析") +public class WarnAnalysisCompany implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("综合得分") + private Integer totalScore; + + @ApiModelProperty("违章次数") + private Integer violationCount; + + @ApiModelProperty("出现次数") + private Integer dangerCount; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisDriver.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisDriver.java new file mode 100644 index 0000000..615b913 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/WarnAnalysisDriver.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.analysis.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 驾驶员综合预警分析 + *

+ * + * @author WendyYang + * @since 2022-11-01 + */ +@Data +@TableName("nd_warn_analysis_driver") +@ApiModel(value = "WarnAnalysisDriver对象", description = "驾驶员综合预警分析") +public class WarnAnalysisDriver implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("出险次数") + private Integer dangerCount; + + @ApiModelProperty("驾驶员风险分值") + private Integer dangerScore; + + @ApiModelProperty("司机ID") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("超速次数") + private Integer overSpeedCount; + + @ApiModelProperty("违章次数") + private Integer violationCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/CompanyWarnStatisticsDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/CompanyWarnStatisticsDto.java new file mode 100644 index 0000000..dd737cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/CompanyWarnStatisticsDto.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.analysis.entity.dto; + +import lombok.Data; + +/** + *

+ * CompanyWarnStatisticsDto + *

+ * + * @author WendyYang + * @since 16:18 2022/10/25 + */ +@Data +public class CompanyWarnStatisticsDto { + + private Integer count; + + private Long regionId; + + private Integer dangerLevel; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/OutDangerImportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/OutDangerImportDto.java new file mode 100644 index 0000000..2c2d9f4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/OutDangerImportDto.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.analysis.entity.dto; + +import java.math.BigDecimal; + +import lombok.Data; + +/** + * @author CMM + * @description + * @since 2022/11/16 17:01 + */ +@Data +public class OutDangerImportDto { + /** + * 序号 + */ + private Integer id; + + /** + * 所属区域 + */ + private String regionName; + + /** + * 车牌号 + */ + private String carNo; + + /** + * 保险公司 + */ + private String insureCompany; + + /** + * 企业名称 + */ + private String companyName; + + + /** + * 事故地点 + */ + private String accidentAddress; + + /** + * 事故时间 + */ + private String accidentTime; + + /** + * 受伤人数 + */ + private Integer injuries; + + /** + * 死亡人数 + */ + private Integer deathToll; + + /** + * 理赔金额 + */ + private BigDecimal compensateAmount; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleAccidentImportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleAccidentImportDto.java new file mode 100644 index 0000000..d82f2a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleAccidentImportDto.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.analysis.entity.dto; + +import lombok.Data; + +/** + *

+ * VehicleAccidentImportDto + *

+ * + * @author WendyYang + * @since 11:17 2022/10/17 + */ +@Data +public class VehicleAccidentImportDto { + + /** + * 序号 + */ + private Integer id; + + /** + * 城市 + */ + private String city; + + /** + * 区(县) + */ + private String zone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 车牌号 + */ + private String carNo; + + /** + * 车架号 + */ + private String chassisNumber; + + /** + * 行驶里程 + */ + private Integer mileage; + + /** + * 累计出险次数 + */ + private Integer accidentCount; + + /** + * 万公里出险次数 + */ + private Integer avgAccidentCount; + + /** + * 风险评估 + */ + private String riskEvaluation; + + /** + * 备注 + */ + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleOverSpeedImportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleOverSpeedImportDto.java new file mode 100644 index 0000000..752b234 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleOverSpeedImportDto.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.analysis.entity.dto; + +import lombok.Data; + +/** + *

+ * VehicleOverSpeedDto + *

+ * + * @author WendyYang + * @since 11:17 2022/10/17 + */ +@Data +public class VehicleOverSpeedImportDto { + + /** + * 序号 + */ + private Integer id; + + /** + * 城市 + */ + private String city; + + /** + * 区(县) + */ + private String zone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 车牌号 + */ + private String carNo; + + /** + * 车架号 + */ + private String chassisNumber; + + /** + * 行驶里程 + */ + private Integer mileage; + + /** + * 累计出险次数 + */ + private Integer overSpeedCount; + + /** + * 万公里出险次数 + */ + private Integer avgOverSpeedCount; + + /** + * 风险评估 + */ + private String riskEvaluation; + + /** + * 备注 + */ + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleViolationImportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleViolationImportDto.java new file mode 100644 index 0000000..4e2e328 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/dto/VehicleViolationImportDto.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.analysis.entity.dto; + +import lombok.Data; + +/** + *

+ * VehicleViolationImportDto + *

+ * + * @author WendyYang + * @since 11:17 2022/10/17 + */ +@Data +public class VehicleViolationImportDto { + + /** + * 序号 + */ + private Integer id; + + /** + * 城市 + */ + private String city; + + /** + * 区(县) + */ + private String zone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 车牌号 + */ + private String carNo; + + /** + * 车架号 + */ + private String chassisNumber; + + /** + * 行驶里程 + */ + private Integer mileage; + + /** + * 累计违章次数 + */ + private Integer violationCount; + + /** + * 万公里违章次数 + */ + private Integer avgViolationCount; + + /** + * 风险评估 + */ + private String riskEvaluation; + + /** + * 备注 + */ + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/DangerLevel.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/DangerLevel.java new file mode 100644 index 0000000..359f255 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/DangerLevel.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.analysis.entity.enumeration; + +import lombok.Getter; + +import java.util.Arrays; + +/** + *

+ * DangerLevel + *

+ * + * @author WendyYang + * @since 17:18 2022/10/25 + */ +@Getter +public enum DangerLevel { + /** + * 预警 + */ + RED(1, "红色预警"), + ORANGE(2, "橙色预警"), + YELLOW(3, "黄色预警"), + BLUE(4, "蓝色预警"); + + private final Integer code; + private final String name; + + DangerLevel(Integer code, String name) { + this.code = code; + this.name = name; + } + + public static DangerLevel getByCode(Integer code) { + return Arrays.stream(values()) + .filter(w -> w.getCode().equals(code)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("预警级别编码无效")); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/IndustryStandardsType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/IndustryStandardsType.java new file mode 100644 index 0000000..da0598d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/IndustryStandardsType.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.analysis.entity.enumeration; + +import lombok.Getter; + +/** + *

+ * IndustryStandardsType + *

+ * + * @author WendyYang + * @since 10:08 2022/10/15 + */ +@Getter +public enum IndustryStandardsType { + + /** + * 车属企业安全管理规范 + */ + SAFETY_MANAGEMENT_SPECIFICATION(1), + /** + * 车辆安全设备规范 + */ + SAFETY_EQUIPMENT_SPECIFICATION(2), + /** + * 车辆驾驶安全标准 + */ + DRIVING_SAFETY_STANDARDS(3), + /** + * 安全生产管理人员标准 + */ + STANDARDS_FOR_SAFETY_PRODUCTION_MANAGEMENT_PERSONNEL(4), + /** + * 驾驶员教育考核标准 + */ + EVALUATION_CRITERIA_FOR_DRIVER_EDUCATION(5); + + private final Integer code; + + IndustryStandardsType(Integer code) { + this.code = code; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/InsuranceDangerLevel.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/InsuranceDangerLevel.java new file mode 100644 index 0000000..5e233eb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/enumeration/InsuranceDangerLevel.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.analysis.entity.enumeration; + +import lombok.Getter; + +/** + *

+ * 保险风险评估-风险等级枚举 + *

+ * + * @author WendyYang + * @since 10:59 2022/11/2 + */ +@Getter +public enum InsuranceDangerLevel { + /** + * 风险等级 + */ + HIGH(1, "高级风险"), + HIGH_2ND(2, "次高及风险"), + MID(3, "中级风险"), + LOW(4, "低级风险"); + + private final Integer code; + private final String value; + + InsuranceDangerLevel(Integer code, String value) { + this.code = code; + this.value = value; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsListReq.java new file mode 100644 index 0000000..659c7b7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsListReq.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + *

+ * IndustryStandardsListReq + *

+ * + * @author WendyYang + * @since 10:25 2022/10/15 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class IndustryStandardsListReq extends PagePo { + + @NotNull(message = "行业标准类型不能为空") + @ApiModelProperty("行业规范类型:1 车属企业安全管理规范、2 车辆安全设备规范、3 车辆驾驶安全标准、4 安全生产管理人员标准、5 驾驶员教育考核标准") + private Integer type; + + @ApiModelProperty("文件名称") + private String fileName; + + @ApiModelProperty("开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + private LocalDateTime endTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsSaveReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsSaveReq.java new file mode 100644 index 0000000..b8803ef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/IndustryStandardsSaveReq.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + *

+ * 行业标准新增实体 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel(value = "行业标准新增实体") +public class IndustryStandardsSaveReq { + + @ApiModelProperty("行业标准说明") + @NotBlank(message = "行业标准说明不能为空") + private String name; + + @ApiModelProperty("标准类型") + @NotNull(message = "标准类型不能为空") + private Integer type; + + @ApiModelProperty("文件ID") + @NotNull(message = "文件ID不能为空") + private Long fileId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityManageGradeListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityManageGradeListReq.java new file mode 100644 index 0000000..b5b5d0b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityManageGradeListReq.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import com.ningdatech.basic.model.PagePo; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * SecurityManagementGradeListReq + *

+ * + * @author WendyYang + * @since 14:56 2022/10/13 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class SecurityManageGradeListReq extends PagePo { + + private Long regionId; + + private Integer year; + + private String securityLevel; + + private String companyName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalListReq.java new file mode 100644 index 0000000..4a33ffb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalListReq.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import cn.hutool.core.util.StrUtil; +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; + +/** + *

+ * SecurityRiskEvaluationListReq + *

+ * + * @author WendyYang + * @since 09:27 2022/10/14 + */ +@ApiModel("安全责任体系分析评估列表参数类") +@Data +@EqualsAndHashCode(callSuper = true) +public class SecurityRiskEvalListReq extends PagePo { + + private Long regionId; + + private Integer year; + + @ApiModelProperty("总分值:格式为-XX,XX-XX,XX-") + private String scoreRange; + + private String companyName; + + private transient Pair scoreRanges; + + public void setScoreRange(String scoreRange) { + this.scoreRange = scoreRange; + this.setScoreRanges(); + } + + private void setScoreRanges() { + if (StringUtils.isNotBlank(this.scoreRange)) { + String[] scoreArray = StrUtil.strip(scoreRange, "-").split("-"); + int indexOf = scoreRange.indexOf("-"); + if (indexOf == scoreRange.length() - 1) { + scoreRanges = Pair.of(Integer.valueOf(scoreArray[0]), null); + } else if (indexOf == 0) { + scoreRanges = Pair.of(null, Integer.valueOf(scoreArray[0])); + } else { + scoreRanges = Pair.of(Integer.valueOf(scoreArray[0]), Integer.valueOf(scoreArray[1])); + } + } + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalSaveReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalSaveReq.java new file mode 100644 index 0000000..4716bf3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecurityRiskEvalSaveReq.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + *

+ * 安全责任体系分析评估 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +@Data +@ApiModel("安全责任体系分析评估新增参数类") +public class SecurityRiskEvalSaveReq { + + @ApiModelProperty("年度") + @NotNull(message = "考核年度不能为空") + private Integer year; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + @NotNull(message = "企业编码不能为空") + private Long companyId; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("综合得分") + @NotNull(message = "综合得分不能为空") + private Integer totalScore; + + @ApiModelProperty("安全承诺得分") + @NotNull(message = "安全承诺得分不能为空") + private Integer promiseScore; + + @ApiModelProperty("安全责任得分") + @NotNull(message = "安全责任得分不能为空") + private Integer riskScore; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("检查地址") + private String checkAddress; + + @ApiModelProperty("检查人") + private String checkUser; + + @ApiModelProperty("检查部门") + private String checkDept; + + @ApiModelProperty("检查内容") + @NotBlank(message = "检查内容不能为空") + private String checkContent; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecuritySystemBuildingEvalSaveReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecuritySystemBuildingEvalSaveReq.java new file mode 100644 index 0000000..09a046c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/SecuritySystemBuildingEvalSaveReq.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + *

+ * 安全制度建设分析评估新增参数类 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +@Data +@ApiModel("安全制度建设分析评估新增参数类") +public class SecuritySystemBuildingEvalSaveReq { + + @ApiModelProperty("年度") + @NotNull(message = "考核年度不能为空") + private Integer year; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + @NotNull(message = "企业编码不能为空") + private Long companyId; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("综合得分") + @NotNull(message = "综合得分不能为空") + private Integer totalScore; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("检查地址") + private String checkAddress; + + @ApiModelProperty("检查人") + private String checkUser; + + @ApiModelProperty("检查部门") + private String checkDept; + + @ApiModelProperty("检查内容") + @NotBlank(message = "检查内容不能为空") + private String checkContent; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleAccidentEvalModReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleAccidentEvalModReq.java new file mode 100644 index 0000000..a904ed8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleAccidentEvalModReq.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + *

+ * 车辆出险情况修改参数 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel("车辆出险情况修改参数") +public class VehicleAccidentEvalModReq { + + @ApiModelProperty("主键") + @NotNull(message = "id不能为空") + private Integer id; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String carNo; + + @ApiModelProperty("累计违章次数") + @NotNull(message = "累计违章次数不能为空") + private Integer accidentCount; + + @ApiModelProperty("万公里出险次数") + @NotNull(message = "万公里出险次数不能为空") + private Integer avgAccidentCount; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleOverSpeedEvalModReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleOverSpeedEvalModReq.java new file mode 100644 index 0000000..859f1df --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleOverSpeedEvalModReq.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + *

+ * 车辆超速情况修改参数 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel("车辆超速情况修改参数") +public class VehicleOverSpeedEvalModReq { + + @ApiModelProperty("主键") + @NotNull(message = "id不能为空") + private Integer id; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String carNo; + + @ApiModelProperty("累计超速次数") + @NotNull(message = "累计超速次数不能为空") + private Integer overSpeedCount; + + @ApiModelProperty("万公里超速次数") + @NotNull(message = "万公里超速次数不能为空") + private Integer avgOverSpeedCount; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleServiceLifeListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleServiceLifeListReq.java new file mode 100644 index 0000000..c00d609 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleServiceLifeListReq.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDate; + +/** + *

+ * VehicleServiceLifeListReq + *

+ * + * @author WendyYang + * @since 14:24 2022/10/15 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("车辆使用年限列表查询参数") +public class VehicleServiceLifeListReq extends PagePo { + + @ApiModelProperty("车辆购置时间(开始)") + private LocalDate buyTimeStart; + + @ApiModelProperty("车辆购置时间(结束)") + private LocalDate buyTimeEnd; + + @ApiModelProperty("地域ID") + private Long regionId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车牌号") + private String carNo; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleViolationEvalModReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleViolationEvalModReq.java new file mode 100644 index 0000000..fb81664 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/VehicleViolationEvalModReq.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + *

+ * 车辆违章情况修改参数 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel("车辆违章情况修改参数") +public class VehicleViolationEvalModReq { + + @ApiModelProperty("主键") + @NotNull(message = "id不能为空") + private Integer id; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String carNo; + + @ApiModelProperty("累计违章次数") + @NotNull(message = "累计违章次数不能为空") + private Integer violationCount; + + @ApiModelProperty("万公里违章次数") + @NotNull(message = "万公里违章次数不能为空") + private Integer avgViolationCount; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/WarnAnalysisListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/WarnAnalysisListReq.java new file mode 100644 index 0000000..0f31ffb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/req/WarnAnalysisListReq.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.analysis.entity.req; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + *

+ * WarnAnalysisListReq + *

+ * + * @author WendyYang + * @since 16:42 2022/10/14 + */ +@Data +@ApiModel("预警分析列表查询参数") +@EqualsAndHashCode(callSuper = true) +public class WarnAnalysisListReq extends PagePo { + + @ApiModelProperty("地域ID") + private Long regionId; + private List regionIds; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + private String dataScopeSql; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/CompanyWarnStatisticsVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/CompanyWarnStatisticsVo.java new file mode 100644 index 0000000..f3c650b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/CompanyWarnStatisticsVo.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +/** + *

+ * CompanyWarnStatisticsVo + *

+ * + * @author WendyYang + * @since 17:04 2022/10/25 + */ +@Data +@Builder +public class CompanyWarnStatisticsVo { + + @Tolerate + public CompanyWarnStatisticsVo() { + } + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("企业地址") + private String companyAddress; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/IndustryStandardsListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/IndustryStandardsListVo.java new file mode 100644 index 0000000..7188be9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/IndustryStandardsListVo.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * IndustryStandardsListVo + *

+ * + * @author WendyYang + * @since 10:19 2022/10/15 + */ +@Data +public class IndustryStandardsListVo { + + private String name; + + private LocalDateTime createOn; + + private Integer downCount; + + private Long fileId; + + private Long id; + private Long regionId; + private String regionName; + private Long companyId; + private String companyName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageGradeVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageGradeVo.java new file mode 100644 index 0000000..4df5637 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageGradeVo.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 安全管理综合评级列表视图类 + *

+ * + * @author WendyYang + * @since 14:41 2022/10/13 + */ +@Data +@ApiModel("安全管理综合评级列表视图类") +public class SecurityManageGradeVo { + + @ApiModelProperty("所属地区") + private List regions; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("安全评级") + private String securityLevel; + + @ApiModelProperty("综合得分") + private Integer score; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageResultEvalListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageResultEvalListVo.java new file mode 100644 index 0000000..113479c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityManageResultEvalListVo.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 安全制度建设分析评估 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@TableName("nd_security_manage_result_eval") +@ApiModel(value = "SecurityManageResultEval对象", description = "安全制度建设分析评估") +public class SecurityManageResultEvalListVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("地区") + private List regions; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("综合得分") + private Integer totalScore; + + @ApiModelProperty("出险次数") + private Integer dangerCount; + + @ApiModelProperty("出险扣分") + private Integer dangerScore; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("死亡扣分") + private Integer deadScore; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("受伤扣分") + private Integer injuredScore; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityRiskEvalListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityRiskEvalListVo.java new file mode 100644 index 0000000..b69053c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecurityRiskEvalListVo.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +import java.util.List; + +/** + *

+ * SecurityRiskEvaluationListVo + *

+ * + * @author WendyYang + * @since 10:17 2022/10/14 + */ +@Data +@Builder +@ApiModel("安全责任分析评估列表视图类") +public class SecurityRiskEvalListVo { + + @Tolerate + public SecurityRiskEvalListVo() { + } + + @ApiModelProperty("所属地区") + private List regions; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("总分值") + private Integer totalScore; + + @ApiModelProperty("安全责任得分") + private Integer riskScore; + + @ApiModelProperty("安全承诺得分") + private Integer promiseScore; + + @ApiModelProperty("检查内容") + private String checkContent; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecuritySystemBuildingEvalListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecuritySystemBuildingEvalListVo.java new file mode 100644 index 0000000..b75760c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/SecuritySystemBuildingEvalListVo.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +import java.util.List; + +/** + *

+ * 安全制度建设分析评估列表视图类 + *

+ * + * @author WendyYang + * @since 10:17 2022/10/14 + */ +@Data +@Builder +@ApiModel("安全制度建设分析评估列表视图类") +public class SecuritySystemBuildingEvalListVo { + + @Tolerate + public SecuritySystemBuildingEvalListVo() { + } + + @ApiModelProperty("所属地区") + private List regions; + + @ApiModelProperty("年度") + private Integer year; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("总分值") + private Integer totalScore; + + @ApiModelProperty("检查内容") + private String checkContent; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleAccidentEvalListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleAccidentEvalListVo.java new file mode 100644 index 0000000..c5b6e71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleAccidentEvalListVo.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 车辆出险情况评估列表视图类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel("车辆出险情况评估列表视图类") +public class VehicleAccidentEvalListVo { + + @ApiModelProperty("主键") + private Integer id; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车辆风险等级名称") + private String dangerLevelName; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("行驶里程") + private Integer mileage; + + @ApiModelProperty("累计出险次数") + private Integer accidentCount; + + @ApiModelProperty("地域") + private List regions; + + @ApiModelProperty("万公里出险次数") + private Integer avgAccidentCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleOverSpeedEvalListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleOverSpeedEvalListVo.java new file mode 100644 index 0000000..b79a888 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleOverSpeedEvalListVo.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 车辆超速情况评估列表视图类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel("车辆超速情况评估列表视图类") +public class VehicleOverSpeedEvalListVo { + + @ApiModelProperty("主键") + private Integer id; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车辆风险等级名称") + private String dangerLevelName; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("行驶里程") + private Integer mileage; + + @ApiModelProperty("累计超速次数") + private Integer overSpeedCount; + + @ApiModelProperty("地域") + private List regions; + + @ApiModelProperty("万公里超速次数") + private Integer avgOverSpeedCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleServiceLifeListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleServiceLifeListVo.java new file mode 100644 index 0000000..5e4bb78 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleServiceLifeListVo.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * 车辆使用年限列表视图类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@Builder +@ApiModel("车辆使用年限列表视图类") +public class VehicleServiceLifeListVo { + + @Tolerate + public VehicleServiceLifeListVo() { + } + + @ApiModelProperty("主键") + private Integer id; + + @ApiModelProperty("地域信息") + private List regions; + + @ApiModelProperty("企业") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("购置时间") + private LocalDate buyTime; + + @ApiModelProperty("车辆使用时间") + private Integer usedTime; + + @ApiModelProperty("车辆使用年限占比(报废年限)") + private Integer usedTimePercent; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleViolationEvalListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleViolationEvalListVo.java new file mode 100644 index 0000000..c641366 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/VehicleViolationEvalListVo.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 车辆违章情况评估列表视图类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Data +@ApiModel("车辆违章情况评估列表视图类") +public class VehicleViolationEvalListVo { + + @ApiModelProperty("主键") + private Integer id; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("车辆风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车辆风险等级名称") + private String dangerLevelName; + + @ApiModelProperty("车架号") + private String carFrameNo; + + @ApiModelProperty("行驶里程") + private Integer mileage; + + @ApiModelProperty("累计违章次数") + private Integer violationCount; + + @ApiModelProperty("地域") + private List regions; + + @ApiModelProperty("万公里违章次数") + private Integer avgViolationCount; + + @ApiModelProperty("备注") + private String remark; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCarVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCarVo.java new file mode 100644 index 0000000..a26fc76 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCarVo.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 车辆综合预警分析 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@ApiModel(value = "车辆综合预警分析列表视图类", description = "") +public class WarnAnalysisByCarVo { + + @ApiModelProperty("主键") + private Integer id; + + @ApiModelProperty("地区ID") + private List regions; + + @ApiModelProperty("企业Id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("出险次数") + private Integer dangerCount; + + @ApiModelProperty("车辆风险分值") + private Integer dangerScore; + + @ApiModelProperty("车牌号") + private String carNo; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("超速次数") + private Integer overSpeedCount; + + @ApiModelProperty("违章次数") + private Integer violationCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCompanyVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCompanyVo.java new file mode 100644 index 0000000..067b90d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByCompanyVo.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 企业综合预警分析列表视图类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@ApiModel("企业综合预警分析列表视图类") +public class WarnAnalysisByCompanyVo { + + @ApiModelProperty("主键") + private Integer id; + + private List regions; + + @ApiModelProperty("企业id") + private String companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("综合得分") + private Integer totalScore; + + @ApiModelProperty("违章次数") + private Integer violationCount; + + @ApiModelProperty("出险次数") + private Integer dangerCount; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("车辆数") + private Integer carCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByDriverVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByDriverVo.java new file mode 100644 index 0000000..3a80e10 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/entity/vo/WarnAnalysisByDriverVo.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.analysis.entity.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 驾驶员综合预警分析列表视图类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Data +@ApiModel("驾驶员综合预警分析列表视图类") +public class WarnAnalysisByDriverVo { + + + @ApiModelProperty("主键") + private Integer id; + + @ApiModelProperty("地区ID") + private List regions; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("受伤人数") + private Integer injuredCount; + + @ApiModelProperty("死亡人数") + private Integer deadCount; + + @ApiModelProperty("出险次数") + private Integer dangerCount; + + @ApiModelProperty("车辆风险分值") + private Integer dangerScore; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("风险等级") + private Integer dangerLevel; + + @ApiModelProperty("超速次数") + private Integer overSpeedCount; + + @ApiModelProperty("违章次数") + private Integer violationCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/AnalysisEvalDataViewManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/AnalysisEvalDataViewManage.java new file mode 100644 index 0000000..595a937 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/AnalysisEvalDataViewManage.java @@ -0,0 +1,190 @@ +package com.ningdatech.carapi.analysis.manage; + +import cn.hutool.core.map.MapUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCar; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany; +import com.ningdatech.carapi.analysis.entity.vo.CompanyWarnStatisticsVo; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCarService; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCompanyService; +import com.ningdatech.carapi.common.model.DataChartVo; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.service.INdInsureInfoService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * DataViewController + *

+ * + * @author WendyYang + * @since 15:34 2022/10/25 + */ +@Component +@AllArgsConstructor +public class AnalysisEvalDataViewManage { + + private final INdInsureInfoService insureInfoService; + private final IWarnAnalysisCompanyService companyWarnAnalysisService; + private final IWarnAnalysisCarService carWarnAnalysisService; + + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + private final CompanyService companyService; + + public List insuranceOrgStatistics(Long regionId) { + List childIds = regionsCacheHelper.listChildRegionId(regionId); + QueryWrapper query = Wrappers.query(); + query.select("count(distinct car_plate) as `count`, insure_company as groupKey"); + query.in("region_id", childIds); + query.groupBy("insure_company"); + List> maps = insureInfoService.listMaps(query); + if (maps.isEmpty()) { + return Collections.emptyList(); + } + int total = CollUtils.sum(maps, w -> Long.valueOf(w.get("count").toString()).intValue()); + return maps.stream().map(w -> { + DataChartVo vo = new DataChartVo(); + vo.setLabel(w.get("groupKey").toString()); + vo.setValue(Long.valueOf(w.get("count").toString()).intValue()); + String percent = BigDecimal.valueOf(vo.getValue() * 100) + .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP) + .stripTrailingZeros().toPlainString(); + vo.setPercent(percent); + return vo; + }).collect(Collectors.toList()); + } + + public List companyWarnStatistics(Long regionId) { + List regionIds = regionsCacheHelper.listChildRegionId(regionId); + QueryWrapper query = Wrappers.query(); + query.select("company_id companyId, danger_level dangerLevel"); + query.in("region_id", regionIds); + List> analysisCompanies = companyWarnAnalysisService.listMaps(query); + if (analysisCompanies.size() == 0) { + return Collections.emptyList(); + } + List result = new ArrayList<>(); + analysisCompanies.forEach(w -> { + CompanyDTO company = companiesCacheHelper.getById(MapUtil.getLong(w, "companyId")); + if (Objects.isNull(company)) { + return; + } + CompanyWarnStatisticsVo vo = CompanyWarnStatisticsVo.builder() + .companyAddress(company.getAddress()) + .companyName(company.getName()) + .dangerLevel(MapUtil.getInt(w, "dangerLevel")) + .longitude(company.getLongitude()) + .latitude(company.getLatitude()) + .build(); + result.add(vo); + }); + return result; + } + + public List carWarnStatistics(Long regionId) { + List regionIds = regionsCacheHelper.listChildRegionId(regionId); + QueryWrapper query = Wrappers.query(); + query.select("count(1) `count`, region_id regionId"); + query.in("region_id", regionIds); + query.groupBy("region_id"); + List> carAnalysis = carWarnAnalysisService.listMaps(query); + if (carAnalysis.size() == 0) { + return Collections.emptyList(); + } + Map> childrenMap = regionsCacheHelper.getChildrenMap(regionId, true); + List result = new ArrayList<>(); + childrenMap.forEach((k, v) -> { + MapDataVO mapData = MapDataVO.builder() + .regionName(k.getRegionName()) + .regionCode(k.getRegionCode()) + .regionId(k.getId()) + .value(0) + .build(); + carAnalysis.removeIf(w -> { + Long currRegionId = MapUtil.getLong(w, "regionId"); + if (v.contains(currRegionId)) { + mapData.setValue(MapUtil.getInt(w, "count") + mapData.getValue()); + return true; + } + return false; + }); + result.add(mapData); + }); + return result; + } + + private QueryWrapper buildCountQueryGroupByRegion(List regionIds, Integer dangerLevel) { + QueryWrapper query = Wrappers.query(); + query.select("count(1) as `count`, region_id as regionId"); + query.in("region_id", regionIds); + query.eq("danger_level", dangerLevel); + query.groupBy("region_id"); + return query; + } + + public List companyWarnStatisticsByLevel(Long regionId, Integer dangerLevel) { + List result = new ArrayList<>(); + List regionIds = regionsCacheHelper.listChildRegionId(regionId); + QueryWrapper query = buildCountQueryGroupByRegion(regionIds, dangerLevel); + List> analysisCompanies = companyWarnAnalysisService.listMaps(query); + Map> childrenMap = regionsCacheHelper.getChildrenMap(regionId, true); + // 如果是区县一级的,只返回区县一级的名字和数量 + if (childrenMap.size() == 0) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + String regionName = regionDto.getRegionName(); + DataChartVo vo = new DataChartVo(regionName, 0); + analysisCompanies.forEach(w -> { + vo.setValue(vo.getValue() + MapUtil.getInt(w, "count")); + }); + result.add(vo); + return result; + } else { + childrenMap.forEach((k, v) -> { + DataChartVo vo = new DataChartVo(k.getRegionName(), 0); + analysisCompanies.forEach(w -> { + Long currRegionId = MapUtil.getLong(w, "regionId"); + if (v.contains(currRegionId)) { + vo.setValue(vo.getValue() + MapUtil.getInt(w, "count")); + } + }); + result.add(vo); + }); + return result; + } + } + + public List carWarnStatisticsByLevel(Long regionId, Integer dangerLevel) { + List result = new ArrayList<>(); + List regionIds = regionsCacheHelper.listChildRegionId(regionId); + QueryWrapper query = buildCountQueryGroupByRegion(regionIds, dangerLevel); + List> analysisCompanies = carWarnAnalysisService.listMaps(query); + Map> childrenMap = regionsCacheHelper.getChildrenMap(regionId, true); + childrenMap.forEach((k, v) -> { + DataChartVo vo = new DataChartVo(k.getRegionName(), 0); + analysisCompanies.forEach(w -> { + Long currRegionId = MapUtil.getLong(w, "regionId"); + if (v.contains(currRegionId)) { + vo.setValue(vo.getValue() + MapUtil.getInt(w, "count")); + } + }); + result.add(vo); + }); + return result; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/IndustryStandardsManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/IndustryStandardsManage.java new file mode 100644 index 0000000..5f77ecc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/IndustryStandardsManage.java @@ -0,0 +1,132 @@ +package com.ningdatech.carapi.analysis.manage; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.analysis.entity.IndustryStandards; +import com.ningdatech.carapi.analysis.entity.req.IndustryStandardsListReq; +import com.ningdatech.carapi.analysis.entity.req.IndustryStandardsSaveReq; +import com.ningdatech.carapi.analysis.entity.vo.IndustryStandardsListVo; +import com.ningdatech.carapi.analysis.service.IIndustryStandardsService; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; + +/** + *

+ * IndustryStandardsManage + *

+ * + * @author WendyYang + * @since 10:24 2022/10/15 + */ +@Component +@RequiredArgsConstructor +public class IndustryStandardsManage { + + private final IIndustryStandardsService industryStandardsService; + + public PageVo list(IndustryStandardsListReq req) { + Integer pageNumber = req.getPageNumber(); + Integer pageSize = req.getPageSize(); + + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + + LambdaQueryWrapper query = Wrappers.lambdaQuery(IndustryStandards.class); + IndustryStandardsManage context = (IndustryStandardsManage) AopContext.currentProxy(); + context.buildQuery(query,req); + + List standardsList = industryStandardsService.list(query); + // 省级部门上传的文件(上传企业所属区域为省级),按照文件类型,下级账号也要能看到 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) { + List standards = industryStandardsService.list(Wrappers.lambdaQuery(IndustryStandards.class) + .eq(IndustryStandards::getRegionId, DefValConstants.ZJREGION_ID) + .eq(IndustryStandards::getType,req.getType())); + standardsList.addAll(standards); + } + + if (CollUtil.isEmpty(standardsList)){ + return PageVo.empty(); + } + + List records = standardsList.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + + //Page page = industryStandardsService.page(req.page(), query); + + List data = CollUtils.convert(records, w -> { + IndustryStandardsListVo vo = BeanUtil.copyProperties(w, IndustryStandardsListVo.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, standardsList.size()); + } + @LambdaDataScope + public void buildQuery(LambdaQueryWrapper query,IndustryStandardsListReq req) { + query.orderByDesc(IndustryStandards::getId).eq(IndustryStandards::getType, req.getType()) + .like(StrUtil.isNotBlank(req.getFileName()), IndustryStandards::getName, req.getFileName()) + .ge(req.getStartTime() != null, IndustryStandards::getCreateOn, req.getStartTime()) + .le(req.getEndTime() != null, IndustryStandards::getCreateOn, req.getEndTime()); + } + + public void save(IndustryStandardsSaveReq req) { + IndustryStandards industryStandards = BeanUtil.copyProperties(req, IndustryStandards.class); + industryStandards.setCreateBy(LoginUserUtil.getUserId()); + industryStandards.setCreateOn(LocalDateTime.now()); + industryStandards.setRegionId(LoginUserUtil.loginUserDetail().getRegionId()); + industryStandards.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + industryStandardsService.save(industryStandards); + } + + public void incrementDownCount(Long id) { + industryStandardsService.incrementDownCount(id); + } + + public void deleteStandardFile(Long id, Long roleId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(IndustryStandards.class); + IndustryStandardsManage context = (IndustryStandardsManage) AopContext.currentProxy(); + context.buildStandardFileQuery(wrapper, id); + IndustryStandards standards = industryStandardsService.getOne(wrapper); + if (Objects.isNull(standards)){ + throw new BizException("文件无法删除!"); + } + // IndustryStandards standards = industryStandardsService.getById(id); + // 如果文件是省级部门上传的文件,只有省级管理员角色可以删除 + Long regionId = standards.getRegionId(); + if (Objects.nonNull(regionId) && + DefValConstants.ZJREGION_ID.equals(regionId)){ + // 判断登录用户角色是否为省管理员 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){ + throw new BizException("您没有权限删除该文件!"); + } + } + industryStandardsService.deleteById(id); + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildStandardFileQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(IndustryStandards::getId,id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/InsuranceRiskEvalManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/InsuranceRiskEvalManage.java new file mode 100644 index 0000000..f808977 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/InsuranceRiskEvalManage.java @@ -0,0 +1,568 @@ +package com.ningdatech.carapi.analysis.manage; + +import java.io.IOException; +import java.io.InputStream; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.analysis.common.DangerLevelEnum; +import com.ningdatech.carapi.analysis.entity.VehicleAccidentEval; +import com.ningdatech.carapi.analysis.entity.VehicleOverSpeedEval; +import com.ningdatech.carapi.analysis.entity.VehicleServiceLife; +import com.ningdatech.carapi.analysis.entity.VehicleViolationEval; +import com.ningdatech.carapi.analysis.entity.dto.OutDangerImportDto; +import com.ningdatech.carapi.analysis.entity.dto.VehicleAccidentImportDto; +import com.ningdatech.carapi.analysis.entity.dto.VehicleOverSpeedImportDto; +import com.ningdatech.carapi.analysis.entity.dto.VehicleViolationImportDto; +import com.ningdatech.carapi.analysis.entity.req.VehicleAccidentEvalModReq; +import com.ningdatech.carapi.analysis.entity.req.VehicleOverSpeedEvalModReq; +import com.ningdatech.carapi.analysis.entity.req.VehicleServiceLifeListReq; +import com.ningdatech.carapi.analysis.entity.req.VehicleViolationEvalModReq; +import com.ningdatech.carapi.analysis.entity.vo.VehicleAccidentEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.VehicleOverSpeedEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.VehicleServiceLifeListVo; +import com.ningdatech.carapi.analysis.entity.vo.VehicleViolationEvalListVo; +import com.ningdatech.carapi.analysis.service.IVehicleAccidentEvalService; +import com.ningdatech.carapi.analysis.service.IVehicleOverSpeedEvalService; +import com.ningdatech.carapi.analysis.service.IVehicleServiceLifeService; +import com.ningdatech.carapi.analysis.service.IVehicleViolationEvalService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.service.INdInsureInfoService; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerService; +import com.ningdatech.carapi.safe.service.IVehicleAccidentReportService; +import com.ningdatech.carapi.scheduler.enums.DataTypeEnum; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.constant.ImportTemplateConstant; +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.ExcelReader; +import cn.hutool.poi.excel.ExcelUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * InsuranceRiskEvalManage + *

+ * + * @author WendyYang + * @since 14:31 2022/10/15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class InsuranceRiskEvalManage { + + private final IVehicleServiceLifeService vehicleServiceLifeService; + private final IVehicleViolationEvalService vehicleViolationEvalService; + private final IVehicleOverSpeedEvalService vehicleOverSpeedEvalService; + private final IVehicleAccidentEvalService vehicleAccidentEvalService; + private final INdInsureOutDangerService ndInsureOutDangerService; + private final RegionsCacheHelper regionsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final CompanyService companyService; + private final INdInsureInfoService insureInfoService; + + private final ApplicationContext applicationContext; + + private final IVehicleAccidentReportService vehicleAccidentReportService; + + /** + * 车辆使用年限列表 + */ + public PageVo vehicleServiceLifeList(VehicleServiceLifeListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(VehicleServiceLife.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildVehicleServiceLife(query,req); + Page page = vehicleServiceLifeService.page(req.page(), query); + List res = page.getRecords().stream().map(w -> { + VehicleServiceLifeListVo vo = BeanUtil.copyProperties(w,VehicleServiceLifeListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + int usedTime = Optional.ofNullable(w.getBuyTime()) + .flatMap(time -> Optional.ofNullable((int) ChronoUnit.YEARS.between(time, LocalDate.now()))) + .orElse(0); + vo.setUsedTime(usedTime); + // TODO 车辆使用年限百分比 + vo.setUsedTimePercent(0); + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildVehicleServiceLife(LambdaQueryWrapper query,VehicleServiceLifeListReq req) { + query.ge(req.getBuyTimeStart() != null, VehicleServiceLife::getBuyTime, req.getBuyTimeStart()) + .le(req.getBuyTimeEnd() != null, VehicleServiceLife::getBuyTime, req.getBuyTimeEnd()) + .like(StrUtil.isNotBlank(req.getCompanyName()), VehicleServiceLife::getCompanyName, req.getCompanyName()) + .like(StrUtil.isNotBlank(req.getCarNo()), VehicleServiceLife::getCarNo, req.getCarNo()) + .eq(Objects.nonNull(req.getDangerLevel()), VehicleServiceLife::getDangerLevel, req.getDangerLevel()); + } + + /** + * 车辆违章情况列表 + * + */ + public PageVo vehicleViolationEvalList(VehicleServiceLifeListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(VehicleViolationEval.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildVehicleViolationEvalQuery(query,req); + buildVehicleViolationEvalQuery(query,req); + Page page = vehicleViolationEvalService.page(req.page(), query); + List res = page.getRecords().stream().map(w -> { + VehicleViolationEvalListVo vo = BeanUtil.copyProperties(w,VehicleViolationEvalListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + vo.setDangerLevelName(DangerLevelEnum.getDescByCode(w.getDangerLevel())); + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildVehicleViolationEvalQuery(LambdaQueryWrapper query,VehicleServiceLifeListReq req) { + query.like(StrUtil.isNotBlank(req.getCompanyName()),VehicleViolationEval::getCompanyName, req.getCompanyName()) + .like(StrUtil.isNotBlank(req.getCarNo()),VehicleViolationEval::getCarNo, req.getCarNo()) + .eq(Objects.nonNull(req.getDangerLevel()),VehicleViolationEval::getDangerLevel, req.getDangerLevel()); + } + + /** + * 车辆出险情况列表 + */ + public PageVo vehicleAccidentList(VehicleServiceLifeListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(VehicleAccidentEval.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildVehicleAccident(query,req); + Page page = vehicleAccidentEvalService.page(req.page(), query); + List res = page.getRecords().stream().map(w -> { + VehicleAccidentEvalListVo vo = BeanUtil.copyProperties(w,VehicleAccidentEvalListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + vo.setDangerLevelName(DangerLevelEnum.getDescByCode(w.getDangerLevel())); + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res,page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildVehicleAccident(LambdaQueryWrapper query,VehicleServiceLifeListReq req) { + query.like(StrUtil.isNotBlank(req.getCompanyName()), VehicleAccidentEval::getCompanyName, req.getCompanyName()) + .like(StrUtil.isNotBlank(req.getCarNo()), VehicleAccidentEval::getCarNo, req.getCarNo()) + .eq(Objects.nonNull(req.getDangerLevel()), VehicleAccidentEval::getDangerLevel, req.getDangerLevel()); + } + + /** + * 车辆超速情况列表 + */ + public PageVo vehicleOverSpeedList(VehicleServiceLifeListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(VehicleOverSpeedEval.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildVehicleOverSpeed(query,req); + Page page = vehicleOverSpeedEvalService.page(req.page(), query); + List res = page.getRecords().stream().map(w -> { + VehicleOverSpeedEvalListVo vo = BeanUtil.copyProperties(w,VehicleOverSpeedEvalListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + vo.setDangerLevelName(DangerLevelEnum.getDescByCode(w.getDangerLevel())); + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res,page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildVehicleOverSpeed(LambdaQueryWrapper query,VehicleServiceLifeListReq req) { + query.like(StrUtil.isNotBlank(req.getCompanyName()), VehicleOverSpeedEval::getCompanyName, req.getCompanyName()) + .like(StrUtil.isNotBlank(req.getCarNo()), VehicleOverSpeedEval::getCarNo, req.getCarNo()) + .eq(Objects.nonNull(req.getDangerLevel()), VehicleOverSpeedEval::getDangerLevel, req.getDangerLevel()); + } + + public void vehicleViolationEvalMod(VehicleViolationEvalModReq req) { + VehicleViolationEval violationEval = BeanUtil.copyProperties(req, VehicleViolationEval.class); + violationEval.setRemark(StrUtil.nullToEmpty(violationEval.getRemark())); + violationEval.setUpdateBy(LoginUserUtil.getUserId()); + violationEval.setUpdateOn(LocalDateTime.now()); + boolean update = vehicleViolationEvalService.updateById(violationEval); + Assert.isTrue(update, "记录不存在"); + } + + public void vehicleAccidentEvalMod(VehicleAccidentEvalModReq req) { + VehicleAccidentEval accidentEval = BeanUtil.copyProperties(req, VehicleAccidentEval.class); + accidentEval.setRemark(StrUtil.nullToEmpty(accidentEval.getRemark())); + accidentEval.setUpdateBy(LoginUserUtil.getUserId()); + accidentEval.setUpdateOn(LocalDateTime.now()); + boolean update = vehicleAccidentEvalService.updateById(accidentEval); + Assert.isTrue(update, "记录不存在"); + } + + public void vehicleOverSpeedEvalMod(VehicleOverSpeedEvalModReq req) { + VehicleOverSpeedEval overSpeedEval = BeanUtil.copyProperties(req, VehicleOverSpeedEval.class); + overSpeedEval.setRemark(StrUtil.nullToEmpty(overSpeedEval.getRemark())); + overSpeedEval.setUpdateBy(LoginUserUtil.getUserId()); + overSpeedEval.setUpdateOn(LocalDateTime.now()); + boolean update = vehicleOverSpeedEvalService.updateById(overSpeedEval); + Assert.isTrue(update, "记录不存在"); + } + + public void vehicleViolationEvalDel(Integer id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleViolationEval.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + VehicleViolationEval violationEval = vehicleViolationEvalService.getOne(wrapper); + if (Objects.isNull(violationEval)){ + throw new BizException("文件无法删除!"); + } + vehicleViolationEvalService.removeById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Integer id) { + wrapper.eq(VehicleViolationEval::getId,id); + } + + public void vehicleAccidentEvalDel(Integer id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleAccidentEval.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildAccidentEvalQuery(wrapper, id); + VehicleAccidentEval accidentEval = vehicleAccidentEvalService.getOne(wrapper); + if (Objects.isNull(accidentEval)){ + throw new BizException("文件无法删除!"); + } + vehicleAccidentEvalService.removeById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildAccidentEvalQuery(LambdaQueryWrapper wrapper, Integer id) { + wrapper.eq(VehicleAccidentEval::getId,id); + } + + public void vehicleOverSpeedEvalDel(Integer id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleOverSpeedEval.class); + InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy(); + context.buildStandardFileQuery(wrapper, id); + VehicleOverSpeedEval overSpeedEval = vehicleOverSpeedEvalService.getOne(wrapper); + if (Objects.isNull(overSpeedEval)){ + throw new BizException("文件无法删除!"); + } + vehicleOverSpeedEvalService.removeById(id); + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildStandardFileQuery(LambdaQueryWrapper wrapper, Integer id) { + wrapper.eq(VehicleOverSpeedEval::getId,id); + } + + private void importVehicleViolationData(List importDataList) { + if (CollectionUtils.isEmpty(importDataList)) { + return; + } + List violationEvalList = new ArrayList<>(); + List carNos = CollUtils.fieldList(importDataList, VehicleViolationImportDto::getCarNo); + Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复"); + Map carInfoMap = vehicleBaseInfoService.listByCarNo(carNos); + Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在"); + List companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId); + Map companyMap = companyService.listCompanyByIds(companyIds); + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + importDataList.forEach(w -> { + VehicleViolationEval eval = new VehicleViolationEval(); + eval.setCreateBy(userId); + eval.setCreateOn(now); + eval.setUpdateBy(userId); + eval.setUpdateOn(now); + eval.setViolationCount(w.getViolationCount()); + eval.setRemark(w.getRemark()); + eval.setAvgViolationCount(w.getAvgViolationCount()); + eval.setCarNo(w.getCarNo()); + eval.setMileage(w.getMileage()); + NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo()); + eval.setCarId(carInfo.getId()); + eval.setCompanyId(carInfo.getCompanyId()); + Company company = companyMap.get(eval.getCompanyId()); + eval.setCompanyName(company.getName()); + eval.setRegionId(company.getRegionId()); + eval.setCarFrameNo(w.getChassisNumber()); + eval.setDangerLevel(DangerLevelEnum.getCodeByDesc(w.getRiskEvaluation())); + violationEvalList.add(eval); + }); + LambdaQueryWrapper delQuery = Wrappers.lambdaQuery(VehicleViolationEval.class) + .in(VehicleViolationEval::getCarNo, carNos); + vehicleViolationEvalService.remove(delQuery); + vehicleViolationEvalService.saveBatch(violationEvalList); + } + + private void importVehicleOverSpeedData(List importDataList) { + if (CollectionUtils.isEmpty(importDataList)) { + return; + } + List carNos = CollUtils.fieldList(importDataList, VehicleOverSpeedImportDto::getCarNo); + Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复"); + Map carInfoMap = vehicleBaseInfoService.listByCarNo(carNos); + Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在"); + List companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId); + Map companyMap = companyService.listCompanyByIds(companyIds); + List violationEvalList = new ArrayList<>(); + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + importDataList.forEach(w -> { + VehicleOverSpeedEval eval = new VehicleOverSpeedEval(); + eval.setCreateBy(userId); + eval.setCreateOn(now); + eval.setUpdateBy(userId); + eval.setUpdateOn(now); + eval.setOverSpeedCount(w.getOverSpeedCount()); + eval.setRemark(w.getRemark()); + eval.setAvgOverSpeedCount(w.getAvgOverSpeedCount()); + eval.setCarNo(w.getCarNo()); + eval.setMileage(w.getMileage()); + NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo()); + eval.setCarId(carInfo.getId()); + eval.setCompanyId(carInfo.getCompanyId()); + Company company = companyMap.get(eval.getCompanyId()); + eval.setCompanyName(company.getName()); + eval.setRegionId(company.getRegionId()); + eval.setCarFrameNo(w.getChassisNumber()); + eval.setDangerLevel(DangerLevelEnum.getCodeByDesc(w.getRiskEvaluation())); + violationEvalList.add(eval); + }); + LambdaQueryWrapper delQuery = Wrappers.lambdaQuery(VehicleOverSpeedEval.class) + .in(VehicleOverSpeedEval::getCarNo, carNos); + vehicleOverSpeedEvalService.remove(delQuery); + vehicleOverSpeedEvalService.saveBatch(violationEvalList); + } + + private void importVehicleAccidentData(List importDataList) { + if (CollectionUtils.isEmpty(importDataList)) { + return; + } + List carNos = CollUtils.fieldList(importDataList, VehicleAccidentImportDto::getCarNo); + Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复"); + Map carInfoMap = vehicleBaseInfoService.listByCarNo(carNos); + Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在"); + List companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId); + Map companyMap = companyService.listCompanyByIds(companyIds); + List violationEvalList = new ArrayList<>(); + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + importDataList.forEach(w -> { + VehicleAccidentEval eval = new VehicleAccidentEval(); + eval.setCreateBy(userId); + eval.setCreateOn(now); + eval.setUpdateBy(userId); + eval.setUpdateOn(now); + eval.setAccidentCount(w.getAccidentCount()); + eval.setRemark(w.getRemark()); + eval.setAvgAccidentCount(w.getAvgAccidentCount()); + eval.setCarNo(w.getCarNo()); + eval.setMileage(w.getMileage()); + NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo()); + eval.setCarId(carInfo.getId()); + eval.setCompanyId(carInfo.getCompanyId()); + Company company = companyMap.get(eval.getCompanyId()); + eval.setCompanyName(company.getName()); + eval.setRegionId(company.getRegionId()); + eval.setCarFrameNo(w.getChassisNumber()); + eval.setDangerLevel(DangerLevelEnum.getCodeByDesc(w.getRiskEvaluation())); + violationEvalList.add(eval); + }); + LambdaQueryWrapper delQuery = Wrappers.lambdaQuery(VehicleAccidentEval.class) + .in(VehicleAccidentEval::getCarNo, carNos); + vehicleAccidentEvalService.remove(delQuery); + vehicleAccidentEvalService.saveBatch(violationEvalList); + } + + private void importOutDangerData(List importDataList) { + if (CollectionUtils.isEmpty(importDataList)) { + return; + } + List carNos = CollUtils.fieldList(importDataList, OutDangerImportDto::getCarNo); + // Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复"); + Map carInfoMap = vehicleBaseInfoService.listByCarNo(carNos); + Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在"); + List companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId); + Map companyMap = companyService.listCompanyByIds(companyIds); + Map insureCompanyInfoMap = insureInfoService.listInsureCompanyByCompanyIds(companyIds); + + List ndInsureOutDangers = new ArrayList<>(); + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + importDataList.forEach(w -> { + NdInsureOutDanger eval = new NdInsureOutDanger(); + eval.setCreateBy(userId); + eval.setCreateOn(now); + eval.setUpdateBy(userId); + eval.setUpdateOn(now); + + NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo()); + Company company = companyMap.get(carInfo.getCompanyId()); + + DateTime parse = DateUtil.parse(w.getAccidentTime()); + Instant instant = parse.toInstant(); + ZoneId zoneId = ZoneId.systemDefault(); + LocalDateTime accidentTime = instant.atZone(zoneId).toLocalDateTime(); + + eval.setAccidentTime(accidentTime); + eval.setAccidentAddress(w.getAccidentAddress()); + eval.setCompanyId(company.getId()); + eval.setCompanyName(company.getName()); + eval.setRegionId(company.getRegionId()); + eval.setRegionName(company.getName()); + eval.setCarPlate(w.getCarNo()); + if (insureCompanyInfoMap.size() == 0){ + eval.setInsureCompany(null); + }else { + NdInsureInfo ndInsureInfo = insureCompanyInfoMap.get(carInfo.getCompanyId()); + eval.setInsureCompany(ndInsureInfo.getInsureCompany()); + } + eval.setInjuries(w.getInjuries()); + eval.setDeathToll(w.getDeathToll()); + eval.setCompensateAmount(w.getCompensateAmount()); + + ndInsureOutDangers.add(eval); + }); + + // 筛选出不在出险信息表中的数据,进行导入 + List insureOutDangers = ndInsureOutDangers.stream().filter(w -> { + NdInsureOutDanger ndInsureOutDanger = ndInsureOutDangerService.getOne(Wrappers.lambdaQuery(NdInsureOutDanger.class) + .eq(NdInsureOutDanger::getCarPlate, w.getCarPlate()) + .eq(NdInsureOutDanger::getInsureCompany,w.getInsureCompany()) + .eq(NdInsureOutDanger::getCompanyName,w.getCompanyName()) + .eq(NdInsureOutDanger::getAccidentAddress,w.getAccidentAddress()) + .eq(NdInsureOutDanger::getAccidentTime,w.getAccidentTime()) + .eq(NdInsureOutDanger::getInjuries,w.getInjuries()) + .eq(NdInsureOutDanger::getDeathToll,w.getDeathToll()) + .eq(NdInsureOutDanger::getCompensateAmount,w.getCompensateAmount())); + if (Objects.isNull(ndInsureOutDanger)){ + return true; + } + return false; + }).collect(Collectors.toList()); + + if (CollUtil.isEmpty(insureOutDangers)){ + throw new BizException("导入数据均已存在,无需重复导入!"); + } + + LambdaQueryWrapper delQuery = Wrappers.lambdaQuery(NdInsureOutDanger.class) + .in(NdInsureOutDanger::getCarPlate, carNos); + ndInsureOutDangerService.remove(delQuery); + ndInsureOutDangerService.saveBatch(insureOutDangers); + } + + @Transactional(rollbackFor = Exception.class) + public void importTemplateData(ImportTemplateEnum template, MultipartFile file) { + String contentType = file.getContentType(); + if (!contentType.equals(ExcelUtil.XLS_CONTENT_TYPE) && + !contentType.equals(ExcelUtil.XLSX_CONTENT_TYPE) + ) { + throw BizException.wrap("导入失败,不支持的文件类型,请按照提供的模板导入文件!"); + } + try (InputStream inputStream = file.getInputStream(); + ExcelReader reader = ExcelUtil.getReader(inputStream)) { + Map alias; + List title = ImportTemplateConstant.getTemplateTitle(template); + switch (template) { + case VEHICLE_VIOLATION: + alias = new HashMap<>(title.size()); + alias.put(title.get(0), "id"); + alias.put(title.get(1), "city"); + alias.put(title.get(2), "zone"); + alias.put(title.get(3), "companyName"); + alias.put(title.get(4), "carNo"); + alias.put(title.get(5), "chassisNumber"); + alias.put(title.get(6), "mileage"); + alias.put(title.get(7), "violationCount"); + alias.put(title.get(8), "avgViolationCount"); + alias.put(title.get(9), "riskEvaluation"); + alias.put(title.get(10), "remark"); + reader.setHeaderAlias(alias); + importVehicleViolationData(reader.readAll(VehicleViolationImportDto.class)); + break; + case VEHICLE_ACCIDENT: + alias = new HashMap<>(title.size()); + alias.put(title.get(0), "id"); + alias.put(title.get(1), "city"); + alias.put(title.get(2), "zone"); + alias.put(title.get(3), "companyName"); + alias.put(title.get(4), "carNo"); + alias.put(title.get(5), "chassisNumber"); + alias.put(title.get(6), "mileage"); + alias.put(title.get(7), "accidentCount"); + alias.put(title.get(8), "avgAccidentCount"); + alias.put(title.get(9), "riskEvaluation"); + alias.put(title.get(10), "remark"); + reader.setHeaderAlias(alias); + importVehicleAccidentData(reader.readAll(VehicleAccidentImportDto.class)); + break; + case VEHICLE_OVER_SPEED: + alias = new HashMap<>(title.size()); + alias.put(title.get(0), "id"); + alias.put(title.get(1), "city"); + alias.put(title.get(2), "zone"); + alias.put(title.get(3), "companyName"); + alias.put(title.get(4), "carNo"); + alias.put(title.get(5), "chassisNumber"); + alias.put(title.get(6), "mileage"); + alias.put(title.get(7), "overSpeedCount"); + alias.put(title.get(8), "avgOverSpeedCount"); + alias.put(title.get(9), "riskEvaluation"); + alias.put(title.get(10), "remark"); + reader.setHeaderAlias(alias); + importVehicleOverSpeedData(reader.readAll(VehicleOverSpeedImportDto.class)); + break; + case INSURE_OUT_DANGER: + alias = new HashMap<>(title.size()); + alias.put(title.get(0), "id"); + alias.put(title.get(1), "regionName"); + alias.put(title.get(2), "carNo"); + alias.put(title.get(3), "insureCompany"); + alias.put(title.get(4), "companyName"); + alias.put(title.get(5), "accidentAddress"); + alias.put(title.get(6), "accidentTime"); + alias.put(title.get(7), "injuries"); + alias.put(title.get(8), "deathToll"); + alias.put(title.get(9), "compensateAmount"); + reader.setHeaderAlias(alias); + importOutDangerData(reader.readAll(OutDangerImportDto.class)); + break; + default: + throw new BizException("不支持的数据导入类型"); + } +} catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/SecurityAnalysisEvalManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/SecurityAnalysisEvalManage.java new file mode 100644 index 0000000..dac8e43 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/SecurityAnalysisEvalManage.java @@ -0,0 +1,245 @@ +package com.ningdatech.carapi.analysis.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.IdVo; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.analysis.entity.SecurityManageGrade; +import com.ningdatech.carapi.analysis.entity.SecurityManageResultEval; +import com.ningdatech.carapi.analysis.entity.SecurityRiskEval; +import com.ningdatech.carapi.analysis.entity.SecuritySystemBuildingEval; +import com.ningdatech.carapi.analysis.entity.req.SecurityManageGradeListReq; +import com.ningdatech.carapi.analysis.entity.req.SecurityRiskEvalListReq; +import com.ningdatech.carapi.analysis.entity.req.SecurityRiskEvalSaveReq; +import com.ningdatech.carapi.analysis.entity.req.SecuritySystemBuildingEvalSaveReq; +import com.ningdatech.carapi.analysis.entity.vo.SecurityManageGradeVo; +import com.ningdatech.carapi.analysis.entity.vo.SecurityManageResultEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.SecurityRiskEvalListVo; +import com.ningdatech.carapi.analysis.entity.vo.SecuritySystemBuildingEvalListVo; +import com.ningdatech.carapi.analysis.service.ISecurityManageGradeService; +import com.ningdatech.carapi.analysis.service.ISecurityManageResultEvalService; +import com.ningdatech.carapi.analysis.service.ISecurityRiskEvalService; +import com.ningdatech.carapi.analysis.service.ISecuritySystemBuildingEvalService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * SecurityAnalysisEvalManage + *

+ * + * @author WendyYang + * @since 14:47 2022/10/13 + */ +@Component +@RequiredArgsConstructor +public class SecurityAnalysisEvalManage { + + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + private final ISecurityManageGradeService securityManagementGradeService; + private final ISecurityRiskEvalService securityRiskEvaluationService; + private final ISecuritySystemBuildingEvalService systemBuildingEvalService; + private final ISecurityManageResultEvalService securityManageResultEvalService; + + /** + * 安全管理综合评级列表 + **/ + public PageVo list(SecurityManageGradeListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(SecurityManageGrade.class); + SecurityAnalysisEvalManage context = (SecurityAnalysisEvalManage) AopContext.currentProxy(); + context.buildSecurityManageGradeQuery(query,req); + Page page = securityManagementGradeService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + SecurityManageGradeVo gradeVo = BeanUtil.copyProperties(w, SecurityManageGradeVo.class); + List regions = regionsCacheHelper.listParents(w.getRegionId()); + gradeVo.setRegions(regions); + CodeUtil.searchCompanyName(gradeVo); + return gradeVo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildSecurityManageGradeQuery(LambdaQueryWrapper query,SecurityManageGradeListReq req) { + if (StringUtils.isNotBlank(req.getCompanyName())) { + query.like(SecurityManageGrade::getCompanyName, req.getCompanyName()); + } + if (StringUtils.isNotBlank(req.getSecurityLevel())) { + query.eq(SecurityManageGrade::getSecurityLevel, req.getSecurityLevel()); + } + if (req.getYear() != null) { + query.eq(SecurityManageGrade::getYear, req.getYear()); + } + query.orderByDesc(SecurityManageGrade::getId); + } + + /** + * 安全责任体系分析评估列表 + */ + public PageVo list(SecurityRiskEvalListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(SecurityRiskEval.class); + SecurityAnalysisEvalManage context = (SecurityAnalysisEvalManage) AopContext.currentProxy(); + context.buildSecurityRiskEvalQuery(query, req); + Page page = securityRiskEvaluationService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + SecurityRiskEvalListVo gradeVo = BeanUtil.copyProperties(w, SecurityRiskEvalListVo.class); + List regions = regionsCacheHelper.listParents(w.getRegionId()); + gradeVo.setRegions(regions); + CodeUtil.searchCompanyName(gradeVo); + return gradeVo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildSecurityRiskEvalQuery(LambdaQueryWrapper query, SecurityRiskEvalListReq req) { + if (StringUtils.isNotBlank(req.getCompanyName())) { + query.like(SecurityRiskEval::getCompanyName, req.getCompanyName()); + } + if (req.getScoreRanges() != null) { + Pair ranges = req.getScoreRanges(); + query.ge(ranges.getLeft() != null, SecurityRiskEval::getTotalScore, ranges.getLeft()); + query.le(ranges.getRight() != null, SecurityRiskEval::getTotalScore, ranges.getRight()); + } + if (req.getYear() != null) { + query.eq(SecurityRiskEval::getYear, req.getYear()); + } + query.orderByDesc(SecurityRiskEval::getId); + } + + /** + * 安全制度建设分析评估列表 + */ + public PageVo listSystemBuildingEval(SecurityRiskEvalListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(SecuritySystemBuildingEval.class); + SecurityAnalysisEvalManage context = (SecurityAnalysisEvalManage) AopContext.currentProxy(); + context.buildSystemBuildingEvalQuery(query, req); + Page page = systemBuildingEvalService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + SecuritySystemBuildingEvalListVo gradeVo = BeanUtil.copyProperties(w, SecuritySystemBuildingEvalListVo.class); + List regions = regionsCacheHelper.listParents(w.getRegionId()); + gradeVo.setRegions(regions); + CodeUtil.searchCompanyName(gradeVo); + return gradeVo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildSystemBuildingEvalQuery(LambdaQueryWrapper query, SecurityRiskEvalListReq req) { + if (StringUtils.isNotBlank(req.getCompanyName())) { + query.like(SecuritySystemBuildingEval::getCompanyName, req.getCompanyName()); + } + if (req.getScoreRanges() != null) { + Pair ranges = req.getScoreRanges(); + query.ge(ranges.getLeft() != null, SecuritySystemBuildingEval::getTotalScore, ranges.getLeft()); + query.le(ranges.getRight() != null, SecuritySystemBuildingEval::getTotalScore, ranges.getRight()); + } + if (req.getYear() != null) { + query.eq(SecuritySystemBuildingEval::getYear, req.getYear()); + } + query.orderByDesc(SecuritySystemBuildingEval::getId); + } + + /** + * 新增安全责任体系评估 + */ + + public IdVo save(SecurityRiskEvalSaveReq req) { + Assert.isTrue(0L == securityRiskEvaluationService.count(Wrappers.lambdaQuery(SecurityRiskEval.class) + .eq(SecurityRiskEval::getYear, req.getYear()) + .eq(SecurityRiskEval::getCompanyId, req.getCompanyId())), "已存在该年度安全责任体系评估"); + CompanyDTO company = companiesCacheHelper.getById(req.getCompanyId()); + SecurityRiskEval insert = BeanUtil.copyProperties(req, SecurityRiskEval.class); + insert.setCreateBy(LoginUserUtil.getUserId()); + insert.setCreateOn(LocalDateTime.now()); + insert.setRegionId(company.getRegionId()); + insert.setUpdateBy(insert.getCreateBy()); + insert.setUpdateOn(insert.getCreateOn()); + securityRiskEvaluationService.save(insert); + return IdVo.of(insert.getId()); + } + + /** + * 新增安全制度建设分析评估 + */ + public IdVo save(SecuritySystemBuildingEvalSaveReq req) { + Assert.isTrue(0L == systemBuildingEvalService.count(Wrappers.lambdaQuery(SecuritySystemBuildingEval.class) + .eq(SecuritySystemBuildingEval::getYear, req.getYear()) + .eq(SecuritySystemBuildingEval::getCompanyId, req.getCompanyId())), "已存在该年度安全制度建设评估"); + CompanyDTO company = companiesCacheHelper.getById(req.getCompanyId()); + SecuritySystemBuildingEval insert = BeanUtil.copyProperties(req, SecuritySystemBuildingEval.class); + insert.setCreateBy(LoginUserUtil.getUserId()); + insert.setCreateOn(LocalDateTime.now()); + insert.setRegionId(company.getRegionId()); + insert.setUpdateBy(insert.getCreateBy()); + insert.setUpdateOn(insert.getCreateOn()); + systemBuildingEvalService.save(insert); + return IdVo.of(insert.getId()); + } + /** + * 安全管理结果分析评估列表 + */ + public PageVo listSecurityManageResultEval(SecurityRiskEvalListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(SecurityManageResultEval.class); + SecurityAnalysisEvalManage context = (SecurityAnalysisEvalManage) AopContext.currentProxy(); + context.buildSecurityManageResultEvalQuery(query, req); + Page page = securityManageResultEvalService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + SecurityManageResultEvalListVo gradeVo = BeanUtil.copyProperties(w, SecurityManageResultEvalListVo.class); + List regions = regionsCacheHelper.listParents(w.getRegionId()); + gradeVo.setRegions(regions); + CodeUtil.searchCompanyName(gradeVo); + return gradeVo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildSecurityManageResultEvalQuery(LambdaQueryWrapper query, SecurityRiskEvalListReq req) { + if (StringUtils.isNotBlank(req.getCompanyName())) { + query.like(SecurityManageResultEval::getCompanyName, req.getCompanyName()); + } + if (req.getScoreRanges() != null) { + Pair ranges = req.getScoreRanges(); + query.ge(ranges.getLeft() != null, SecurityManageResultEval::getTotalScore, ranges.getLeft()); + query.le(ranges.getRight() != null, SecurityManageResultEval::getTotalScore, ranges.getRight()); + } + if (req.getYear() != null) { + query.eq(SecurityManageResultEval::getYear, req.getYear()); + } + query.orderByDesc(SecurityManageResultEval::getId); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/WarnAnalysisManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/WarnAnalysisManage.java new file mode 100644 index 0000000..4f61238 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/manage/WarnAnalysisManage.java @@ -0,0 +1,149 @@ +package com.ningdatech.carapi.analysis.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCar; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisDriver; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import com.ningdatech.carapi.analysis.entity.vo.WarnAnalysisByCarVo; +import com.ningdatech.carapi.analysis.entity.vo.WarnAnalysisByCompanyVo; +import com.ningdatech.carapi.analysis.entity.vo.WarnAnalysisByDriverVo; +import com.ningdatech.carapi.analysis.mapper.WarnAnalysisCarMapper; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCarService; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCompanyService; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisDriverService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + *

+ * WarnAnalysisManage + *

+ * + * @author WendyYang + * @since 16:34 2022/10/14 + */ +@Component +@RequiredArgsConstructor +public class WarnAnalysisManage { + + private final IWarnAnalysisCarService warnAnalysisCarService; + private final IWarnAnalysisCompanyService warnAnalysisCompanyService; + private final RegionsCacheHelper regionsCacheHelper; + private final IWarnAnalysisDriverService warnAnalysisDriverService; + + private final WarnAnalysisCarMapper warnAnalysisCarMapper; + + /** + * 车辆综合预警分析列表 + */ + public PageVo listCarWarnAnalysis(WarnAnalysisListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(WarnAnalysisCar.class); + WarnAnalysisManage context = (WarnAnalysisManage) AopContext.currentProxy(); + context.buildCarWarnAnalysisQuery(query, req); + Page page = warnAnalysisCarService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + WarnAnalysisByCarVo vo = BeanUtil.copyProperties(w, WarnAnalysisByCarVo.class); + if (Objects.nonNull(w.getRegionId())) { + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + } + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildCarWarnAnalysisQuery(LambdaQueryWrapper query, WarnAnalysisListReq req) { + query.like(StrUtil.isNotBlank(req.getCarNo()), WarnAnalysisCar::getCarNo, req.getCarNo()) + .like(StrUtil.isNotBlank(req.getCompanyName()), WarnAnalysisCar::getCompanyName, req.getCompanyName()) + .eq(Objects.nonNull(req.getDangerLevel()), WarnAnalysisCar::getDangerLevel, req.getDangerLevel()) + .orderByDesc(WarnAnalysisCar::getDangerScore) + .orderByDesc(WarnAnalysisCar::getUpdateOn); + } + + /** + * 企业综合预警分析列表 + */ + public PageVo listCompanyWarnAnalysis(WarnAnalysisListReq req) { + String companyName = req.getCompanyName(); + Integer carCount = warnAnalysisCarMapper.selectVehiclesNum(companyName); + LambdaQueryWrapper query = Wrappers.lambdaQuery(WarnAnalysisCompany.class); + WarnAnalysisManage context = (WarnAnalysisManage) AopContext.currentProxy(); + context.buildCompanyWarnAnalysisQuery(query, req); + Page page = warnAnalysisCompanyService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + WarnAnalysisByCompanyVo vo = BeanUtil.copyProperties(w, WarnAnalysisByCompanyVo.class); + if (Objects.nonNull(w.getRegionId())) { + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + } + vo.setCarCount(carCount); + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildCompanyWarnAnalysisQuery(LambdaQueryWrapper query, WarnAnalysisListReq req) { + query.like(StrUtil.isNotBlank(req.getCompanyName()), WarnAnalysisCompany::getCompanyName, req.getCompanyName()) + .eq(Objects.nonNull(req.getDangerLevel()), WarnAnalysisCompany::getDangerLevel, req.getDangerLevel()) + .orderByDesc(WarnAnalysisCompany::getTotalScore) + .orderByDesc(WarnAnalysisCompany::getUpdateOn); + } + + /** + * 驾驶员综合预警分析列表 + */ + public PageVo listDriverWarnAnalysis(WarnAnalysisListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(WarnAnalysisDriver.class); + WarnAnalysisManage context = (WarnAnalysisManage) AopContext.currentProxy(); + context.buildDriverWarnAnalysisQuery(query, req); + Page page = warnAnalysisDriverService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List res = page.getRecords().stream().map(w -> { + WarnAnalysisByDriverVo vo = BeanUtil.copyProperties(w, WarnAnalysisByDriverVo.class); + if (Objects.nonNull(w.getRegionId())) { + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + } + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildDriverWarnAnalysisQuery(LambdaQueryWrapper query, WarnAnalysisListReq req) { + query.eq(StrUtil.isNotBlank(req.getDriverName()), WarnAnalysisDriver::getDriverName, req.getDriverName()) + .like(StrUtil.isNotBlank(req.getCompanyName()), WarnAnalysisDriver::getCompanyName, req.getCompanyName()) + .eq(Objects.nonNull(req.getDangerLevel()), WarnAnalysisDriver::getDangerLevel, req.getDangerLevel()) + .orderByDesc(WarnAnalysisDriver::getDangerScore) + .orderByDesc(WarnAnalysisDriver::getUpdateOn); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.java new file mode 100644 index 0000000..9657e90 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.IndustryStandards; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +public interface IndustryStandardsMapper extends BaseMapper { + + int incrementDownCount(Long id); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.xml new file mode 100644 index 0000000..f46e7b1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/IndustryStandardsMapper.xml @@ -0,0 +1,9 @@ + + + + + + update nd_industry_standards set down_count = down_count + 1 where id = #{id} + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.java new file mode 100644 index 0000000..3ae63ec --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.java @@ -0,0 +1,7 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerVO; + +public interface NdInsureOutDangerVOMapper extends BaseMapper { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.xml new file mode 100644 index 0000000..60c8dbe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/NdInsureOutDangerVOMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.java new file mode 100644 index 0000000..b512cc6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.SecurityManageGrade; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全管理综合评级 Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-13 + */ +public interface SecurityManageGradeMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.xml new file mode 100644 index 0000000..ac4d9cf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageGradeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.java new file mode 100644 index 0000000..d342383 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.SecurityManageResultEval; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全制度建设分析评估 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface SecurityManageResultEvalMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.xml new file mode 100644 index 0000000..3402376 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityManageResultEvalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.java new file mode 100644 index 0000000..a314112 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.SecurityRiskEval; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全责任体系分析评估 Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +public interface SecurityRiskEvalMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.xml new file mode 100644 index 0000000..e1377fa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecurityRiskEvalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.java new file mode 100644 index 0000000..f4b7d59 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.analysis.entity.SecuritySystemBuildingEval; + +/** + *

+ * 安全责任体系分析评估 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface SecuritySystemBuildingEvalMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.xml new file mode 100644 index 0000000..46ee371 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/SecuritySystemBuildingEvalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.java new file mode 100644 index 0000000..c7b696a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.VehicleAccidentEval; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆事故情况评估 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +public interface VehicleAccidentEvalMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.xml new file mode 100644 index 0000000..cfe57cb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleAccidentEvalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.java new file mode 100644 index 0000000..0cf0e1f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.VehicleOverSpeedEval; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆超速情况评估 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +public interface VehicleOverSpeedEvalMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.xml new file mode 100644 index 0000000..a429d9b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleOverSpeedEvalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.java new file mode 100644 index 0000000..11698e3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.VehicleServiceLife; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆使用年限 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +public interface VehicleServiceLifeMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.xml new file mode 100644 index 0000000..b02880d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleServiceLifeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.java new file mode 100644 index 0000000..2720585 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.VehicleViolationEval; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆违章情况评估 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +public interface VehicleViolationEvalMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.xml new file mode 100644 index 0000000..679720d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/VehicleViolationEvalMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.java new file mode 100644 index 0000000..25b65f2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCar; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 车辆综合预警分析 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface WarnAnalysisCarMapper extends BaseMapper { + + Integer selectVehiclesNum(@Param("companyName") String companyName); + + Page pageCarAnalysis(Page page, @Param("param") WarnAnalysisListReq req); + + List listCarAnalysis(@Param("param") WarnAnalysisListReq req); + + Integer saveBatchXml(@Param("singleList") List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.xml new file mode 100644 index 0000000..80aa5ae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCarMapper.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + INSERT INTO nd_warn_analysis_car + (region_id, + company_id, + company_name, + injured_count, + dead_count, + danger_count, + danger_score, + car_id, + car_no, + danger_level, + over_speed_count, + violation_count + ) + values + + ( + #{item.regionId}, + #{item.companyId}, + #{item.companyName}, + #{item.injuredCount}, + #{item.deadCount}, + #{item.dangerCount}, + #{item.dangerScore}, + #{item.carId}, + #{item.carNo}, + #{item.dangerLevel}, + #{item.overSpeedCount}, + #{item.violationCount} + ) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.java new file mode 100644 index 0000000..6956984 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 企业综合预警分析 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface WarnAnalysisCompanyMapper extends BaseMapper { + + List listCompanyAnalysis(@Param("param") WarnAnalysisListReq req); + + Integer saveBatchXml(@Param("singleList") List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.xml new file mode 100644 index 0000000..004da0f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisCompanyMapper.xml @@ -0,0 +1,95 @@ + + + + + + + + INSERT INTO nd_warn_analysis_company + (region_id, + company_id, + company_name, + injured_count, + dead_count, + danger_count, + total_score, + danger_level, + violation_count + ) + values + + ( + #{item.regionId}, + #{item.companyId}, + #{item.companyName}, + #{item.injuredCount}, + #{item.deadCount}, + #{item.dangerCount}, + #{item.totalScore}, + #{item.dangerLevel}, + #{item.violationCount} + ) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.java new file mode 100644 index 0000000..22a07aa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.analysis.mapper; + +import com.ningdatech.carapi.analysis.entity.WarnAnalysisDriver; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 驾驶员综合预警分析 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-01 + */ +public interface WarnAnalysisDriverMapper extends BaseMapper { + + List listDriverAnalysis(@Param("param") WarnAnalysisListReq req); + + Integer saveBatchXml(@Param("singleList") List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.xml new file mode 100644 index 0000000..ff8923d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/mapper/WarnAnalysisDriverMapper.xml @@ -0,0 +1,87 @@ + + + + + + + INSERT INTO nd_warn_analysis_driver + (region_id, + driver_id, + driver_name, + company_id, + company_name, + injured_count, + dead_count, + danger_count, + danger_score, + danger_level, + over_speed_count, + violation_count + ) + values + + ( + #{item.regionId}, + #{item.driverId}, + #{item.driverName}, + #{item.companyId}, + #{item.companyName}, + #{item.injuredCount}, + #{item.deadCount}, + #{item.dangerCount}, + #{item.dangerScore}, + #{item.dangerLevel}, + #{item.overSpeedCount}, + #{item.violationCount} + ) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IIndustryStandardsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IIndustryStandardsService.java new file mode 100644 index 0000000..54d448d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IIndustryStandardsService.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.IndustryStandards; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +public interface IIndustryStandardsService extends IService { + + boolean incrementDownCount(Long id); + + void deleteById(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/INdInsureOutDangerVOService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/INdInsureOutDangerVOService.java new file mode 100644 index 0000000..1fbc4a0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/INdInsureOutDangerVOService.java @@ -0,0 +1,7 @@ +package com.ningdatech.carapi.analysis.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerVO; + +public interface INdInsureOutDangerVOService extends IService { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageGradeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageGradeService.java new file mode 100644 index 0000000..f223f50 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageGradeService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.SecurityManageGrade; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 安全管理综合评级 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-13 + */ +public interface ISecurityManageGradeService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageResultEvalService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageResultEvalService.java new file mode 100644 index 0000000..4e003eb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityManageResultEvalService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.SecurityManageResultEval; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 安全制度建设分析评估 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface ISecurityManageResultEvalService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityRiskEvalService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityRiskEvalService.java new file mode 100644 index 0000000..ffabb99 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecurityRiskEvalService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.analysis.entity.SecurityRiskEval; + +/** + *

+ * 安全责任体系分析评估 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +public interface ISecurityRiskEvalService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecuritySystemBuildingEvalService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecuritySystemBuildingEvalService.java new file mode 100644 index 0000000..24d4e9d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/ISecuritySystemBuildingEvalService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.SecuritySystemBuildingEval; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 安全责任体系分析评估 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface ISecuritySystemBuildingEvalService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleAccidentEvalService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleAccidentEvalService.java new file mode 100644 index 0000000..f34757f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleAccidentEvalService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.VehicleAccidentEval; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆事故情况评估 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +public interface IVehicleAccidentEvalService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleOverSpeedEvalService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleOverSpeedEvalService.java new file mode 100644 index 0000000..267aaae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleOverSpeedEvalService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.VehicleOverSpeedEval; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆超速情况评估 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +public interface IVehicleOverSpeedEvalService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleServiceLifeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleServiceLifeService.java new file mode 100644 index 0000000..a78d0e8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleServiceLifeService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.VehicleServiceLife; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆使用年限 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +public interface IVehicleServiceLifeService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleViolationEvalService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleViolationEvalService.java new file mode 100644 index 0000000..1529e3f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IVehicleViolationEvalService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.VehicleViolationEval; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆违章情况评估 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +public interface IVehicleViolationEvalService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCarService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCarService.java new file mode 100644 index 0000000..de88f03 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCarService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.analysis.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCar; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; + +import java.util.List; + +/** + *

+ * 车辆综合预警分析 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface IWarnAnalysisCarService extends IService { + + Page pageCarAnalysis(Page page, WarnAnalysisListReq req); + + List listCarAnalysis(WarnAnalysisListReq req); + + Integer saveBatchXml(List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCompanyService.java new file mode 100644 index 0000000..4a96dcf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisCompanyService.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCar; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; + +import java.util.List; + +/** + *

+ * 企业综合预警分析 服务类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +public interface IWarnAnalysisCompanyService extends IService { + + List listCompanyAnalysis(WarnAnalysisListReq req); + + Integer saveBatchXml(List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisDriverService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisDriverService.java new file mode 100644 index 0000000..ab5c634 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/IWarnAnalysisDriverService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.analysis.service; + +import com.ningdatech.carapi.analysis.entity.WarnAnalysisDriver; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; + +import java.util.List; + +/** + *

+ * 驾驶员综合预警分析 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-01 + */ +public interface IWarnAnalysisDriverService extends IService { + + List listDriverAnalysis(WarnAnalysisListReq warnAnalysisListReq); + + Integer saveBatchXml(List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/IndustryStandardsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/IndustryStandardsServiceImpl.java new file mode 100644 index 0000000..e541a7d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/IndustryStandardsServiceImpl.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.analysis.entity.IndustryStandards; +import com.ningdatech.carapi.analysis.mapper.IndustryStandardsMapper; +import com.ningdatech.carapi.analysis.service.IIndustryStandardsService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Service +public class IndustryStandardsServiceImpl extends ServiceImpl implements IIndustryStandardsService { + + @Override + public boolean incrementDownCount(Long id) { + return baseMapper.incrementDownCount(id) > 0; + } + + @Override + public void deleteById(Long id) { + baseMapper.deleteById(id); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/NdInsureOutDangerVOServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/NdInsureOutDangerVOServiceImpl.java new file mode 100644 index 0000000..97fb3d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/NdInsureOutDangerVOServiceImpl.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.analysis.mapper.NdInsureOutDangerVOMapper; +import com.ningdatech.carapi.analysis.service.INdInsureOutDangerVOService; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerVO; +import org.springframework.stereotype.Service; + +/** + * @author CMM + * @description + * @since 2022/11/16 17:42 + */ +@Service +public class NdInsureOutDangerVOServiceImpl extends ServiceImpl implements INdInsureOutDangerVOService { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageGradeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageGradeServiceImpl.java new file mode 100644 index 0000000..b1a6f67 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageGradeServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.SecurityManageGrade; +import com.ningdatech.carapi.analysis.mapper.SecurityManageGradeMapper; +import com.ningdatech.carapi.analysis.service.ISecurityManageGradeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全管理综合评级 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-13 + */ +@Service +public class SecurityManageGradeServiceImpl extends ServiceImpl implements ISecurityManageGradeService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageResultEvalServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageResultEvalServiceImpl.java new file mode 100644 index 0000000..702e4d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityManageResultEvalServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.SecurityManageResultEval; +import com.ningdatech.carapi.analysis.mapper.SecurityManageResultEvalMapper; +import com.ningdatech.carapi.analysis.service.ISecurityManageResultEvalService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全制度建设分析评估 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Service +public class SecurityManageResultEvalServiceImpl extends ServiceImpl implements ISecurityManageResultEvalService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityRiskEvalServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityRiskEvalServiceImpl.java new file mode 100644 index 0000000..e581480 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecurityRiskEvalServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.SecurityRiskEval; +import com.ningdatech.carapi.analysis.mapper.SecurityRiskEvalMapper; +import com.ningdatech.carapi.analysis.service.ISecurityRiskEvalService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全责任体系分析评估 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +@Service +public class SecurityRiskEvalServiceImpl extends ServiceImpl implements ISecurityRiskEvalService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecuritySystemBuildingEvalServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecuritySystemBuildingEvalServiceImpl.java new file mode 100644 index 0000000..9b60bc3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/SecuritySystemBuildingEvalServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.SecuritySystemBuildingEval; +import com.ningdatech.carapi.analysis.mapper.SecuritySystemBuildingEvalMapper; +import com.ningdatech.carapi.analysis.service.ISecuritySystemBuildingEvalService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全责任体系分析评估 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-14 + */ +@Service +public class SecuritySystemBuildingEvalServiceImpl extends ServiceImpl implements ISecuritySystemBuildingEvalService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleAccidentEvalServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleAccidentEvalServiceImpl.java new file mode 100644 index 0000000..9e75e5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleAccidentEvalServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.VehicleAccidentEval; +import com.ningdatech.carapi.analysis.mapper.VehicleAccidentEvalMapper; +import com.ningdatech.carapi.analysis.service.IVehicleAccidentEvalService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆事故情况评估 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +@Service +public class VehicleAccidentEvalServiceImpl extends ServiceImpl implements IVehicleAccidentEvalService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleOverSpeedEvalServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleOverSpeedEvalServiceImpl.java new file mode 100644 index 0000000..3a77710 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleOverSpeedEvalServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.VehicleOverSpeedEval; +import com.ningdatech.carapi.analysis.mapper.VehicleOverSpeedEvalMapper; +import com.ningdatech.carapi.analysis.service.IVehicleOverSpeedEvalService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆超速情况评估 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-17 + */ +@Service +public class VehicleOverSpeedEvalServiceImpl extends ServiceImpl implements IVehicleOverSpeedEvalService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleServiceLifeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleServiceLifeServiceImpl.java new file mode 100644 index 0000000..b57e341 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleServiceLifeServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.VehicleServiceLife; +import com.ningdatech.carapi.analysis.mapper.VehicleServiceLifeMapper; +import com.ningdatech.carapi.analysis.service.IVehicleServiceLifeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆使用年限 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Service +public class VehicleServiceLifeServiceImpl extends ServiceImpl implements IVehicleServiceLifeService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleViolationEvalServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleViolationEvalServiceImpl.java new file mode 100644 index 0000000..815ea44 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/VehicleViolationEvalServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.VehicleViolationEval; +import com.ningdatech.carapi.analysis.mapper.VehicleViolationEvalMapper; +import com.ningdatech.carapi.analysis.service.IVehicleViolationEvalService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆违章情况评估 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-15 + */ +@Service +public class VehicleViolationEvalServiceImpl extends ServiceImpl implements IVehicleViolationEvalService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCarServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCarServiceImpl.java new file mode 100644 index 0000000..9c4d0e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCarServiceImpl.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCar; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import com.ningdatech.carapi.analysis.mapper.WarnAnalysisCarMapper; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCarService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 车辆综合预警分析 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Service +@RequiredArgsConstructor +public class WarnAnalysisCarServiceImpl extends ServiceImpl implements IWarnAnalysisCarService { + + private final WarnAnalysisCarMapper mapper; + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page pageCarAnalysis(Page page, WarnAnalysisListReq req) { + return mapper.pageCarAnalysis(page,req); + } + + @Override + public List listCarAnalysis(WarnAnalysisListReq req) { + return mapper.listCarAnalysis(req); + } + + @Override + public Integer saveBatchXml(List singleList) { + return mapper.saveBatchXml(singleList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCompanyServiceImpl.java new file mode 100644 index 0000000..78e5ec9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisCompanyServiceImpl.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import com.ningdatech.carapi.analysis.mapper.WarnAnalysisCompanyMapper; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCompanyService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 企业综合预警分析 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-10-14 + */ +@Service +@RequiredArgsConstructor +public class WarnAnalysisCompanyServiceImpl extends ServiceImpl implements IWarnAnalysisCompanyService { + + private final WarnAnalysisCompanyMapper mapper; + + @Override + public List listCompanyAnalysis(WarnAnalysisListReq req) { + return mapper.listCompanyAnalysis(req); + } + + @Override + public Integer saveBatchXml(List singleList) { + return mapper.saveBatchXml(singleList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisDriverServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisDriverServiceImpl.java new file mode 100644 index 0000000..2b6369f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/analysis/service/impl/WarnAnalysisDriverServiceImpl.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.analysis.service.impl; + +import com.ningdatech.carapi.analysis.entity.WarnAnalysisDriver; +import com.ningdatech.carapi.analysis.entity.req.WarnAnalysisListReq; +import com.ningdatech.carapi.analysis.mapper.WarnAnalysisDriverMapper; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisDriverService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 驾驶员综合预警分析 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-01 + */ +@Service +@RequiredArgsConstructor +public class WarnAnalysisDriverServiceImpl extends ServiceImpl implements IWarnAnalysisDriverService { + + private final WarnAnalysisDriverMapper mapper; + + @Override + public List listDriverAnalysis(WarnAnalysisListReq req) { + return mapper.listDriverAnalysis(req); + } + + @Override + public Integer saveBatchXml(List singleList) { + return mapper.saveBatchXml(singleList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicle.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicle.java new file mode 100644 index 0000000..606e2a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicle.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.archives.aop; + +import java.lang.annotation.*; + +/** + * @Classname Audit + * @Description + * @Date 2022/10/31 15:34 + * @Created by PoffyZhang + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AuditVehicle { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicleAspect.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicleAspect.java new file mode 100644 index 0000000..9f979d7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/aop/AuditVehicleAspect.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.archives.aop; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @program: + * @description: 车辆审核切面 + * @author: PoffyZhang + * @created: 2021/10/29 09:12 + */ +@Aspect +@Component +@Slf4j +@AllArgsConstructor +@Order(10) +public class AuditVehicleAspect { + + private IVehicleBaseInfoService vehicleBaseInfoService; + + @Pointcut("@annotation(com.ningdatech.carapi.archives.aop.AuditVehicle)") + public void auditVehicleAspect() { + + } + + @Before("auditVehicleAspect() && @annotation(auditVehicle)") + public void doBebore(JoinPoint joinPoint, AuditVehicle auditVehicle) throws Throwable { + Object[] values = joinPoint.getArgs(); + String carPlate = (String) values[0]; + + VUtils.isTrueFormat(StringUtils.isBlank(carPlate)) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "车牌号未传 {}!",carPlate); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + wrapper.eq(NdVehicleBaseInfo::getCarPlate,carPlate); + //由于 车辆信息 车牌号不唯一 一辆车可能绑定多个企业 + List vehicles = vehicleBaseInfoService.list(wrapper); + + VUtils.isTrueFormat(CollUtil.isEmpty(vehicles)) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "系统中没有此车辆 {}!",carPlate); + + //暂时取第一辆 + NdVehicleBaseInfo vehicle = vehicles.get(0); + VUtils.isTrueFormat(!AuditStateEnum.AUDIT_SUCCESS.getCode().equals(vehicle.getAuditState())) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "此车辆未审核成功 {}!",carPlate); + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/assembler/QuestionAssembler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/assembler/QuestionAssembler.java new file mode 100644 index 0000000..804fffa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/assembler/QuestionAssembler.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.archives.assembler; + +import cn.hutool.core.collection.CollUtil; +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.ningdatech.carapi.archives.model.JudgmentalQuestionTextContent; +import com.ningdatech.carapi.archives.model.MultipleChoiceQuestionTextContent; +import com.ningdatech.carapi.archives.model.SingleChoiceQuestionTextContent; +import com.ningdatech.carapi.archives.model.vo.ResQuestionDetailVO; +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; + +/** + * @author liuxinxin + * @date 2022/10/22 下午3:36 + */ + +public class QuestionAssembler { + + public static ResQuestionDetailVO buildResQuestionDetailVO(PaperQuestion paperQuestion) { + ResQuestionDetailVO resQuestionDetailVO = new ResQuestionDetailVO(); + QuestionTypeEnum questionTypeEnum = QuestionTypeEnum.valueOf(paperQuestion.getQuestionType()); + String questionTextContent = paperQuestion.getQuestionTextContent(); + switch (questionTypeEnum) { + case MULTIPLE_CHOICE: + MultipleChoiceQuestionTextContent multipleChoiceQuestionTextContent + = JSONObject.parseObject(questionTextContent, MultipleChoiceQuestionTextContent.class); + resQuestionDetailVO.setChoiceQuestionCorrectAnswer(multipleChoiceQuestionTextContent.getAnswer()); + resQuestionDetailVO.setOptions(multipleChoiceQuestionTextContent.getOptions()); + break; + case SINGLE_CHOICE: + SingleChoiceQuestionTextContent singleChoiceQuestionTextContent + = JSONObject.parseObject(questionTextContent, SingleChoiceQuestionTextContent.class); + resQuestionDetailVO.setChoiceQuestionCorrectAnswer(CollUtil.toList(singleChoiceQuestionTextContent.getAnswer())); + resQuestionDetailVO.setOptions(singleChoiceQuestionTextContent.getOptions()); + break; + case JUDGMENTAL: + JudgmentalQuestionTextContent judgmentalQuestionTextContent + = JSONObject.parseObject(questionTextContent, JudgmentalQuestionTextContent.class); + resQuestionDetailVO.setJudgmentalQuestionCorrectAnswer(judgmentalQuestionTextContent.getAnswer()); + break; + default: + } + resQuestionDetailVO.setQuestionType(QuestionTypeEnum.valueOf(paperQuestion.getQuestionType())); + resQuestionDetailVO.setStem(paperQuestion.getStem()); + resQuestionDetailVO.setId(paperQuestion.getId()); + return resQuestionDetailVO; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ArchivesController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ArchivesController.java new file mode 100644 index 0000000..b186bc6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ArchivesController.java @@ -0,0 +1,131 @@ +package com.ningdatech.carapi.archives.controller; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.archives.aop.AuditVehicle; +import com.ningdatech.carapi.archives.manage.ArchivesManage; +import com.ningdatech.carapi.qrcode.model.vo.GetOnVehicleVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname ArchivesController + * @Description + * @Date 2022/11/1 14:16 + * @Created by PoffyZhang + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/archives/vehicle") +@Api(value = "archives", tags = "车辆管理-档案管理") +@RequiredArgsConstructor +public class ArchivesController { + + private final ArchivesManage archivesManage; + + /** + * 查询车辆的运营商档案 + * + * @param carPlate 车牌号 + * @return 查询运营商 + */ + @ApiOperation(value = "运营商信息档案", notes = "运营商信息档案") + @GetMapping("/operator-detail") + @AuditVehicle + public OperatorQueryDTO getOperatorDetails(@Valid @RequestParam String carPlate) { + return archivesManage.getOperatorDetails(carPlate); + } + + /** + * 查询车辆违章记录档案 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆违章记录档案", notes = "查询车辆违章记录档案") + @GetMapping("/violation") + @AuditVehicle + public List getViolation(@Valid @RequestParam String carPlate, @Valid @RequestParam Integer violationType) { + return archivesManage.getViolation(carPlate,violationType); + } + + /** + * 查询车辆事故记录档案 + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆事故记录档案", notes = "查询车辆事故记录档案") + @GetMapping("/accident-vehicle") + @AuditVehicle + public List getAccidentVehicle(@Valid @RequestParam String carPlate) { + return archivesManage.getAccidentVehicle(carPlate); + } + + /** + * 查询车辆死亡事故记录档案 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆死亡事故记录档案", notes = "查询车辆死亡事故记录档案") + @GetMapping("/accident-dead") + @AuditVehicle + public List getAccidentDead(@Valid @RequestParam String carPlate) { + return archivesManage.getAccidentDead(carPlate); + } + + /** + * 查询车辆事故分析记录档案 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆事故分析记录档案", notes = "查询车辆事故分析记录档案") + @GetMapping("/accident-analysis") + @AuditVehicle + public List getAccidentAnalysis(@Valid @RequestParam String carPlate) { + return archivesManage.getAccidentAnalysis(carPlate); + } + + /** + * 查询车辆上车记录 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆上车记录", notes = "查询车辆上车记录") + @GetMapping("/get-on-car-list") + @AuditVehicle + public List getOnCar(@Valid @RequestParam String carPlate) { + return archivesManage.getOnCar(carPlate); + } + + /** + * 查询车辆上车记录 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询车辆上车记录-驾驶员ID", notes = "查询车辆上车记录") + @GetMapping("/get-driver-on-car-list") + public List getOnCarDriver(@Valid @RequestParam String driverId) { + return archivesManage.getOnCarDriver(driverId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ExaminationPaperController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ExaminationPaperController.java new file mode 100644 index 0000000..534f563 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/ExaminationPaperController.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.archives.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.archives.manage.ExaminationPaperManage; +import com.ningdatech.carapi.archives.model.po.ReqExamPaperListPO; +import com.ningdatech.carapi.archives.model.po.ReqExamRulePO; +import com.ningdatech.carapi.archives.model.po.ReqSaveExamPaperPO; +import com.ningdatech.carapi.archives.model.po.ReqSaveExamRulePO; +import com.ningdatech.carapi.archives.model.vo.ResExamPaperListVO; +import com.ningdatech.carapi.archives.model.vo.ResExamPaperVO; +import com.ningdatech.carapi.archives.model.vo.ResExamRuleVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/17 下午4:07 + */ +@RequestMapping("/api/v1/exam-paper") +@Validated +@RestController +@Api(tags = "培训试卷") +@RequiredArgsConstructor +public class ExaminationPaperController { + + private final ExaminationPaperManage examinationPaperManage; + + @PostMapping("/save") + @ApiOperation("保存培训试卷") + @WebLog + public void saveExamPaper(@Valid @RequestBody ReqSaveExamPaperPO po) { + examinationPaperManage.saveExamPaper(po); + } + + @PostMapping("/get/{examPaperId}") + @ApiOperation("获取培训试卷") + public ResExamPaperVO getExamPaperId(@Valid @PathVariable Long examPaperId) { + return examinationPaperManage.getExamPaperId(examPaperId); + } + + @PostMapping("/list") + @ApiOperation("培训试卷列表") + public PageVo listExamPaper(@Valid @RequestBody ReqExamPaperListPO request) { + return examinationPaperManage.listExamPaper(request); + } + + @PostMapping("/save/exam-rule") + @ApiOperation("保存试卷规则-全局配置") + @WebLog + public void saveExamRule(@Valid @RequestBody ReqSaveExamRulePO request) { + examinationPaperManage.saveExamRule(request); + } + + @PostMapping("/get/exam-rule") + @ApiOperation("获取试卷规则-全局配置") + public ResExamRuleVO getExamRule(@Valid @RequestBody ReqExamRulePO request) { + return examinationPaperManage.getExamRule(request); + } + + @PostMapping("/delete/{id}") + @ApiOperation("删除试卷") + @WebLog + public void deleteExamPaper(@PathVariable("id") Long id) { + examinationPaperManage.deleteExamPaper(id); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/PaperQuestionController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/PaperQuestionController.java new file mode 100644 index 0000000..cdff65a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/controller/PaperQuestionController.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.archives.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.archives.manage.PaperQuestionManage; +import com.ningdatech.carapi.archives.model.po.ReqQuestionListPO; +import com.ningdatech.carapi.archives.model.po.ReqSaveNewQuestionPO; +import com.ningdatech.carapi.archives.model.vo.ResQuestionDetailVO; +import com.ningdatech.carapi.archives.model.vo.ResQuestionListVO; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author LiuXinXin + * @since 2022-10-11 + */ +@RequestMapping("/api/v1/paper-question") +@Validated +@RestController +@Api(tags = "培训考题") +@RequiredArgsConstructor +public class PaperQuestionController { + private final PaperQuestionManage paperQuestionManage; + + @PostMapping("/list") + @ApiOperation("培训题库列表查询") + public PageVo questionList(@Valid @RequestBody ReqQuestionListPO po) { + return paperQuestionManage.questionList(po); + } + + @GetMapping("/detail/{questionId}") + @ApiOperation("培训题库详情") + public ResQuestionDetailVO questionDetail(@Valid @PathVariable("questionId") Long questionId) { + return paperQuestionManage.questionDetail(questionId); + } + + @PostMapping("/create") + @ApiOperation("新增试题") + @WebLog + public void createNewQuestion(@Valid @RequestBody ReqSaveNewQuestionPO po) { + paperQuestionManage.createNewQuestion(po); + } + + @PostMapping("/save") + @ApiOperation("保存试题") + @WebLog + public void saveQuestion(@Valid @RequestBody ReqSaveNewQuestionPO request) { + paperQuestionManage.saveQuestion(request); + } + + @PostMapping("/delete/{id}") + @ApiOperation("删除试题") + @WebLog + public void deleteQuestion(@PathVariable("id") Long id) { + paperQuestionManage.deleteQuestion(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaper.java new file mode 100644 index 0000000..5dcd220 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaper.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.archives.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +@TableName("nd_exam_paper") +@Data +@ApiModel(value = "ExamPaper对象", description = "") +public class ExamPaper implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("所属区域标识") + private Long regionId; + + @ApiModelProperty("满分") + private Long fullScore; + + @ApiModelProperty("合格分") + private Long qualifiedScore; + + @ApiModelProperty("试卷名称") + private String examPaperName; + + @ApiModelProperty("试卷规则") + private String examRuleJson; + + @ApiModelProperty("是否随机试卷") + private Integer isRandom; + + @ApiModelProperty("考试开始时间") + private LocalDateTime examStartTime; + + @ApiModelProperty("考试结束时间") + private LocalDateTime examEndTime; + + @ApiModelProperty("随机试卷对应驾驶员用户ID") + private Long driverUserId; + + @ApiModelProperty("随机试卷所在的培训组织ID") + private Long trainingOrganizationId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaperQuestion.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaperQuestion.java new file mode 100644 index 0000000..b26fb6f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/ExamPaperQuestion.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.archives.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +@TableName("nd_exam_paper_question") +@ApiModel(value = "ExamPaperQuestion对象", description = "") +@Data +public class ExamPaperQuestion implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("考试试卷id") + private Long examPaperId; + + @ApiModelProperty("考试题目id") + private Long paperQuestionId; + + @ApiModelProperty("排序值") + private Long sortValue; + + @ApiModelProperty("题目类型") + private String questionType; + + @ApiModelProperty("是否随机试卷") + private Integer isRandom; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/PaperQuestion.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/PaperQuestion.java new file mode 100644 index 0000000..d45f093 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/entity/PaperQuestion.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.archives.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.archives.enums.PaperQuestionStatusEnum; +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-10-11 + */ +@TableName("nd_paper_question") +@Data +public class PaperQuestion implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 题目原题 + */ + private String stem; + + /** + * 题目类型 + * {@link QuestionTypeEnum} + */ + private String questionType; + + /** + * 正确答案 + */ + private String correct; + + /** + * 题目 填空、 题干、解析、答案等信息 + */ + private String questionTextContent; + + /** + * 状态 + * {@link PaperQuestionStatusEnum} + */ + private String questionStatus; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long regionId; + + /** + * 使用次数 + */ + private Long usageCnt; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ApproveStateEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ApproveStateEnum.java new file mode 100644 index 0000000..27d925e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ApproveStateEnum.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.archives.enums; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 通过审核 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "ApproveStateEnum", description = "通过审核-枚举") +public enum ApproveStateEnum { + /** + * 待审核 + */ + AUDIT(0, "待审核"), + + /** + * 审核成功 + */ + AUDIT_SUCESS(1, "已审核"); + + /** + * code + */ + private Integer code; + + /** + * 描述 + */ + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public Integer getCode() { + return this.code; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/AuditStateEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/AuditStateEnum.java new file mode 100644 index 0000000..028204c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/AuditStateEnum.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.archives.enums; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 审核状态 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AuditStateEnum", description = "审核状态-枚举") +public enum AuditStateEnum { + /** + * 待审核 + */ + AUDIT(1, "待审核"), + + /** + * 审核成功 + */ + AUDIT_SUCCESS(2, "审核成功"), + + /** + * 审核失败 + */ + AUDIT_FAIL(3, "审核失败"); + + /** + * code + */ + private Integer code; + + /** + * 描述 + */ + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @ApiModelProperty(value = "编码", allowableValues = "1,2,3", example = "1") + public Integer getCode() { + return this.code; + } + + public static String getDescByCode(int code) { + for (AuditStateEnum auditStateEnum : AuditStateEnum.values()) { + if (auditStateEnum.getCode() == code) { + return auditStateEnum.getDesc(); + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/CertOperTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/CertOperTypeEnum.java new file mode 100644 index 0000000..0ab21f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/CertOperTypeEnum.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.archives.enums; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 证书操作 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "CertOperTypeEnum", description = "证书操作-枚举") +public enum CertOperTypeEnum { + /** + * 申请 + */ + APPLICATION(1, "申请"), + + /** + * 补换 + */ + REISSUE(2, "补换"); + + /** + * code + */ + private Integer code; + + /** + * 描述 + */ + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public Integer getCode() { + return this.code; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/DriverRelationConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/DriverRelationConstant.java new file mode 100644 index 0000000..615b1ba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/DriverRelationConstant.java @@ -0,0 +1,14 @@ +package com.ningdatech.carapi.archives.enums; + +/** + * @author liuxinxin + * @date 2022/11/4 上午9:23 + */ + +public class DriverRelationConstant { + + /** + * 驾驶员基础分数 100分 + */ + public static final Integer DRIVER_FULL_SCORE = 100; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ExamPaperQualifiedScoreConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ExamPaperQualifiedScoreConstant.java new file mode 100644 index 0000000..d1cba83 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/ExamPaperQualifiedScoreConstant.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.archives.enums; + +/** + * @author liuxinxin + * @date 2022/10/22 上午11:47 + * 考试试卷合格分常量 + */ + +public class ExamPaperQualifiedScoreConstant { + + /** + * 试卷合格分 60分 + */ + public static final Long EXAM_PAPER_QUALIFIED_SCORE = 60L; + + /** + * 试卷总分 100分 + */ + public static final Long EXAM_PAPER_FULL_SCORE = 100L; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/IsRandomEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/IsRandomEnum.java new file mode 100644 index 0000000..a5d9437 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/IsRandomEnum.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.archives.enums; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 审核状态 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "IsRandomEnum", description = "随机试卷-枚举") +public enum IsRandomEnum { + /** + * 非随机试卷 + */ + NOT_RANDOM_PAPER(0, "否"), + + /** + * 随机试卷 + */ + RANDOM_PAPER(1, "是"); + + /** + * code + */ + private Integer code; + + /** + * 描述 + */ + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @ApiModelProperty("编码") + public Integer getCode() { + return this.code; + } + + public static String getDescByCode(int code) { + for (IsRandomEnum isRandomEnum : IsRandomEnum.values()) { + if (isRandomEnum.getCode() == code) { + return isRandomEnum.getDesc(); + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/PaperQuestionStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/PaperQuestionStatusEnum.java new file mode 100644 index 0000000..776cba0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/enums/PaperQuestionStatusEnum.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.archives.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/17 下午3:22 + * 培训试题枚举 + */ +@AllArgsConstructor +@Getter +public enum PaperQuestionStatusEnum { + + /** + * 使用中 + */ + IN_USE, + + /** + * 已删除 + */ + DELETED +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ArchivesManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ArchivesManage.java new file mode 100644 index 0000000..43aea63 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ArchivesManage.java @@ -0,0 +1,246 @@ +package com.ningdatech.carapi.archives.manage; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.MissCertEnum; +import com.ningdatech.carapi.common.constant.ViolationTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn; +import com.ningdatech.carapi.qrcode.model.vo.GetOnVehicleVO; +import com.ningdatech.carapi.qrcode.service.VehicleGetOnService; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; +import com.ningdatech.carapi.safe.manage.VehicleAccidentManage; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentAnalysisService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.manage.OperatorManage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + * @Classname ArchivesManage + * @Description + * @Date 2022/11/1 14:33 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +public class ArchivesManage { + + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final INdVehicleViolationService vehicleViolationService; + private final INdVehicleAccidentDeadService vehicleAccidentDeadService; + private final INdVehicleAccidentAnalysisService vehicleAccidentAnalysisService; + + private final VehicleGetOnService vehicleGetOnService; + private final OperatorManage operatorManage; + + private final VehicleAccidentManage vehicleAccidentManage; + + + /** + * 根据车牌号查询运营商 + * @param carPlate + * @return + */ + public OperatorQueryDTO getOperatorDetails(String carPlate) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + wrapper.eq(NdVehicleBaseInfo::getCarPlate,carPlate); + List vehicles = vehicleBaseInfoService.list(wrapper); + if(CollUtil.isEmpty(vehicles)){ + return null; + } + return operatorManage.getDetails(vehicles.get(0).getOperatorId()); + } + + /** + * 违章信息 + * @param carPlate violationType + * @return + */ + public List getViolation(String carPlate, Integer violationType) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleViolation.class); + ArchivesManage context = (ArchivesManage) AopContext.currentProxy(); + context.buildQuery(wrapper, carPlate,violationType); + List list = vehicleViolationService.list(wrapper); + + if(CollUtil.isEmpty(list)){ + return Collections.emptyList(); + } + + return list.stream().map(w -> { + NdVehicleViolationVO vo = BeanUtil.copyProperties(w, NdVehicleViolationVO.class); + if(Objects.nonNull(vo.getViolationType())){ + vo.setViolationTypeName(ViolationTypeEnum.getDescByCode(vo.getViolationType())); + } + if(Objects.nonNull(vo.getMissingCertificateType())){ + vo.setMissingCertificateTypeName(MissCertEnum.getDescByCode(vo.getMissingCertificateType())); + } + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }).collect(Collectors.toList()); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, String carPlate, Integer violationType) { + wrapper.eq(NdVehicleViolation::getCarPlate,carPlate); + wrapper.eq(NdVehicleViolation::getViolationType, violationType); + } + + /** + * 车辆事故 + * @param carPlate + * @return + */ + public List getAccidentVehicle(String carPlate) { + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(carPlate); + PageVo page = vehicleAccidentManage.queryVehicleAccident(param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + public List getAccidentVehicleOpen(String carPlate) { + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(carPlate); + PageVo page = vehicleAccidentManage.queryVehicleAccidentOpen(param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List getAccidentDead(String carPlate) { + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(carPlate); + PageVo page = vehicleAccidentManage.queryDead(param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentDeadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + public List getAccidentDeadOpen(String carPlate) { + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(carPlate); + PageVo page = vehicleAccidentManage.queryDeadOpen(param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentDeadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List getAccidentAnalysis(String carPlate) { + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(carPlate); + PageVo page = vehicleAccidentManage.queryAccidentAnalysis(param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentAnalysisVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + public List getAccidentAnalysisOpen(String carPlate) { + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(carPlate); + PageVo page = vehicleAccidentManage.queryAccidentAnalysis(param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentAnalysisVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + public List getOnCar(String carPlate) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class); + ArchivesManage context = (ArchivesManage) AopContext.currentProxy(); + context.buildGetOnCarQuery(wrapper, carPlate); + List list = vehicleGetOnService.list(wrapper); + if (CollUtil.isEmpty(list)){ + return Collections.emptyList(); + } + return CollUtils.convert(list, w -> { + GetOnVehicleVO vo = BeanUtil.copyProperties(w, GetOnVehicleVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildGetOnCarQuery(LambdaQueryWrapper wrapper, String carPlate) { + wrapper.eq(NdVehicleGetOn::getCarPlate,carPlate); + } + + public List getOnCarDriver(String driverId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class); + ArchivesManage context = (ArchivesManage) AopContext.currentProxy(); + context.buildGetOnQuery(wrapper, Long.valueOf(driverId)); + List list = vehicleGetOnService.list(wrapper); + if (CollUtil.isEmpty(list)){ + return Collections.emptyList(); + } + return CollUtils.convert(list, w -> { + GetOnVehicleVO vo = BeanUtil.copyProperties(w, GetOnVehicleVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildGetOnQuery(LambdaQueryWrapper wrapper, Long driverId) { + wrapper.eq(NdVehicleGetOn::getDriverId,driverId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ExaminationPaperManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ExaminationPaperManage.java new file mode 100644 index 0000000..f989280 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/ExaminationPaperManage.java @@ -0,0 +1,458 @@ +package com.ningdatech.carapi.archives.manage; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.archives.assembler.QuestionAssembler; +import com.ningdatech.carapi.archives.entity.ExamPaper; +import com.ningdatech.carapi.archives.entity.ExamPaperQuestion; +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.ningdatech.carapi.archives.enums.ExamPaperQualifiedScoreConstant; +import com.ningdatech.carapi.archives.enums.IsRandomEnum; +import com.ningdatech.carapi.archives.model.ExamRuleInfo; +import com.ningdatech.carapi.archives.model.po.ReqExamPaperListPO; +import com.ningdatech.carapi.archives.model.po.ReqExamRulePO; +import com.ningdatech.carapi.archives.model.po.ReqSaveExamPaperPO; +import com.ningdatech.carapi.archives.model.po.ReqSaveExamPaperPO.ExamPaperQuestionIdPO; +import com.ningdatech.carapi.archives.model.po.ReqSaveExamRulePO; +import com.ningdatech.carapi.archives.model.vo.ResExamPaperListVO; +import com.ningdatech.carapi.archives.model.vo.ResExamPaperVO; +import com.ningdatech.carapi.archives.model.vo.ResExamRuleVO; +import com.ningdatech.carapi.archives.model.vo.ResQuestionDetailVO; +import com.ningdatech.carapi.archives.service.IExamPaperQuestionService; +import com.ningdatech.carapi.archives.service.IExamPaperService; +import com.ningdatech.carapi.archives.service.IPaperQuestionService; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import com.ningdatech.carapi.sys.entity.ExamRule; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.IExamRuleService; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollectionUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/17 下午4:28 + */ +@Component +@RequiredArgsConstructor +public class ExaminationPaperManage { + + private final IPaperQuestionService iPaperQuestionService; + private final IExamPaperService iExamPaperService; + private final IExamPaperQuestionService iExamPaperQuestionService; + private final UserInfoHelper userInfoHelper; + private final IExamRuleService iExamRuleService; + private final RegionsCacheHelper regionsCacheHelper; + + @Transactional(rollbackFor = Exception.class) + public void createExamPaper(ReqSaveExamPaperPO po, ReqExamRulePO examRulePo) { + // 获取全局试卷规则 校验分数 + ResExamRuleVO examRule = getExamRule(examRulePo); + // 获取入参 + Long regionId = userInfoHelper.getUserRegionId(); + + List singleChoiceQuestionList = po.getSingleChoiceQuestionList(); + List multipleChoiceQuestionList = po.getMultipleChoiceQuestionList(); + List judgmentalQuestionList = po.getJudgmentalQuestionList(); + List examPaperQuestionIdList = new ArrayList<>(); + examPaperQuestionIdList.addAll(singleChoiceQuestionList); + examPaperQuestionIdList.addAll(multipleChoiceQuestionList); + examPaperQuestionIdList.addAll(judgmentalQuestionList); + + List questionIdList = examPaperQuestionIdList.stream() + .map(ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList()); + + List paperQuestionList = iPaperQuestionService + .list(Wrappers.lambdaQuery(PaperQuestion.class).in(PaperQuestion::getId, questionIdList)); + Map paperQuestionIdTypeMap = paperQuestionList.stream().collect(Collectors.toMap(PaperQuestion::getId, PaperQuestion::getQuestionType)); + + // 保存试卷基本信息 + ExamPaper examPaper = new ExamPaper(); + examPaper.setCreateOn(LocalDateTime.now()); + examPaper.setUpdateOn(LocalDateTime.now()); + examPaper.setExamPaperName(po.getExamPaperName()); + examPaper.setFullScore(ExamPaperQualifiedScoreConstant.EXAM_PAPER_FULL_SCORE); + examPaper.setQualifiedScore(ExamPaperQualifiedScoreConstant.EXAM_PAPER_QUALIFIED_SCORE); + examPaper.setRegionId(regionId); + examPaper.setExamRuleJson(JSONObject.toJSONString(examRule)); + examPaper.setIsRandom(IsRandomEnum.NOT_RANDOM_PAPER.getCode()); + iExamPaperService.save(examPaper); + + // 保存试卷题目关联关系 + List saveRecordList = new ArrayList<>(); + for (ExamPaperQuestionIdPO idPo : examPaperQuestionIdList) { + ExamPaperQuestion examPaperQuestion = new ExamPaperQuestion(); + examPaperQuestion.setExamPaperId(examPaper.getId()); + examPaperQuestion.setPaperQuestionId(idPo.getPaperQuestionId()); + examPaperQuestion.setCreateOn(LocalDateTime.now()); + examPaperQuestion.setUpdateOn(LocalDateTime.now()); + examPaperQuestion.setSortValue(idPo.getSortValue()); + examPaperQuestion.setQuestionType(paperQuestionIdTypeMap.get(idPo.getPaperQuestionId())); + saveRecordList.add(examPaperQuestion); + } + iExamPaperQuestionService.saveBatch(saveRecordList); + + List questionUsageCntUpdateList = examPaperQuestionIdList.stream().map(ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList()); + for (Long questionId : questionUsageCntUpdateList) { + questionUsageCntUpdate(questionId); + } + } + + @Transactional(rollbackFor = Exception.class) + public void saveExamPaper(ReqSaveExamPaperPO request) { + // 根据登录用户所在区域,获取全局试卷规则 + UserBasicInfoVO userFullInfo = userInfoHelper.getUserFullInfo(); + Long regionId = userFullInfo.getRegionId(); + ReqExamRulePO examRulePo = new ReqExamRulePO(); + examRulePo.setRegionId(regionId); + ResExamRuleVO examRule = getExamRule(examRulePo); + // 获取入参 + Long id = request.getId(); + List singleChoiceQuestionList = request.getSingleChoiceQuestionList(); + List multipleChoiceQuestionList = request.getMultipleChoiceQuestionList(); + List judgmentalQuestionList = request.getJudgmentalQuestionList(); + List questionUsageCntUpdateList = new ArrayList<>(); + + // 校验分数 + validExamRule(examRule, singleChoiceQuestionList, multipleChoiceQuestionList, judgmentalQuestionList); + + questionUsageCntUpdateList.addAll(singleChoiceQuestionList.stream().map(ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList())); + questionUsageCntUpdateList.addAll(multipleChoiceQuestionList.stream().map(ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList())); + questionUsageCntUpdateList.addAll(judgmentalQuestionList.stream().map(ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList())); + + if (Objects.isNull(id)) { + createExamPaper(request,examRulePo); + } else { + ExamPaper examPaper = iExamPaperService.getById(id); + if (Objects.isNull(examPaper)) { + throw new BizException("试卷不存在"); + } + // 获取入参 + List examPaperQuestionIdList = new ArrayList<>(); + examPaperQuestionIdList.addAll(singleChoiceQuestionList); + examPaperQuestionIdList.addAll(multipleChoiceQuestionList); + examPaperQuestionIdList.addAll(judgmentalQuestionList); + + List questionIdList = examPaperQuestionIdList.stream() + .map(ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList()); + + List paperQuestionList = iPaperQuestionService + .list(Wrappers.lambdaQuery(PaperQuestion.class).in(PaperQuestion::getId, questionIdList)); + Map paperQuestionIdTypeMap = paperQuestionList.stream().collect(Collectors.toMap(PaperQuestion::getId, PaperQuestion::getQuestionType)); + + List oldExamPaperQuestionList = iExamPaperQuestionService.list(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getExamPaperId, examPaper.getId())); + + // 保存试卷基本信息 + examPaper.setUpdateOn(LocalDateTime.now()); + examPaper.setExamPaperName(request.getExamPaperName()); + examPaper.setFullScore(ExamPaperQualifiedScoreConstant.EXAM_PAPER_FULL_SCORE); + examPaper.setQualifiedScore(ExamPaperQualifiedScoreConstant.EXAM_PAPER_QUALIFIED_SCORE); + examPaper.setRegionId(regionId); + examPaper.setExamRuleJson(JSONObject.toJSONString(examRule)); + examPaper.setIsRandom(IsRandomEnum.NOT_RANDOM_PAPER.getCode()); + iExamPaperService.updateById(examPaper); + + // 删除旧关系 保存新试卷题目关联关系 + iExamPaperQuestionService.remove(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getExamPaperId, examPaper.getId())); + + List saveRecordList = new ArrayList<>(); + for (ExamPaperQuestionIdPO po : examPaperQuestionIdList) { + ExamPaperQuestion examPaperQuestion = new ExamPaperQuestion(); + examPaperQuestion.setExamPaperId(examPaper.getId()); + examPaperQuestion.setPaperQuestionId(po.getPaperQuestionId()); + examPaperQuestion.setCreateOn(LocalDateTime.now()); + examPaperQuestion.setUpdateOn(LocalDateTime.now()); + examPaperQuestion.setSortValue(po.getSortValue()); + examPaperQuestion.setQuestionType(paperQuestionIdTypeMap.get(po.getPaperQuestionId())); + saveRecordList.add(examPaperQuestion); + } + iExamPaperQuestionService.saveBatch(saveRecordList); + + if (CollectionUtil.isNotEmpty(oldExamPaperQuestionList)) { + questionUsageCntUpdateList.addAll(oldExamPaperQuestionList.stream() + .map(ExamPaperQuestion::getPaperQuestionId).collect(Collectors.toList())); + questionUsageCntUpdateList = questionUsageCntUpdateList.stream().distinct().collect(Collectors.toList()); + for (Long questionId : questionUsageCntUpdateList) { + questionUsageCntUpdate(questionId); + } + } + } + } + + private void validExamRule(ResExamRuleVO examRule, List singleChoiceQuestionList, List multipleChoiceQuestionList, List judgmentalQuestionList) { + ExamRuleInfo judgmentalQuestionRule = examRule.getJudgmentalQuestionRule(); + ExamRuleInfo multipleChoiceQuestionRule = examRule.getMultipleChoiceQuestionRule(); + ExamRuleInfo singleChoiceQuestionRule = examRule.getSingleChoiceQuestionRule(); + int singleChoiceQuestionNum = singleChoiceQuestionList.size(); + int multipleChoiceQuestionNum = multipleChoiceQuestionList.size(); + int judgmentalQuestionNum = judgmentalQuestionList.size(); + if (singleChoiceQuestionNum != singleChoiceQuestionRule.getQuestionCnt() + || multipleChoiceQuestionNum != multipleChoiceQuestionRule.getQuestionCnt() + || judgmentalQuestionNum != judgmentalQuestionRule.getQuestionCnt()) { + throw new BizException("题目数量不正确,请按规定选择!"); + } + } + + /** + * questionId + * + * @param questionId + */ + public void questionUsageCntUpdate(Long questionId) { + PaperQuestion paperQuestion = iPaperQuestionService.getById(questionId); + if (Objects.isNull(paperQuestion)) { + return; + } else { + long usage = iExamPaperQuestionService.count(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getPaperQuestionId, questionId)); + paperQuestion.setUsageCnt(usage); + iPaperQuestionService.updateById(paperQuestion); + } + } + + + public ResExamPaperVO getExamPaperId(Long examPaperId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ExamPaper.class); + ExaminationPaperManage context = (ExaminationPaperManage) AopContext.currentProxy(); + context.buildQuery(wrapper, examPaperId); + ExamPaper examPaper = iExamPaperService.getOne(wrapper); + if (Objects.isNull(examPaper)) { + throw new BizException("未获取到考试试卷!"); + } + + // 判断是否可以考试 + LocalDateTime now = LocalDateTime.now(); + LocalDateTime examStartTime = examPaper.getExamStartTime(); + LocalDateTime examEndTime = examPaper.getExamEndTime(); + // 设置了考试时间 + if (Objects.nonNull(examStartTime) && Objects.nonNull(examEndTime)) { + String examStartStr = NdDateUtils.format(examStartTime, NdDateUtils.DEFAULT_DATE_FORMAT); + String examEndStr = NdDateUtils.format(examEndTime, NdDateUtils.DEFAULT_DATE_FORMAT); + if (now.compareTo(examStartTime) < 0){ + throw new BizException("当前培训考试未开始,考试时间为:" + examStartStr + StrPool.DASH + examEndStr); + } else if (now.compareTo(examEndTime) > 0) { + throw new BizException("当前培训考试已结束,考试时间为:" + examStartStr + StrPool.DASH + examEndStr); + } + } + + // 获取题目id 列表 + List examPaperQuestionList = iExamPaperQuestionService.list(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getExamPaperId, examPaperId)); + List paperQuestionIdList = examPaperQuestionList.stream().map(ExamPaperQuestion::getPaperQuestionId).collect(Collectors.toList()); + List paperQuestionList = iPaperQuestionService + .list(Wrappers.lambdaQuery(PaperQuestion.class).in(PaperQuestion::getId, paperQuestionIdList)); + + Map> groupByQuestionTypeList = paperQuestionList.stream().map(QuestionAssembler::buildResQuestionDetailVO) + .collect(Collectors.groupingBy(ResQuestionDetailVO::getQuestionType)); + + // 装配返回 + ResExamPaperVO resExamPaperVO = new ResExamPaperVO(); + resExamPaperVO.setExamPaperName(examPaper.getExamPaperName()); + resExamPaperVO.setResExamRuleVO(JSONObject.parseObject(examPaper.getExamRuleJson(), ResExamRuleVO.class)); + resExamPaperVO.setSingleChoiceQuestionList(groupByQuestionTypeList + .get(QuestionTypeEnum.SINGLE_CHOICE)); + resExamPaperVO.setMultipleChoiceQuestionList(groupByQuestionTypeList + .get(QuestionTypeEnum.MULTIPLE_CHOICE)); + resExamPaperVO.setJudgmentalQuestionList(groupByQuestionTypeList + .get(QuestionTypeEnum.JUDGMENTAL)); + return resExamPaperVO; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildQuery(LambdaQueryWrapper wrapper, Long examPaperId) { + wrapper.eq(ExamPaper::getId,examPaperId); + } + + + @Transactional(rollbackFor = Exception.class) + public void saveExamRule(ReqSaveExamRulePO request) { + // 判断 题目类型 总分是否为100 + ExamRuleInfo jr = request.getJudgmentalQuestionRule(); + ExamRuleInfo mr = request.getMultipleChoiceQuestionRule(); + ExamRuleInfo sr = request.getSingleChoiceQuestionRule(); + if (jr.getPerQuestionScore() * jr.getQuestionCnt() + + mr.getPerQuestionScore() * mr.getQuestionCnt() + + sr.getPerQuestionScore() * sr.getQuestionCnt() != 100) { + throw new BizException("试卷满分不为100分,请重新选择!"); + } + Long regionId = request.getRegionId(); + saveExamRule(sr, QuestionTypeEnum.SINGLE_CHOICE,regionId); + saveExamRule(mr, QuestionTypeEnum.MULTIPLE_CHOICE,regionId); + saveExamRule(jr, QuestionTypeEnum.JUDGMENTAL,regionId); + } + + public void saveExamRule(ExamRuleInfo examRuleInfo, QuestionTypeEnum questionTypeEnum, Long regionId) { + ExamRule examRule = iExamRuleService.getOne(Wrappers.lambdaQuery(ExamRule.class) + .eq(ExamRule::getRegionId,regionId) + .eq(ExamRule::getQuestionType, questionTypeEnum.name())); + if (Objects.isNull(examRule)) { + examRule = new ExamRule(); + examRule.setCreateOn(LocalDateTime.now()); + examRule.setCreateBy(LoginUserUtil.getUserId()); + } + examRule.setQuestionType(questionTypeEnum.name()); + examRule.setQuestionCnt(examRuleInfo.getQuestionCnt()); + examRule.setPerQuestionScore(examRuleInfo.getPerQuestionScore()); + examRule.setUpdateOn(LocalDateTime.now()); + examRule.setUpdateBy(LoginUserUtil.getUserId()); + examRule.setRegionId(regionId); + iExamRuleService.saveOrUpdate(examRule); + } + + public ResExamRuleVO getExamRule(ReqExamRulePO request) { + Long regionId = request.getRegionId(); + // 判断登录用户区域权限是否包含传入的区域 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + List childList = regionsCacheHelper.listChildRegionId(userDetail.getRegionId(), true, true); + // 传入的区域ID不在登录用户权限内,返回空 + if (!childList.contains(regionId)){ + return null; + } + ExamRuleInfo singleChoiceExamRule = getExamRule(QuestionTypeEnum.SINGLE_CHOICE,regionId); + ExamRuleInfo multipleChoiceExamRule = getExamRule(QuestionTypeEnum.MULTIPLE_CHOICE,regionId); + ExamRuleInfo judgmentalExamRule = getExamRule(QuestionTypeEnum.JUDGMENTAL,regionId); + + ResExamRuleVO resExamRuleVO = new ResExamRuleVO(); + resExamRuleVO.setSingleChoiceQuestionRule(singleChoiceExamRule); + resExamRuleVO.setMultipleChoiceQuestionRule(multipleChoiceExamRule); + resExamRuleVO.setJudgmentalQuestionRule(judgmentalExamRule); + return resExamRuleVO; + } + + public ExamRuleInfo getExamRule(QuestionTypeEnum questionTypeEnum,Long regionId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ExamRule.class); + wrapper.eq(ExamRule::getQuestionType, questionTypeEnum.name()); + wrapper.eq(ExamRule::getRegionId,regionId); + // 获取当前区域的试卷规则 + ExamRule examRule = iExamRuleService.getOne(wrapper); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + Integer regionLevel = regionDto.getRegionLevel(); + + // 如果登录用户所属区域没有设置试卷规则,则获取其上一级行政区域的规则 + // 如果是区县一级 + if (DefValConstants.QU_REGION_LEVEL.equals(regionLevel)) { + // 如果为空,获取市一级的试卷规则 + if (Objects.isNull(examRule)) { + Long parentRegionId = regionDto.getParentId(); + examRule = getRegionExamRule(questionTypeEnum,parentRegionId); + // 如果为空,获取省一级的试卷规则 + if (Objects.isNull(examRule)){ + examRule = getRegionExamRule(questionTypeEnum,DefValConstants.ZJREGION_ID); + } + } + } + // 如果是市一级 + else if (DefValConstants.CITY_REGION_LEVEL.equals(regionLevel)) { + // 如果为空,获取省一级的试卷规则 + if (Objects.isNull(examRule)){ + examRule = getRegionExamRule(questionTypeEnum,DefValConstants.ZJREGION_ID); + } + } + + ExamRuleInfo examRuleInfo = new ExamRuleInfo(); + if (Objects.nonNull(examRule)) { + examRuleInfo.setQuestionType(QuestionTypeEnum.valueOf(examRule.getQuestionType())); + examRuleInfo.setQuestionCnt(examRule.getQuestionCnt()); + examRuleInfo.setPerQuestionScore(examRule.getPerQuestionScore()); + } + return examRuleInfo; + } + + private ExamRule getRegionExamRule(QuestionTypeEnum questionTypeEnum,Long regionId) { + ExamRule examRule; + examRule = iExamRuleService.getOne(Wrappers.lambdaQuery(ExamRule.class) + .eq(ExamRule::getQuestionType, questionTypeEnum.name()) + .eq(ExamRule::getRegionId, regionId)); + return examRule; + } + + public PageVo listExamPaper(ReqExamPaperListPO request) { + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ExamPaper.class); + ExaminationPaperManage context = (ExaminationPaperManage) AopContext.currentProxy(); + context.buildExamPaperQuery(wrapper, request); + Page page = iExamPaperService.page(new Page<>(pageNumber, pageSize), wrapper); + + PageVo pageVo = new PageVo<>(); + long total = page.getTotal(); + pageVo.setTotal(total); + if (0 == total) { + pageVo.setRecords(new ArrayList<>()); + return pageVo; + } + List records = page.getRecords(); + List resVOList = records.stream().map(r -> { + ResExamPaperListVO resVO = new ResExamPaperListVO(); + resVO.setId(r.getId()); + resVO.setCreateTime(r.getCreateOn()); + resVO.setPaperName(r.getExamPaperName()); + if (Objects.nonNull(r.getRegionId())) { + resVO.setRegionId(r.getRegionId()); + resVO.setRegionName(regionsCacheHelper.getDisplayName(r.getRegionId())); + } + return resVO; + }).collect(Collectors.toList()); + pageVo.setRecords(resVOList); + return pageVo; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildExamPaperQuery(LambdaQueryWrapper wrapper, ReqExamPaperListPO request) { + // 获取入参 + String paperName = request.getPaperName(); + Long regionId = request.getRegionId(); + List regionIdList = new ArrayList<>(); + if (Objects.nonNull(regionId)) { + regionIdList = regionsCacheHelper.listChildRegionId(regionId); + } + wrapper.like(StringUtils.isNotBlank(paperName), ExamPaper::getExamPaperName, paperName) + .eq(ExamPaper::getIsRandom,IsRandomEnum.NOT_RANDOM_PAPER.getCode()) + .in(CollectionUtil.isNotEmpty(regionIdList), ExamPaper::getRegionId, regionIdList) + .orderByDesc(ExamPaper::getCreateOn); + } + + public void deleteExamPaper(Long id) { + iExamPaperService.removeById(id); + List examPaperQuestionList = iExamPaperQuestionService.list(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getExamPaperId, id)); + + if (CollectionUtil.isNotEmpty(examPaperQuestionList)) { + List questionUsageCntUpdateList = examPaperQuestionList.stream() + .map(ExamPaperQuestion::getPaperQuestionId).collect(Collectors.toList()); + for (Long questionId : questionUsageCntUpdateList) { + questionUsageCntUpdate(questionId); + } + iExamPaperQuestionService.remove(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getExamPaperId, id)); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/PaperQuestionManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/PaperQuestionManage.java new file mode 100644 index 0000000..b0c53a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/manage/PaperQuestionManage.java @@ -0,0 +1,215 @@ +package com.ningdatech.carapi.archives.manage; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.archives.assembler.QuestionAssembler; +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.ningdatech.carapi.archives.enums.PaperQuestionStatusEnum; +import com.ningdatech.carapi.archives.model.JudgmentalQuestionTextContent; +import com.ningdatech.carapi.archives.model.MultipleChoiceQuestionTextContent; +import com.ningdatech.carapi.archives.model.SingleChoiceQuestionTextContent; +import com.ningdatech.carapi.archives.model.po.ReqQuestionListPO; +import com.ningdatech.carapi.archives.model.po.ReqSaveNewQuestionPO; +import com.ningdatech.carapi.archives.model.vo.ResQuestionDetailVO; +import com.ningdatech.carapi.archives.model.vo.ResQuestionListVO; +import com.ningdatech.carapi.archives.service.IPaperQuestionService; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author liuxinxin + * @date 2022/10/11 下午4:28 + */ +@Component +@RequiredArgsConstructor +public class PaperQuestionManage { + + private final IPaperQuestionService iPaperQuestionService; + private final RegionsCacheHelper regionsCacheHelper; + private final UserInfoHelper userInfoHelper; + + public PageVo questionList(ReqQuestionListPO request) { + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PaperQuestion.class); + buildQuestionQuery(wrapper, request); + Page page = iPaperQuestionService.page(new Page<>(pageNumber, pageSize),wrapper); + List records = page.getRecords(); + long total = page.getTotal(); + + PageVo pageVo = new PageVo<>(); + pageVo.setTotal(total); + if (total == 0) { + return pageVo; + } + List resQuestionListVOList = records.stream().map(r -> { + ResQuestionListVO resQuestionListVO = new ResQuestionListVO(); + resQuestionListVO.setId(r.getId()); + resQuestionListVO.setQuestion(r.getStem()); + resQuestionListVO.setQuestionType(QuestionTypeEnum.valueOf(r.getQuestionType())); + resQuestionListVO.setUsageCnt(r.getUsageCnt()); + resQuestionListVO.setFormulationTime(r.getCreateOn()); + return resQuestionListVO; + }).collect(Collectors.toList()); + pageVo.setRecords(resQuestionListVOList); + return pageVo; + } + + //@LambdaDataScope + private void buildQuestionQuery(LambdaQueryWrapper wrapper, ReqQuestionListPO request) { + // 获取入参信息 + String question = request.getQuestion(); + QuestionTypeEnum questionType = request.getQuestionType(); + Long regionId = request.getRegionId(); + // 入参转换参数 + String questionTypeStr = Objects.isNull(questionType) ? null : questionType.name(); + List regionIdList = new ArrayList<>(); + if (Objects.nonNull(regionId)) { + regionIdList = regionsCacheHelper.listChildRegionId(regionId); + } + wrapper.eq(Objects.nonNull(questionType), PaperQuestion::getQuestionType, questionTypeStr) + .eq(PaperQuestion::getQuestionStatus, PaperQuestionStatusEnum.IN_USE.name()) + .in(CollectionUtil.isNotEmpty(regionIdList), PaperQuestion::getRegionId, regionIdList) + .like(StringUtils.isNotBlank(question), PaperQuestion::getQuestionTextContent, question); + } + + public ResQuestionDetailVO questionDetail(Long questionId) { + PaperQuestion paperQuestion = iPaperQuestionService.getById(questionId); + if (Objects.isNull(paperQuestion)) { + return null; + } + return QuestionAssembler.buildResQuestionDetailVO(paperQuestion); + } + + public void createNewQuestion(ReqSaveNewQuestionPO po) { + QuestionTypeEnum questionType = po.getQuestionType(); + PaperQuestion paperQuestion = new PaperQuestion(); + + String stem = po.getStem(); + String questionTextContent = null; + String correctJsonStr = null; + switch (questionType) { + case JUDGMENTAL: + JudgmentalQuestionTextContent judgmentalQuestionTextContent = new JudgmentalQuestionTextContent(); + judgmentalQuestionTextContent.setStem(stem); + judgmentalQuestionTextContent.setAnswer(po.getJudgmentalQuestionCorrectAnswer()); + questionTextContent = JSONObject.toJSONString(judgmentalQuestionTextContent); + correctJsonStr = JSONObject.toJSONString(po.getJudgmentalQuestionCorrectAnswer()); + break; + case SINGLE_CHOICE: + SingleChoiceQuestionTextContent singleChoiceQuestionTextContent = new SingleChoiceQuestionTextContent(); + singleChoiceQuestionTextContent.setStem(stem); + singleChoiceQuestionTextContent.setOptions(po.getOptions()); + singleChoiceQuestionTextContent.setAnswer(po.getChoiceQuestionCorrectAnswer().get(0)); + questionTextContent = JSONObject.toJSONString(singleChoiceQuestionTextContent); + correctJsonStr = JSONObject.toJSONString(po.getChoiceQuestionCorrectAnswer().get(0)); + + break; + case MULTIPLE_CHOICE: + MultipleChoiceQuestionTextContent multipleChoiceQuestionTextContent = new MultipleChoiceQuestionTextContent(); + multipleChoiceQuestionTextContent.setStem(stem); + multipleChoiceQuestionTextContent.setOptions(po.getOptions()); + multipleChoiceQuestionTextContent.setAnswer(po.getChoiceQuestionCorrectAnswer()); + questionTextContent = JSONObject.toJSONString(multipleChoiceQuestionTextContent); + correctJsonStr = JSONObject.toJSONString(po.getChoiceQuestionCorrectAnswer()); + break; + default: + break; + } + + paperQuestion.setCreateOn(LocalDateTime.now()); + paperQuestion.setUpdateOn(LocalDateTime.now()); + paperQuestion.setStem(stem); + paperQuestion.setCorrect(correctJsonStr); + paperQuestion.setQuestionStatus(PaperQuestionStatusEnum.IN_USE.name()); + paperQuestion.setQuestionTextContent(questionTextContent); + paperQuestion.setQuestionType(questionType.name()); + paperQuestion.setUsageCnt(0L); + paperQuestion.setRegionId(userInfoHelper.getUserRegionId()); + iPaperQuestionService.save(paperQuestion); + } + + public void saveQuestion(ReqSaveNewQuestionPO request) { + Long id = request.getId(); + if (Objects.nonNull(id)) { + PaperQuestion currentPaperQuestion = iPaperQuestionService.getById(id); + if (Objects.isNull(currentPaperQuestion)) { + throw new BizException("试题不存在"); + } + assemblerQuestionSaveRecord(currentPaperQuestion, request); + iPaperQuestionService.updateById(currentPaperQuestion); + + } else { + PaperQuestion paperQuestion = new PaperQuestion(); + assemblerQuestionSaveRecord(paperQuestion, request); + paperQuestion.setCreateOn(LocalDateTime.now()); + paperQuestion.setQuestionStatus(PaperQuestionStatusEnum.IN_USE.name()); + paperQuestion.setUsageCnt(0L); + paperQuestion.setRegionId(userInfoHelper.getUserRegionId()); + iPaperQuestionService.save(paperQuestion); + } + } + + private void assemblerQuestionSaveRecord(PaperQuestion saveRecord, ReqSaveNewQuestionPO request) { + QuestionTypeEnum questionType = request.getQuestionType(); + String stem = request.getStem(); + String questionTextContent = null; + String correctJsonStr = null; + switch (questionType) { + case JUDGMENTAL: + JudgmentalQuestionTextContent judgmentalQuestionTextContent = new JudgmentalQuestionTextContent(); + judgmentalQuestionTextContent.setStem(stem); + judgmentalQuestionTextContent.setAnswer(request.getJudgmentalQuestionCorrectAnswer()); + questionTextContent = JSONObject.toJSONString(judgmentalQuestionTextContent); + correctJsonStr = JSONObject.toJSONString(request.getJudgmentalQuestionCorrectAnswer()); + break; + case SINGLE_CHOICE: + SingleChoiceQuestionTextContent singleChoiceQuestionTextContent = new SingleChoiceQuestionTextContent(); + singleChoiceQuestionTextContent.setStem(stem); + singleChoiceQuestionTextContent.setOptions(request.getOptions()); + singleChoiceQuestionTextContent.setAnswer(request.getChoiceQuestionCorrectAnswer().get(0)); + questionTextContent = JSONObject.toJSONString(singleChoiceQuestionTextContent); + correctJsonStr = JSONObject.toJSONString(request.getChoiceQuestionCorrectAnswer().get(0)); + + break; + case MULTIPLE_CHOICE: + MultipleChoiceQuestionTextContent multipleChoiceQuestionTextContent = new MultipleChoiceQuestionTextContent(); + multipleChoiceQuestionTextContent.setStem(stem); + multipleChoiceQuestionTextContent.setOptions(request.getOptions()); + multipleChoiceQuestionTextContent.setAnswer(request.getChoiceQuestionCorrectAnswer()); + questionTextContent = JSONObject.toJSONString(multipleChoiceQuestionTextContent); + correctJsonStr = JSONObject.toJSONString(request.getChoiceQuestionCorrectAnswer()); + break; + default: + break; + } + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setStem(stem); + saveRecord.setCorrect(correctJsonStr); + saveRecord.setQuestionTextContent(questionTextContent); + saveRecord.setQuestionType(questionType.name()); + } + + public void deleteQuestion(Long id) { + PaperQuestion paperQuestion = iPaperQuestionService.getById(id); + if (paperQuestion.getUsageCnt() > 0) { + throw new BizException("试题已被使用无法删除"); + } + iPaperQuestionService.removeById(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.java new file mode 100644 index 0000000..f49cdd0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.archives.mapper; + +import com.ningdatech.carapi.archives.entity.ExamPaper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +public interface ExamPaperMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.xml new file mode 100644 index 0000000..7fcaeb8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.java new file mode 100644 index 0000000..3efc6f5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.archives.mapper; + +import com.ningdatech.carapi.archives.entity.ExamPaperQuestion; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +public interface ExamPaperQuestionMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.xml new file mode 100644 index 0000000..516dc51 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/ExamPaperQuestionMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.java new file mode 100644 index 0000000..7bf8300 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.archives.mapper; + +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-11 + */ +public interface NdPaperQuestionMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.xml new file mode 100644 index 0000000..70c431b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/mapper/NdPaperQuestionMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ExamRuleInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ExamRuleInfo.java new file mode 100644 index 0000000..81f6f24 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ExamRuleInfo.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.archives.model; + +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/22 下午2:33 + */ +@ApiModel("试卷规则") +@Data +public class ExamRuleInfo { + + @ApiModelProperty("每题分数") + private Integer perQuestionScore; + + @ApiModelProperty(value = "题目类型", allowableValues = "SINGLE_CHOICE 单项选择题" + + ",MULTIPLE_CHOICE 多项选择题 ,JUDGMENTAL 判断题") + @NotNull(message = "题目类型 不能为空") + private QuestionTypeEnum questionType; + + @ApiModelProperty("题目需要数量") + private Integer questionCnt; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/JudgmentalQuestionTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/JudgmentalQuestionTextContent.java new file mode 100644 index 0000000..c49000a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/JudgmentalQuestionTextContent.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.archives.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/17 下午3:00 + */ +@Data +@ApiModel("判断题题目 填空、 题干、解析、答案等信息") +public class JudgmentalQuestionTextContent { + + @ApiModelProperty("题目") + private String stem; + + @ApiModelProperty("答案") + private Boolean answer; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/MultipleChoiceQuestionTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/MultipleChoiceQuestionTextContent.java new file mode 100644 index 0000000..f8185b6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/MultipleChoiceQuestionTextContent.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.archives.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/17 下午3:00 + */ +@Data +@ApiModel("多选题题目 填空、 题干、解析、答案等信息") +public class MultipleChoiceQuestionTextContent { + + @ApiModelProperty("题目") + private String stem; + + @ApiModelProperty("选项") + private List options; + + @ApiModelProperty("答案") + private List answer; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ShortAnswerQuestionTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ShortAnswerQuestionTextContent.java new file mode 100644 index 0000000..71f8eda --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/ShortAnswerQuestionTextContent.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.archives.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/17 下午2:55 + */ +@Data +@ApiModel("简答题题目 填空、 题干、解析、答案等信息") +public class ShortAnswerQuestionTextContent { + @ApiModelProperty("题目") + private String stem; + + @ApiModelProperty("答案") + private String answer; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/SingleChoiceQuestionTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/SingleChoiceQuestionTextContent.java new file mode 100644 index 0000000..71246fe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/SingleChoiceQuestionTextContent.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.archives.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/17 下午3:00 + */ +@Data +@ApiModel("单选题题目 填空、 题干、解析、答案等信息") +public class SingleChoiceQuestionTextContent { + + @ApiModelProperty("题目") + private String stem; + + @ApiModelProperty("选项") + private List options; + + @ApiModelProperty("答案") + private String answer; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamPaperListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamPaperListPO.java new file mode 100644 index 0000000..c53fe97 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamPaperListPO.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.archives.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/22 下午5:21 + */ +@Data +@ApiModel("培训试卷列表请求PO") +public class ReqExamPaperListPO extends PagePo { + + @ApiModelProperty("试卷名称") + private String paperName; + + @ApiModelProperty("所属区域id") + private Long regionId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamRulePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamRulePO.java new file mode 100644 index 0000000..ed61b8f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqExamRulePO.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.archives.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/22 下午2:32 + */ +@Data +@ApiModel("保存试卷规则") +public class ReqExamRulePO { + + @ApiModelProperty("区域ID") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqQuestionListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqQuestionListPO.java new file mode 100644 index 0000000..b103b5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqQuestionListPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.archives.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/11 下午4:30 + */ +@Data +@ApiModel(description = "培训题库列表查询入参") +public class ReqQuestionListPO extends PagePo { + @ApiModelProperty("题目") + private String question; + + @ApiModelProperty("试题类型") + private QuestionTypeEnum questionType; + + @ApiModelProperty("区域id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamPaperPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamPaperPO.java new file mode 100644 index 0000000..892d2f4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamPaperPO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.archives.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/17 下午4:31 + */ + +@Data +@ApiModel(description = "新增试卷PO") +public class ReqSaveExamPaperPO { + + private Long id; + + @ApiModelProperty("试卷名称") + @NotBlank + private String examPaperName; + + @ApiModelProperty("单选题列表") + List singleChoiceQuestionList; + + @ApiModelProperty("多项选择题列表") + List multipleChoiceQuestionList; + + @ApiModelProperty("判断题列表") + List judgmentalQuestionList; + + @Data + @ApiModel + public static class ExamPaperQuestionIdPO { + + @ApiModelProperty("题目id") + private Long paperQuestionId; + + @ApiModelProperty("题目排序值 按从小到大排序") + private Long sortValue; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamRulePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamRulePO.java new file mode 100644 index 0000000..123bbc8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveExamRulePO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.archives.model.po; + +import com.ningdatech.carapi.archives.model.ExamRuleInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/22 下午2:32 + */ +@Data +@ApiModel("保存试卷规则") +public class ReqSaveExamRulePO { + + @ApiModelProperty("单项选择题 规则") + private ExamRuleInfo singleChoiceQuestionRule; + + @ApiModelProperty("多项选择题 规则") + private ExamRuleInfo multipleChoiceQuestionRule; + + @ApiModelProperty("判断题 规则") + private ExamRuleInfo judgmentalQuestionRule; + + @ApiModelProperty("区域ID") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveNewQuestionPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveNewQuestionPO.java new file mode 100644 index 0000000..77e4cce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/po/ReqSaveNewQuestionPO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.archives.model.po; + +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/17 下午2:26 + */ +@Data +@ApiModel("创建新试题PO") +public class ReqSaveNewQuestionPO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty(value = "题目类型", allowableValues = "SINGLE_CHOICE 单项选择题" + + ",MULTIPLE_CHOICE 多项选择题 ,JUDGMENTAL 判断题") + @NotNull(message = "题目类型 不能为空") + private QuestionTypeEnum questionType; + + @ApiModelProperty("题目内容") + @NotBlank(message = "题目内容不能为空") + private String stem; + + @ApiModelProperty("选择题选项") + private List options; + + @ApiModelProperty("选择题正确答案") + private List choiceQuestionCorrectAnswer; + + @ApiModelProperty("判断题正确答案") + private Boolean judgmentalQuestionCorrectAnswer; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperListVO.java new file mode 100644 index 0000000..87cc8c7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperListVO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.archives.model.vo; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/22 下午5:21 + */ +@Data +@ApiModel("培训试卷列表VO") +public class ResExamPaperListVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("试卷名称") + private String paperName; + + @ApiModelProperty("所属区域id") + private Long regionId; + + @ApiModelProperty("所属区域") + private String regionName; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperVO.java new file mode 100644 index 0000000..b14574d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamPaperVO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.archives.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/18 上午11:08 + */ +@Data +@ApiOperation("试卷") +public class ResExamPaperVO { + + @ApiModelProperty("试卷规则") + private ResExamRuleVO resExamRuleVO; + + @ApiModelProperty("试卷名称") + @NotBlank + private String examPaperName; + + @ApiModelProperty("单选题列表") + List singleChoiceQuestionList; + + @ApiModelProperty("多项选择题列表") + List multipleChoiceQuestionList; + + @ApiModelProperty("判断题列表") + List judgmentalQuestionList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamRuleVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamRuleVO.java new file mode 100644 index 0000000..fc2e8d2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResExamRuleVO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.archives.model.vo; + +import com.ningdatech.carapi.archives.model.ExamRuleInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/22 下午2:50 + */ +@ApiModel("试卷规则") +@Data +public class ResExamRuleVO { + + @ApiModelProperty("单项选择题 规则") + private ExamRuleInfo singleChoiceQuestionRule; + + @ApiModelProperty("多项选择题 规则") + private ExamRuleInfo multipleChoiceQuestionRule; + + @ApiModelProperty("判断题 规则") + private ExamRuleInfo judgmentalQuestionRule; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionDetailVO.java new file mode 100644 index 0000000..62cd7b2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionDetailVO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.archives.model.vo; + +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/11 下午5:54 + */ +@Data +@ApiModel(description = "培训题详情VO") +public class ResQuestionDetailVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("题目类型") + private QuestionTypeEnum questionType; + + @ApiModelProperty("题干") + private String stem; + + @ApiModelProperty("选择题选项") + private List options; + + @ApiModelProperty("选择题正确答案") + private List choiceQuestionCorrectAnswer; + + @ApiModelProperty("判断题正确答案") + private Boolean judgmentalQuestionCorrectAnswer; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionListVO.java new file mode 100644 index 0000000..6499456 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/model/vo/ResQuestionListVO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.archives.model.vo; + +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/11 下午4:30 + */ +@Data +@ApiModel(description = "培训题库列表VO") +public class ResQuestionListVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("题目") + private String question; + + @ApiModelProperty("试题类型") + private QuestionTypeEnum questionType; + + @ApiModelProperty("选择次数") + private Long usageCnt; + + @ApiModelProperty("制定时间") + private LocalDateTime formulationTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperQuestionService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperQuestionService.java new file mode 100644 index 0000000..a277b2f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperQuestionService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.archives.service; + +import com.ningdatech.carapi.archives.entity.ExamPaperQuestion; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +public interface IExamPaperQuestionService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperService.java new file mode 100644 index 0000000..8871e90 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IExamPaperService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.archives.service; + +import com.ningdatech.carapi.archives.entity.ExamPaper; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +public interface IExamPaperService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IPaperQuestionService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IPaperQuestionService.java new file mode 100644 index 0000000..037c678 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/IPaperQuestionService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.archives.service; + +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-11 + */ +public interface IPaperQuestionService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperQuestionServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperQuestionServiceImpl.java new file mode 100644 index 0000000..e0de2c1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperQuestionServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.archives.service.impl; + +import com.ningdatech.carapi.archives.entity.ExamPaperQuestion; +import com.ningdatech.carapi.archives.mapper.ExamPaperQuestionMapper; +import com.ningdatech.carapi.archives.service.IExamPaperQuestionService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +@Service +public class ExamPaperQuestionServiceImpl extends ServiceImpl implements IExamPaperQuestionService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperServiceImpl.java new file mode 100644 index 0000000..b7580db --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/ExamPaperServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.archives.service.impl; + +import com.ningdatech.carapi.archives.entity.ExamPaper; +import com.ningdatech.carapi.archives.mapper.ExamPaperMapper; +import com.ningdatech.carapi.archives.service.IExamPaperService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-17 + */ +@Service +public class ExamPaperServiceImpl extends ServiceImpl implements IExamPaperService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/NdIPaperQuestionServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/NdIPaperQuestionServiceImpl.java new file mode 100644 index 0000000..34e322a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/archives/service/impl/NdIPaperQuestionServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.archives.service.impl; + +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.ningdatech.carapi.archives.mapper.NdPaperQuestionMapper; +import com.ningdatech.carapi.archives.service.IPaperQuestionService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-11 + */ +@Service +public class NdIPaperQuestionServiceImpl extends ServiceImpl implements IPaperQuestionService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/contants/DigitalCockpitContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/contants/DigitalCockpitContant.java new file mode 100644 index 0000000..f8ccf29 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/contants/DigitalCockpitContant.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.datascreen.contants; + +/** + * @Classname DigitalCockpitContant + * @Description + * @Date 2022/11/17 9:10 + * @Created by PoffyZhang + */ +public interface DigitalCockpitContant { + + public static final String FIELD_DAILY_OVERSPEED = "digital-cockpit:daily-overspeed-times"; + + public static final String FIELD_MONTHLY_VIOLATION = "digital-cockpit:monthly-violation-times"; + + public static final String FIELD_YEARLY_OUTDANGER = "digital-cockpit:yearly-outdanger-times"; + + public static final String FIELD_YEARLY_INJURIES = "digital-cockpit:yearly-injuries"; + + public static final String FIELD_YEARLY_DEATHTOLL = "digital-cockpit:yearly-deathToll"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/DigitalCockpitController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/DigitalCockpitController.java new file mode 100644 index 0000000..75a8653 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/DigitalCockpitController.java @@ -0,0 +1,166 @@ +package com.ningdatech.carapi.car.datascreen.controller; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.car.datascreen.manage.DigitalCockpitManage; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.vo.StatisticsCenterVO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 数字驾驶舱 + *

+ * + * @author PoffyZhang + * @since 2022-10-22 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/v1/digital-cockpit") +@Api(value = "digital-cockpit", tags = "数字驾驶舱") +@RequiredArgsConstructor +public class DigitalCockpitController { + + private final DigitalCockpitManage digitalCockpitManage; + + private static final Integer OUT_DANGER = 1; + private static final Integer INJURIES = 2; + private static final Integer DEATH_TOLL = 3; + + @ApiOperation(value = "大屏中间统计数字", notes = "大屏中间统计数字") + @GetMapping("/statistics-center") + public StatisticsCenterVO statisticsCenter(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.statisticsCenter(param); + } + + @ApiOperation(value = "车辆gps点分布", notes = "车辆gps点分布") + @GetMapping("/gps") + public List getVehicleGps(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.getVehicleGps(param); + } + + @ApiOperation(value = "车辆超速次数", notes = "车辆超速次数") + @GetMapping("/overspeed-group") + public List overspeedGroup(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.overspeedGroup(param); + } + + @ApiOperation(value = "车辆违章次数", notes = "车辆违章次数") + @GetMapping("/violation-group") + public List violationGroup(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.violationGroup(param); + } + + @ApiOperation(value = "车辆出险次数", notes = "车辆出险次数") + @GetMapping("/outDanger-group") + public List outDangerGroup(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.outDangerGroup(param); + } + + @ApiOperation(value = "车辆受伤人数", notes = "车辆受伤人数") + @GetMapping("/injuries-group") + public List injuriesGroup(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.injuriesGroup(param); + } + + @ApiOperation(value = "车辆死亡人数", notes = "车辆死亡人数") + @GetMapping("/death-group") + public List deathGroup(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.deathGroup(param); + } + + @ApiOperation(value = "万车死亡人数", notes = "万车死亡人数") + @GetMapping("/death-group-ten-thousand") + public List deathGroupTenThousand(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.deathGroupTenThousand(param); + } + + @ApiOperation(value = "上线率分析", notes = "上线率分析") + @GetMapping("/online-analysis") + public JSONObject onlineAnalysis(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.onlineAnalysis(param); + } + + @ApiOperation(value = "超速分析", notes = "超速分析") + @GetMapping("/overspeed-analysis") + public JSONObject overspeedAnalysis(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.overspeedAnalysis(param); + } + + @ApiOperation(value = "全省月度超速对比", notes = "全省月度超速对比") + @GetMapping("/monthly-overspeed-analysis") + public JSONObject monthlyOverspeedAnalysis(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.monthlyOverspeedAnalysis(param); + } + + @ApiOperation(value = "全省月度出险对比", notes = "全省月度出险对比") + @GetMapping("/monthly-out-danger-analysis") + public JSONObject monthlyOutDangerAnalysis(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setType(OUT_DANGER); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.getInsureAnalysis(param,OUT_DANGER); + } + + @ApiOperation(value = "全省月度受伤人数对比", notes = "全省月度受伤人数对比") + @GetMapping("/monthly-injuries-analysis") + public JSONObject monthlyInjuriesAnalysis(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setType(INJURIES); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.getInsureAnalysis(param,INJURIES); + } + + @ApiOperation(value = "全省月度死亡人数对比", notes = "全省月度死亡人数对比") + @GetMapping("/monthly-death-analysis") + public JSONObject monthlyDeathAnalysis(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + param.setType(DEATH_TOLL); + param.setOperatorId(LoginUserUtil.getUserId()); + return digitalCockpitManage.getInsureAnalysis(param,DEATH_TOLL); + } + + @ApiOperation(value = "清缓存", notes = "清缓存") + @PostMapping("/remove-cache") + public String removeCache(@RequestParam(required = false) String cacheName) { + return digitalCockpitManage.removeCache(cacheName); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/VehicleManageDataScreenController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/VehicleManageDataScreenController.java new file mode 100644 index 0000000..198e2ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/controller/VehicleManageDataScreenController.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.car.datascreen.controller; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.vo.*; +import com.ningdatech.carapi.car.datascreen.service.VehicleStatisticsService; +import com.ningdatech.carapi.common.util.CodeUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-22 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/vehicle/data-screen") +@Api(value = "vehicle", tags = "车辆管理-大屏") +@RequiredArgsConstructor +public class VehicleManageDataScreenController { + + private final VehicleStatisticsService vehicleStatisticsService; + + @ApiOperation(value = "车辆类型分布", notes = "车辆类型分布") + @GetMapping("/vehicle-types") + public List vehicleTypes(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return vehicleStatisticsService.getVehicleTypesStatistics(param); + } + + @ApiOperation(value = "各区域车辆分布", notes = "各区域车辆分布") + @GetMapping("/region") + public List regionDistribution(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return vehicleStatisticsService.getRegionDistribution(param); + } + + @ApiOperation(value = "保险机构出险分布", notes = "保险机构出险分布") + @GetMapping("/insure") + public List insureDistribution(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return vehicleStatisticsService.getInsureDistribution(param); + } + + @ApiOperation(value = "运营商机构分布", notes = "运营商机构分布") + @GetMapping("/operator") + public List operatorDistribution(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return vehicleStatisticsService.getOperatorDistribution(param); + } + + @ApiOperation(value = "车辆使用年限分布", notes = "车辆使用年限分布") + @GetMapping("/useful-life") + public List usefulLiftDistribution(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return vehicleStatisticsService.getUsefulLiftDistribution(param); + } + + @ApiOperation(value = "新增车辆数走势图", notes = "新增车辆数走势图") + @GetMapping("/year") + public List newVehicleNum(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return vehicleStatisticsService.getNewVehicleNum(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/manage/DigitalCockpitManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/manage/DigitalCockpitManage.java new file mode 100644 index 0000000..fb2d47a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/manage/DigitalCockpitManage.java @@ -0,0 +1,659 @@ +package com.ningdatech.carapi.car.datascreen.manage; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.TemporalAdjusters; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OnlineVehicleRegionsPO; +import com.ningdatech.carapi.car.datascreen.model.po.OnlineVehicleTimesPO; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import com.ningdatech.carapi.car.datascreen.model.vo.StatisticsCenterVO; +import com.ningdatech.carapi.car.datascreen.service.VehicleStatisticsService; +import com.ningdatech.carapi.car.position.manage.PositionMonitorManage; +import com.ningdatech.carapi.car.position.model.po.ReqRealTimeMonitorPO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.model.KeyValueDTO; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo; +import com.ningdatech.carapi.safe.model.po.OutDangerAnalysisPO; +import com.ningdatech.carapi.safe.model.po.OverspeedAnalysisPO; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerService; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; +import com.ningdatech.carapi.safe.service.IVehicleOverspeedInfoService; +import com.ningdatech.carapi.safe.service.SecurityManageDataScreenService; +import com.ningdatech.carapi.safe.utils.InitDataUtil; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.NumberUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname DigitalCockpitManage + * @Description + * @Date 2022/11/17 9:01 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class DigitalCockpitManage { + + private final CachePlusOps cachePlusOps; + + private final IVehicleOverspeedInfoService vehicleOverspeedInfoService; + + private final INdVehicleViolationService vehicleViolationService; + private final INdInsureOutDangerService insureOutDangerService; + + private final RegionsCacheHelper regionsCacheHelper; + + private final PositionMonitorManage positionMonitorManage; + private final CompanyService companyService; + + private final VehicleStatisticsService vehicleStatisticsService; + + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final SecurityManageDataScreenService securityManageDataScreenService; + + /** + * 大屏中间统计数字 + * + * @param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:statisticsCenter",key = "#param.regionId+'-'+#param.operatorId") + public StatisticsCenterVO statisticsCenter(DataScreenParam param) { + + List regionIds = null; + if (Objects.nonNull(param.getRegionId())) { + regionIds = regionsCacheHelper.listChildRegionId(param.getRegionId()); + } + + // 日超速总数 + LocalDateTime todayStart = + NdDateUtils.getStartTime(NdDateUtils.format(LocalDateTime.now(), DatePattern.NORM_DATE_PATTERN)); + LocalDateTime todayEnd = + NdDateUtils.getEndTime(NdDateUtils.format(LocalDateTime.now(), DatePattern.NORM_DATE_PATTERN)); + Long dailyOverspeeds = vehicleOverspeedInfoService.countStatistics(regionIds, todayStart, todayEnd); + + // 月违章 + LocalDateTime monthStart = + NdDateUtils.getStartTime(NdDateUtils.format(LocalDateTime.now().minusMonths(1), DatePattern.NORM_MONTH_PATTERN)); + LocalDateTime monthEnd = + NdDateUtils.getEndTime(NdDateUtils.format(LocalDateTime.now().minusMonths(1), DatePattern.NORM_MONTH_PATTERN)); + Long monthlyViolation = vehicleViolationService.countStatistics(regionIds, monthStart, monthEnd); + + LocalDateTime yearStart = getYearStartTime(); + LocalDateTime yearEnd = getYearEndTime(); + // 年出险 受伤 死亡 + List statistics = insureOutDangerService.statistics(regionIds, yearStart, yearEnd); + Long yearlyOutdanger = statistics.stream().count(); + Long yearlyInjuries = statistics.stream().mapToLong(NdInsureOutDanger::getInjuries).sum(); + Long yearlyDeathToll = statistics.stream().mapToLong(NdInsureOutDanger::getDeathToll).sum(); + return StatisticsCenterVO.of(dailyOverspeeds, monthlyViolation, yearlyOutdanger, yearlyInjuries, + yearlyDeathToll); + } + + /** + * 获取GPS列表 根据区域id + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:getVehicleGps",key = "#param.regionId+'-'+#param.operatorId") + public List getVehicleGps(DataScreenParam param) { + List companyIds = companyService.findCompanyIdsByRegionId(param); + + ReqRealTimeMonitorPO po = new ReqRealTimeMonitorPO(companyIds); + + return positionMonitorManage.realTimeMonitorVehicleGisList(po); + } + + /** + * 超速次数 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:overspeedGroup",key = "#param.regionId+'-'+#param.operatorId") + public List overspeedGroup(DataScreenParam param) { + List mapDatas = vehicleStatisticsService.getOverspeedRegions(param); + if (CollUtil.isEmpty(mapDatas)) { + return Collections.emptyList(); + } + List list = mapDatas.stream().map(d -> { + MapDataVO vo = new MapDataVO(); + BeanUtils.copyProperties(d, vo); + return vo; + }).collect(Collectors.toList()); + CodeUtil.complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 违章次数 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:violationGroup",key = "#param.regionId+'-'+#param.operatorId") + public List violationGroup(DataScreenParam param) { + List mapDatas = vehicleStatisticsService.getViolationRegions(param); + if (CollUtil.isEmpty(mapDatas)) { + return Collections.emptyList(); + } + List list = mapDatas.stream().map(d -> { + MapDataVO vo = new MapDataVO(); + BeanUtils.copyProperties(d, vo); + return vo; + }).collect(Collectors.toList()); + CodeUtil.complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 出险次数计算 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:outDangerGroup",key = "#param.regionId+'-'+#param.operatorId") + public List outDangerGroup(DataScreenParam param) { + List mapDatas = vehicleStatisticsService.getOutDangerRegions(param); + if (CollUtil.isEmpty(mapDatas)) { + return Collections.emptyList(); + } + List list = mapDatas.stream().map(d -> { + MapDataVO vo = new MapDataVO(); + BeanUtils.copyProperties(d, vo); + return vo; + }).collect(Collectors.toList()); + CodeUtil.complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 受伤人数 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:injuriesGroup",key = "#param.regionId+'-'+#param.operatorId") + public List injuriesGroup(DataScreenParam param) { + List mapDatas = vehicleStatisticsService.getInjuriesRegion(param); + if (CollUtil.isEmpty(mapDatas)) { + return Collections.emptyList(); + } + List list = mapDatas.stream().map(d -> { + MapDataVO vo = new MapDataVO(); + BeanUtils.copyProperties(d, vo); + return vo; + }).collect(Collectors.toList()); + CodeUtil.complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 死亡人数 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:deathGroup",key = "#param.regionId+'-'+#param.operatorId") + public List deathGroup(DataScreenParam param) { + List mapDatas = vehicleStatisticsService.getDeathRegion(param); + if (CollUtil.isEmpty(mapDatas)) { + return Collections.emptyList(); + } + List list = mapDatas.stream().map(d -> { + MapDataVO vo = new MapDataVO(); + BeanUtils.copyProperties(d, vo); + return vo; + }).collect(Collectors.toList()); + CodeUtil.complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 万车死亡人数 + * + * @param param + * @return + */ + @Cacheable(cacheNames = "cockpit:deathGroupTenThousand",key = "#param.regionId+'-'+#param.operatorId") + public List deathGroupTenThousand(DataScreenParam param) { + List mapDatas = vehicleStatisticsService.getDeathRegion(param); + List> carCntByRegion = vehicleStatisticsService.getVehicleNumsGroupByRegion(param); + Map carCntMap = CollUtils.listToMap(carCntByRegion, KeyValueDTO::getKey, KeyValueDTO::getValue); + if (CollUtil.isEmpty(mapDatas)) { + return Collections.emptyList(); + } + List list = mapDatas.stream().map(d -> { + MapDataVO vo = new MapDataVO(); + BeanUtils.copyProperties(d, vo); + Long carCnt = carCntMap.getOrDefault(d.getRegionId(), 0L); + if (carCnt == 0) { + vo.setPercent("0"); + } else { + BigDecimal percent = NumberUtil.div(vo.getValue(), carCnt).multiply(BigDecimal.valueOf(10000)) + .setScale(0, RoundingMode.UP); + vo.setPercent(percent.stripTrailingZeros().toPlainString()); + } + return vo; + }).collect(Collectors.toList()); + CodeUtil.complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 上线率分析 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:onlineAnalysis",key = "#param.regionId+'-'+#param.operatorId") + public JSONObject onlineAnalysis(DataScreenParam param) { + JSONObject res = new JSONObject(); + JSONObject timeOnlineData = genericOnlineData(param); + List regionOnlineVehicleNums = vehicleStatisticsService.getVehicleOnlineRegions(param); + CodeUtil.complementaryRegions(regionOnlineVehicleNums, param.getRegionId()); + return convertOnlineJson(regionOnlineVehicleNums, timeOnlineData, res); + } + + /** + * 超速占比分析图 + * + * @param param + * @return + */ + @XmlDataScope + @Cacheable(cacheNames = "cockpit:overspeedAnalysis",key = "#param.regionId+'-'+#param.operatorId") + public JSONObject overspeedAnalysis(DataScreenParam param) { + JSONObject res = new JSONObject(); + // 查询今日 + param.setStartTime(LocalDateTimeUtil.beginOfDay(LocalDateTime.now())); + param.setEndTime(LocalDateTimeUtil.endOfDay(LocalDateTime.now())); + + // List mapDatas = vehicleStatisticsService.getOverspeedRegions(param); + + List mapDatas = Lists.newArrayList(); + + List regionIds = null; + if (Objects.nonNull(param.getRegionId())) { + regionIds = regionsCacheHelper.listChildRegionId(param.getRegionId()); + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleOverspeedInfo.class); + DigitalCockpitManage contex = (DigitalCockpitManage)AopContext.currentProxy(); + contex.dataScopeCount(wrapper, regionIds, param.getStartTime(), param.getEndTime()); + List overspeedInfos = vehicleOverspeedInfoService.list(wrapper); + + // 根据车辆类型,过滤出真实超速的 + Map baseInfoMap = + vehicleBaseInfoService.list().stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + List overspeedInfoList = overspeedInfos.stream().filter(v -> { + NdVehicleBaseInfo baseInfo = baseInfoMap.get(v.getCarPlate()); + if (Objects.nonNull(baseInfo)) { + if (Boolean.TRUE.equals(checkIsOverSpeed(v, baseInfo))) { + return true; + } + } + return false; + }).collect(Collectors.toList()); + + RegionDTO regionDto = regionsCacheHelper.getByRegionId(param.getRegionId()); + List regionIdList = Lists.newArrayList(); + // 传入区域为浙江省,筛选出市级(不包含市本级) + if (regionIds.size() > 1 && regionDto.getParentId().equals(0L)) { + + regionIdList = regionsCacheHelper.listChildOnly(param.getRegionId()).stream().map(RegionDTO::getId) + .collect(Collectors.toList()); + + for (Long id : regionIdList) { + MapDataPO po = new MapDataPO(); + po.setRegionId(id); + RegionDTO dto = regionsCacheHelper.getByRegionId(id); + String regionCode = dto.getRegionCode(); + po.setRegionCode(regionCode); + po.setRegionName(dto.getRegionName()); + List infos = overspeedInfoList.stream().filter(c -> { + Long regionId = c.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + if (regionDTO.getParentId().equals(id)) { + return true; + } + return false; + }).collect(Collectors.toList()); + po.setValue(infos.size()); + mapDatas.add(po); + } + complementaryRegion(mapDatas, param.getRegionId()); + return convertAnalysisJson(mapDatas, res); + } + // 传入区域为市级 + else if (regionIds.size() > 1 && regionDto.getParentId().equals(116L)) { + regionIdList = regionsCacheHelper.listChildOnly(param.getRegionId()).stream().map(RegionDTO::getId) + .collect(Collectors.toList()); + for (Long id : regionIdList) { + MapDataPO po = new MapDataPO(); + po.setRegionId(id); + RegionDTO dto = regionsCacheHelper.getByRegionId(id); + String regionCode = dto.getRegionCode(); + po.setRegionCode(regionCode); + po.setRegionName(dto.getRegionName()); + List infos = overspeedInfoList.stream().filter(c -> { + Long regionId = c.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + if (regionDTO.getId().equals(id)) { + return true; + } + return false; + }).collect(Collectors.toList()); + po.setValue(infos.size()); + mapDatas.add(po); + } + complementaryRegion(mapDatas, param.getRegionId()); + return convertAnalysisJson(mapDatas, res); + } + // 传入区域为区县 + else { + MapDataPO po = new MapDataPO(); + po.setRegionId(param.getRegionId()); + RegionDTO dto = regionsCacheHelper.getByRegionId(param.getRegionId()); + String regionCode = dto.getRegionCode(); + po.setRegionCode(regionCode); + po.setRegionName(dto.getRegionName()); + List infos = overspeedInfoList.stream() + .filter(c -> c.getRegionId().equals(param.getRegionId())).collect(Collectors.toList()); + po.setValue(infos.size()); + mapDatas.add(po); + return convertAnalysisJson(mapDatas, res); + } + + } + + @LambdaDataScope + public void dataScopeCount(LambdaQueryWrapper wrapper, List regionIds, + LocalDateTime startTime, LocalDateTime endTime) { + wrapper.in(CollUtil.isNotEmpty(regionIds), VehicleOverspeedInfo::getRegionId, regionIds) + .ge(VehicleOverspeedInfo::getOverspeedDate, startTime).le(VehicleOverspeedInfo::getOverspeedDate, endTime); + } + + private void complementaryRegion(List mapDatas, Long regionId) { + Map dataMap = CollUtils.listToMap(mapDatas, MapDataPO::getRegionId); + List regions = regionsCacheHelper.listChildOnly(regionId, true); + List tmpList = new ArrayList<>(); + regions.forEach(w -> { + MapDataPO odc = dataMap.get(w.getId()); + if (odc == null) { + odc = new MapDataPO(); + odc.setRegionId(w.getId()); + odc.setRegionName(w.getRegionName()); + odc.setRegionName(w.getRegionName()); + odc.setRegionCode(w.getRegionCode()); + odc.setValue(0); + odc.setPercent("0"); + } + tmpList.add(odc); + }); + mapDatas.clear(); + mapDatas.addAll(tmpList); + } + + /** + * 月度 超速 对比 + * + * @param param + * @return + */ + @XmlDataScope + @BuildChildrenRegionEntity + @Cacheable(cacheNames = "cockpit:monthlyOverspeedAnalysis",key = "#param.regionId+'-'+#param.operatorId") + public JSONObject monthlyOverspeedAnalysis(DataScreenParam param) { + List times = securityManageDataScreenService.getOverspeedAnalysis(param); + return convertOverspeed(times); + } + + /** + * 出险相关统计 月份 + * + * @param param + * @param type + * @return + */ + @XmlDataScope + @BuildChildrenRegionEntity + @Cacheable(cacheNames = "cockpit:getInsureAnalysis",key = "#param.regionId+'-'+#param.operatorId+'-'+#param.type") + public JSONObject getInsureAnalysis(DataScreenParam param, Integer type) { + List times = securityManageDataScreenService.getOutDangerAnalysis(param); + return convertInsureAnalysis(times, type); + } + + private JSONObject convertInsureAnalysis(List outDangerTimes, Integer type) { + Map> yearMap = InitDataUtil.initTwoYears(); + for (OutDangerAnalysisPO outDangerTime : outDangerTimes) { + if (yearMap.containsKey(outDangerTime.getYear())) { + Map monthMap = yearMap.get(outDangerTime.getYear()); + if (monthMap.containsKey(outDangerTime.getMonth())) { + switch (type) { + case 1: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getOutDangerTimes()); + break; + case 2: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getInjuries()); + break; + case 3: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getDeathToll()); + break; + default: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getOutDangerTimes()); + } + } + } + } + Map total = countTotal(yearMap); + yearMap.put("total", total); + return JSONObject.parseObject(JSON.toJSONString(yearMap)); + } + + private JSONObject convertOverspeed(List times) { + Map> yearMap = InitDataUtil.initTwoYears(); + for (OverspeedAnalysisPO time : times) { + if (yearMap.containsKey(time.getYear())) { + Map monthMap = yearMap.get(time.getYear()); + if (monthMap.containsKey(time.getMonth())) { + monthMap.put(time.getMonth(), time.getTimes()); + } + } + } + Map total = countTotal(yearMap); + yearMap.put("total", total); + return JSONObject.parseObject(JSON.toJSONString(yearMap)); + } + + private Map countTotal(Map> yearMap) { + Map total = Maps.newHashMap(); + Map currentMap = yearMap.get(String.valueOf(LocalDateTime.now().getYear())); + int currentSum = + currentMap.entrySet().stream().mapToInt(o -> Integer.parseInt(String.valueOf(o.getValue()))).sum(); + total.put(String.valueOf(LocalDateTime.now().getYear()), currentSum); + Map lastMap = yearMap.get(String.valueOf(LocalDateTime.now().minusYears(1).getYear())); + int lastSum = lastMap.entrySet().stream().mapToInt(o -> Integer.parseInt(String.valueOf(o.getValue()))).sum(); + total.put(String.valueOf(LocalDateTime.now().minusYears(1).getYear()), lastSum); + return total; + } + + private JSONObject convertAnalysisJson(List mapDatas, JSONObject res) { + Long total = mapDatas.stream().mapToLong(MapDataPO::getValue).sum(); + for (MapDataPO po : mapDatas) { + po.setPercent(total.compareTo(0L) == 0 ? "0" + : BigDecimal.valueOf(po.getValue() * 100).divide(BigDecimal.valueOf(total), 2, BigDecimal.ROUND_HALF_UP) + + StringUtils.EMPTY); + } + res.put("total", total); + res.put("data", mapDatas); + return res; + } + + /** + * 上线率 + * + * @param data + * @param res + * @return + */ + private JSONObject convertOnlineJson(List data, JSONObject timeOnlineData, JSONObject res) { + JSONObject rate = new JSONObject(); + for (OnlineVehicleRegionsPO po : data) { + rate.put(po.getRegionName(), po.getRate()); + } + res.put("time-data", timeOnlineData); + res.put("rate", rate); + return res; + } + + /** + * 先弄点假数据 + * + * @return + */ + private JSONObject genericOnlineData(DataScreenParam param) { + List onlineVehicleDatas = vehicleStatisticsService.getOnlineRateToday(param); + Long vehicleNums = vehicleStatisticsService.getVehicleNums(param); + JSONObject res = new JSONObject(); + for (OnlineVehicleTimesPO onlineVehicleTimes : onlineVehicleDatas) { + BigDecimal rate = 0L == vehicleNums ? BigDecimal.ZERO + : BigDecimal.valueOf(onlineVehicleTimes.getOnlineNum()).multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(vehicleNums), 2, BigDecimal.ROUND_HALF_UP); + res.put(onlineVehicleTimes.getHour() + ":00", rate); + } + return res; + } + + private JSONObject convertCityJson(List data, JSONObject res) { + for (OverspeedStatisticsPO po : data) { + res.put(po.getRegionName(), po.getTimes()); + } + return res; + } + + private LocalDateTime getYearStartTime() { + LocalDate nowDay = LocalDate.now(); + LocalDate firstDayOfYear = nowDay.with(TemporalAdjusters.firstDayOfYear()); + return LocalDateTime.of(firstDayOfYear, LocalTime.MIN); + } + + private LocalDateTime getYearEndTime() { + LocalDate nowDay = LocalDate.now(); + LocalDate lastDayOfYear = nowDay.with(TemporalAdjusters.lastDayOfYear()); + return LocalDateTime.of(lastDayOfYear, LocalTime.MAX); + } + + private Boolean checkIsOverSpeed(VehicleOverspeedInfo gpsData, NdVehicleBaseInfo baseInfo) { + // 混凝土和移动泵车 是50 + Integer vehicleType = baseInfo.getVehicleType(); + VehicleTypeEnum enumByValue = VehicleTypeEnum.getEnumByValue(vehicleType); + if (VehicleTypeEnum.OTHER.equals(enumByValue)) { + if (gpsData.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.KRHP.equals(enumByValue)) { + if (gpsData.getMaxSpeed().compareTo(BigDecimal.valueOf(50)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.MIXER.equals(enumByValue)) { + if (gpsData.getMaxSpeed().compareTo(BigDecimal.valueOf(50)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.BULK_CEMENT_TRUCK.equals(enumByValue)) { + if (gpsData.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.READY_MIXED_MORTAR_TRUC.equals(enumByValue)) { + return gpsData.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0; + } + return Boolean.FALSE; + } + + /** + * 清缓存 + * @param cacheName + */ + public String removeCache(String cacheName) { + if(StringUtils.isBlank(cacheName)){ + removeCacheAll(); + return "清缓存成功"; + } + if(cachePlusOps.del(cacheName) > 0){ + return "清缓存" + cacheName + "成功"; + } + return "清缓存失败"; + } + + /** + * 请所有 + */ + @Caching(evict ={ + @CacheEvict(cacheNames = "cockpit:statisticsCenter",allEntries = true), + @CacheEvict(cacheNames = "cockpit:getVehicleGps",allEntries = true), + @CacheEvict(cacheNames = "cockpit:overspeedGroup",allEntries = true), + @CacheEvict(cacheNames = "cockpit:violationGroup",allEntries = true), + @CacheEvict(cacheNames = "cockpit:outDangerGroup",allEntries = true), + @CacheEvict(cacheNames = "cockpit:injuriesGroup",allEntries = true), + @CacheEvict(cacheNames = "cockpit:deathGroup",allEntries = true), + @CacheEvict(cacheNames = "cockpit:deathGroupTenThousand",allEntries = true), + @CacheEvict(cacheNames = "cockpit:onlineAnalysis",allEntries = true), + @CacheEvict(cacheNames = "cockpit:overspeedAnalysis",allEntries = true), + @CacheEvict(cacheNames = "cockpit:monthlyOverspeedAnalysis",allEntries = true), + @CacheEvict(cacheNames = "cockpit:getInsureAnalysis",allEntries = true) + }) + public void removeCacheAll() { + log.info("清空驾驶舱所有缓存!"); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.java new file mode 100644 index 0000000..8b86897 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.car.datascreen.mapper; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.*; +import com.ningdatech.carapi.common.model.KeyValueDTO; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Classname VehicleStatisticsMapper + * @Description + * @Date 2022/10/22 15:57 + * @Created by PoffyZhang + */ +public interface VehicleStatisticsMapper { + + List getTypesStatistics(@Param("param") DataScreenParam param); + + /** + * 查浙江省 各个市的区域车辆数 + * + * @return + */ + List getZjRegionsStatistics(@Param("param") DataScreenParam param); + + /** + * 保险公司分布 + * + * @param param + * @return + */ + List getInsureDistribution(@Param("param") DataScreenParam param); + + /** + * 运营商分布 + * + * @param param + * @return + */ + List getOperatorDistribution(@Param("param") DataScreenParam param); + + /** + * 年度车辆新增分布 + * + * @param param + * @return + */ + List getNewVehicleDistribution(@Param("param") DataScreenParam param); + + /** + * 根据公司ids 查询车辆总数 + * + * @param param + * @return + */ + Long getVehicleNums(@Param("param") DataScreenParam param); + + List> getVehicleNumsGroupByRegion(@Param("param") DataScreenParam param); + + + List getOverspeedRegions(@Param("param") DataScreenParam param); + + List getViolationRegions(@Param("param") DataScreenParam param); + + List getOutDangerRegions(@Param("param") DataScreenParam param); + + List getInjuriesRegion(@Param("param") DataScreenParam param); + + List getDeathRegion(@Param("param") DataScreenParam param); + + List getOnlineRateToday(@Param("param") DataScreenParam param, @Param("tableName") String tableName); + + List getVehicleOnlineRegions(@Param("param") DataScreenParam param); + + List getVehicleUsefulLife(@Param("param") DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.xml new file mode 100644 index 0000000..54a0bee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/mapper/VehicleStatisticsMapper.xml @@ -0,0 +1,542 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/dto/DataScreenParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/dto/DataScreenParam.java new file mode 100644 index 0000000..c36c471 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/dto/DataScreenParam.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.car.datascreen.model.dto; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +import com.ningdatech.carapi.sys.contants.RegionContant; + +import lombok.Data; +import lombok.ToString; + +/** + * @Classname DataScreenParam + * @Description + * @Date 2022/11/21 13:50 + * @Created by PoffyZhang + */ +@Data +@ToString +public class DataScreenParam { + + private Long regionId; + private Integer regionLevel; + + private String regionCode; + + private List regionIds; + + private List companyIds; + + private Integer type; + + private String dataScopeSql; + + private LocalDateTime startTime; + private LocalDateTime endTime; + + private Long operatorId; + + public Long getRegionId(){ + if(Objects.isNull(this.regionId)){ + this.regionId = RegionContant.ZJ_REGION_ID; + return this.regionId; + } + return this.regionId; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/InsureDistributionStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/InsureDistributionStatisticsPO.java new file mode 100644 index 0000000..3408b46 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/InsureDistributionStatisticsPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "保险公司分布-PO") +public class InsureDistributionStatisticsPO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("保险公司名") + private String insureCompany; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleRegionsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleRegionsPO.java new file mode 100644 index 0000000..960e28c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleRegionsPO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @Classname OnlineVehicleTimesPO + * @Description + * @Date 2022/11/17 13:35 + * @Created by PoffyZhang + */ +@Data +public class OnlineVehicleRegionsPO { + + @ApiModelProperty("区域Id") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("区域code") + private String regionCode; + + @ApiModelProperty("总车辆数") + private Integer vehicleNum; + + @ApiModelProperty("在线车辆数") + private Integer onlineNum; + + @ApiModelProperty("比例") + private BigDecimal rate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleTimesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleTimesPO.java new file mode 100644 index 0000000..a5c34b2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OnlineVehicleTimesPO.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @Classname OnlineVehicleTimesPO + * @Description + * @Date 2022/11/17 13:35 + * @Created by PoffyZhang + */ +@Data +public class OnlineVehicleTimesPO { + + @ApiModelProperty("年份") + private Integer year; + + @ApiModelProperty("月份") + private Integer month; + + @ApiModelProperty("日") + private Integer day; + + @ApiModelProperty("小时") + private Integer hour; + + @ApiModelProperty("总车辆数") + private Integer vehicleNum; + + @ApiModelProperty("在线车辆数") + private Integer onlineNum; + + @ApiModelProperty("比例") + private BigDecimal rate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OperatorDistributionStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OperatorDistributionStatisticsPO.java new file mode 100644 index 0000000..5895bae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OperatorDistributionStatisticsPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "运营商分布-PO") +public class OperatorDistributionStatisticsPO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("运营商名") + private String operatorName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OverspeedStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OverspeedStatisticsPO.java new file mode 100644 index 0000000..040e84d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/OverspeedStatisticsPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Classname OverspeedStatisticsPO + * @Description + * @Date 2022/11/17 13:35 + * @Created by PoffyZhang + */ +@Data +public class OverspeedStatisticsPO { + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("次数") + private Long times; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/RegionDistributionStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/RegionDistributionStatisticsPO.java new file mode 100644 index 0000000..24cd8a9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/RegionDistributionStatisticsPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "区域车辆分布-PO") +public class RegionDistributionStatisticsPO { + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名字") + private String regionName; + + @ApiModelProperty("车辆数") + private Long vehicleNum; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleStatusTimePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleStatusTimePO.java new file mode 100644 index 0000000..d3f0f34 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleStatusTimePO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "车辆状态统计时间段-PO") +public class VehicleStatusTimePO { + + @ApiModelProperty("时间范围") + private String timeScope; + + @ApiModelProperty("在线数") + private Long onlineNum; + + @ApiModelProperty("离线数") + private Long offlineNum; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleTypeStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleTypeStatisticsPO.java new file mode 100644 index 0000000..cda1599 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleTypeStatisticsPO.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "车辆类型统计-PO") +public class VehicleTypeStatisticsPO { + + @ApiModelProperty("车辆类型ID") + private Integer vehicleTypesId; + + @ApiModelProperty("车辆数") + private Long vehicleNum; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleUsefulLifeStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleUsefulLifeStatisticsPO.java new file mode 100644 index 0000000..fe6dd8c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/VehicleUsefulLifeStatisticsPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/25 下午2:10 + */ + +@Data +@ApiModel(description = "车辆年限分布-PO") +public class VehicleUsefulLifeStatisticsPO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("年限范围") + private String usefulLife; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/YearVehicleStatisticsPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/YearVehicleStatisticsPO.java new file mode 100644 index 0000000..edb5b2e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/po/YearVehicleStatisticsPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.datascreen.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/25 下午2:10 + */ + +@Data +@ApiModel(description = "年份车辆数分布-PO") +public class YearVehicleStatisticsPO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("年份") + private Integer year; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/InsureDistributionStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/InsureDistributionStatisticsVO.java new file mode 100644 index 0000000..04c5149 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/InsureDistributionStatisticsVO.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "保险公司分布-VO") +@AllArgsConstructor +@NoArgsConstructor +public class InsureDistributionStatisticsVO { + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("保险公司名") + private String insureCompany; + + @ApiModelProperty("占比") + private BigDecimal ratio; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/OperatorDistributionStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/OperatorDistributionStatisticsVO.java new file mode 100644 index 0000000..018b959 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/OperatorDistributionStatisticsVO.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "运营商分布-VO") +public class OperatorDistributionStatisticsVO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("占比") + private BigDecimal ratio; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/RegionDistributionStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/RegionDistributionStatisticsVO.java new file mode 100644 index 0000000..a0cb6dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/RegionDistributionStatisticsVO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "区域车辆分布-VO") +public class RegionDistributionStatisticsVO { + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名字") + private String regionName; + + @ApiModelProperty("车辆数") + private Long vehicleNum; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/StatisticsCenterVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/StatisticsCenterVO.java new file mode 100644 index 0000000..b06086b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/StatisticsCenterVO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author PoffyZhang + * @date 2022/11/16 下午2:10 + */ + +@Data +@ApiModel(description = "大屏中间统计数据-VO") +@NoArgsConstructor +@AllArgsConstructor +public class StatisticsCenterVO { + + public static StatisticsCenterVO of(Long dailyOverspeedTimes,Long monthlyViolationTimes,Long yearlyOutDangerTimes, + Long yearlyInjuries,Long yearlyDeathToll){ + return new StatisticsCenterVO(dailyOverspeedTimes,monthlyViolationTimes,yearlyOutDangerTimes,yearlyInjuries,yearlyDeathToll); + } + + @ApiModelProperty("日超速次数") + private Long dailyOverspeedTimes = 0L; + + @ApiModelProperty("月违章次数") + private Long monthlyViolationTimes = 0L; + + @ApiModelProperty("年出险次数") + private Long yearlyOutDangerTimes = 0L; + + @ApiModelProperty("年受伤人数") + private Long yearlyInjuries = 0L; + + @ApiModelProperty("年死亡人数") + private Long yearlyDeathToll = 0L; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleTypeStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleTypeStatisticsVO.java new file mode 100644 index 0000000..685d194 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleTypeStatisticsVO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author PoffyZhang + * @date 2022/10/22 下午2:10 + */ + +@Data +@ApiModel(description = "车辆类型统计-VO") +public class VehicleTypeStatisticsVO { + + @ApiModelProperty("车辆类型ID") + private Integer vehicleTypesId; + + @ApiModelProperty("车辆类型名") + private String vehicleTypesName; + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("占比") + private BigDecimal ratio; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleUsefulLifeStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleUsefulLifeStatisticsVO.java new file mode 100644 index 0000000..1b52d34 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/VehicleUsefulLifeStatisticsVO.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author PoffyZhang + * @date 2022/10/25 下午2:10 + */ + +@Data +@ApiModel(description = "车辆年限分布-PO") +@AllArgsConstructor +@NoArgsConstructor +public class VehicleUsefulLifeStatisticsVO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("年限范围") + private String usefulLife; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/YearVehicleStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/YearVehicleStatisticsVO.java new file mode 100644 index 0000000..be09659 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/model/vo/YearVehicleStatisticsVO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.datascreen.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/25 下午2:10 + */ + +@Data +@ApiModel(description = "年份车辆数分布-VO") +public class YearVehicleStatisticsVO { + + @ApiModelProperty("车辆数") + private Long vehicleNum; + + @ApiModelProperty("年份") + private Integer year; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/VehicleStatisticsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/VehicleStatisticsService.java new file mode 100644 index 0000000..62f7aa2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/VehicleStatisticsService.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.car.datascreen.service; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OnlineVehicleRegionsPO; +import com.ningdatech.carapi.car.datascreen.model.po.OnlineVehicleTimesPO; +import com.ningdatech.carapi.car.datascreen.model.vo.*; +import com.ningdatech.carapi.common.model.KeyValueDTO; +import com.ningdatech.carapi.common.model.po.MapDataPO; + +import java.util.List; + +public interface VehicleStatisticsService { + + List getVehicleTypesStatistics(DataScreenParam param); + + List getRegionDistribution(DataScreenParam param); + + List getInsureDistribution(DataScreenParam param); + + List getOperatorDistribution(DataScreenParam param); + + List getNewVehicleNum(DataScreenParam param); + + List getUsefulLiftDistribution(DataScreenParam param); + + Long getVehicleNums(DataScreenParam param); + + List> getVehicleNumsGroupByRegion(DataScreenParam param); + + List getOverspeedRegions(DataScreenParam param); + + List getViolationRegions(DataScreenParam param); + + List getOutDangerRegions(DataScreenParam param); + + List getInjuriesRegion(DataScreenParam param); + + List getDeathRegion(DataScreenParam param); + + List getOnlineRateToday(DataScreenParam param); + + List getVehicleOnlineRegions(DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/impl/VehicleStatisticsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/impl/VehicleStatisticsServiceImpl.java new file mode 100644 index 0000000..1ac370f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/datascreen/service/impl/VehicleStatisticsServiceImpl.java @@ -0,0 +1,378 @@ +package com.ningdatech.carapi.car.datascreen.service.impl; + +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.datascreen.mapper.VehicleStatisticsMapper; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.*; +import com.ningdatech.carapi.car.datascreen.model.vo.*; +import com.ningdatech.carapi.car.datascreen.service.VehicleStatisticsService; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoJoinMapper; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.model.KeyValueDTO; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.service.INdInsureInfoService; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerService; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class VehicleStatisticsServiceImpl implements VehicleStatisticsService { + + private final VehicleStatisticsMapper vehicleStatisticsMapper; + private final VehicleBaseInfoJoinMapper vehicleBaseInfoJoinMapper; + private final RegionsCacheHelper regionsCacheHelper; + private final INdInsureOutDangerService insureOutDangerService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final INdInsureInfoService insureInfoService; + + private final String USEFUL_LIFE_ONE = "3年以下"; + private final String USEFUL_LIFE_TWO = "3-5年"; + private final String USEFUL_LIFE_THREE = "5-10年"; + private final String USEFUL_LIFE_FOUR = "10年以上"; + + /** + * 获取车辆类型分布 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getVehicleTypesStatistics(DataScreenParam param) { + List typesStatistics = vehicleStatisticsMapper.getTypesStatistics(param); + if (CollUtil.isEmpty(typesStatistics)) { + return Collections.emptyList(); + } + return convertVehicleTypes(typesStatistics); + } + + /** + * 获取区域车辆分布 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getRegionDistribution(DataScreenParam param) { + //区域车辆 根据 所传的regionId来判断 查询甚么数据 + CodeUtil.buildRegionLevel(param); + List list = statisticsRegionDistribution(vehicleStatisticsMapper.getZjRegionsStatistics(param)); + complementaryRegion(list, param.getRegionId()); + return list; + } + + /** + * 获取保险公司分布 + * + * @param param + * @return + */ + @Override + public List getInsureDistribution(DataScreenParam param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdInsureOutDanger.class); + VehicleStatisticsServiceImpl context = (VehicleStatisticsServiceImpl) AopContext.currentProxy(); + context.buildWrapper(wrapper,param); + // 获取系统车牌号 + List carPlates = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate)).stream() + .map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + // 获取筛选时间的车辆出险数据,并过滤出在系统内的车辆 + List insureList = insureOutDangerService.list(wrapper) + .stream().filter(c -> carPlates.contains(c.getCarPlate())).collect(Collectors.toList()); + // 获取车辆的保险信息 + List insureInfos = insureInfoService.list(Wrappers.lambdaQuery(NdInsureInfo.class) + .in(NdInsureInfo::getCarPlate, carPlates)); + Map> insureInfoMap = insureInfos.stream() + .collect(Collectors.groupingBy(NdInsureInfo::getInsureCompany)); + + // 按照保险机构分组,再将车牌号去重,统计数量 + Map> insureMap = insureList.stream() + .filter(c -> Objects.nonNull(c.getInsureCompany())) + .collect(Collectors.groupingBy(NdInsureOutDanger::getInsureCompany)); + List resultList = Lists.newArrayList(); + for (String insureCompany : insureMap.keySet()) { + InsureDistributionStatisticsVO vo = new InsureDistributionStatisticsVO(); + vo.setInsureCompany(insureCompany); + List outDangers = insureMap.get(insureCompany); + long count = outDangers.stream().map(NdInsureOutDanger::getCarPlate).distinct().count(); + vo.setVehicleNum(count); + // 获取该保险公司下保险的车辆总数 + List infoList = insureInfoMap.get(insureCompany); + if (CollUtil.isEmpty(infoList)){ + // 该保险公司不在车辆承保信息中,跳过该保险机构 + continue; + } + long total = infoList.stream().map(NdInsureInfo::getCarPlate).distinct().count(); + vo.setRatio(BigDecimal.valueOf(count).multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(total), 2, BigDecimal.ROUND_HALF_UP)); + resultList.add(vo); + } + return resultList; + //List insuresStatistics = vehicleStatisticsMapper.getInsureDistribution(param); + //if (CollUtil.isEmpty(insuresStatistics)) { + // return Collections.emptyList(); + //} + //return convertInsures(insuresStatistics); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + private void buildWrapper(LambdaQueryWrapper wrapper,DataScreenParam param) { + wrapper.between(NdInsureOutDanger::getAccidentTime, param.getStartTime(), param.getEndTime()); + } + + /** + * 运营商分布 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getOperatorDistribution(DataScreenParam param) { + List operatorStatistics = vehicleStatisticsMapper.getOperatorDistribution(param); + if (CollUtil.isEmpty(operatorStatistics)) { + return Collections.emptyList(); + } + return convertOperators(operatorStatistics); + } + + /** + * 新增车辆分布图 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getNewVehicleNum(DataScreenParam param) { + List yearVehicleStatistics = vehicleStatisticsMapper.getNewVehicleDistribution(param); + if (CollUtil.isEmpty(yearVehicleStatistics)) { + return Collections.emptyList(); + } + return convertYears(yearVehicleStatistics); + } + + /** + * 车辆年限分布 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getUsefulLiftDistribution(DataScreenParam param) { + List vehicleUsefulLife = vehicleStatisticsMapper.getVehicleUsefulLife(param); + if (CollUtil.isEmpty(vehicleUsefulLife)) { + return Collections.emptyList(); + } + return vehicleUsefulLife.stream().map(v -> { + VehicleUsefulLifeStatisticsVO vo = new VehicleUsefulLifeStatisticsVO(); + BeanUtils.copyProperties(v, vo); + return vo; + }).collect(Collectors.toList()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public List searchVehicleList(LambdaQueryWrapper wrapper, + DataScreenParam param) { + log.info(param.toString()); + return vehicleBaseInfoJoinMapper.listJoin(wrapper); + } + + @Override + @XmlDataScope + public Long getVehicleNums(DataScreenParam param) { + return vehicleStatisticsMapper.getVehicleNums(param); + } + + @Override + @XmlDataScope + public List> getVehicleNumsGroupByRegion(DataScreenParam param) { + return vehicleStatisticsMapper.getVehicleNumsGroupByRegion(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getOverspeedRegions(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return vehicleStatisticsMapper.getOverspeedRegions(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getViolationRegions(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return vehicleStatisticsMapper.getViolationRegions(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getOutDangerRegions(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return vehicleStatisticsMapper.getOutDangerRegions(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getInjuriesRegion(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return vehicleStatisticsMapper.getInjuriesRegion(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getDeathRegion(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return vehicleStatisticsMapper.getDeathRegion(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getOnlineRateToday(DataScreenParam param) { + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(), "yyyy_MM"); + return vehicleStatisticsMapper.getOnlineRateToday(param, tableName); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List getVehicleOnlineRegions(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return vehicleStatisticsMapper.getVehicleOnlineRegions(param); + } + + private List convertUsefulLife(List vehicles) { + List res = Lists.newArrayList(); + AtomicLong usefulLifeOne = new AtomicLong(0L); + AtomicLong usefulLifeTwo = new AtomicLong(0L); + AtomicLong usefulLifeThree = new AtomicLong(0L); + AtomicLong usefulLifeFour = new AtomicLong(0L); + vehicles.forEach(v -> { + if (Objects.isNull(v.getUsefulLife())) { + return; + } + if (0 < v.getUsefulLife() && 3 > v.getUsefulLife()) { + usefulLifeOne.addAndGet(1L); + } else if (3 <= v.getUsefulLife() && 5 > v.getUsefulLife()) { + usefulLifeTwo.addAndGet(1L); + } else if (5 <= v.getUsefulLife() && 10 > v.getUsefulLife()) { + usefulLifeThree.addAndGet(1L); + } else if (10 <= v.getUsefulLife()) { + usefulLifeFour.addAndGet(1L); + } + }); + //1.3年以下 + res.add(new VehicleUsefulLifeStatisticsVO(usefulLifeOne.get(), USEFUL_LIFE_ONE)); + //2.3-5年 + res.add(new VehicleUsefulLifeStatisticsVO(usefulLifeTwo.get(), USEFUL_LIFE_TWO)); + //3.5-10年 + res.add(new VehicleUsefulLifeStatisticsVO(usefulLifeThree.get(), USEFUL_LIFE_THREE)); + //4.10年以上 + res.add(new VehicleUsefulLifeStatisticsVO(usefulLifeFour.get(), USEFUL_LIFE_FOUR)); + return res; + } + + private List convertYears(List yearVehicleStatistics) { + if (CollUtil.isEmpty(yearVehicleStatistics)) { + return Collections.emptyList(); + } + return yearVehicleStatistics.stream().map(t -> BeanUtil.copyProperties(t, YearVehicleStatisticsVO.class)).collect(Collectors.toList()); + } + + + private List convertVehicleTypes(List typesStatistics) { + long sum = typesStatistics.stream().mapToLong(VehicleTypeStatisticsPO::getVehicleNum).sum(); + return typesStatistics.stream().map(t -> { + VehicleTypeStatisticsVO vo = BeanUtil.copyProperties(t, VehicleTypeStatisticsVO.class); + vo.setVehicleTypesName(VehicleTypeEnum.getDescByCode(vo.getVehicleTypesId())); + vo.setRatio(BigDecimal.valueOf(vo.getVehicleNum()).multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(sum), 2, BigDecimal.ROUND_HALF_UP)); + return vo; + }).collect(Collectors.toList()); + } + + private List statisticsRegionDistribution(List regionsStatistics) { + if (CollUtil.isEmpty(regionsStatistics)) { + return Collections.emptyList(); + } + return regionsStatistics.stream().map(t -> BeanUtil.copyProperties(t, RegionDistributionStatisticsVO.class)).collect(Collectors.toList()); + } + + private List convertInsures(List insuresStatistics) { + long sum = insuresStatistics.stream().mapToLong(InsureDistributionStatisticsPO::getVehicleNum).sum(); + return insuresStatistics.stream().map(insure -> { + InsureDistributionStatisticsVO vo = BeanUtil.copyProperties(insure, InsureDistributionStatisticsVO.class); + vo.setRatio(BigDecimal.valueOf(vo.getVehicleNum()).multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(sum), 2, BigDecimal.ROUND_HALF_UP)); + return vo; + }).collect(Collectors.toList()); + } + + private List convertOperators(List operatorStatistics) { + long sum = operatorStatistics.stream().mapToLong(OperatorDistributionStatisticsPO::getVehicleNum).sum(); + return operatorStatistics.stream().map(operator -> { + OperatorDistributionStatisticsVO vo = BeanUtil.copyProperties(operator, OperatorDistributionStatisticsVO.class); + vo.setRatio(BigDecimal.valueOf(vo.getVehicleNum()).multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(sum), 2, BigDecimal.ROUND_HALF_UP)); + return vo; + }).collect(Collectors.toList()); + } + + public void complementaryRegion(List list, Long regionId) { + Map dataMap = CollUtils.listToMap(list, m -> m.getRegionName()); + List regions = regionsCacheHelper.listChildOnly(regionId); + for (RegionDTO region : regions) { + if (!dataMap.containsKey(region.getRegionName())) { + RegionDistributionStatisticsVO data = new RegionDistributionStatisticsVO(); + data.setRegionId(region.getId()); + data.setRegionName(region.getRegionName()); + data.setVehicleNum(0L); + list.add(data); + } + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/controller/VehicleEquipmentController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/controller/VehicleEquipmentController.java new file mode 100644 index 0000000..ec24067 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/controller/VehicleEquipmentController.java @@ -0,0 +1,110 @@ +package com.ningdatech.carapi.car.equipment.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.equipment.model.res.SipEquipmentRes; +import com.ningdatech.carapi.car.equipment.model.vo.VehicleEquipmentVO; +import com.ningdatech.carapi.car.equipment.manage.VehicleEquipmentManage; +import com.ningdatech.carapi.car.equipment.model.dto.EquipmentSaveDTO; +import com.ningdatech.carapi.car.equipment.model.dto.EquipmentUpdateDTO; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentPageQuery; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentQueryDTO; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesPageQuery; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/archives/equipment") +@Api(value = "archives", tags = "车辆管理-档案管理") +@RequiredArgsConstructor +public class VehicleEquipmentController { + private final VehicleEquipmentManage equipmentManage; + private final INdVehicleEquipmentInfoService vehicleEquipmentInfoService; + + @ApiOperation(value = "车辆设备待添加列表", notes = "车辆设备待添加列表") + @GetMapping("/toBeAddedList") + public PageVo queryToBeAdded(@ModelAttribute VehicleArchivesPageQuery vehicleArchivesPageQuery) { + return equipmentManage.queryToBeAdded(vehicleArchivesPageQuery); + } + + @ApiOperation(value = "车辆设备已添加列表", notes = "车辆设备已添加列表") + @GetMapping("/addedList") + public PageVo queryAdded(@ModelAttribute VehicleEquipmentPageQuery vehicleArchivesPageQuery) { + return equipmentManage.queryAdded(vehicleArchivesPageQuery); + } + + @ApiOperation(value = "车辆设备列表导出", notes = "车辆设备列表导出") + @GetMapping("/export") + @WebLog + public void export(VehicleEquipmentPageQuery req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, equipmentManage::export); + } + + /** + * 查询车辆设备信息 + * @param id 设备ID + * @return 查询结果 + */ + @ApiOperation(value = "查询车辆设备信息-以设备ID查询", notes = "查询车辆设备信息-以设备ID查询") + @GetMapping("/detailsbyId/{id}") + public VehicleEquipmentQueryDTO getEquipmentById(@PathVariable("id") Long id) { + return equipmentManage.getEquipmentById(id); + } + + /** + * 查询车辆设备信息 + * @param vehicleId 车辆ID + * @return 查询结果 + */ + @ApiOperation(value = "查询车辆设备信息-以车辆ID查询", notes = "查询车辆设备信息-以车辆ID查询") + @GetMapping("/detailsbyVehicleId/{vehicleId}") + public List getEquipment(@PathVariable("vehicleId") Long vehicleId) { + return equipmentManage.getEquipment(vehicleId); + } + + @ApiOperation(value = "批量保存车辆设备", notes = "批量保存车辆设备") + @PostMapping("/save") + @WebLog + public List handlerSave(@Valid @RequestBody List datas) { + vehicleEquipmentInfoService.save(datas, LoginUserUtil.getUserId()); + return CollUtils.convert(datas,w -> BeanUtil.toBean(w, VehicleEquipmentQueryDTO.class)); + } + + @ApiOperation(value = "编辑车辆设备", notes = "编辑车辆设备") + @PostMapping("/modify") + @WebLog + public VehicleEquipmentQueryDTO handlerUpdate(@Valid @RequestBody EquipmentUpdateDTO data) { + vehicleEquipmentInfoService.update(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, VehicleEquipmentQueryDTO.class); + } + + @ApiOperation(value = "删除车辆设备", notes = "删除车辆设备") + @PostMapping("/remove") + @WebLog + public Boolean handlerDelete(@Valid @RequestBody List ids) { + return vehicleEquipmentInfoService.removeByIdWithCache(ids); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/converter/VehicleEquipmentConverter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/converter/VehicleEquipmentConverter.java new file mode 100644 index 0000000..b4b2120 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/converter/VehicleEquipmentConverter.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.car.equipment.converter; + +import java.util.Objects; + +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentJoin; +import com.ningdatech.carapi.car.equipment.model.vo.VehicleEquipmentVO; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; +import com.ningdatech.carapi.common.constant.CarStatusEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; + +import cn.hutool.core.bean.BeanUtil; + +/** + * @Classname CompanyRegionConverter + * @Description + * @Date 2022/10/9 10:30 + * @Created by PoffyZhang + */ +public class VehicleEquipmentConverter { + + public static VehicleEquipmentVO convert(NdVehicleBaseInfoJoin vehicle) { + if(Objects.isNull(vehicle) || Objects.isNull(vehicle.getId())){ + return null; + } + VehicleEquipmentVO res = BeanUtil.copyProperties(vehicle, VehicleEquipmentVO.class); + CodeUtil.searchCompanyNameAndRegionName(res); + res.setVehicleTypeName(VehicleTypeEnum.getDescByCode(res.getVehicleType())); + res.setVehicleStatus(vehicle.getVehicleStatus()); + res.setVehicleStatusName(CarStatusEnum.getDescByCode(vehicle.getVehicleStatus())); + res.setLastOnlineTime(vehicle.getLastOnlineTime()); + return res; + } + + public static VehicleEquipmentVO convert(NdVehicleEquipmentJoin equipment) { + if(Objects.isNull(equipment) || Objects.isNull(equipment.getId())){ + return null; + } + VehicleEquipmentVO res = BeanUtil.copyProperties(equipment, VehicleEquipmentVO.class); + CodeUtil.searchCompanyNameAndRegionName(res); + res.setId(equipment.getVehicleId()); + res.setEquipmentId(equipment.getId()); + res.setVehicleTypeName(VehicleTypeEnum.getDescByCode(res.getVehicleType())); + return res; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/manage/VehicleEquipmentManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/manage/VehicleEquipmentManage.java new file mode 100644 index 0000000..380fdab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/manage/VehicleEquipmentManage.java @@ -0,0 +1,510 @@ +package com.ningdatech.carapi.car.equipment.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Repository; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.equipment.converter.VehicleEquipmentConverter; +import com.ningdatech.carapi.car.equipment.model.DataAccessDevices; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentDTO; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentPageQuery; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentQueryDTO; +import com.ningdatech.carapi.car.equipment.model.res.SipEquipmentRes; +import com.ningdatech.carapi.car.equipment.model.vo.VehicleEquipmentVO; +import com.ningdatech.carapi.car.equipment.service.IDataAccessDevicesService; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentChannelsService; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.ningdatech.carapi.car.equipment.service.IVehicleEquipmentNoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesPageQuery; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoJoinService; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleEquipFuncEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname VehicleEquipmentRepository + * @Description + * @Date 2022/10/14 14:33 + * @Created by PoffyZhang + */ +@Repository +@RequiredArgsConstructor +@Slf4j +public class VehicleEquipmentManage { + + private final IVehicleBaseInfoJoinService vehicleBaseInfoJoinService; + + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final INdVehicleEquipmentInfoService vehicleEquipmentInfoService; + private final INdVehicleEquipmentChannelsService vehicleEquipmentChannelsService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IDataAccessDevicesService dataAccessDevicesService; + private final IVehicleEquipmentNoService vehicleEquipmentNoService; + + public PageVo queryToBeAdded(VehicleArchivesPageQuery vehicleArchivesPageQuery) { + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id、名字 + Long operatorId = operatorQueryDTO.getId(); + + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildBaseInfoQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.eq(NdVehicleBaseInfoJoin::getOperatorId,operatorId); + vehicleBaseInfoJoinService.pageJoinWithNotEquipment(page,wrapper); + List data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert); + return PageVo.of(data, page.getTotal()); + } else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + Long companyId = userDetail.getCompanyId(); + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildBaseInfoQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.and(w -> w.eq(NdVehicleBaseInfoJoin::getCompanyId,companyId).or() + .eq(NdVehicleBaseInfoJoin::getUseCompanyId,companyId)); + vehicleBaseInfoJoinService.pageJoinWithNotEquipmentAndUseCompany(page,wrapper); + List data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert); + return PageVo.of(data, page.getTotal()); + } else { + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + VehicleEquipmentManage context = (VehicleEquipmentManage) AopContext.currentProxy(); + context.searchTobeAddedPage(page, wrapper, vehicleArchivesPageQuery); + List data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert); + return PageVo.of(data, page.getTotal()); + } + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchTobeAddedPage(Page page, LambdaQueryWrapper wrapper, + VehicleArchivesPageQuery vehicleArchivesPageQuery) { + buildBaseInfoQueryWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoJoinService.pageJoinWithNotEquipment(page,wrapper); + } + + public PageVo queryAdded(VehicleEquipmentPageQuery vehicleArchivesPageQuery) { + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + VUtils.isTrue(Objects.isNull(operatorQueryDTO)).throwMessage("运营商:" + companyName + "不存在!"); + Long operatorId = operatorQueryDTO.getId(); + + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.eq(NdVehicleBaseInfoJoin::getOperatorId,operatorId); + vehicleBaseInfoJoinService.pageJoinWithEquipment(page,wrapper); + List data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert); + return PageVo.of(data, page.getTotal()); + } else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + Long companyId = userDetail.getCompanyId(); + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.and(w -> w.eq(NdVehicleBaseInfoJoin::getCompanyId,companyId).or() + .eq(NdVehicleBaseInfoJoin::getUseCompanyId,companyId)); + vehicleBaseInfoJoinService.pageJoinWithEquipmentAndUseCompany(page,wrapper); + List data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert); + return PageVo.of(data, page.getTotal()); + } else { + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + VehicleEquipmentManage context = (VehicleEquipmentManage) AopContext.currentProxy(); + context.searchAddedPage(page, wrapper, vehicleArchivesPageQuery); + List data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert); + return PageVo.of(data, page.getTotal()); + } + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchAddedPage(Page page, + LambdaQueryWrapper wrapper, VehicleEquipmentPageQuery vehicleArchivesPageQuery) { + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoJoinService.pageJoinWithEquipment(page,wrapper); + } + + public VehicleEquipmentQueryDTO getEquipmentById(Long id) { + + NdVehicleEquipmentInfo vehicleEquipmentInfo = vehicleEquipmentInfoService.getById(id); + if (Objects.isNull(vehicleEquipmentInfo)){ + return null; + } + Long vehicleId = vehicleEquipmentInfo.getVehicleId(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + VehicleEquipmentManage context = (VehicleEquipmentManage) AopContext.currentProxy(); + context.buildQuery(wrapper, vehicleId); + NdVehicleBaseInfo ndVehicleBaseInfo = vehicleBaseInfoService.getOne(wrapper); + // 设备所属的车辆,当前登录用户没有权限查看 + if (Objects.isNull(ndVehicleBaseInfo)){ + return null; + } + + VehicleEquipmentQueryDTO query = BeanUtil.toBean(vehicleEquipmentInfo, VehicleEquipmentQueryDTO.class); + if(Objects.nonNull(query)){ + query.setChannels(vehicleEquipmentChannelsService.list(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class) + .eq(NdVehicleEquipmentChannels::getEquipmentId,query.getId()))); + if(Objects.nonNull(vehicleEquipmentInfo.getSubordinatePlatform()) && + StringUtils.isNumeric(vehicleEquipmentInfo.getSubordinatePlatform())){ + query.setSubordinatePlatform(Long.valueOf(vehicleEquipmentInfo.getSubordinatePlatform())); + } + + } + return query; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdVehicleBaseInfo::getId,id); + } + + + public List getEquipmentByCarPlate(String carPlate) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class); + wrapper.eq(NdVehicleEquipmentInfo::getCarPlate,carPlate); + wrapper.eq(NdVehicleEquipmentInfo::getEquipmentFunction, VehicleEquipFuncEnum.video.name()); + List vehicleEquipments = vehicleEquipmentInfoService.list(wrapper); + return CollUtils.convert(vehicleEquipments, w -> { + VehicleEquipmentQueryDTO equipmentQueryDTO = BeanUtil.copyProperties(w, VehicleEquipmentQueryDTO.class); + if(Objects.nonNull(w.getSubordinatePlatform()) && + StringUtils.isNumeric(w.getSubordinatePlatform())){ + equipmentQueryDTO.setSubordinatePlatform(Long.valueOf(w.getSubordinatePlatform())); + } + return equipmentQueryDTO; + }); + } + + public List getEquipment(Long vehicleId) { + List vehicleEquipments = vehicleEquipmentInfoService + .list(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class).eq(NdVehicleEquipmentInfo::getVehicleId,vehicleId)); + List res = CollUtils.convert(vehicleEquipments, e -> BeanUtil.copyProperties(e,VehicleEquipmentQueryDTO.class)); + if(CollUtil.isNotEmpty(res)){ + for(VehicleEquipmentQueryDTO dto: res){ + dto.setChannels(vehicleEquipmentChannelsService.list(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class) + .eq(NdVehicleEquipmentChannels::getEquipmentId,dto.getId()))); + dto.setSubordinatePlatformName(operatorsCacheHelper.getNameById(dto.getSubordinatePlatform())); + } + } + return res; + } + + /** + * 处理regionCode 拼接 + * @param wrapper + * @param vehicleEquipmentPageQuery + */ + private void buildQueryWrapper(LambdaQueryWrapper wrapper, VehicleEquipmentPageQuery vehicleEquipmentPageQuery) { + wrapper.like(StringUtils.isNotBlank(vehicleEquipmentPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleEquipmentPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleEquipmentPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleEquipmentPageQuery.getCompanyName()) + .eq(Objects.nonNull(vehicleEquipmentPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleEquipmentPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleEquipmentPageQuery.getVehicleStatus()),NdVehicleBaseInfoJoin::getVehicleStatus,vehicleEquipmentPageQuery.getVehicleStatus()) + //只有审核成功的才会进入该列表 + .eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .like(StringUtils.isNotBlank(vehicleEquipmentPageQuery.getOperatorName()), NdVehicleBaseInfoJoin::getOperatorName, vehicleEquipmentPageQuery.getOperatorName()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn); + } + + + /** + * + * @param wrapper + * @param vehicleArchivesPageQuery + */ + private void buildBaseInfoQueryWrapper(LambdaQueryWrapper wrapper, + VehicleArchivesPageQuery vehicleArchivesPageQuery) { + wrapper.like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleArchivesPageQuery.getCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleStatus()),NdVehicleBaseInfoJoin::getVehicleStatus,vehicleArchivesPageQuery.getVehicleStatus()) + //只有审核成功的才会进入该列表 + .eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getOperatorName()), NdVehicleBaseInfoJoin::getOperatorName, vehicleArchivesPageQuery.getOperatorName()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn); + + } + + public void export(HttpServletResponse response, VehicleEquipmentPageQuery equipmentPageQuery) { + equipmentPageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + VehicleArchivesPageQuery vehicleArchivesPageQuery = BeanUtil.copyProperties(equipmentPageQuery,VehicleArchivesPageQuery.class); + PageVo toBePage = queryToBeAdded(vehicleArchivesPageQuery); + PageVo addPage = queryAdded(equipmentPageQuery); + List toBeList = toBePage.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleEquipmentVO.class)).collect(Collectors.toList()); + List auditList = addPage.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleEquipmentVO.class)).collect(Collectors.toList()); + String fileName = "车辆设备列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + String sheetNameToBe = "车辆设备待安装列表"; + String sheetNameAdded = "车辆设备已安装列表"; + try { + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build(); + //埋点基础信息 sheet + WriteSheet writeSheet = EasyExcel.writerSheet(0, sheetNameToBe) + .head(VehicleEquipmentDTO.class).build(); + excelWriter.write(toBeList, writeSheet); + //埋点数据转换信息 sheet + writeSheet = EasyExcel.writerSheet(1, sheetNameAdded) + .head(VehicleEquipmentDTO.class).build(); + excelWriter.write(auditList, writeSheet); + excelWriter.finish(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 从sip获取到 该车牌号的设备 + * @param car_plate + * @return + */ + public Boolean initEquipmentFromSip(String car_plate) { + List sipEquipments = vehicleEquipmentInfoService.getSipEquipmentsByCarPlate(car_plate); + if(CollUtil.isNotEmpty(sipEquipments)){ + //如果有设备的话 就去更新这个车牌下的所有设备 + //1.查看系统里 是否有这个车牌号 + NdVehicleBaseInfo vehicle = vehicleBaseInfoService.getOne( + Wrappers.lambdaQuery(NdVehicleBaseInfo.class).eq(NdVehicleBaseInfo::getCarPlate,car_plate) + .eq(NdVehicleBaseInfo::getDeleted,Boolean.FALSE) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode())); + if(Objects.isNull(vehicle)){ + log.warn("该车辆 【{}】不存在 系统中",car_plate); + return Boolean.FALSE; + } + //2.先删除现有的设备 + vehicleEquipmentInfoService.remove(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) + .eq(NdVehicleEquipmentInfo::getCarPlate,car_plate)); + List toAdds = sipEquipments.stream() + .filter(e -> Objects.nonNull(e) && StringUtils.isNotBlank(e.getDevice_id())) + .map(e -> { + NdVehicleEquipmentInfo equipmentInfo = new NdVehicleEquipmentInfo(); + equipmentInfo.setName(e.getName()); + equipmentInfo.setEquipmentNo(e.getDevice_id()); + equipmentInfo.setCarPlate(car_plate); + equipmentInfo.setVehicleId(vehicle.getId()); + equipmentInfo.setSubordinatePlatform(e.getPlatform_id()); + return equipmentInfo; + }).collect(Collectors.toList()); + //3.再批量添加 + vehicleEquipmentInfoService.saveBatch(toAdds); + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + public Boolean initEquipmentFromSipAll() { + //1.查看系统里 审核过的车牌号 + List vehicles = vehicleBaseInfoService.list( + Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getDeleted,Boolean.FALSE) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode())); + Integer total = 0; + if(CollUtil.isNotEmpty(vehicles)){ + //2.去遍历 并且添加车辆的设备 + for(NdVehicleBaseInfo vehicle : vehicles){ + if(StringUtils.isNotBlank(vehicle.getCarPlate())){ + List sipEquipments = vehicleEquipmentInfoService.getSipEquipmentsByCarPlate(vehicle.getCarPlate()); + //2.先删除现有的设备 + vehicleEquipmentInfoService.remove(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) + .eq(NdVehicleEquipmentInfo::getCarPlate,vehicle.getCarPlate())); + if(CollUtil.isNotEmpty(sipEquipments)){ + List toAdds = sipEquipments.stream() + .filter(e -> Objects.nonNull(e) && StringUtils.isNotBlank(e.getDevice_id())) + .map(e -> { + NdVehicleEquipmentInfo equipmentInfo = new NdVehicleEquipmentInfo(); + equipmentInfo.setName(e.getName()); + equipmentInfo.setEquipmentNo(e.getDevice_id()); + equipmentInfo.setCarPlate(vehicle.getCarPlate()); + equipmentInfo.setVehicleId(vehicle.getId()); + equipmentInfo.setSubordinatePlatform("1"); + return equipmentInfo; + }).collect(Collectors.toList()); + //3.再批量添加 + total += toAdds.size(); + if(CollUtil.isNotEmpty(toAdds)){ + vehicleEquipmentInfoService.insertBatch(toAdds); + } + log.info("当前插入了 total :{}",total); + } + } + } + log.info("最后的批量插入了 total :{}",total); + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + public void getEquipNo() { + // 获取系统中所有车牌号 + List carPlateList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .select(NdVehicleBaseInfo::getCarPlate) + .isNotNull(NdVehicleBaseInfo::getCarPlate)) + .stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + // 获取实时视频设备表中的车牌号集合 + Set dataCarPlates = dataAccessDevicesService.list(Wrappers.lambdaQuery(DataAccessDevices.class) + .select(DataAccessDevices::getCarPlate)) + .stream().filter(Objects::nonNull).map(DataAccessDevices::getCarPlate) + .collect(Collectors.toSet()); + // 获取在系统中的车牌号 + List carNoList = dataCarPlates.stream().filter(carPlateList::contains).collect(Collectors.toList()); + log.info("存在于系统中的车牌号数量:{}", carNoList.size()); + // 获取实时视频设备表中所有数据 并按车牌号分组 + Map> devicesDataMap = dataAccessDevicesService.list(Wrappers.lambdaQuery(DataAccessDevices.class) + .isNotNull(DataAccessDevices::getDeviceId) + .isNotNull(DataAccessDevices::getPlatformId) + .select(DataAccessDevices::getId, DataAccessDevices::getCarPlate, DataAccessDevices::getDeviceId, + DataAccessDevices::getStatus,DataAccessDevices::getPlatformId) + .in(DataAccessDevices::getCarPlate,carNoList)) + .stream().collect(Collectors.groupingBy(DataAccessDevices::getCarPlate)); + // 实时视频设备表中车牌号集合 + Set deviceCarPlates = devicesDataMap.keySet(); + + // 获取同步设备编号表中的数据 + Map> dataMap = vehicleEquipmentNoService.list(Wrappers.lambdaQuery(VehicleEquipmentNo.class) + .select(VehicleEquipmentNo::getId, VehicleEquipmentNo::getCarPlate, + VehicleEquipmentNo::getDeviceId, VehicleEquipmentNo::getStatus, VehicleEquipmentNo::getPlatformId)) + .stream().collect(Collectors.groupingBy(VehicleEquipmentNo::getCarPlate)); + // 同步设备编号表中车牌号集合 + Set carPlates = dataMap.keySet(); + + // 判断数据是否需要新增、删除或者更新 + // 新增:实时视频设备表中有的车牌号而同步设备表中没有 + Set addCarPlates = deviceCarPlates.stream().filter(d -> !carPlates.contains(d)).collect(Collectors.toSet()); + if (CollUtil.isNotEmpty(addCarPlates)){ + addCarPlates.forEach(d -> { + List dataAccessDevices = devicesDataMap.get(d); + List addDataList = Lists.newArrayList(); + int i = 1; + for (DataAccessDevices dataAccessDevice : dataAccessDevices) { + VehicleEquipmentNo vehicleEquipmentNo = new VehicleEquipmentNo(); + vehicleEquipmentNo.setCarPlate(d); + vehicleEquipmentNo.setDeviceId(dataAccessDevice.getDeviceId()); + vehicleEquipmentNo.setDeviceName(d + StrPool.DASH + DefValConstants.TONG_DAO + i++); + String status = dataAccessDevice.getStatus(); + if (StringUtils.isNotBlank(status)) { + vehicleEquipmentNo.setStatus(status); + } + vehicleEquipmentNo.setPlatformId(dataAccessDevice.getPlatformId()); + vehicleEquipmentNo.setCreateBy(1L); + vehicleEquipmentNo.setCreateOn(LocalDateTime.now()); + vehicleEquipmentNo.setUpdateBy(1L); + vehicleEquipmentNo.setUpdateOn(LocalDateTime.now()); + addDataList.add(vehicleEquipmentNo); + } + vehicleEquipmentNoService.saveBatch(addDataList); + }); + } + // 删除:实时视频设备表中没有车牌号而同步设备表中有 + Set delCarPlates = carPlates.stream().filter(d -> !deviceCarPlates.contains(d)).collect(Collectors.toSet()); + if (CollUtil.isNotEmpty(delCarPlates)){ + vehicleEquipmentNoService.remove(Wrappers.lambdaQuery(VehicleEquipmentNo.class) + .in(VehicleEquipmentNo::getCarPlate, delCarPlates)); + } + + // 更新:实时视频设备表和同步设备编号表中对应车牌号下对应ID的设备编号、设备状态不一致或者不存在 + for (Map.Entry> entry : dataMap.entrySet()) { + String carPlate = entry.getKey(); + List equipmentNos = entry.getValue(); + List dataAccessDevices = devicesDataMap.get(carPlate); + + // 如果当前车牌号对应的设备编号及设备状态完全相同,则不做任何操作 + Set data = equipmentNos.stream().map(e -> e.getDeviceId() + StrPool.DASH + e.getStatus()).collect(Collectors.toSet()); + Set deviceData = dataAccessDevices.stream().map(d -> { + String status = d.getStatus(); + if (StrPool.EMPTY.equals(status)) { + status = StrPool.NULL; + } + return d.getDeviceId() + StrPool.DASH + status; + }).collect(Collectors.toSet()); + if (data.equals(deviceData)) { + log.info("车牌号:{}下的设备编号及设备状态完全相同,无需更新", carPlate); + continue; + } + + Map equipmentNoMap = equipmentNos.stream().collect(Collectors.toMap(e -> e.getDeviceId() + StrPool.DASH + e.getPlatformId(), e -> e)); + Map dataAccessDevicesMap = dataAccessDevices.stream().collect(Collectors.toMap(d -> d.getDeviceId() + StrPool.DASH + d.getPlatformId(), d -> d)); + + // 如果对应车牌号下的设备数不为0,先删除再保存 + if (CollUtil.isNotEmpty(equipmentNoMap) && CollUtil.isNotEmpty(dataAccessDevicesMap)) { + vehicleEquipmentNoService.remove(Wrappers.lambdaQuery(VehicleEquipmentNo.class) + .eq(VehicleEquipmentNo::getCarPlate, carPlate)); + int index = 1; + List addDataList = Lists.newArrayList(); + for (Map.Entry devicesEntry : dataAccessDevicesMap.entrySet()) { + String[] split = devicesEntry.getKey().split(StrPool.DASH); + String addEquipNo = split[0]; + DataAccessDevices accessDevices = devicesEntry.getValue(); + VehicleEquipmentNo vehicleEquipmentNo = new VehicleEquipmentNo(); + vehicleEquipmentNo.setCarPlate(carPlate); + vehicleEquipmentNo.setDeviceId(addEquipNo); + vehicleEquipmentNo.setDeviceName(carPlate + StrPool.DASH + DefValConstants.TONG_DAO + index++); + if (Objects.nonNull(accessDevices)){ + String status = accessDevices.getStatus(); + if (StringUtils.isNotBlank(status)) { + vehicleEquipmentNo.setStatus(status); + } + } + vehicleEquipmentNo.setPlatformId(accessDevices.getPlatformId()); + vehicleEquipmentNo.setCreateBy(1L); + vehicleEquipmentNo.setCreateOn(LocalDateTime.now()); + vehicleEquipmentNo.setUpdateBy(1L); + vehicleEquipmentNo.setUpdateOn(LocalDateTime.now()); + addDataList.add(vehicleEquipmentNo); + } + vehicleEquipmentNoService.saveBatch(addDataList); + + } + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.java new file mode 100644 index 0000000..b8a12ca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.equipment.mapper; + +import com.ningdatech.carapi.car.equipment.model.DataAccessDevices; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2023-05-17 + */ +public interface DataAccessDevicesMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.xml new file mode 100644 index 0000000..ee5a7d4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/DataAccessDevicesMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.java new file mode 100644 index 0000000..2d251d2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.equipment.mapper; + +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleEquipmentChannelsMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.xml new file mode 100644 index 0000000..46f1967 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentChannelsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.java new file mode 100644 index 0000000..c31603c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.equipment.mapper; + +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleEquipmentInfoMapper extends BaseMapper { + + Boolean insertBatch(@Param("list") List toAddEp); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.xml new file mode 100644 index 0000000..d672136 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + INSERT INTO nd_vehicle_equipment_info + (name, + sim_card_no, + end_point, + equipment_no, + equipment_function, + end_type, + subordinate_platform, + vehicle_id, + car_plate + ) + values + + ( + #{item.name}, + #{item.simCardNo}, + #{item.endPoint}, + #{item.equipmentNo}, + #{item.equipmentFunction}, + #{item.endType}, + #{item.subordinatePlatform}, + #{item.vehicleId}, + #{item.carPlate} + ) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentJoinMapper.java new file mode 100644 index 0000000..625d6bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/NdVehicleEquipmentJoinMapper.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.car.equipment.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentJoin; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleEquipmentJoinMapper extends BaseMapper { + String QUERY_SQL = "SELECT eq.*,b.vehicle_type,c.id as company_id,c.name as company_name,o.name as operator_name," + + "c.region_id,b.audit_state" + + " FROM nd_vehicle_equipment_info AS eq " + + " LEFT JOIN nd_vehicle_base_info AS b ON eq.vehicle_id = b.id " + + " LEFT JOIN nd_company_info AS c ON b.company_id = c.id " + + " LEFT JOIN nd_operator_info AS o ON b.operator_id = o.id "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoinBaseInfo(Page page, @Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.java new file mode 100644 index 0000000..ec2d003 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.equipment.mapper; + +import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2024-02-23 + */ +public interface VehicleEquipmentNoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.xml new file mode 100644 index 0000000..db3129f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/mapper/VehicleEquipmentNoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/DataAccessDevices.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/DataAccessDevices.java new file mode 100644 index 0000000..34be19f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/DataAccessDevices.java @@ -0,0 +1,115 @@ +package com.ningdatech.carapi.car.equipment.model; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2023-05-17 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("nd_data_access_devices") +@ApiModel(value = "DataAccessDevices对象", description = "") +public class DataAccessDevices implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private Long addtime; + + private Long uptime; + + private Long deltime; + + private String deviceId; + + private String name; + + private String manufacturer; + + private String model; + + private String owner; + + private String civilCode; + + private String address; + + private Integer parental; + + private String parentId; + + private Integer safetyWay; + + private Integer registerWay; + + private String certnum; + + private Integer certifiable; + + private Integer errCode; + + private String endTime; + + private Integer secrecy; + + private String ipAddress; + + private String port; + + private String password; + + private String status; + + private String longitude; + + private String latitude; + + private String resolution; + + private String firmware; + + private String channel; + + private String platformId; + + private String region; + + private String host; + + private String transport; + + private String proto; + + private String report; + + private String raddr; + + private String deviceType; + + private String uri; + + private String active; + + private String source; + + private String url; + + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentChannels.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentChannels.java new file mode 100644 index 0000000..b1f7b13 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentChannels.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.car.equipment.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_equipment_channels") +@Data +public class NdVehicleEquipmentChannels extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 通道名称 + */ + private String name; + + /** + * 位置 + */ + private String location; + + /** + * 备注 + */ + private String remark; + + /** + * 车辆设备ID + */ + private Long equipmentId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentInfo.java new file mode 100644 index 0000000..43d2177 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentInfo.java @@ -0,0 +1,143 @@ +package com.ningdatech.carapi.car.equipment.model; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_equipment_info") +@Data +@ApiModel(value = "NdVehicleBaseInfo", description = "车辆档案-车辆设备信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleEquipmentInfo extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String name; + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + @TableField(value = "sim_card_no") + private String simCardNo; + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + @TableField(value = "end_point") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + @TableField(value = "equipment_no") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + @TableField(value = "equipment_function") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + @TableField(value = "end_type") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + @TableField(value = "subordinate_platform") + private String subordinatePlatform; + + /** + * 车辆ID + */ + @ApiModelProperty("车辆ID") + @TableField(value = "vehicle_id") + private Long vehicleId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 车牌类型 + */ + @ApiModelProperty("车牌类型") + @TableField(exist = false) + private Long vehicleType; + + /** + * 企业名称 + */ + @ApiModelProperty("企业名称") + @TableField(exist = false) + private String companyName; + + /** + * 运营商名称 + */ + @ApiModelProperty("运营商名称") + @TableField(exist = false) + private String operatorName; + + + /** + * 区域id + */ + @ApiModelProperty("区域id") + @TableField(exist = false) + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(exist = false) + private String regionName; + + /** + * 平台ID + */ + @ApiModelProperty("平台ID") + @TableField(value = "platform_id") + private String platformId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentJoin.java new file mode 100644 index 0000000..1799c5b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/NdVehicleEquipmentJoin.java @@ -0,0 +1,145 @@ +package com.ningdatech.carapi.car.equipment.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_equipment_info") +@Data +@ApiModel(value = "NdVehicleBaseInfo", description = "车辆档案-车辆设备信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleEquipmentJoin extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + @TableField(value = "sim_card_no") + private String simCardNo; + + + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + @TableField(value = "end_point") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + @TableField(value = "equipment_no") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + @TableField(value = "equipment_function") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + @TableField(value = "end_type") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + @TableField(value = "subordinate_platform") + private String subordinatePlatform; + + /** + * 车辆ID + */ + @ApiModelProperty("车辆ID") + @TableField(value = "vehicle_id") + private Long vehicleId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 车牌类型 + */ + @ApiModelProperty("车牌类型") + private Long vehicleType; + + /** + * 企业名称 + */ + @ApiModelProperty("企业id") + private Long companyId; + + /** + * 企业名称 + */ + @ApiModelProperty("企业名称") + private String companyName; + + /** + * 运营商名称 + */ + @ApiModelProperty("运营商名称") + private String operatorName; + + + /** + * 区域id + */ + @ApiModelProperty("区域id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(exist = false) + private String regionName; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + private Long auditState; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/VehicleEquipmentNo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/VehicleEquipmentNo.java new file mode 100644 index 0000000..d87eb8b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/VehicleEquipmentNo.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.car.equipment.model; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2024-02-23 + */ +@Data +@TableName("nd_vehicle_equipment_no") +@ApiModel(value = "VehicleEquipmentNo对象", description = "") +public class VehicleEquipmentNo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("设备编号") + private String deviceId; + + @ApiModelProperty("设备名称") + private String deviceName; + + @ApiModelProperty("设备状态 ON 在线、OFF 离线") + private String status; + + @ApiModelProperty("平台ID") + private String platformId; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentChannelsSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentChannelsSaveDTO.java new file mode 100644 index 0000000..ae30177 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentChannelsSaveDTO.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.car.equipment.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "EquipmentChannelsSaveDTO", description = "车辆设备通道") +public class EquipmentChannelsSaveDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 通道名称 + */ + @ApiModelProperty("通道名称") + private String name; + + /** + * 位置 + */ + @ApiModelProperty("位置") + private String location; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentSaveDTO.java new file mode 100644 index 0000000..3c99980 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentSaveDTO.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.car.equipment.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 车辆信息 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "EquipmentSaveDTO", description = "车辆设备保存") +public class EquipmentSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + private String simCardNo; + + private String name; + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + private String subordinatePlatform; + + /** + * 车辆ID + */ + @ApiModelProperty("车辆ID") + @NotNull(message = "请传车辆id") + private Long vehicleId; + + @ApiModelProperty("设备通道") + private List channels; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentUpdateDTO.java new file mode 100644 index 0000000..0749e34 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/EquipmentUpdateDTO.java @@ -0,0 +1,81 @@ +package com.ningdatech.carapi.car.equipment.model.dto; + +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 车辆设备 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "EquipmentUpdateDTO", description = "车辆设备编辑") +public class EquipmentUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "请传id") + private Long id; + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + private String simCardNo; + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + private String subordinatePlatform; + + /** + * 车辆ID + */ + @ApiModelProperty("车辆ID") + private Long vehicleId; + + @ApiModelProperty("设备通道") + private List channels; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentDTO.java new file mode 100644 index 0000000..5fb59de --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentDTO.java @@ -0,0 +1,119 @@ +package com.ningdatech.carapi.car.equipment.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.TableField; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@ApiModel(value = "VehicleEquipmentDTO", description = "车辆档案-车辆设备DTO") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleEquipmentDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @ExcelProperty("ID") + private Long id; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("所属企业ID") + @ExcelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("所属企业名称") + @ExcelProperty("所属企业名称") + private String companyName; + + @ApiModelProperty("行政区域id") + @ExcelProperty("行政区域id") + private Long regionId; + + @ApiModelProperty("行政区域名称") + @ExcelProperty("行政区域名称") + private String regionName; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("设备ID") + @ExcelProperty("设备ID") + private Long equipmentId; + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + @ExcelProperty("SIM卡号") + private String simCardNo; + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + @ExcelProperty("终端号") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + @ExcelProperty("设备号") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + @ExcelProperty("设备功能") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + @ExcelProperty("终端类型") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + @ExcelProperty("下级平台") + private String subordinatePlatform; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentPageQuery.java new file mode 100644 index 0000000..ea999c9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentPageQuery.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.equipment.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 实体类 + * 车辆设备 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleEquipmentPageQuery", description = "车辆设备") +public class VehicleEquipmentPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 车牌号 + */ + @ApiModelProperty(value = "车牌号") + private String carPlate; + + /** + * 所属企业名 + */ + @ApiModelProperty(value = "所属企业名") + private String companyName; + + /** + * 车辆类型 + */ + @ApiModelProperty(value = "车辆类型") + private Integer vehicleType; + + /** + * 所属区域id + */ + @ApiModelProperty(value = "所属区域id") + private Long regionId; + + + /** + * 运营商名 + */ + @ApiModelProperty(value = "运营商名") + private String operatorName; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentQueryDTO.java new file mode 100644 index 0000000..1331d40 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/dto/VehicleEquipmentQueryDTO.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.car.equipment.model.dto; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import lombok.Builder; +import lombok.Data; +import lombok.ToString; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_equipment_info") +@Data +@Builder +@ToString +public class VehicleEquipmentQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + private String name; + + /** + * 创建时间 + */ + private LocalDateTime createOn; + + /** + * 创建人 + */ + private Long createBy; + + /** + * 修改时间 + */ + private LocalDateTime updateOn; + + /** + * 修改人 + */ + private Long updateBy; + + /** + * SIM卡号 + */ + private String simCardNo; + + /** + * 终端号 + */ + private String endPoint; + + /** + * 设备号 + */ + private String equipmentNo; + + /** + * 设备功能 + */ + private String equipmentFunction; + + /** + * 终端类型 + */ + private String endType; + + /** + * 下级平台 + */ + private Long subordinatePlatform; + private String subordinatePlatformName; + + /** + * 车辆ID + */ + private Long vehicleId; + + private List channels; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipApiResponse.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipApiResponse.java new file mode 100644 index 0000000..0d967e0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipApiResponse.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.equipment.model.res; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.util.List; + +/** + * @Classname SipApiResponse + * @Description + * @Date 2023/3/23 14:20 + * @Author PoffyZhang + */ +@Data +@ApiModel(value = "SIP结果返回Api",description = "SIP结果返回Api") +public class SipApiResponse { + + private Integer status_code; + private String status; + private String message; + private Long t; + private List result; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipEquipmentRes.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipEquipmentRes.java new file mode 100644 index 0000000..79878f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/res/SipEquipmentRes.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.car.equipment.model.res; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @Classname SipEquipmentRes + * @Description + * @Date 2023/3/23 14:20 + * @Author PoffyZhang + */ +@Data +@ApiModel(value = "请求车辆GPS设备信息结果返回",description = "请求车辆GPS设备信息结果返回") +public class SipEquipmentRes { + + private String device_id; + private String name; + private String manufacturer; + private String model; + private String owner; + private String civil_code; + private String address; + private Integer parental; + private String parent_id; + private Integer safety_way; + private Integer register_way; + private String certnum; + private Integer certifiable; + private Integer err_code; + private String end_time; + private Integer secrecy; + private String ip_address; + private String port; + private String password; + private String status; + private String longitude; + private String latitude; + private String resolution; + private String firmware; + private String Channel; + private String platform_id; + private String region; + private String host; + private String transport; + private String proto; + private String report; + private String raddr; + private String device_type; + private String uri; + private String active; + private String source; + private String uurlri; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/NdVehicleEquipmentVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/NdVehicleEquipmentVO.java new file mode 100644 index 0000000..d1ad86a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/NdVehicleEquipmentVO.java @@ -0,0 +1,115 @@ +package com.ningdatech.carapi.car.equipment.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleEquipmentVO", description = "车辆档案-车辆设备信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleEquipmentVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + private String simCardNo; + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + private String subordinatePlatform; + + /** + * 车辆ID + */ + @ApiModelProperty("车辆ID") + private Long vehicleId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 车牌类型 + */ + @ApiModelProperty("车牌类型") + private Long vehicleType; + + /** + * 企业名称 + */ + @ApiModelProperty("企业名称") + private String companyName; + + /** + * 运营商名称 + */ + @ApiModelProperty("运营商名称") + private String operatorName; + + + /** + * 区域id + */ + @ApiModelProperty("区域id") + private String regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/VehicleEquipmentVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/VehicleEquipmentVO.java new file mode 100644 index 0000000..48b4768 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/model/vo/VehicleEquipmentVO.java @@ -0,0 +1,121 @@ +package com.ningdatech.carapi.car.equipment.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@ApiModel(value = "VehicleEquipmentVO", description = "车辆档案-车辆信息VO") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleEquipmentVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + private String name; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("所属企业名称") + private String companyName; + + @ApiModelProperty("行政区域id") + private Long regionId; + + @ApiModelProperty("行政区域名称") + private String regionName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("设备ID") + private Long equipmentId; + + /** + * SIM卡号 + */ + @ApiModelProperty("SIM卡号") + @TableField(value = "sim_card_no") + private String simCardNo; + + /** + * 终端号 + */ + @ApiModelProperty("终端号") + @TableField(value = "end_point") + private String endPoint; + + /** + * 设备号 + */ + @ApiModelProperty("设备号") + @TableField(value = "equipment_no") + private String equipmentNo; + + /** + * 设备功能 + */ + @ApiModelProperty("设备功能") + @TableField(value = "equipment_function") + private String equipmentFunction; + + /** + * 终端类型 + */ + @ApiModelProperty("终端类型") + @TableField(value = "end_type") + private String endType; + + /** + * 下级平台 + */ + @ApiModelProperty("下级平台") + @TableField(value = "subordinate_platform") + private String subordinatePlatform; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("车辆状态名称") + private String vehicleStatusName; + + @ApiModelProperty("车辆最后上线时间") + private LocalDateTime lastOnlineTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IDataAccessDevicesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IDataAccessDevicesService.java new file mode 100644 index 0000000..e014e10 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IDataAccessDevicesService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.equipment.service; + +import com.ningdatech.carapi.car.equipment.model.DataAccessDevices; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2023-05-17 + */ +public interface IDataAccessDevicesService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentChannelsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentChannelsService.java new file mode 100644 index 0000000..e76cec6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentChannelsService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.equipment.service; + +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleEquipmentChannelsService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentInfoService.java new file mode 100644 index 0000000..a4c30cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentInfoService.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.car.equipment.service; + +import com.ningdatech.carapi.car.equipment.model.dto.EquipmentSaveDTO; +import com.ningdatech.carapi.car.equipment.model.dto.EquipmentUpdateDTO; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.equipment.model.res.SipApiResponse; +import com.ningdatech.carapi.car.equipment.model.res.SipEquipmentRes; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleEquipmentInfoService extends IService { + void save(List equipments, Long uerId); + + void update(EquipmentUpdateDTO equipmentUpdateDTO, Long uerId); + + Boolean removeByIdWithCache(List ids); + + List getSipEquipmentsByCarPlate(String carPlate); + + Boolean insertBatch(List toAddEp); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentJoinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentJoinService.java new file mode 100644 index 0000000..1ab38b9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/INdVehicleEquipmentJoinService.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.equipment.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentJoin; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleEquipmentJoinService extends IService { + + Page pageJoinBaseInfo(Page page, LambdaQueryWrapper wrapper); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IVehicleEquipmentNoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IVehicleEquipmentNoService.java new file mode 100644 index 0000000..361628b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/IVehicleEquipmentNoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.equipment.service; + +import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2024-02-23 + */ +public interface IVehicleEquipmentNoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/DataAccessDevicesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/DataAccessDevicesServiceImpl.java new file mode 100644 index 0000000..e9fafdb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/DataAccessDevicesServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.equipment.service.impl; + +import com.ningdatech.carapi.car.equipment.model.DataAccessDevices; +import com.ningdatech.carapi.car.equipment.mapper.DataAccessDevicesMapper; +import com.ningdatech.carapi.car.equipment.service.IDataAccessDevicesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2023-05-17 + */ +@Service +public class DataAccessDevicesServiceImpl extends ServiceImpl implements IDataAccessDevicesService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentChannelsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentChannelsServiceImpl.java new file mode 100644 index 0000000..32d9c8f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentChannelsServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.equipment.service.impl; + +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.mapper.NdVehicleEquipmentChannelsMapper; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentChannelsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdVehicleEquipmentChannelsServiceImpl extends ServiceImpl implements INdVehicleEquipmentChannelsService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentInfoServiceImpl.java new file mode 100644 index 0000000..1fa353f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentInfoServiceImpl.java @@ -0,0 +1,185 @@ +package com.ningdatech.carapi.car.equipment.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.http.HttpStatus; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Maps; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.carapi.car.equipment.model.dto.EquipmentSaveDTO; +import com.ningdatech.carapi.car.equipment.model.dto.EquipmentUpdateDTO; +import com.ningdatech.carapi.car.equipment.model.res.SipApiResponse; +import com.ningdatech.carapi.car.equipment.model.res.SipEquipmentRes; +import com.ningdatech.carapi.car.position.contants.PositionContant; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.equipment.mapper.NdVehicleEquipmentChannelsMapper; +import com.ningdatech.carapi.car.equipment.mapper.NdVehicleEquipmentInfoMapper; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class NdVehicleEquipmentInfoServiceImpl extends ServiceImpl implements INdVehicleEquipmentInfoService { + + private final NdVehicleEquipmentChannelsMapper equipmentChannelsMapper; + private final VehicleBaseInfoMapper vehicleBaseInfoMapper; + + private final NdVehicleEquipmentInfoMapper equipmentInfoMapper; + + private final RestTemplate restTemplate; + + @Value("${vedio.host}") + private String HOST; + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + // 车辆设备 + boolean removeFlag = removeByIds(ids); + + if(removeFlag){ + ids.forEach(id -> { + //删除通道信息 + equipmentChannelsMapper.delete(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class) + .eq(NdVehicleEquipmentChannels::getEquipmentId,id)); + }); + } + + return removeFlag; + } + + @Override + public List getSipEquipmentsByCarPlate(String carPlate) { + SipApiResponse res = null; + Map map = Maps.newConcurrentMap(); + map.put(PositionContant.FIELD_CAR_PLATE, carPlate); + map.put(PositionContant.HOST_FEILD, HOST); + res = restTemplate.getForObject(PositionContant.VEHICLE_DEVICE_URL, SipApiResponse.class, map); + log.info("request equipment 【{}】:", JSON.toJSONString(res)); + Integer statusCode = res.getStatus_code(); + if (null == statusCode || 0 != statusCode) { + return Collections.emptyList(); +// throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), res.getMessage()); + } + return res.getResult(); + } + + @Override + public Boolean insertBatch(List toAddEp) { + return equipmentInfoMapper.insertBatch(toAddEp); + } + + + /** + * 保存车辆 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void save(List datas, Long userId) { + if(CollUtil.isEmpty(datas)){ + return; + } + + Long vehicleId = datas.get(0).getVehicleId(); + List equipments = equipmentInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) + .eq(NdVehicleEquipmentInfo::getVehicleId,vehicleId)); + for(NdVehicleEquipmentInfo equipment : equipments){ + //先删除设备和通道信息 + removeById(equipment.getId()); + equipmentChannelsMapper.delete(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class) + .eq(NdVehicleEquipmentChannels::getEquipmentId,equipment.getId())); + } + + for(EquipmentSaveDTO data : datas){ + if(Objects.isNull(data.getVehicleId())){ + throw new BizException(ExceptionCode.OPERATION_EX.getCode(),String.format("添加车辆id %d 为空",data.getVehicleId())); + } + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMapper.selectById(data.getVehicleId()); + if(Objects.isNull(vehicleBaseInfo)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,String.format("车辆不存在",data.getVehicleId())); + } + if(!AuditStateEnum.AUDIT_SUCCESS.getCode().equals(vehicleBaseInfo.getAuditState())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,String.format("车辆审核成功才能添加设备",data.getVehicleId())); + } + + NdVehicleEquipmentInfo equipmentInfo = BeanUtil.toBean(data, NdVehicleEquipmentInfo.class); + equipmentInfo.setCarPlate(vehicleBaseInfo.getCarPlate()); + //创建人 最后修改人 + equipmentInfo.setCreateBy(userId); + equipmentInfo.setUpdateBy(userId); + save(equipmentInfo); + + if(CollUtil.isNotEmpty(data.getChannels())){ + data.getChannels().forEach(channel ->{ + NdVehicleEquipmentChannels equipmentChannel = BeanUtil.toBean(channel, NdVehicleEquipmentChannels.class); + equipmentChannel.setEquipmentId(equipmentInfo.getId()); + equipmentChannel.setCreateBy(userId); + equipmentChannel.setUpdateBy(userId); + equipmentChannelsMapper.insert(equipmentChannel); + }); + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(EquipmentUpdateDTO data, Long userId) { + NdVehicleEquipmentInfo equipmentInfo = getById(data.getId()); + if (Objects.isNull(equipmentInfo)) { + throw new BaseUncheckedException(HttpStatus.HTTP_OK, String.format("修改车辆设备%d 为空", data.getId())); + } + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMapper.selectById(data.getVehicleId()); + if (Objects.isNull(vehicleBaseInfo)) { + throw new BaseUncheckedException(HttpStatus.HTTP_OK, String.format("车辆不存在", data.getVehicleId())); + } + if (!AuditStateEnum.AUDIT_SUCCESS.getCode().equals(vehicleBaseInfo.getAuditState())) { + throw new BaseUncheckedException(HttpStatus.HTTP_OK, String.format("车辆审核成功才能修改设备", data.getVehicleId())); + } + NdVehicleEquipmentInfo equipment = BeanUtil.toBean(data, NdVehicleEquipmentInfo.class); + //最后修改人 + equipment.setUpdateBy(userId); + updateById(equipment); + + if (CollUtil.isNotEmpty(data.getChannels())) { + //先删除通道信息 + equipmentChannelsMapper.delete(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class) + .eq(NdVehicleEquipmentChannels::getEquipmentId, equipmentInfo.getId())); + data.getChannels().forEach(channel -> { + channel.setEquipmentId(equipmentInfo.getId()); + channel.setCreateBy(userId); + channel.setUpdateBy(userId); + equipmentChannelsMapper.insert(channel); + }); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentJoinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentJoinServiceImpl.java new file mode 100644 index 0000000..03883ad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/NdVehicleEquipmentJoinServiceImpl.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.car.equipment.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentJoin; +import com.ningdatech.carapi.car.equipment.mapper.NdVehicleEquipmentJoinMapper; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentJoinService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class NdVehicleEquipmentJoinServiceImpl extends ServiceImpl implements INdVehicleEquipmentJoinService { + + private final NdVehicleEquipmentJoinMapper vehicleEquipmentJoinMapper; + + @Override + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL,wrapperIndex = 1) + public Page pageJoinBaseInfo(Page page, LambdaQueryWrapper wrapper) { + return vehicleEquipmentJoinMapper.pageJoinBaseInfo(page,wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/VehicleEquipmentNoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/VehicleEquipmentNoServiceImpl.java new file mode 100644 index 0000000..bbb9921 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/equipment/service/impl/VehicleEquipmentNoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.equipment.service.impl; + +import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo; +import com.ningdatech.carapi.car.equipment.mapper.VehicleEquipmentNoMapper; +import com.ningdatech.carapi.car.equipment.service.IVehicleEquipmentNoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2024-02-23 + */ +@Service +public class VehicleEquipmentNoServiceImpl extends ServiceImpl implements IVehicleEquipmentNoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/controller/StatusMonitorController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/controller/StatusMonitorController.java new file mode 100644 index 0000000..da748b7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/controller/StatusMonitorController.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.car.monitor.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.monitor.manage.StatusMonitorManage; +import com.ningdatech.carapi.car.monitor.model.dto.LoadMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.dto.SecurityMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.vo.AlarmDataLoadVO; +import com.ningdatech.carapi.car.monitor.model.vo.SecurityMonitorVO; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.sys.entity.dto.CascadeCodeDTO; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + * @Classname SecurityMonitorController + * @Description + * @Date 2022/11/4 16:30 + * @Created by PoffyZhang + */ +@RestController +@RequestMapping(value = "/api/v1/car-manage/status-monitor") +@Api(tags = "车辆管理-状态监控") +@Validated +@RequiredArgsConstructor +public class StatusMonitorController { + + private final StatusMonitorManage statusMonitorManage; + + @ApiOperation("安全监控") + @GetMapping("/security-monitor-list") + public PageVo securityMonitorList( + @Valid @ModelAttribute SecurityMonitorPageParamDTO param) { + return statusMonitorManage.securityMonitorList(param); + } + + @ApiOperation("告警事件类型列表") + @GetMapping("/alarm-types") + public List alarmTypes() { + return statusMonitorManage.alarmTypes(); + } + + @ApiOperation("载重监控") + @GetMapping("/load-monitor-list") + public PageVo loadMonitorList( + @Valid @ModelAttribute LoadMonitorPageParamDTO param) { + return statusMonitorManage.loadMonitorList(param); + } + + @ApiOperation(value = "安全监控导出", notes = "安全监控导出") + @GetMapping("/export-security-monitor") + @WebLog + public void exportSecurityMonitor(SecurityMonitorPageParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, statusMonitorManage::exportSecurityMonitor); + } + + @ApiOperation(value = "载重监控导出", notes = "载重监控导出") + @GetMapping("/export-load-monitor") + @WebLog + public void exportLoadMonitor(LoadMonitorPageParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, statusMonitorManage::exportLoadMonitor); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/AlarmDataLoad.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/AlarmDataLoad.java new file mode 100644 index 0000000..460deb4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/AlarmDataLoad.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.car.monitor.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 异常告警 载重 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@TableName("nd_alarm_data_load") +@ApiModel(value = "AlarmDataLoad对象", description = "异常告警 载重") +@Data +public class AlarmDataLoad extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车牌号") + private String plateNo; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("区域id") + private String regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("告警事件ID") + private String alarmId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆自重 吨") + private Double kerbWeight; + + @ApiModelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("标准吨位") + private Double standardTonnage; + + @ApiModelProperty("运营商名字") + private String operatorName; + + @ApiModelProperty("运量 吨") + private Double freightVolume; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarn.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarn.java new file mode 100644 index 0000000..ea4baac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarn.java @@ -0,0 +1,94 @@ +package com.ningdatech.carapi.car.monitor.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 报警预警表 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +@TableName("nd_data_access_alarm_warn") +@ApiModel(value = "DataAccessAlarmWarn对象", description = "报警预警表") +@Data +public class DataAccessAlarmWarn implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("发起报警平台的唯一编号") + private String platformId; + + @ApiModelProperty("报警类型,详情参考jtt809-809表3-4") + private Integer warnType; + + @ApiModelProperty("报警时间") + private LocalDateTime warnTime; + + @ApiModelProperty("事件开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("事件结束时间") + private LocalDateTime endTime; + + @ApiModelProperty("车牌号码") + private String vehicleNo; + + @ApiModelProperty("车牌颜色") + private Integer vehicleColor; + + @ApiModelProperty("被报警平台的唯一编号") + private String platformId1; + + @ApiModelProperty("线路ID") + private String drvLineId; + + @ApiModelProperty("报警预警内容") + private String content; + + @ApiModelProperty("是否是主动上报 0:下发 1:主动上报") + private Boolean isActiveReport; + + @ApiModelProperty("发起报警的序列号 (可能分为开始结束)") + private Integer msgSeq; + + @ApiModelProperty("处理结果") + private Integer resultCode; + + @ApiModelProperty("报警唯一序号") + private Long alarmMsgSn; + + @ApiModelProperty("0: 瞬时报警; 1:报警开始; 2: 报警结束 ") + private Integer eventStatus; + + @ApiModelProperty("0: 无文件 1: 有文件等待下发 2:已下发 3:已上报 ") + private Boolean fileReport; + + @ApiModelProperty("平台id") + private Long gnssCenterId; + + @ApiModelProperty("告警类型") + private Integer bgType; + + @ApiModelProperty("告警级别") + private Integer grade; + + @ApiModelProperty("速度") + private Integer speed; + + @ApiModelProperty("告警地点") + private String address; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarnFile.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarnFile.java new file mode 100644 index 0000000..f6286dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/DataAccessAlarmWarnFile.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.car.monitor.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +@TableName("nd_data_access_alarm_warn_file") +@ApiModel(value = "DataAccessAlarmWarnFile对象", description = "") +@Data +public class DataAccessAlarmWarnFile implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private Long alarmMsgSn; + + private Integer fileType; + + private Integer fileFormat; + + private String filePath; + + private String srcPath; + + private Long gnssCenterId; + + private LocalDateTime createTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/SecurityMonitorJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/SecurityMonitorJoin.java new file mode 100644 index 0000000..08a69a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/SecurityMonitorJoin.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.car.monitor.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Classname SecurityMonitorJoin + * @Description + * @Date 2022/11/6 20:59 + * @Created by PoffyZhang + */ +@Data +public class SecurityMonitorJoin implements Serializable { + @ApiModelProperty("告警事件id") + private Long alarmId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("事件类型") + private String alarmType; + + @ApiModelProperty("告警时间") + private String alarmTime; + + @ApiModelProperty("地址") + private String alarmAddress; + + @ApiModelProperty("图片链接") + private String pictureUrl; + + @ApiModelProperty("视频链接") + private String videoUrl; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/VehicleSecurityMonitor.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/VehicleSecurityMonitor.java new file mode 100644 index 0000000..d24e102 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/entity/VehicleSecurityMonitor.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.car.monitor.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆安全监控 + *

+ * + * @author PoffyZhang + * @since 2022-12-07 + */ +@TableName("nd_vehicle_security_monitor") +@ApiModel(value = "VehicleSecurityMonitor对象", description = "车辆安全监控") +@Data +public class VehicleSecurityMonitor implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("告警事件id") + private Long alarmId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("公司名") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("告警类型") + private Integer alarmType; + + @ApiModelProperty("告警类型名") + private String alarmTypeName; + + @ApiModelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("告警地址") + private String alarmAddress; + + @ApiModelProperty("图片地址") + private String pictureUrl; + + @ApiModelProperty("视频地址") + private String videoUrl; + + @ApiModelProperty("级别") + private Integer alarmLevel; + + private Long operatorId; + private BigDecimal speed; + + private BigDecimal longitude; + private BigDecimal latitude; + private Integer deleted; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/manage/StatusMonitorManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/manage/StatusMonitorManage.java new file mode 100644 index 0000000..b173a8e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/manage/StatusMonitorManage.java @@ -0,0 +1,186 @@ +package com.ningdatech.carapi.car.monitor.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.monitor.entity.AlarmDataLoad; +import com.ningdatech.carapi.car.monitor.entity.VehicleSecurityMonitor; +import com.ningdatech.carapi.car.monitor.model.dto.AlarmDataLoadDTO; +import com.ningdatech.carapi.car.monitor.model.dto.LoadMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.dto.SecurityMonitorExportDTO; +import com.ningdatech.carapi.car.monitor.model.dto.SecurityMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.vo.AlarmDataLoadVO; +import com.ningdatech.carapi.car.monitor.model.vo.SecurityMonitorVO; +import com.ningdatech.carapi.car.monitor.service.IAlarmDataLoadService; +import com.ningdatech.carapi.car.monitor.service.IVehicleSecurityMonitorService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.BgTypeEnum; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.sys.entity.dto.CascadeCodeDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @Classname StatusMonitorManage + * @Description + * @Date 2022/11/4 16:30 + * @Created by PoffyZhang + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class StatusMonitorManage { + + private final IAlarmDataLoadService alarmDataLoadService; + private final IVehicleSecurityMonitorService vehicleSecurityMonitorService; + private final RegionsCacheHelper regionsCacheHelper; + + public PageVo securityMonitorList(SecurityMonitorPageParamDTO param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleSecurityMonitor.class); + wrapper.in(VehicleSecurityMonitor::getAlarmType, BgTypeEnum.listCode(false)); + ((StatusMonitorManage) AopContext.currentProxy()).searchSecurityMonitor(page, wrapper, param); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), this::convert); + return PageVo.of(data, page.getTotal()); + } + + public PageVo loadMonitorList(LoadMonitorPageParamDTO param) { + Page page = param.page(); + searchLoad(page, param); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), this::convertLoad); + return PageVo.of(data, page.getTotal()); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchSecurityMonitor(Page page, LambdaQueryWrapper wrapper + , SecurityMonitorPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCarPlate()), VehicleSecurityMonitor::getCarPlate, param.getCarPlate()) + .eq(Objects.nonNull(param.getVehicleType()), VehicleSecurityMonitor::getVehicleType, param.getVehicleType()) + .ge(Objects.nonNull(param.getStartTime()), VehicleSecurityMonitor::getAlarmTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), VehicleSecurityMonitor::getAlarmTime, param.getEndTime()) + .eq(Objects.nonNull(param.getAlarmType()), VehicleSecurityMonitor::getAlarmType, param.getAlarmType()) + .orderBy(Boolean.TRUE, Boolean.FALSE, VehicleSecurityMonitor::getAlarmTime); + vehicleSecurityMonitorService.page(page, wrapper); + } + + private void searchLoad(Page page, LoadMonitorPageParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(AlarmDataLoad.class); + StatusMonitorManage clazz = (StatusMonitorManage) AopContext.currentProxy(); + clazz.searchLoadWrapper(page, wrapper, param); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchLoadWrapper(Page page, LambdaQueryWrapper wrapper, LoadMonitorPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getPlateNo()), AlarmDataLoad::getPlateNo, param.getPlateNo()) + .ge(Objects.nonNull(param.getStartTime()), AlarmDataLoad::getAlarmTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), AlarmDataLoad::getAlarmTime, param.getEndTime()) + .orderBy(Boolean.TRUE, Boolean.FALSE, AlarmDataLoad::getAlarmTime); + alarmDataLoadService.page(page, wrapper); + } + + private SecurityMonitorVO convert(VehicleSecurityMonitor securityMonitor) { + if (Objects.isNull(securityMonitor)) { + return null; + } + SecurityMonitorVO vo = BeanUtil.copyProperties(securityMonitor, SecurityMonitorVO.class); + if (StrUtil.startWith(vo.getPictureUrl(), StrPool.HTTP)) { + vo.setPictureUrl(null); + } + if (StrUtil.startWith(vo.getVideoUrl(), StrPool.HTTP)) { + vo.setVideoUrl(null); + } + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + private AlarmDataLoadVO convertLoad(AlarmDataLoad data) { + if (Objects.isNull(data)) { + return null; + } + AlarmDataLoadVO vo = BeanUtil.copyProperties(data, AlarmDataLoadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + public List alarmTypes() { + return Arrays.stream(BgTypeEnum.values()) + .filter(w -> !w.getHidden()) + .map(w -> CascadeCodeDTO.of(String.valueOf(w.getCode()), w.getDesc())) + .collect(Collectors.toList()); + } + + public void exportSecurityMonitor(HttpServletResponse response, SecurityMonitorPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = securityMonitorList(param); + List collect = page.getRecords().stream() + .map(w -> { + SecurityMonitorExportDTO monitorExportDTO = new SecurityMonitorExportDTO(); + BeanUtils.copyProperties(w, monitorExportDTO); + String timeStr = NdDateUtils.format(w.getAlarmTime(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + monitorExportDTO.setAlarmTime(timeStr); + return monitorExportDTO; + }) + .collect(Collectors.toList()); + String fileName = "状态监控列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), SecurityMonitorExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void exportLoadMonitor(HttpServletResponse response, LoadMonitorPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = loadMonitorList(param); + List collect = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, AlarmDataLoadVO.class)).collect(Collectors.toList()); + String fileName = "载重监控列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), AlarmDataLoadDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.java new file mode 100644 index 0000000..da76236 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.mapper; + +import com.ningdatech.carapi.car.monitor.entity.AlarmDataLoad; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 异常告警 载重 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface AlarmDataLoadMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.xml new file mode 100644 index 0000000..83f6e2d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/AlarmDataLoadMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.java new file mode 100644 index 0000000..01306bb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.mapper; + +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarnFile; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +public interface DataAccessAlarmWarnFileMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.xml new file mode 100644 index 0000000..8759bb4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnFileMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.java new file mode 100644 index 0000000..d784cb7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.mapper; + +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarn; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 报警预警表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +public interface DataAccessAlarmWarnMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.xml new file mode 100644 index 0000000..6d28eef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/DataAccessAlarmWarnMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/SecurityMonitorJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/SecurityMonitorJoinMapper.java new file mode 100644 index 0000000..800756f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/SecurityMonitorJoinMapper.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.car.monitor.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.monitor.entity.SecurityMonitorJoin; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-08 + */ +public interface SecurityMonitorJoinMapper extends BaseMapper { + + String QUERY_SQL = "SELECT " + + " (case when p.alarm_id is not null then p.alarm_id else v.alarm_id end) alarm_id, " + + " (case when p.plate_no is not null then p.plate_no else v.plate_no end) car_plate, " + + " c.name company_name,c.region_id,b.vehicle_type, " + + " (case when p.alarm_type is not null then p.alarm_type else v.alarm_type end) alarm_type, " + + " (case when p.capture_time is not null then p.capture_time else v.alarm_time end) alarm_time," + + " (case when p.region_name is not null then p.region_name else v.region_name end) alarm_address, " + + " p.url picture_url,v.url video_url " + + " from nd_vehicle_base_info b " + + " left join nd_company_info c on b.company_id = c.id " + + " right join nd_alarm_data_picture p on b.car_plate = p.plate_no " + + " right join nd_alarm_data_video v on p.alarm_id = v.alarm_id " + + " group by " + + " (case when p.alarm_id is not null then p.alarm_id else v.alarm_id end), " + + " (case when p.plate_no is not null then p.plate_no else v.plate_no end), " + + " c.name,c.region_id,b.vehicle_type, " + + " (case when p.alarm_type is not null then p.alarm_type else v.alarm_type end), " + + " (case when p.capture_time is not null then p.capture_time else v.alarm_time end), " + + " (case when p.region_name is not null then p.region_name else v.region_name end),p.url,v.url "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoin(Page page, @Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + SecurityMonitorJoin getOneJoin(@Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.java new file mode 100644 index 0000000..d9ce918 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.mapper; + +import com.ningdatech.carapi.car.monitor.entity.VehicleSecurityMonitor; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆安全监控 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-12-07 + */ +public interface VehicleSecurityMonitorMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.xml new file mode 100644 index 0000000..d612553 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mapper/VehicleSecurityMonitorMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/AlarmDataLoadDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/AlarmDataLoadDTO.java new file mode 100644 index 0000000..bc643c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/AlarmDataLoadDTO.java @@ -0,0 +1,86 @@ +package com.ningdatech.carapi.car.monitor.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 异常告警 载重 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@ApiModel(value = "AlarmDataLoadDTO", description = "异常告警 载重") +@Data +public class AlarmDataLoadDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @ExcelProperty("ID") + private Long id; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String plateNo; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("区域id") + @ExcelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("告警事件ID") + @ExcelProperty("告警事件ID") + private String alarmId; + + @ApiModelProperty("企业ID") + @ExcelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆自重 吨") + @ExcelProperty("车辆自重 吨") + private Double kerbWeight; + + @ApiModelProperty("告警时间") + @ExcelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("标准吨位") + @ExcelProperty("标准吨位") + private Double standardTonnage; + + @ApiModelProperty("运营商名字") + @ExcelProperty("运营商名字") + private String operatorName; + + @ApiModelProperty("运量 吨") + @ExcelProperty("运量 吨") + private Double freightVolume; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/LoadMonitorPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/LoadMonitorPageParamDTO.java new file mode 100644 index 0000000..9310a67 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/LoadMonitorPageParamDTO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.car.monitor.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author PoffyZhang + * @date 2022/11/07 下午2:10 + */ + +@Data +@ApiModel(description = "载重监控分页PARAM DTO") +public class LoadMonitorPageParamDTO extends PagePo implements Serializable { + + @ApiModelProperty("车牌号") + private String plateNo; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorExportDTO.java new file mode 100644 index 0000000..b2d2767 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorExportDTO.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.car.monitor.model.dto; + +import java.io.Serializable; +import java.math.BigDecimal; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +/** + * @Classname SecurityMonitorExportDTO + * @Description + * @Date 2022/11/6 20:59 + * @Created by PoffyZhang + */ +@RequiredArgsConstructor +@Data +public class SecurityMonitorExportDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ExcelProperty("车牌号") + private String carPlate; + + @ExcelProperty("车辆类型") + private String vehicleTypeName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("报警类型") + private String alarmTypeName; + + @ExcelProperty("报警级别") + private String alarmLevelName; + + @ExcelProperty("速度") + private BigDecimal speed; + + @ExcelProperty("报警时间") + private String alarmTime; + + @ExcelProperty("地址") + private String alarmAddress; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorPageParamDTO.java new file mode 100644 index 0000000..5c60d62 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/dto/SecurityMonitorPageParamDTO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.car.monitor.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author PoffyZhang + * @date 2022/11/03 下午2:10 + */ + +@Data +@ApiModel(description = "安全监控分页PARAM DTO") +public class SecurityMonitorPageParamDTO extends PagePo implements Serializable { + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("事件报警类型ID") + private String alarmType; + + @ApiModelProperty("车辆类型ID") + private Long vehicleType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/AlarmDataLoadVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/AlarmDataLoadVO.java new file mode 100644 index 0000000..396470a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/AlarmDataLoadVO.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.car.monitor.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 异常告警 载重 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@ApiModel(value = "AlarmDataLoad对象", description = "异常告警 载重") +@Data +public class AlarmDataLoadVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车牌号") + private String plateNo; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("告警事件ID") + private String alarmId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆自重 吨") + private Double kerbWeight; + + @ApiModelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("标准吨位") + private Double standardTonnage; + + @ApiModelProperty("运营商名字") + private String operatorName; + + @ApiModelProperty("运量 吨") + private Double freightVolume; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/SecurityMonitorVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/SecurityMonitorVO.java new file mode 100644 index 0000000..7e0c35b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/model/vo/SecurityMonitorVO.java @@ -0,0 +1,106 @@ +package com.ningdatech.carapi.car.monitor.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; + +import com.ningdatech.carapi.common.constant.AlarmLevelEnum; +import com.ningdatech.carapi.common.constant.BgTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.RequiredArgsConstructor; + +/** + * @Classname SecurityMonitorVO + * @Description + * @Date 2022/11/6 20:59 + * @Created by PoffyZhang + */ +@RequiredArgsConstructor +@Data +public class SecurityMonitorVO implements Serializable { + + @ApiModelProperty("告警事件id") + private Long alarmId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("事件类型") + private Integer alarmType; + + @ApiModelProperty("事件类型名") + private String alarmTypeName; + + @ApiModelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("地址") + private String alarmAddress; + + @ApiModelProperty("图片链接") + private String pictureUrl; + + @ApiModelProperty("视频链接") + private String videoUrl; + + @ApiModelProperty("级别") + private Integer alarmLevel; + + @ApiModelProperty("速度") + private BigDecimal speed; + + @ApiModelProperty("级别名") + private String alarmLevelName; + + public String getVehicleTypeName(){ + if(Objects.nonNull(this.vehicleType)){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(vehicleType)).ifPresent(v -> + this.vehicleTypeName = v); + return this.vehicleTypeName; + } + return StringUtils.EMPTY; + } + + public String getAlarmTypeName(){ + if(Objects.nonNull(this.alarmType)){ + Optional.ofNullable(BgTypeEnum.getDescByCode(alarmType)).ifPresent(a -> + this.alarmTypeName = a); + return this.alarmTypeName; + } + return StringUtils.EMPTY; + } + + public String getAlarmLevelName(){ + if(Objects.nonNull(this.alarmLevel)){ + Optional.ofNullable(AlarmLevelEnum.getDescByCode(alarmLevel)).ifPresent(a -> + this.alarmLevelName = a); + return this.alarmLevelName; + } + return StringUtils.EMPTY; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mqtt/MqttReceiveConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mqtt/MqttReceiveConfig.java new file mode 100644 index 0000000..3165690 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/mqtt/MqttReceiveConfig.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.car.monitor.mqtt; + + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageProducer; +import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; +import org.springframework.integration.mqtt.core.MqttPahoClientFactory; +import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; +import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.MessagingException; +import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; + +@Configuration +//@IntegrationComponentScan +@Slf4j +public class MqttReceiveConfig { + + @Value("${spring.mqtt.username}") + private String username; + + @Value("${spring.mqtt.password}") + private String password; + + @Value("${spring.mqtt.url}") + private String hostUrl; + + @Value("${spring.mqtt.clientid}") + private String clientId; + + @Value("${spring.mqtt.default_topic}") + private String defaultTopic; + + @Value("${spring.mqtt.completionTimeout}") + private int completionTimeout; //连接超时 + +// @Bean + public MqttPahoClientFactory mqttClientFactory() { + DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); + MqttConnectOptions mqttConnectOptions = new MqttConnectOptions(); + mqttConnectOptions.setUserName(username); + mqttConnectOptions.setPassword(password.toCharArray()); + // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录, + // 把配置里的 cleanSession 设为false,客户端掉线后 服务器端不会清除session, + // 当重连后可以接收之前订阅主题的消息。当客户端上线后会接受到它离线的这段时间的消息 + mqttConnectOptions.setCleanSession(false); + mqttConnectOptions.setServerURIs(new String[]{hostUrl}); + // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制 + mqttConnectOptions.setKeepAliveInterval(20); + factory.setConnectionOptions(mqttConnectOptions); + return factory; + } + + //接收通道 +// @Bean + public MessageChannel mqttInputChannel() { + return new DirectChannel(); + } + +// @Bean + public MessageProducer inbound() { + MqttPahoMessageDrivenChannelAdapter adapter = + new MqttPahoMessageDrivenChannelAdapter(clientId, mqttClientFactory(), defaultTopic); + adapter.setCompletionTimeout(completionTimeout); + adapter.setConverter(new DefaultPahoMessageConverter()); + adapter.setQos(1); + adapter.setOutputChannel(mqttInputChannel()); + adapter.setTaskScheduler(new ConcurrentTaskScheduler()); + log.info("adapter ==> " + adapter); + return adapter; + } + + //通过通道获取数据 +// @Bean + @ServiceActivator(inputChannel = "mqttInputChannel") + public MessageHandler handler() { + return message -> { + try { + String string = message.getPayload().toString(); + String res = "{\"method\":\"OnEventNotify\",\"params\":{\"ability\":\"event_msa_alarm\",\"events\":[{\"data\":{\"alarmId\":\"35323136353734221026091604000200\",\"alarmInfo\":\"{\\\"BSDRightRearWarn\\\":[{\\\"accelerateMaxValue\\\":0,\\\"accelerateValue\\\":0,\\\"alarmAttachMent\\\":{\\\"audioChans\\\":\\\"\\\",\\\"audioNum\\\":0,\\\"othersNum\\\":0,\\\"picChans\\\":\\\"\\\",\\\"picNum\\\":0,\\\"res\\\":\\\"\\\",\\\"serverType\\\":0,\\\"totalNum\\\":2,\\\"videoChans\\\":\\\"\\\",\\\"videoNum\\\":0},\\\"alarmID\\\":\\\"35323136353734221026091604000200\\\",\\\"alarmMaxValue\\\":0,\\\"alarmSeq\\\":0,\\\"alarmType\\\":0,\\\"alarmValue\\\":0,\\\"angularMaxValue\\\":0,\\\"angularValue\\\":0,\\\"fatigueValue\\\":0,\\\"frontCarDistance\\\":0,\\\"frontCarSpeed\\\":0,\\\"identifiData\\\":0.0,\\\"logicalChannel\\\":0,\\\"publicData\\\":{\\\"driverCertificatesID\\\":\\\"\\\",\\\"durationTime\\\":0,\\\"gps\\\":{\\\"altitude\\\":\\\"4000\\\",\\\"direction\\\":\\\"0\\\",\\\"directionEW\\\":\\\"E\\\",\\\"directionNS\\\":\\\"N\\\",\\\"latitude\\\":\\\"10984327\\\",\\\"longitude\\\":\\\"43253100\\\",\\\"speed\\\":\\\"0\\\"},\\\"vehicleStatus\\\":4097},\\\"similarity\\\":0,\\\"similarityMax\\\":0,\\\"targetAttrs\\\":{\\\"cameraIndexCode\\\":\\\"6f6e67980cf842a4b8fba5aa9dc68d18\\\",\\\"cameraType\\\":\\\"CZ\\\",\\\"deviceIndexCode\\\":\\\"049704746b384849b7cc8ffad89dbdda\\\"}}],\\\"channelID\\\":1,\\\"dateTime\\\":\\\"2022-10-26T09:16:04.000+08:00\\\",\\\"eventDescription\\\":\\\"BSDRightRearWarn\\\",\\\"eventType\\\":\\\"BSDRightRearWarn\\\",\\\"ipAddress\\\":\\\"36.113.97.203\\\",\\\"portNo\\\":22592}\",\"alarmTime\":\"2022-10-26 09:16:04\",\"deviceIndexCode\":\"049704746b384849b7cc8ffad89dbdda\",\"direction\":0,\"driverIndexCode\":\"\",\"driverNo\":\"\",\"eventId\":\"30FD188342653C44B9ABA7F2DA19A65\",\"eventType\":132385,\"height\":4000,\"latitude\":10984327,\"level\":\"m\",\"longitude\":43253100,\"picNum\":0,\"sourceType\":0,\"speed\":0,\"status\":0,\"vehicleIndexCode\":\"549b8b8a734a497596d43ab6f6d88241\",\"videoNum\":0},\"eventId\":\"30FD188342653C44B9ABA7F2DA19A65\",\"eventType\":5201154049,\"happenTime\":\"2022-10-26 09:17:07\",\"srcIndex\":\"549b8b8a734a497596d43ab6f6d88241\",\"srcType\":\"vehicle\",\"status\":0,\"timeout\":0}],\"sendTime\":\"2022-10-26 09:17:07\"}}\n"; + log.info("接收到消息:" + string); + } catch (MessagingException e) { + e.printStackTrace(); + } + }; + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IAlarmDataLoadService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IAlarmDataLoadService.java new file mode 100644 index 0000000..508833b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IAlarmDataLoadService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.service; + +import com.ningdatech.carapi.car.monitor.entity.AlarmDataLoad; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 异常告警 载重 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface IAlarmDataLoadService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnFileService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnFileService.java new file mode 100644 index 0000000..6e84f9e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnFileService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.service; + +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarnFile; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +public interface IDataAccessAlarmWarnFileService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnService.java new file mode 100644 index 0000000..e6e173b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IDataAccessAlarmWarnService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.service; + +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarn; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 报警预警表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +public interface IDataAccessAlarmWarnService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IVehicleSecurityMonitorService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IVehicleSecurityMonitorService.java new file mode 100644 index 0000000..ad9ad12 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/IVehicleSecurityMonitorService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.monitor.service; + +import com.ningdatech.carapi.car.monitor.entity.VehicleSecurityMonitor; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆安全监控 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-12-07 + */ +public interface IVehicleSecurityMonitorService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/SecurityMonitorService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/SecurityMonitorService.java new file mode 100644 index 0000000..ccd8ca6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/SecurityMonitorService.java @@ -0,0 +1,13 @@ +package com.ningdatech.carapi.car.monitor.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.monitor.entity.SecurityMonitorJoin; + +public interface SecurityMonitorService extends IService { + + Page pageJoin(Page page, LambdaQueryWrapper wrapper); + + SecurityMonitorJoin getOneJoin(LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/AlarmDataLoadServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/AlarmDataLoadServiceImpl.java new file mode 100644 index 0000000..32967a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/AlarmDataLoadServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.monitor.service.impl; + +import com.ningdatech.carapi.car.monitor.entity.AlarmDataLoad; +import com.ningdatech.carapi.car.monitor.mapper.AlarmDataLoadMapper; +import com.ningdatech.carapi.car.monitor.service.IAlarmDataLoadService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 异常告警 载重 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Service +public class AlarmDataLoadServiceImpl extends ServiceImpl implements IAlarmDataLoadService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnFileServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnFileServiceImpl.java new file mode 100644 index 0000000..f5a8c33 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnFileServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.monitor.service.impl; + +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarnFile; +import com.ningdatech.carapi.car.monitor.mapper.DataAccessAlarmWarnFileMapper; +import com.ningdatech.carapi.car.monitor.service.IDataAccessAlarmWarnFileService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +@Service +public class DataAccessAlarmWarnFileServiceImpl extends ServiceImpl implements IDataAccessAlarmWarnFileService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnServiceImpl.java new file mode 100644 index 0000000..77a1f40 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/DataAccessAlarmWarnServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.monitor.service.impl; + +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarn; +import com.ningdatech.carapi.car.monitor.mapper.DataAccessAlarmWarnMapper; +import com.ningdatech.carapi.car.monitor.service.IDataAccessAlarmWarnService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 报警预警表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-12-06 + */ +@Service +public class DataAccessAlarmWarnServiceImpl extends ServiceImpl implements IDataAccessAlarmWarnService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/SecurityMonitorServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/SecurityMonitorServiceImpl.java new file mode 100644 index 0000000..9baf715 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/SecurityMonitorServiceImpl.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.car.monitor.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.monitor.entity.SecurityMonitorJoin; +import com.ningdatech.carapi.car.monitor.mapper.SecurityMonitorJoinMapper; +import com.ningdatech.carapi.car.monitor.service.SecurityMonitorService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class SecurityMonitorServiceImpl extends ServiceImpl implements SecurityMonitorService { + + private final SecurityMonitorJoinMapper securityMonitorJoinMapper; + + @Override + public Page pageJoin(Page page, LambdaQueryWrapper wrapper) { + return securityMonitorJoinMapper.pageJoin(page, wrapper); + } + + @Override + public SecurityMonitorJoin getOneJoin(LambdaQueryWrapper wrapper) { + return securityMonitorJoinMapper.getOneJoin(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/VehicleSecurityMonitorServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/VehicleSecurityMonitorServiceImpl.java new file mode 100644 index 0000000..3aa1d32 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/monitor/service/impl/VehicleSecurityMonitorServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.monitor.service.impl; + +import com.ningdatech.carapi.car.monitor.entity.VehicleSecurityMonitor; +import com.ningdatech.carapi.car.monitor.mapper.VehicleSecurityMonitorMapper; +import com.ningdatech.carapi.car.monitor.service.IVehicleSecurityMonitorService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆安全监控 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-12-07 + */ +@Service +public class VehicleSecurityMonitorServiceImpl extends ServiceImpl implements IVehicleSecurityMonitorService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/contants/PositionContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/contants/PositionContant.java new file mode 100644 index 0000000..554afce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/contants/PositionContant.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.car.position.contants; + +/** + * @Classname PositionContant + * @Description + * @Date 2022/10/26 10:37 + * @Created by PoffyZhang + */ +public class PositionContant { + + public static final String REAL_GPS_URL = "http://{host}:8092/gps/car_plate?car_plate={car_plate}"; + + public static final String REAL_DEVICE_URL = "http://{host}:8090/devices?limit={limit}&skip={skip}&sort={sort}&filters={filters}"; + + public static final String VEHICLE_DEVICE_URL = "http://{host}:8090/get/car/device/{car_plate}"; + + public static final String RECORD_LIST_URL = "http://{host}:8090/record/{deviceId}/list?" + + "start={start}&end={end}"; + public static final String STREAM_URL = "http://%s:8090/streams/"; + + public static final String RECORD_URL = "http://%s:8090/record/"; + + public static final String HOST_FEILD = "host"; + public static final String FIELD_CAR_PLATE = "car_plate"; + + public static final String LONGITUDE = "car_longitude"; + + public static final String LATITUDE = "car_latitude"; + + public static final String ALTITUDE = "car_altitude"; + + public static final String DIRECTION = "car_direction"; + + public static final String PLATE_COLOR = "plate_color"; + + public static final String UPDATE_TIME = "update_time"; + + public static final String ONLINE_STATUS = "online_status"; + + public static final String CAR_VELOCITY = "car_velocity"; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/controller/PositionMonitorController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/controller/PositionMonitorController.java new file mode 100644 index 0000000..1951689 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/controller/PositionMonitorController.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.car.position.controller; + +import com.ningdatech.carapi.car.position.manage.PositionMonitorManage; +import com.ningdatech.carapi.car.position.model.po.ReqRealTimeMonitorPO; +import com.ningdatech.carapi.car.position.model.po.ReqTrajectoryDataPO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorStatisticsVO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.car.position.model.vo.ResTrajectoryDataVO; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/8 上午10:25 + */ + +@RestController +@RequestMapping(value = "/api/v1/car-manage/position-monitor") +@Api(tags = "车辆管理-定位监控") +@Validated +@RequiredArgsConstructor +public class PositionMonitorController { + + private final PositionMonitorManage positionMonitorManage; + + @PostMapping("/trajectory-data-list") + @ApiOperation("获取车辆轨迹数据列表(无分页)") + @WebLog + public List trajectoryDatalist(@Valid @RequestBody ReqTrajectoryDataPO po) { + return positionMonitorManage.trajectoryDatalist(po); + } + + @PostMapping("/real-time-monitor-statistics") + @ApiOperation("实时监控数量统计") + public ResRealTimeMonitorStatisticsVO realTimeMonitorStatistics(@Valid @RequestBody ReqRealTimeMonitorPO po) { + return positionMonitorManage.realTimeMonitorStatistics(po); + } + + @PostMapping("/real-time-monitor-vehicle-gis-list") + @ApiOperation("实时监控车辆gis列表") + public List realTimeMonitorVehicleGisList(@Valid @RequestBody ReqRealTimeMonitorPO po) { + return positionMonitorManage.realTimeMonitorVehicleGisList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/entity/VehiclePositionInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/entity/VehiclePositionInfo.java new file mode 100644 index 0000000..7c413a8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/entity/VehiclePositionInfo.java @@ -0,0 +1,100 @@ +package com.ningdatech.carapi.car.position.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +@TableName("nd_data_access_gps_2022_11") +@Data +@ApiModel(value = "VehiclePositionInfo对象", description = "") +public class VehiclePositionInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String carPlate; + + private Boolean plateColor; + + private BigDecimal carLongitude; + + private BigDecimal carLatitude; + + private BigDecimal carAltitude; + + private BigDecimal carVelocity; + + private BigDecimal carDirection; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String updateTime; + + private String operatorName; + + private String operatorId; + + @ApiModelProperty("报警标识") + private Integer alarmFlag; + + @ApiModelProperty("状态,根据需求去取对应的位数参考jtt808/8.21下的状态定义") + private Integer status; + + @ApiModelProperty("仪表盘里程数") + private Integer dashboardMileage; + + @ApiModelProperty("仪表盘速度") + private Integer dashboardSpeed; + + @ApiModelProperty("recordId") + @TableId(value = "record_id", type = IdType.AUTO) + private Long recordId; + + public BigDecimal getCarLatitude(){ + if(Objects.nonNull(this.carLatitude)){ + this.carLatitude = this.carLatitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLatitude; + } + return this.carLatitude; + } + + public BigDecimal getCarLongitude(){ + if(Objects.nonNull(this.carLongitude)){ + this.carLongitude = this.carLongitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLongitude; + } + return this.carLongitude; + } + + public BigDecimal getCarAltitude(){ + if(Objects.nonNull(this.carAltitude)){ + this.carAltitude = this.carAltitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carAltitude; + } + return this.carAltitude; + } + + public BigDecimal getCarVelocity(){ + if(Objects.nonNull(this.carVelocity)){ + this.carVelocity = this.carVelocity.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carVelocity; + } + return this.carVelocity; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/manage/PositionMonitorManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/manage/PositionMonitorManage.java new file mode 100644 index 0000000..aa0ad60 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/manage/PositionMonitorManage.java @@ -0,0 +1,398 @@ +package com.ningdatech.carapi.car.position.manage; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.position.contants.PositionContant; +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.ningdatech.carapi.car.position.model.po.ReqRealTimeMonitorPO; +import com.ningdatech.carapi.car.position.model.po.ReqTrajectoryDataPO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorStatisticsVO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.car.position.model.vo.ResTrajectoryDataVO; +import com.ningdatech.carapi.car.position.service.IVehiclePositionInfoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.model.po.VehicleCompanyPO; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.DeletedEnum; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleLimitSpeedEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.homepage.entity.model.OnlineNumCnt; +import com.ningdatech.carapi.homepage.entity.po.VehicleNumPO; +import com.ningdatech.carapi.homepage.service.IHomepageService; +import com.ningdatech.carapi.sys.contants.RegionContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.StopWatch; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author liuxinxin + * @date 2022/10/8 上午11:18 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class PositionMonitorManage { + + private final IVehiclePositionInfoService iVehiclePositionInfoService; + + private final IHomepageService homepageService; + + private final RestTemplate restTemplate; + + private final IVehicleBaseInfoService vehicleBaseInfoService; + + private final CompanyService companyService; + + private final RegionsCacheHelper regionsCacheHelper; + + private final VehiclesCacheHelper vehiclesCacheHelper; + + @Value("${gps.host}") + private String HOST; + + private final RedisTemplate redisTemplate; + private final OperatorsCacheHelper operatorsCacheHelper; + private final StringRedisTemplate stringRedisTemplate; + + + public List trajectoryDatalist(ReqTrajectoryDataPO po) { + String carPlate = po.getCarPlate(); + LocalDateTime startTime = po.getStartTime(); + LocalDateTime endTime = po.getEndTime(); + if (Objects.isNull(startTime)) { + startTime = LocalDateTime.now().minusHours(2); + } + // 默认时间区间为2小时前到现在 + if (Objects.isNull(endTime)) { + endTime = LocalDateTime.now(); + } + + // 判断车辆所属区域是否在登录用户的区域权限内 + NdVehicleBaseInfo car = vehiclesCacheHelper.getByCarPlate(carPlate); + Long regionId = car.getRegionId(); + Long companyId = car.getCompanyId(); + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long userDetailRegionId = userDetail.getRegionId(); + List listChild = regionsCacheHelper.listChildRegionId(userDetailRegionId,true,true); + // 不在登录用户的区域权限内 返回空数据 + if (!listChild.contains(regionId)){ + return Collections.emptyList(); + } + + //判断日期有没有跨天 + checkDateExtendIntoNextDay(startTime, endTime); + + //动态表名 + List vehiclePositionInfoList = iVehiclePositionInfoService + .dynamicGpsTableHistorySearch(carPlate, startTime, endTime,NdDateUtils.format(startTime, "yyyy_MM_dd")); + + + List resTrajectoryDataVOList = vehiclePositionInfoList.stream().map( + r -> { + ResTrajectoryDataVO vo = BeanUtil.copyProperties(r, ResTrajectoryDataVO.class); + vo.setIsOverSpeed(checkIsOverSpeed(r,car)); + return vo; + }).collect(Collectors.toList()); + //连续6次超速 才算超速 + checkContinuousOverspeed(resTrajectoryDataVOList); + return resTrajectoryDataVOList; + } + + private final String REDIS_CAR_FILED = "car-gps:"; + + private void checkContinuousOverspeed(List resTrajectoryDataVOList) { + if(CollUtil.isNotEmpty(resTrajectoryDataVOList)){ + for(int i = 0;i < resTrajectoryDataVOList.size();i++){ + ResTrajectoryDataVO vo = resTrajectoryDataVOList.get(i); + String carPlate = vo.getCarPlate(); + if(vo.getIsOverSpeed()){ + Object num = redisTemplate.opsForValue().get(carPlate); + //如果之前已经有连续6个了 那就相安无事 + if(Objects.isNull(num)){ + redisTemplate.opsForValue().set(REDIS_CAR_FILED + carPlate,1,500,TimeUnit.SECONDS); + }else{ + redisTemplate.opsForValue().increment(REDIS_CAR_FILED + carPlate); + } + }else{ + Object num = redisTemplate.opsForValue().get(REDIS_CAR_FILED + carPlate); + if(Objects.isNull(num)){ + redisTemplate.opsForValue().set(REDIS_CAR_FILED + carPlate,0,500,TimeUnit.SECONDS); + continue; + } + //如果之前已经有连续6个了 那就相安无事 + Integer overNum = Integer.valueOf(String.valueOf(num)); + if(Objects.nonNull(num) && overNum >= 6){ + redisTemplate.opsForValue().set(REDIS_CAR_FILED + carPlate,0,500,TimeUnit.SECONDS); + }else{ + //如果不是的话 要把之前的 置为不超速 + changeOverspeedFalse(resTrajectoryDataVOList,i,vo,overNum); + } + } + } + } + } + + private void changeOverspeedFalse(List resTrajectoryDataVOList,int index, ResTrajectoryDataVO vo, Integer overNum) { + int flagNum = overNum; + for(int i = index;i >= 0;i--){ + if(flagNum <= 0){ + break; + } + ResTrajectoryDataVO innerVo = resTrajectoryDataVOList.get(i); + if(innerVo.getCarPlate().equals(vo.getCarPlate())){ + innerVo.setIsOverSpeed(Boolean.FALSE); + flagNum--; + } + } + } + + private Boolean checkIsOverSpeed(VehiclePositionInfo positionInfo, NdVehicleBaseInfo car) { + //混凝土和移动泵车 是50 + Integer vehicleType = car.getVehicleType(); + VehicleTypeEnum enumByValue = VehicleTypeEnum.getEnumByValue(vehicleType); + if(enumByValue.equals(VehicleTypeEnum.OTHER)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(80)) >= 0){ + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.KRHP)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(50)) >= 0) { + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.MIXER)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(50)) >= 0) { + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.BULK_CEMENT_TRUCK)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(80)) >= 0) { + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.READY_MIXED_MORTAR_TRUC)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(80)) >= 0) { + return Boolean.TRUE; + } + } + + return Boolean.FALSE; + } + + //判断日期有没有跨月 + private void checkDateExtendIntoNextDay(LocalDateTime startTime, LocalDateTime endTime) { + if (!NdDateUtils.format(startTime, DatePattern.NORM_DATE_PATTERN) + .equals(NdDateUtils.format(endTime, DatePattern.NORM_DATE_PATTERN))) { + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "由于GPS数据量大 不支持跨日查询!"); + } + } + + public ResRealTimeMonitorStatisticsVO realTimeMonitorStatistics(ReqRealTimeMonitorPO po) { + // 统计时间 请求发起60秒内的数据为实时数据 + LocalDateTime statistics = LocalDateTime.now().minusSeconds(60L); + + List companyIdList = po.getCompanyIdList(); + DataScreenParam param = new DataScreenParam(); + param.setCompanyIds(companyIdList); + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + List vehicleBaseInfos = Lists.newArrayList(); + // 如果登录用户是运营商,只过滤出运营商下的车辆 + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + param.setOperatorId(operatorId); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + PositionMonitorManage context = (PositionMonitorManage) AopContext.currentProxy(); + context.buildSearchQuery(wrapper, param); + vehicleBaseInfos = vehicleBaseInfoService.list(wrapper); + } + // 如果登录用户是企业信息员,过滤出使用企业和所属企业为该企业的车辆 + else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)){ + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + wrapper.eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .and(w -> w.eq(NdVehicleBaseInfo::getCompanyId,userDetail.getCompanyId()).or() + .eq(NdVehicleBaseInfo::getUseCompanyId,userDetail.getCompanyId())); + vehicleBaseInfos = vehicleBaseInfoService.list(wrapper); + }else{ + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + PositionMonitorManage context = (PositionMonitorManage) AopContext.currentProxy(); + context.buildSearchQuery(wrapper, param); + vehicleBaseInfos = vehicleBaseInfoService.list(wrapper); + } + ResRealTimeMonitorStatisticsVO resRealTimeMonitorStatisticsVO = new ResRealTimeMonitorStatisticsVO(); + if (CollUtil.isEmpty(vehicleBaseInfos)){ + return resRealTimeMonitorStatisticsVO; + } + VehicleNumPO vehicleNumPO = homepageService.vehicleNum(param); + Integer vehiclesTotalCount = vehicleNumPO.getTotalNum(); + Integer vehiclesOnlineCount = vehicleNumPO.getTotalOnlineNum(); + Integer vehiclesOfflineCount = vehicleNumPO.getTotalOfflineNum(); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + List cntList = homepageService.getOnlineNumCnt(vehicleBaseInfos); + AtomicInteger cnt = new AtomicInteger(0); + for (OnlineNumCnt onlineNumCnt : cntList) { + Integer onlineNum = onlineNumCnt.getCnt(); + cnt.addAndGet(onlineNum); + } + stopWatch.stop(); + log.info("共耗时 {}s", stopWatch.getTotalTimeSeconds()); + log.info("缓存中车辆在线数为:" + cnt); + vehiclesOnlineCount = cnt.get(); + vehiclesOfflineCount = vehiclesTotalCount - cnt.get(); + + Integer todayVehiclesAccumulatedOnlineCount = homepageService.searchAccumulativeOnlineNum(param); + + resRealTimeMonitorStatisticsVO.setVehiclesTotalCount(vehiclesTotalCount); + resRealTimeMonitorStatisticsVO.setVehiclesOnlineCount(vehiclesOnlineCount); + resRealTimeMonitorStatisticsVO.setVehiclesOfflineCount(vehiclesOfflineCount); + resRealTimeMonitorStatisticsVO.setTodayVehiclesAccumulatedOnlineCount(todayVehiclesAccumulatedOnlineCount); + return resRealTimeMonitorStatisticsVO; + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildSearchQuery(LambdaQueryWrapper wrapper, DataScreenParam param) { + wrapper.eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .eq(Objects.nonNull(param.getOperatorId()),NdVehicleBaseInfo::getOperatorId,param.getOperatorId()) + .in(Objects.nonNull(param.getCompanyIds()) && CollUtil.isNotEmpty(param.getCompanyIds()),NdVehicleBaseInfo::getCompanyId,param.getCompanyIds()); + } + + public List realTimeMonitorVehicleGisList(ReqRealTimeMonitorPO po) { + if (CollUtil.isEmpty(po.getCompanyIdList())) { + return Collections.emptyList(); + } + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + List carPlates = Lists.newArrayList(); + // 如果登录用户是运营商,只过滤出运营商下的车辆 + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + carPlates = vehicleBaseInfoService.getCarPlatesByCompanyIds(po.getCompanyIdList()); + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + carPlates = carPlates.stream() + .filter(v -> operatorId.equals(v.getOperatorId())) + .collect(Collectors.toList()); + } + // 如果登录用户是企业信息员,过滤出使用企业和所属企业为该企业的车辆 + else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + Long companyId = userDetail.getCompanyId(); + carPlates = vehicleBaseInfoService.getCarPlatesByUseCompanyId(companyId); + }else{ + carPlates = vehicleBaseInfoService.getCarPlatesByCompanyIds(po.getCompanyIdList()); + } + log.info("request real carPlates 【{}】:", JSON.toJSONString(carPlates)); + if (CollUtil.isEmpty(carPlates)) { + return Collections.emptyList(); + } + Map map = Maps.newConcurrentMap(); + map.put(PositionContant.FIELD_CAR_PLATE, carPlates.stream().map(VehicleCompanyPO::getCarPlate).collect(Collectors.joining(","))); + map.put(PositionContant.HOST_FEILD, HOST); + JSONObject response = restTemplate.getForObject(PositionContant.REAL_GPS_URL, JSONObject.class, map); + log.info("request real gps 【{}】:", JSON.toJSONString(response)); + if (Objects.isNull(response)) { + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), "实时数据请求失败 网络异常"); + } + Integer statusCode = response.getInteger("status_code"); + if (0 != statusCode) { + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), response.getString("message")); + } + JSONArray resultJsonArray = response.getJSONArray("result"); + if (Objects.isNull(resultJsonArray) || resultJsonArray.size() == 0) { + return Collections.emptyList(); + } + + Map carMap = carPlates.stream() + .filter(w -> Objects.nonNull(w) && Objects.nonNull(w.getCarPlate())) + .filter(CodeUtil.distinctByKey(VehicleCompanyPO::getCarPlate)).collect(Collectors.toMap(VehicleCompanyPO::getCarPlate, v -> v)); + List res = resultJsonArray.stream().map(o -> { + JSONObject j = JSON.parseObject(JSON.toJSONString(o)); + String carPlate = j.getString(PositionContant.FIELD_CAR_PLATE); + VehicleCompanyPO vehicleCompany = carMap.get(carPlate); + ResRealTimeMonitorVehicleGisListVO vo = new ResRealTimeMonitorVehicleGisListVO(); + vo.setCarLongitude(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.LONGITUDE,BigDecimal.valueOf(0L))))); + vo.setCarLatitude(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.LATITUDE,BigDecimal.valueOf(0L))))); + vo.setCarAltitude(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.ALTITUDE,BigDecimal.valueOf(0L))))); + vo.setCarDirection(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.DIRECTION,BigDecimal.valueOf(0L))))); + vo.setCarPlate(carPlate); + vo.setPlateColor(j.getString(PositionContant.PLATE_COLOR)); + vo.setCompanyId(vehicleCompany.getCompanyId()); + vo.setCompanyName(vehicleCompany.getCompanyName()); + vo.setCarVelocity(BigDecimal.valueOf(Double.valueOf(String.valueOf(j.getOrDefault(PositionContant.CAR_VELOCITY,BigDecimal.valueOf(0L)))))); + vo.setUpdateTime((j.getString(PositionContant.UPDATE_TIME))); + vo.setSelfNo(vehicleCompany.getSelfNo()); + vo.setStatus(j.getInteger(PositionContant.ONLINE_STATUS)); + vo.setMoving(vehicleCompany.getMoving()); + vo.setVehicleType(vehicleCompany.getVehicleType()); + vo.setVehicleTypeName(vehicleCompany.getVechileTypeName()); + vo.setLimitSpeed(VehicleLimitSpeedEnum.getLimitSpeedByCode(vehicleCompany.getVehicleType())); + return vo; + }).collect(Collectors.toList()); + return res; + } + + public List realTimeMonitorVehicleGisList(DataScreenParam param) { + if (Objects.isNull(param.getRegionId())) { + param.setRegionId(RegionContant.ZJ_REGION_ID); + } + List companies = companyService.list(Wrappers.lambdaQuery(Company.class).in(Company::getRegionId, regionsCacheHelper.listChildRegionId(param.getRegionId()))); + List companyIds = CollUtil.isNotEmpty(companies) ? companies.stream().map(c -> + String.valueOf(c.getId())).collect(Collectors.toList()) : Collections.emptyList(); + return realTimeMonitorVehicleGisList(new ReqRealTimeMonitorPO(companyIds)); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.java new file mode 100644 index 0000000..9a0de55 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.position.mapper; + +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +public interface VehiclePositionInfoMapper extends BaseMapper { + List dynamicGpsTableHistorySearch(@Param("carPlate") String carPlate, @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, @Param("date") String date); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.xml new file mode 100644 index 0000000..659da9e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/mapper/VehiclePositionInfoMapper.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqDataPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqDataPO.java new file mode 100644 index 0000000..90b8db9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqDataPO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.car.position.model.po; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author ZPF + * @date 2024/3/18 上午11:23 + */ +@ApiModel(description = "对外入参") +@Data +public class ReqDataPO { + + @ApiModelProperty("车牌") + private List carPlates; + + @ApiModelProperty("身份证号") + private List idCards; + + @ApiModelProperty("开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime endTime; + + @ApiModelProperty("校验公钥") + private String key; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorPO.java new file mode 100644 index 0000000..1d9b0d0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorPO.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.car.position.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/8 下午2:15 + */ +@ApiModel(description = "实时监控请求入参") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ReqRealTimeMonitorPO { + + @ApiModelProperty("公司唯一标识列表") + List companyIdList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorVehicleGisDetailPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorVehicleGisDetailPO.java new file mode 100644 index 0000000..a402a07 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqRealTimeMonitorVehicleGisDetailPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.position.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author liuxinxin + * @date 2022/10/8 下午2:51 + */ +@ApiModel(description = "实时监控gis车辆详情请求") +@Data +public class ReqRealTimeMonitorVehicleGisDetailPO { + + @ApiModelProperty("记录id") + @NotBlank(message = "gis记录id不能为空") + private String recordId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqTrajectoryDataPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqTrajectoryDataPO.java new file mode 100644 index 0000000..f4f615b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/po/ReqTrajectoryDataPO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.car.position.model.po; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/8 上午11:23 + */ +@ApiModel(description = "获取车辆轨迹数据列表(无分页)请求") +@Data +public class ReqTrajectoryDataPO { + + @NotBlank(message = "车牌不能为空") + @ApiModelProperty("车牌") + private String carPlate; + + @ApiModelProperty("开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime endTime; + + @ApiModelProperty("校验公钥") + @NotBlank(message = "秘钥不能为空") + private String key; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/DeviceVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/DeviceVO.java new file mode 100644 index 0000000..ec94e35 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/DeviceVO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.car.position.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/11/03 下午2:10 + */ + +@Data +@ApiModel(description = "车辆设备返回-VO") +public class DeviceVO { + + @ApiModelProperty("设备ID") + private String deviceId; + + @ApiModelProperty("设备名") + private String name; + + @ApiModelProperty("设备品牌") + private String manufacturer; + + @ApiModelProperty("状态") + private String status; + + @ApiModelProperty("时间") + private String active; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorStatisticsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorStatisticsVO.java new file mode 100644 index 0000000..7e8ea62 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorStatisticsVO.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.car.position.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/8 下午2:10 + */ + +@Data +@ApiModel(description = "实时监控统计") +public class ResRealTimeMonitorStatisticsVO { + + @ApiModelProperty("车辆总数") + private Integer vehiclesTotalCount; + + @ApiModelProperty("在线数") + private Integer vehiclesOnlineCount; + + @ApiModelProperty("离线数") + private Integer vehiclesOfflineCount; + + @ApiModelProperty("今日累计在线数") + private Integer todayVehiclesAccumulatedOnlineCount; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisDetailVO.java new file mode 100644 index 0000000..9c59184 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisDetailVO.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.car.position.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/10/8 下午2:30 + */ + +@ApiModel(description = "实时监控gis车辆详情") +@Data +public class ResRealTimeMonitorVehicleGisDetailVO { + + + @ApiModelProperty("记录id") + private String recordId; + + @ApiModelProperty("车牌") + private String carPlate; + + @ApiModelProperty("经度") + private BigDecimal carLongitude; + + @ApiModelProperty("纬度") + private BigDecimal carLatitude; + + @ApiModelProperty("海拔高度") + private BigDecimal carAltitude; + + @ApiModelProperty("行驶速度") + private BigDecimal carVelocity; + + @ApiModelProperty("行驶方向") + private String carDirection; + + @ApiModelProperty("上传时间") + private LocalDateTime uploadTime; + + @ApiModelProperty("在线状态") + private String onlineStatus; + + @ApiModelProperty("运营商名称") + private String operatorName; + + @ApiModelProperty("运营商id") + private String operatorId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("公司id") + private String companyId; + + public BigDecimal getCarLatitude(){ + if(Objects.nonNull(this.carLatitude)){ + this.carLatitude = this.carLatitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLatitude; + } + return this.carLatitude; + } + + public BigDecimal getCarLongitude(){ + if(Objects.nonNull(this.carLongitude)){ + this.carLongitude = this.carLongitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLongitude; + } + return this.carLongitude; + } + + public BigDecimal getCarAltitude(){ + if(Objects.nonNull(this.carAltitude)){ + this.carAltitude = this.carAltitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carAltitude; + } + return this.carAltitude; + } + + public BigDecimal getCarVelocity(){ + if(Objects.nonNull(this.carVelocity)){ + this.carVelocity = this.carVelocity.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carVelocity; + } + return this.carVelocity; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisListVO.java new file mode 100644 index 0000000..8734db8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResRealTimeMonitorVehicleGisListVO.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.car.position.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/10/8 下午2:30 + */ + +@ApiModel(description = "实时监控车辆gis列表") +@Data +public class ResRealTimeMonitorVehicleGisListVO { + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("经度") + private BigDecimal carLongitude; + + @ApiModelProperty("纬度") + private BigDecimal carLatitude; + + @ApiModelProperty("海拔高度") + private BigDecimal carAltitude; + + @ApiModelProperty("行驶方向") + private BigDecimal carDirection; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("公司名id") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("时间") + private String updateTime; + + @ApiModelProperty("自编号") + private String selfNo; + + @ApiModelProperty("速度") + private BigDecimal carVelocity; + + private Integer limitSpeed; + + private Integer status; + private Integer moving; + + public BigDecimal getCarLatitude(){ + if(Objects.nonNull(this.carLatitude)){ + this.carLatitude = this.carLatitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLatitude; + } + return this.carLatitude; + } + + public BigDecimal getCarLongitude(){ + if(Objects.nonNull(this.carLongitude)){ + this.carLongitude = this.carLongitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLongitude; + } + return this.carLongitude; + } + + public BigDecimal getCarAltitude(){ + if(Objects.nonNull(this.carAltitude)){ + this.carAltitude = this.carAltitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carAltitude; + } + return this.carAltitude; + } + + public BigDecimal getCarVelocity(){ + if(Objects.nonNull(this.carVelocity)){ + this.carVelocity = this.carVelocity.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carVelocity; + } + return this.carVelocity; + } + + public BigDecimal getCarDirection(){ + if(Objects.nonNull(this.carDirection)){ + this.carDirection = this.carDirection.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carDirection; + } + return this.carDirection; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResTrajectoryDataVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResTrajectoryDataVO.java new file mode 100644 index 0000000..f7455af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/model/vo/ResTrajectoryDataVO.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.car.position.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/10/8 上午11:13 + */ + +@ApiModel(description = "车辆轨迹数据") +@Data +public class ResTrajectoryDataVO { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("记录id") + private String recordId; + + @ApiModelProperty("车牌") + private String carPlate; + + @ApiModelProperty("经度") + private BigDecimal carLongitude; + + @ApiModelProperty("纬度") + private BigDecimal carLatitude; + + @ApiModelProperty("海拔高度") + private BigDecimal carAltitude; + + @ApiModelProperty("行驶速度") + private BigDecimal carVelocity; + + @ApiModelProperty("行驶方向") + private BigDecimal carDirection; + + @ApiModelProperty("在线状态") + private String onlineStatus; + + @ApiModelProperty("运营商名称") + private String operatorName; + + @ApiModelProperty("运营商id") + private String operatorId; + + @ApiModelProperty("时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String updateTime; + + @ApiModelProperty("是否超速") + private Boolean isOverSpeed = Boolean.FALSE; + + public BigDecimal getCarLongitude(){ + if(Objects.nonNull(this.carLongitude)){ + this.carLongitude = this.carLongitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carLongitude; + } + return this.carLongitude; + } + + public BigDecimal getCarAltitude(){ + if(Objects.nonNull(this.carAltitude)){ + this.carAltitude = this.carAltitude.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carAltitude; + } + return this.carAltitude; + } + + public BigDecimal getCarVelocity(){ + if(Objects.nonNull(this.carVelocity)){ + this.carVelocity = this.carVelocity.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carVelocity; + } + return this.carVelocity; + } + + public BigDecimal getCarDirection(){ + if(Objects.nonNull(this.carDirection)){ + this.carDirection = this.carDirection.setScale(BigDecimal.ROUND_HALF_EVEN, RoundingMode.HALF_UP); + return this.carDirection; + } + return this.carDirection; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/IVehiclePositionInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/IVehiclePositionInfoService.java new file mode 100644 index 0000000..b3da6fe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/IVehiclePositionInfoService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.position.service; + +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +public interface IVehiclePositionInfoService extends IService { + + List dynamicGpsTableHistorySearch(String carPlate, LocalDateTime startTime, LocalDateTime endTime,String date); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/impl/VehiclePositionInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/impl/VehiclePositionInfoServiceImpl.java new file mode 100644 index 0000000..d7fa8b0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/position/service/impl/VehiclePositionInfoServiceImpl.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.car.position.service.impl; + +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.ningdatech.carapi.car.position.mapper.VehiclePositionInfoMapper; +import com.ningdatech.carapi.car.position.service.IVehiclePositionInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +@Service +@RequiredArgsConstructor +public class VehiclePositionInfoServiceImpl extends ServiceImpl implements IVehiclePositionInfoService { + + private final VehiclePositionInfoMapper vehiclePositionInfoMapper; + + @Override + public List dynamicGpsTableHistorySearch(String carPlate, LocalDateTime startTime, LocalDateTime endTime, String date) { + return vehiclePositionInfoMapper.dynamicGpsTableHistorySearch(carPlate,startTime,endTime,date); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptDailyController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptDailyController.java new file mode 100644 index 0000000..6fe6999 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptDailyController.java @@ -0,0 +1,119 @@ +package com.ningdatech.carapi.car.rpt.controller; + + +import com.ningdatech.carapi.car.rpt.manage.RptDailyManage; +import com.ningdatech.carapi.car.rpt.model.dto.*; +import com.ningdatech.carapi.car.rpt.model.vo.*; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 报表统计 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ + +@RequestMapping("/api/car-rpt") +@RequiredArgsConstructor +@RestController +@Api(tags = "车辆管理-统计报表") +@Validated +public class RptDailyController { + + private final RptDailyManage rptDailyManage; + + @ApiOperation("浙江省专用车辆上线率日报") + @GetMapping("/daily-special-vehicles-launch-rate") + public List dailySpecialVehiclesLaunchRate( + @Valid @ModelAttribute RptDailySpecialVehiclesLaunchRateParamDTO param) { + return rptDailyManage.dailySpecialVehiclesLaunchRate(param); + } + + @ApiOperation("浙江省运营商车辆上线率日报") + @GetMapping("/daily-operator-vehicles-launch-rate") + public List dailyOperatorVehiclesLaunchRate( + @Valid @ModelAttribute RptDailyOperatorVehiclesLaunchRateParamDTO param) { + return rptDailyManage.dailyOperatorVehiclesLaunchRate(param); + } + + @ApiOperation("专用车辆企业上线率低于60日报") + @GetMapping("/daily-special-vehicles-company-launch-rate-60") + public List dailySpecialVehiclesCompanyLaunchRate( + @Valid @ModelAttribute RptDailySpecialVehiclesCompanyLaunchRateParamDTO param) { + return rptDailyManage.dailySpecialVehiclesCompanyLaunchRate(param); + } + + @ApiOperation("专用车辆超速日报") + @GetMapping("/daily-special-vehicles-overspeed") + public List dailySpecialVehiclesOverspeed( + @Valid @ModelAttribute RptDailySpecialVehiclesOverspeedParamDTO param) { + return rptDailyManage.dailySpecialVehiclesOverspeed(param); + } + + @ApiOperation("超速企业情况日报") + @GetMapping("/daily-overspeed-company") + public List dailyOverspeedCompany( + @Valid @ModelAttribute RptDailyOverspeedCompanyParamDTO param) { + return rptDailyManage.dailyOverspeedCompany(param); + } + + @ApiOperation("超速专用车辆日报") + @GetMapping("/daily-overspeed-special-vehicles") + public List dailyOverspeedSpecialVehicles( + @Valid @ModelAttribute RptDailyOverspeedSpecialVehiclesParamDTO param) { + return rptDailyManage.dailyOverspeedSpecialVehicles(param); + } + + @ApiOperation("浙江省专用车辆上线率日报表导出") + @GetMapping("/ZJ-special-vehicles-onlineRate-dailyReport-export") + public void specialVehiclesOnlineRateDailyReportExport(RptDailySpecialVehiclesLaunchRateParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptDailyManage::specialVehiclesOnlineRateDailyReportExport); + } + + @ApiOperation("运营商车辆上线率日报表导出") + @GetMapping("/operators-vehicles-onlineRate-dailyReport-export") + public void operatorsVehiclesOnlineRateDailyReportExport(RptDailyOperatorVehiclesLaunchRateParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptDailyManage::operatorsVehiclesOnlineRateDailyReportExport); + } + + @ApiOperation("浙江省专用车辆上线率低于60%的企业日报表导出") + @GetMapping("/ZJ-special-vehicles-onlineRate-enterprise-dailyReport-export-60") + public void specialVehiclesOnlineRateEnterpriseDailyReportExport60(RptDailySpecialVehiclesCompanyLaunchRateParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptDailyManage::specialVehiclesOnlineRateEnterpriseDailyReportExport60); + } + + @ApiOperation("浙江省专用车辆超速情况日报表导出") + @GetMapping("/ZJ-special-vehicles-overSpeed-dailyReport-export") + public void specialVehiclesOverSpeedDailyReportExport(RptDailySpecialVehiclesOverspeedParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptDailyManage::specialVehiclesOverSpeedDailyReportExport); + } + + @ApiOperation("浙江省超速企业排名日报表导出") + @GetMapping("/ZJ-overSpeed-enterprise-rank-dailyReport-export") + public void overSpeedEnterpriseRankDailyReportExport(RptDailyOverspeedCompanyParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptDailyManage::overSpeedEnterpriseRankDailyReportExport); + } + + @ApiOperation("浙江省超速专用车辆排名日报表导出") + @GetMapping("/ZJ-overSpeed-special-vehicles-rank-dailyReport-export") + public void overSpeedSpecialVehiclesRankDailyReportExport(RptDailyOverspeedSpecialVehiclesParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptDailyManage::overSpeedSpecialVehiclesRankDailyReportExport); + } + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptMonthController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptMonthController.java new file mode 100644 index 0000000..9a353e4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptMonthController.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.car.rpt.controller; + +import com.ningdatech.carapi.car.rpt.manage.RptMonthManage; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOfflineParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedCompanyVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedSpecialCompanyVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedSpecialVehiclesVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthSpecialOfflineVO; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 报表统计 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ + +@RequestMapping("/api/car-rpt") +@RequiredArgsConstructor +@RestController +@Api(tags = "车辆管理-统计报表") +@Validated +public class RptMonthController { + + private final RptMonthManage rptMonthManage; + + @ApiOperation("浙江省超速企业月报") + @GetMapping("/monthly-overspeed-company") + public List monthlyOverspeedCompany( + @Valid @ModelAttribute RptMonthOverspeedCompanyParamDTO param) { + return rptMonthManage.monthlyOverspeedCompany(param); + } + + @ApiOperation("浙江省专用车辆排名月报") + @GetMapping("/monthly-special-overspeed-company") + public List monthlySpecialOverspeedCompany( + @Valid @ModelAttribute RptMonthSpecialOverspeedCompanyParamDTO param) { + return rptMonthManage.monthlySpecialOverspeedCompany(param); + } + + @ApiOperation("浙江省专用车辆不上线排序月报") + @GetMapping("/monthly-special-offline") + public List monthlySpecialOffline( + @Valid @ModelAttribute RptMonthSpecialOfflineParamDTO param) { + return rptMonthManage.monthlySpecialOffline(param); + } + + @ApiOperation("浙江省专用车辆月对比") + @GetMapping("/monthly-special-overspeed-vehicles") + public List monthlyOverspeedVehicles( + @Valid @ModelAttribute RptMonthSpecialOverspeedVehiclesParamDTO param) { + return rptMonthManage.monthlyOverspeedVehicles(param); + } + + @ApiOperation("浙江省超速企业排名月报表导出") + @GetMapping("/ZJ-overSpeed-enterprise-rank-monthReport-export") + public void overSpeedEnterpriseRankMonthReportExport + (RptMonthOverspeedCompanyParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptMonthManage::overSpeedEnterpriseRankMonthReportExport); + } + + @ApiOperation("浙江省超速专用车辆排名月报表导出") + @GetMapping("/ZJ-overSpeed-special-vehicles-rank-monthReport-export") + public void overSpeedSpecialVehiclesRankMonthReportExport + (RptMonthSpecialOverspeedCompanyParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptMonthManage::overSpeedSpecialVehiclesRankMonthReportExport); + } + + @ApiOperation("浙江省不上线的专用车辆排序表月报导出") + @GetMapping("/ZJ-special-vehicles-offline-sorting-monthReport-export") + public void specialVehiclesOfflineSortingMonthReportExport + (RptMonthSpecialOfflineParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptMonthManage::specialVehiclesOfflineSortingMonthReportExport); + } + + @ApiOperation("浙江省超速专用车辆月对比报表导出") + @GetMapping("/ZJ-overSpeed-special-vehicles-contrast-monthReport-export") + public void overSpeedSpecialVehiclesContrastMonthReportExport + (RptMonthSpecialOverspeedVehiclesParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptMonthManage::overSpeedSpecialVehiclesContrastMonthReportExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptOtherController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptOtherController.java new file mode 100644 index 0000000..6722d6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptOtherController.java @@ -0,0 +1,173 @@ +package com.ningdatech.carapi.car.rpt.controller; + + +import com.ningdatech.carapi.car.rpt.manage.RptOtherManage; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.vo.*; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 车辆报警清理分析表 其它报表 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@RequestMapping("/api/car-rpt") +@RequiredArgsConstructor +@RestController +@Api(tags = "车辆管理-统计报表") +@Validated +public class RptOtherController { + private final RptOtherManage rptOtherManage; + + @ApiOperation("专用车辆超速记录") + @GetMapping("/other-special-overspeed") + public List otherSpecialOverspeed( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherSpecialOverspeed(param); + } + + @ApiOperation("专用车辆趟次记录") + @GetMapping("/other-special-trips") + public List otherSpecialTrips( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherSpecialTrips(param); + } + + @ApiOperation("企业车辆趟次记录") + @GetMapping("/other-company-trips") + public List otherCompanyTrips( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherCompanyTrips(param); + } + + @ApiOperation("车辆上线情况统计表") + @GetMapping("/other-online-vehicles") + public List otherOnlineVehicles( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherOnlineVehicles(param); + } + + @ApiOperation("车辆跨域情况统计表") + @GetMapping("/other-cross-domain-vehicles") + public List otherCrossDomainVehicles( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherCrossDomainVehicles(param); + } + + @ApiOperation("车辆报警清理情况统计表") + @GetMapping("/other-alaram-clean-vehicles") + public List otherAlarmCleanVehicles( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherAlarmCleanVehicles(param); + } + + @ApiOperation("车辆上线情况同比环比分析") + @GetMapping("/other-online-analysis-vehicles") + public List otherOnlineAnalysisVehicles( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherOnlineAnalysisVehicles(param); + } + + @ApiOperation("车辆跨域情况同比环比分析") + @GetMapping("/other-cross-domain-analysis-vehicles") + public List otherCrossDomainAnalysisVehicles( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherCrossDomainAnalysisVehicles(param); + } + + @ApiOperation("车辆告警情况同比环比分析") + @GetMapping("/other-alarm-analysis-vehicles") + public List otherAlarmAnalysisVehicles( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherAlarmAnalysisVehicles(param); + } + + @ApiOperation("企业车辆终端安装情况统计") + @GetMapping("/other-terminal-install") + public List otherTerminalInstall( + @Valid @ModelAttribute RptOtherParamDTO param) { + return rptOtherManage.otherTerminalInstall(param); + } + + + @ApiOperation("专用车辆超速记录查询导出") + @GetMapping("/special-vehicles-overSpeed-record-query-export") + public void specialVehiclesOverSpeedRecordQueryExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::specialVehiclesOverSpeedRecordQueryExport); + } + + @ApiOperation("专用车辆趟次记录查询导出") + @GetMapping("/special-vehicles-trips-record-query-export") + public void specialVehiclesTripsRecordQueryExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::specialVehiclesTripsRecordQueryExport); + } + + @ApiOperation("企业车辆趟次记录查询导出") + @GetMapping("/enterprise-vehicles-trips-record-query-export") + public void enterpriseVehiclesTripsRecordQueryExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::enterpriseVehiclesTripsRecordQueryExport); + } + + @ApiOperation("车辆上线情况统计报表导出") + @GetMapping("/vehicles-online-statistics-report-export") + public void vehiclesOnlineStatisticsReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::vehiclesOnlineStatisticsReportExport); + } + + @ApiOperation("车辆跨域情况统计报表导出") + @GetMapping("/vehicles-cross-domain-statistics-report-export") + public void vehiclesCrossDomainStatisticsReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::vehiclesCrossDomainStatisticsReportExport); + } + + @ApiOperation("车辆报警清理统计报表导出") + @GetMapping("/vehicles-alarm-clear-statistics-report-export") + public void vehiclesAlarmClearStatisticsReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::vehiclesAlarmClearStatisticsReportExport); + } + + @ApiOperation("车辆上线情况同比/环比分析导出") + @GetMapping("/vehicles-online-situation-annulus-analysis-report-export") + public void vehiclesOnlineSituationAnnulusAnalysisReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::vehiclesOnlineSituationAnnulusAnalysisReportExport); + } + + @ApiOperation("车辆报警情况同比/环比分析导出") + @GetMapping("/vehicles-alarm-situation-annulus-analysis-report-export") + public void vehiclesAlarmSituationAnnulusAnalysisReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::vehiclesAlarmSituationAnnulusAnalysisReportExport); + } + + @ApiOperation("车辆跨域情况同比/环比分析导出") + @GetMapping("/vehicles-cross-domain-situation-annulus-analysis-report-export") + public void vehiclesCrossDomainSituationAnnulusAnalysisReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::vehiclesCrossDomainSituationAnnulusAnalysisReportExport); + } + + @ApiOperation("企业车辆车载终端安装率统计导出") + @GetMapping("/enterprise-vehicles-car-terminal-installation-rate-report-export") + public void enterpriseVehiclesCarTerminalInstallationRateReportExport(RptOtherParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, rptOtherManage::enterpriseVehiclesCarTerminalInstallationRateReportExport); + } + + //@ApiOperation("9地区车辆上线情况统计导出") + //@GetMapping("/nine-areas-vehicles-online-statistics-report-export") + //public void nineAreasVehiclesOnlineStatisticsReportExport(RptOtherParamDTO req, HttpServletResponse response) { + // ExcelDownUtil.downXls(response, req, rptOtherManage::nineAreasVehiclesOnlineStatisticsReportExport); + //} +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptTendaysController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptTendaysController.java new file mode 100644 index 0000000..0537a2b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/controller/RptTendaysController.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.car.rpt.controller; + +import com.ningdatech.carapi.car.rpt.manage.RptTendaysManage; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOfflineWeekSpecialParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOfflineWeekPO; +import com.ningdatech.carapi.car.rpt.model.vo.RptTendaysSpecialOfflineWeekVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptTendaysSpecialOverspeedCompanyVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptTendaysSpecialOverspeedVehiclesVO; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 报表统计 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ + +@RequestMapping("/api/car-rpt") +@RequiredArgsConstructor +@RestController +@Api(tags = "车辆管理-统计报表") +@Validated +public class RptTendaysController { + + private final RptTendaysManage rptTendaysManage; + + @ApiOperation("浙江省专用车辆超速企业旬报") + @GetMapping("/tendays-special-overspeed-company") + public List tendaysSpecialOverspeedCompany( + @Valid @ModelAttribute RptTendaysOverspeedSpecialCompanyParamDTO param) { + return rptTendaysManage.tendaysSpecialOverspeedCompany(param); + } + + @ApiOperation("浙江省专用车辆超速车辆排序旬报") + @GetMapping("/tendays-special-overspeed-vehicles") + public List tendaysSpecialOverspeedVehicles( + @Valid @ModelAttribute RptTendaysOverspeedSpecialVehiclesParamDTO param) { + return rptTendaysManage.tendaysSpecialOverspeedVehicles(param); + } + + @ApiOperation("全省一周不上线的专用车辆旬报") + @GetMapping("/tendays-special-offline-week") + public List tendaysSpecialOfflineWeek( + @Valid @ModelAttribute RptTendaysOfflineWeekSpecialParamDTO param) { + return rptTendaysManage.tendaysSpecialOfflineWeek(param); + } + + @ApiOperation("全省专用车辆企业排序表导出") + @GetMapping("/special-vehicles-enterprise-sorting-tenDaysReport-export") + public void specialVehiclesEnterpriseSortingTenDaysReportExport + (RptTendaysOverspeedSpecialCompanyParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptTendaysManage::specialVehiclesEnterpriseSortingTenDaysReportExport); + } + + @ApiOperation("企业专用车辆排序表导出") + @GetMapping("/enterprise-special-vehicles-sorting-tenDaysReport-export") + public void enterpriseSpecialVehiclesSortingTenDaysReportExport + (RptTendaysOverspeedSpecialVehiclesParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptTendaysManage::enterpriseSpecialVehiclesSortingTenDaysReportExport); + } + + @ApiOperation("全省一周以上不上线的专用车辆排序导出") + @GetMapping("/special-vehicles-offline-week-tenDaysReport-export") + public void specialVehiclesOfflineWeekTenDaysReportExport + (RptTendaysOfflineWeekSpecialParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,rptTendaysManage::specialVehiclesOfflineWeekTenDaysReportExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOperatorVehiclesLaunchRate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOperatorVehiclesLaunchRate.java new file mode 100644 index 0000000..85084c1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOperatorVehiclesLaunchRate.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 运营商车辆上线率日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_rpt_daily_operator_vehicles_launch_rate") +@Data +@ApiModel(value = "RptDailyOperatorVehiclesLaunchRate对象", description = "运营商车辆上线率日报") +public class RptDailyOperatorVehiclesLaunchRate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("为监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedCompany.java new file mode 100644 index 0000000..5e125ee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedCompany.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 超速企业情况日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_rpt_daily_overspeed_company") +@Data +@ApiModel(value = "RptDailyOverspeedCompany对象", description = "超速企业情况日报") +public class RptDailyOverspeedCompany implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速车辆总数") + private Long overspeedVehicleNums; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedSpecialVehicles.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedSpecialVehicles.java new file mode 100644 index 0000000..74ed28c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailyOverspeedSpecialVehicles.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 超速专用车辆日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_rpt_daily_overspeed_special_vehicles") +@Data +@ApiModel(value = "RptDailyOverspeedSpecialVehicles对象", description = "超速专用车辆日报") +public class RptDailyOverspeedSpecialVehicles implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速%20-50%次数") + private Long overspeed2050Times; + + @ApiModelProperty("超速50以上 次数") + private Long overspeed50Times; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("总超速次数") + private Long overspeedTotalTimes; + + @ApiModelProperty("比例") + private BigDecimal rate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesCompanyLaunchRate60.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesCompanyLaunchRate60.java new file mode 100644 index 0000000..27a2e0f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesCompanyLaunchRate60.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆企业上线率低于60日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_rpt_daily_special_vehicles_company_launch_rate_60") +@Data +@ApiModel(value = "RptDailySpecialVehiclesCompanyLaunchRate60对象", description = "专用车辆企业上线率低于60日报") +public class RptDailySpecialVehiclesCompanyLaunchRate60 implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("为监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesLaunchRate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesLaunchRate.java new file mode 100644 index 0000000..8df9ba7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesLaunchRate.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆上线率日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_rpt_daily_special_vehicles_launch_rate") +@ApiModel(value = "RptDailySpecialVehiclesLaunchRate对象", description = "专用车辆上线率日报") +@Data +public class RptDailySpecialVehiclesLaunchRate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("为监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesOverspeed.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesOverspeed.java new file mode 100644 index 0000000..f27e4f1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptDailySpecialVehiclesOverspeed.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆超速日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_rpt_daily_special_vehicles_overspeed") +@Data +@ApiModel(value = "RptDailySpecialVehiclesOverspeed对象", description = "专用车辆超速日报") +public class RptDailySpecialVehiclesOverspeed implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("20%-50%车辆数") + private Long overspeed2050VehicleNums; + + @ApiModelProperty("超速50%以上的车辆") + private Long overspeed50VehicleNums; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedCompany.java new file mode 100644 index 0000000..946b122 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedCompany.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 超速企业情况月报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_month_overspeed_company") +@Data +@ApiModel(value = "RptMonthOverspeedCompany对象", description = "超速企业情况月报") +public class RptMonthOverspeedCompany implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速次数") + private Long overspeedTimes; + + @ApiModelProperty("企业车辆数") + private Long vehicleNums; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialCompany.java new file mode 100644 index 0000000..e4d1576 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialCompany.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆超速企业情况月报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_month_overspeed_special_company") +@Data +@ApiModel(value = "RptMonthOverspeedSpecialCompany对象", description = "专用车辆超速企业情况月报") +public class RptMonthOverspeedSpecialCompany implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速次数") + private Long overspeedTimes; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("最高速率") + private BigDecimal maxSpeed; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialVehicles.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialVehicles.java new file mode 100644 index 0000000..78d4aaa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthOverspeedSpecialVehicles.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆超速月对比 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_month_overspeed_special_vehicles") +@Data +@ApiModel(value = "RptMonthOverspeedSpecialVehicles对象", description = "专用车辆超速月对比") +public class RptMonthOverspeedSpecialVehicles implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("本月超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("企业车辆数") + private Long vehicleNums; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; + + @ApiModelProperty("上月超速次数") + private Long overspeedLastTimes; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthSpecialOffline.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthSpecialOffline.java new file mode 100644 index 0000000..d74ac7b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptMonthSpecialOffline.java @@ -0,0 +1,63 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆不上线月报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_month_special_offline") +@Data +@ApiModel(value = "RptMonthSpecialOffline对象", description = "专用车辆不上线月报") +public class RptMonthSpecialOffline implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("未上线天数") + private Integer offlineDays; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehicles.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehicles.java new file mode 100644 index 0000000..8ae313e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehicles.java @@ -0,0 +1,91 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆报警清理表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_alarm_clean_vehicles") +@Data +@ApiModel(value = "RptOtherAlarmCleanVehicles对象", description = "车辆报警清理表 其它报表") +public class RptOtherAlarmCleanVehicles implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("报警车总数") + private Long alarmVehicleNums; + + @ApiModelProperty("报警车辆占比") + private BigDecimal alarmVehicleRate; + + @ApiModelProperty("报警处理总数") + private Long alarmProcessNums; + + @ApiModelProperty("报警处理占比") + private BigDecimal alarmProcessRate; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehiclesAnalysis.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehiclesAnalysis.java new file mode 100644 index 0000000..7e40cf9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherAlarmCleanVehiclesAnalysis.java @@ -0,0 +1,118 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆报警清理分析表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_alarm_clean_vehicles_analysis") +@Data +@ApiModel(value = "RptOtherAlarmCleanVehiclesAnalysis对象", description = "车辆报警清理分析表 其它报表") +public class RptOtherAlarmCleanVehiclesAnalysis implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("报警车总数") + private Long alarmVehicleNums; + + @ApiModelProperty("报警车辆占比") + private BigDecimal alarmVehicleRate; + + @ApiModelProperty("报警处理总数") + private Long alarmProcessNums; + + @ApiModelProperty("报警处理占比") + private BigDecimal alarmProcessRate; + + @ApiModelProperty("报警车同比") + private BigDecimal alarmVehicleYoy; + + @ApiModelProperty("报警车环比") + private BigDecimal alarmVehicleQoq; + + @ApiModelProperty("报警处理同比") + private BigDecimal alarmProcessYoy; + + @ApiModelProperty("报警处理环比") + private BigDecimal alarmProcessQoq; + + @ApiModelProperty("在线同比") + private BigDecimal onlineYoy; + + @ApiModelProperty("在线环比") + private BigDecimal onlineQoq; + + @ApiModelProperty("离线同比") + private BigDecimal offlineYoy; + + @ApiModelProperty("离线环比") + private BigDecimal offlineQoq; + + @ApiModelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehicles.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehicles.java new file mode 100644 index 0000000..339e99a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehicles.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆跨域情况表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_cross_domain_vehicles") +@Data +@ApiModel(value = "RptOtherCrossDomainVehicles对象", description = "车辆跨域情况表 其它报表") +public class RptOtherCrossDomainVehicles implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("散装水泥车数") + private Long bulkCementTruckNums; + + @ApiModelProperty("散装水泥车占比") + private BigDecimal bulkCementTruckRate; + + @ApiModelProperty("预拌砂浆车数") + private Long readyMixedMortarTruckNums; + + @ApiModelProperty("预拌砂浆车占比") + private BigDecimal readyMixedMortarTruckRate; + + @ApiModelProperty("混凝土搅拌车数") + private Long concreteDeliveryTruckNums; + + @ApiModelProperty("混凝土搅拌车数占比") + private BigDecimal concreteDeliveryTruckRate; + + @ApiModelProperty("移动泵车数") + private Long mobilePumpTruckNums; + + @ApiModelProperty("移动泵车占比") + private BigDecimal mobilePumpTruckRate; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehiclesAnalysis.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehiclesAnalysis.java new file mode 100644 index 0000000..6ed48dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherCrossDomainVehiclesAnalysis.java @@ -0,0 +1,142 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆跨域情况分析表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_cross_domain_vehicles_analysis") +@Data +@ApiModel(value = "RptOtherCrossDomainVehiclesAnalysis对象", description = "车辆跨域情况分析表 其它报表") +public class RptOtherCrossDomainVehiclesAnalysis implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("散装水泥车数") + private Long bulkCementTruckNums; + + @ApiModelProperty("散装水泥车占比") + private BigDecimal bulkCementTruckRate; + + @ApiModelProperty("预拌砂浆车数") + private Long readyMixedMortarTruckNums; + + @ApiModelProperty("预拌砂浆车占比") + private BigDecimal readyMixedMortarTruckRate; + + @ApiModelProperty("混凝土搅拌车数") + private Long concreteDeliveryTruckNums; + + @ApiModelProperty("混凝土搅拌车数占比") + private BigDecimal concreteDeliveryTruckRate; + + @ApiModelProperty("移动泵车数") + private Long mobilePumpTruckNums; + + @ApiModelProperty("移动泵车占比") + private BigDecimal mobilePumpTruckRate; + + @ApiModelProperty("散装水泥车同比") + private BigDecimal bulkCementTruckYoy; + + @ApiModelProperty("散装水泥车环比") + private BigDecimal bulkCementTruckQoq; + + @ApiModelProperty("预拌砂浆车同比") + private BigDecimal readyMixedMortarTruckYoy; + + @ApiModelProperty("瘀斑砂浆车环比") + private BigDecimal readyMixedMortarTruckQoq; + + @ApiModelProperty("混凝土搅拌车同比") + private BigDecimal concreteDeliveryTruckYoy; + + @ApiModelProperty("混凝土搅拌车环比") + private BigDecimal concreteDeliveryTruckQoq; + + @ApiModelProperty("移动泵车同比") + private BigDecimal mobilePumpTruckYoy; + + @ApiModelProperty("移动泵车环比") + private BigDecimal mobilePumpTruckQoq; + + @ApiModelProperty("在线同比") + private BigDecimal onlineYoy; + + @ApiModelProperty("在线环比") + private BigDecimal onlineQoq; + + @ApiModelProperty("离线同比") + private BigDecimal offlineYoy; + + @ApiModelProperty("离线环比") + private BigDecimal offlineQoq; + + @ApiModelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehicles.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehicles.java new file mode 100644 index 0000000..3a4be23 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehicles.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 在线车辆统计表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_online_vehicles") +@Data +@ApiModel(value = "RptOtherOnlineVehicles对象", description = "在线车辆统计表 其它报表") +public class RptOtherOnlineVehicles implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehiclesAnalysis.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehiclesAnalysis.java new file mode 100644 index 0000000..434a70c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherOnlineVehiclesAnalysis.java @@ -0,0 +1,94 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 在线车辆统计分析表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_online_vehicles_analysis") +@Data +@ApiModel(value = "RptOtherOnlineVehiclesAnalysis对象", description = "在线车辆统计分析表 其它报表") +public class RptOtherOnlineVehiclesAnalysis implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("在线同比") + private BigDecimal onlineYoy; + + @ApiModelProperty("在线环比") + private BigDecimal onlineQoq; + + @ApiModelProperty("离线同比") + private BigDecimal offlineYoy; + + @ApiModelProperty("离线环比") + private BigDecimal offlineQoq; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialOverspeed.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialOverspeed.java new file mode 100644 index 0000000..63cd174 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialOverspeed.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆超速记录 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_special_overspeed") +@Data +@ApiModel(value = "RptOtherSpecialOverspeed对象", description = "专用车辆超速记录 其它报表") +public class RptOtherSpecialOverspeed implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("超速开始时间") + private LocalDateTime overspeedStartTime; + + @ApiModelProperty("超速结束时间") + private LocalDateTime overspeedEndTime; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("限速") + private BigDecimal limitSpeed; + + @ApiModelProperty("最高速") + private BigDecimal maxSpeed; + + @ApiModelProperty("超速率") + private Double overspeedRate; + + @ApiModelProperty("持续时间 秒") + private Integer duration; + + @ApiModelProperty("地点") + private String address; + + @ApiModelProperty("道路") + private String road; + + @ApiModelProperty("经纬度") + private String longtitudeLatitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialTrips.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialTrips.java new file mode 100644 index 0000000..cd00720 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherSpecialTrips.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆趟次记录 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_special_trips") +@Data +@ApiModel(value = "RptOtherSpecialTrips对象", description = "专用车辆趟次记录 其它报表") +public class RptOtherSpecialTrips implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车辆数") + private Integer vehicleNums; + + @ApiModelProperty("趟次") + private Long trips; + + @ApiModelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherTerminalInstall.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherTerminalInstall.java new file mode 100644 index 0000000..51829db --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptOtherTerminalInstall.java @@ -0,0 +1,94 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 终端车载安装统计 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_other_terminal_install") +@Data +@ApiModel(value = "RptOtherTerminalInstall对象", description = "终端车载安装统计 其它报表") +public class RptOtherTerminalInstall implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("车辆类型") + private Long vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("安装终端的车辆数") + private Long installedNums; + + @ApiModelProperty("安装终端的车辆占比") + private BigDecimal installedRate; + + @ApiModelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOfflineWeek.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOfflineWeek.java new file mode 100644 index 0000000..9006a5e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOfflineWeek.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆一周以上不上线旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_tendays_special_offline_week") +@ApiModel(value = "RptTendaysSpecialOfflineWeek对象", description = "专用车辆一周以上不上线旬报") +@Data +public class RptTendaysSpecialOfflineWeek implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("未上线天数") + private Integer offlineDays; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedCompany.java new file mode 100644 index 0000000..adbfb9b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedCompany.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆超速企业情况旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_tendays_special_overspeed_company") +@ApiModel(value = "RptTendaysSpecialOverspeedCompany对象", description = "专用车辆超速企业情况旬报") +@Data +public class RptTendaysSpecialOverspeedCompany implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("当前旬超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("上一旬超速次数") + private Long overspeedLastTimes; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedVehicles.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedVehicles.java new file mode 100644 index 0000000..e7e789d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/entity/RptTendaysSpecialOverspeedVehicles.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.car.rpt.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 专用车辆超速车辆情况旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_rpt_tendays_special_overspeed_vehicles") +@ApiModel(value = "RptTendaysSpecialOverspeedVehicles对象", description = "专用车辆超速车辆情况旬报") +@Data +public class RptTendaysSpecialOverspeedVehicles implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("当前旬超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("上一旬超速次数") + private Long overspeedLastTimes; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptDailyManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptDailyManage.java new file mode 100644 index 0000000..a8a204d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptDailyManage.java @@ -0,0 +1,192 @@ +package com.ningdatech.carapi.car.rpt.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.rpt.entity.*; +import com.ningdatech.carapi.car.rpt.model.dto.*; +import com.ningdatech.carapi.car.rpt.model.po.*; +import com.ningdatech.carapi.car.rpt.model.vo.*; +import com.ningdatech.carapi.car.rpt.service.*; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +/** + * @Classname RptManage + * @Description + * @Date 2022/11/8 17:03 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class RptDailyManage { + private final IRptDailySpecialVehiclesLaunchRateService rptDailySpecialVehiclesLaunchRateService; + private final IRptDailyOperatorVehiclesLaunchRateService rptDailyOperatorVehiclesLaunchRateService; + private final IRptDailySpecialVehiclesCompanyLaunchRate60Service rptDailySpecialVehiclesCompanyLaunchRate60Service; + private final IRptDailySpecialVehiclesOverspeedService rptDailySpecialVehiclesOverspeedService; + private final IRptDailyOverspeedCompanyService rptDailyOverspeedCompanyService; + private final IRptDailyOverspeedSpecialVehiclesService rptDailyOverspeedSpecialVehiclesService; + + @XmlDataScope + @BuildChildrenRegionEntity + public List dailySpecialVehiclesLaunchRate( + RptDailySpecialVehiclesLaunchRateParamDTO param) { + List list = rptDailySpecialVehiclesLaunchRateService.report(param); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptDailySpecialVehiclesLaunchRateVO.class)); + } + + @XmlDataScope + public List dailyOperatorVehiclesLaunchRate( + RptDailyOperatorVehiclesLaunchRateParamDTO param) { + List list = rptDailyOperatorVehiclesLaunchRateService.report(param); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptDailyOperatorVehiclesLaunchRateVO.class)); + } + + public List dailySpecialVehiclesCompanyLaunchRate( + RptDailySpecialVehiclesCompanyLaunchRateParamDTO param) { + List list = rptDailySpecialVehiclesCompanyLaunchRate60Service.report(param); + return CollUtils.convert(list,w -> { + RptDailySpecialVehiclesCompanyLaunchRate60VO vo = BeanUtil.copyProperties(w, RptDailySpecialVehiclesCompanyLaunchRate60VO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List dailySpecialVehiclesOverspeed( + RptDailySpecialVehiclesOverspeedParamDTO param) { + List list = rptDailySpecialVehiclesOverspeedService.report(param); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptDailySpecialVehiclesOverspeedVO.class)); + } + + public List dailyOverspeedCompany( + RptDailyOverspeedCompanyParamDTO param) { + List list = rptDailyOverspeedCompanyService.report(param); + return CollUtils.convert(list,w -> { + RptDailyOverspeedCompanyVO vo = BeanUtil.copyProperties(w, RptDailyOverspeedCompanyVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + public List dailyOverspeedSpecialVehicles(RptDailyOverspeedSpecialVehiclesParamDTO param) { + List list = rptDailyOverspeedSpecialVehiclesService.report(param); + return CollUtils.convert(list,w -> { + RptDailyOverspeedSpecialVehiclesVO vo = BeanUtil.copyProperties(w, RptDailyOverspeedSpecialVehiclesVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + public void specialVehiclesOnlineRateDailyReportExport(HttpServletResponse response,RptDailySpecialVehiclesLaunchRateParamDTO param) { + List collect = dailySpecialVehiclesLaunchRate(param); + String fileName = "浙江省专用车辆上线率日报表"; + ExcelDownUtil.setFileName(fileName,response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(),RptDailySpecialVehiclesLaunchRateVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + public void operatorsVehiclesOnlineRateDailyReportExport(HttpServletResponse response, RptDailyOperatorVehiclesLaunchRateParamDTO param) { + List collect = dailyOperatorVehiclesLaunchRate(param); + String fileName = "运营商车辆上线率日报表"; + ExcelDownUtil.setFileName(fileName,response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(),RptDailyOperatorVehiclesLaunchRateVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void specialVehiclesOnlineRateEnterpriseDailyReportExport60(HttpServletResponse response, RptDailySpecialVehiclesCompanyLaunchRateParamDTO param) { + List collect = dailySpecialVehiclesCompanyLaunchRate(param); + String fileName = "浙江省专用车辆上线率低于60%的企业日报表"; + ExcelDownUtil.setFileName(fileName,response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(),RptDailySpecialVehiclesCompanyLaunchRate60VO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void specialVehiclesOverSpeedDailyReportExport(HttpServletResponse response, RptDailySpecialVehiclesOverspeedParamDTO param) { + List collect = dailySpecialVehiclesOverspeed(param); + String fileName = "浙江省专用车辆超速情况日报表"; + ExcelDownUtil.setFileName(fileName,response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(),RptDailySpecialVehiclesOverspeedVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void overSpeedEnterpriseRankDailyReportExport(HttpServletResponse response, RptDailyOverspeedCompanyParamDTO param) { + List collect = dailyOverspeedCompany(param); + String fileName = "浙江省超速企业排名日报表"; + ExcelDownUtil.setFileName(fileName,response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(),RptDailyOverspeedCompanyVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void overSpeedSpecialVehiclesRankDailyReportExport(HttpServletResponse response, RptDailyOverspeedSpecialVehiclesParamDTO param) { + List collect = dailyOverspeedSpecialVehicles(param); + String fileName = "浙江省超速专用车辆排名日报表"; + ExcelDownUtil.setFileName(fileName,response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(),RptDailyOverspeedSpecialVehiclesVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptMonthManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptMonthManage.java new file mode 100644 index 0000000..822cd11 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptMonthManage.java @@ -0,0 +1,239 @@ +package com.ningdatech.carapi.car.rpt.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOfflineParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedCompanyPO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedSpecialVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialVehiclesOverspeedPO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedCompanyVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedSpecialCompanyVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedSpecialVehiclesVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptMonthSpecialOfflineVO; +import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedCompanyService; +import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedSpecialCompanyService; +import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedSpecialVehiclesService; +import com.ningdatech.carapi.car.rpt.service.IRptMonthSpecialOfflineService; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusDay; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusDayService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Field; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.List; + +/** + * @author CMM + * @Classname RptManage + * @Description + * @Date 2022/11/8 17:03 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class RptMonthManage { + private final RegionsCacheHelper regionsCacheHelper; + private final IRptMonthOverspeedCompanyService rptMonthOverspeedCompanyService; + private final IRptMonthOverspeedSpecialCompanyService rptMonthOverspeedSpecialCompanyService; + private final IRptMonthOverspeedSpecialVehiclesService rptMonthOverspeedSpecialVehiclesService; + private final IRptMonthSpecialOfflineService rptMonthSpecialOfflineService; + private final IVehicleOnlineStatusDayService vehicleOnlineStatusDayService; + + public List monthlyOverspeedCompany(RptMonthOverspeedCompanyParamDTO param) { + validMonthDays(param); + List list = rptMonthOverspeedCompanyService.report(param); + return CollUtils.convert(list,m ->{ + RptMonthOverspeedCompanyVO vo = BeanUtil.copyProperties(m, RptMonthOverspeedCompanyVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + private void validMonthDays(T param) { + + Field startTimeField = null; + Field endTimeField = null; + String startTime = null; + String endTime = null; + try { + startTimeField = param.getClass().getDeclaredField("startTime"); + endTimeField = param.getClass().getDeclaredField("endTime"); + startTimeField.setAccessible(Boolean.TRUE); + endTimeField.setAccessible(Boolean.TRUE); + startTime = ((String) startTimeField.get(param)); + endTime = ((String) endTimeField.get(param)); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + LocalDate start = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(startTime)); + LocalDate end = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(endTime)); + int startYear = start.getYear(); + int endYear = end.getYear(); + if (endYear != startYear){ + throw new BizException("选择日期错误,请重新选择!"); + } + int startMonth = start.getMonthValue(); + int endMonth = end.getMonthValue(); + if (endMonth != startMonth){ + throw new BizException("选择日期错误,请重新选择!"); + } + int startDayOfMonth = start.getDayOfMonth(); + int endDayOfMonth = end.getDayOfMonth(); + int days = endDayOfMonth - startDayOfMonth; + if (days > (int) (NdDateUtils.MAX_MONTH_DAY + 1)){ + throw new BizException("选择日期天数大于31天,请重新选择!"); + } + } + + public List monthlySpecialOverspeedCompany(RptMonthSpecialOverspeedCompanyParamDTO param) { + validMonthDays(param); + List list = rptMonthOverspeedSpecialCompanyService.report(param); + return CollUtils.convert(list,m ->{ + RptMonthOverspeedSpecialCompanyVO vo = BeanUtil.copyProperties(m, RptMonthOverspeedSpecialCompanyVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + public List monthlySpecialOffline(RptMonthSpecialOfflineParamDTO param) { + // 不允许跨年和跨月,时间区间在某个月内 + validMonthDays(param); + Page page = param.page(); + + String startTimeStr = param.getStartTime(); + LocalDateTime startTime = LocalDateTime.parse(startTimeStr, DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + int startDay = startTime.getDayOfYear(); + String endTimeStr = param.getEndTime(); + LocalDateTime endTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + int endDay = endTime.getDayOfYear(); + + // 从车辆天在线表中查询出所选时间区间内所有的车辆 + VehicleOnlineStatusDay statusday = new VehicleOnlineStatusDay(); + statusday.setYear(String.valueOf(LocalDateTime.now().getYear())); + statusday.setMonth(String.valueOf(LocalDateTime.now().getMonthValue())); + statusday.setDay(String.valueOf(LocalDateTime.now().getDayOfMonth())); + //vehicleOnlineStatusDayService.listInMonthTable(); + // 计算车辆最大不在线天数 + + + + List pageList = rptMonthSpecialOfflineService.reportPage(page,param); + if (CollUtil.isEmpty(pageList)){ + return Collections.emptyList(); + } + return CollUtils.convert(pageList,m ->{ + RptMonthSpecialOfflineVO vo = BeanUtil.copyProperties(m, RptMonthSpecialOfflineVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List monthlyOverspeedVehicles(RptMonthSpecialOverspeedVehiclesParamDTO param) { + validMonthDays(param); + Page page = param.page(); + LocalDate start = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(param.getStartTime())); + LocalDate end = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(param.getEndTime())); + String lastMonthStartTime = start.minusMonths(1).toString(); + String lastMonthEndTime = end.minusMonths(1).toString(); + param.setLastMonthStartTime(lastMonthStartTime); + param.setLastMonthEndTime(lastMonthEndTime); + List pageList = rptMonthOverspeedSpecialVehiclesService.reportPage(page,param); + if (CollUtil.isEmpty(pageList)){ + return Collections.emptyList(); + } + return CollUtils.convert(pageList,m ->{ + RptMonthOverspeedSpecialVehiclesVO vo = BeanUtil.copyProperties(m, RptMonthOverspeedSpecialVehiclesVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public void overSpeedEnterpriseRankMonthReportExport + (HttpServletResponse response, RptMonthOverspeedCompanyParamDTO param) { + List collect = monthlyOverspeedCompany(param); + String fileName = "浙江省超速企业排名月报表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptMonthOverspeedCompanyVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void overSpeedSpecialVehiclesRankMonthReportExport(HttpServletResponse response, RptMonthSpecialOverspeedCompanyParamDTO param) { + List collect = monthlySpecialOverspeedCompany(param); + String fileName = "浙江省超速专用车辆排名月报表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptMonthOverspeedSpecialCompanyVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void specialVehiclesOfflineSortingMonthReportExport(HttpServletResponse response, RptMonthSpecialOfflineParamDTO param) { + List collect = monthlySpecialOffline(param); + String fileName = "浙江省不上线的专用车辆排序表月报"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptMonthSpecialOfflineVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void overSpeedSpecialVehiclesContrastMonthReportExport(HttpServletResponse response, RptMonthSpecialOverspeedVehiclesParamDTO param) { + List collect = monthlyOverspeedVehicles(param); + String fileName = "浙江省超速专用车辆月对比报表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptMonthOverspeedSpecialVehiclesVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptOtherManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptOtherManage.java new file mode 100644 index 0000000..7e8692e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptOtherManage.java @@ -0,0 +1,389 @@ +package com.ningdatech.carapi.car.rpt.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.rpt.entity.*; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherAlarmCleanVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherCrossDomainVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherSpecialOverspeedPO; +import com.ningdatech.carapi.car.rpt.model.vo.*; +import com.ningdatech.carapi.car.rpt.service.*; +import com.ningdatech.carapi.car.trips.manage.VehicleTripsManage; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; +import com.ningdatech.carapi.car.trips.model.vo.VehicleTripsCityVO; +import com.ningdatech.carapi.car.trips.model.vo.VehicleTripsCompanyVO; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.CompanyJoin; +import com.ningdatech.carapi.sys.entity.dto.CompanyPageQuery; +import com.ningdatech.carapi.sys.entity.vo.CompanyVO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.manage.CompanyManage; +import com.ningdatech.carapi.sys.service.CompanyService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * @Classname RptOtherManage + * @Description + * @Date 2022/11/8 17:03 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class RptOtherManage { + private final VehicleTripsManage vehicleTripsManage; + + private final IRptOtherAlarmCleanVehiclesService rptOtherAlarmCleanVehiclesService; + private final IRptOtherAlarmCleanVehiclesAnalysisService rptOtherAlarmCleanVehiclesAnalysisService; + private final IRptOtherCrossDomainVehiclesAnalysisService rptOtherCrossDomainVehiclesAnalysisService; + private final IRptOtherCrossDomainVehiclesService rptOtherCrossDomainVehiclesService; + private final IRptOtherOnlineVehiclesService rptOtherOnlineVehiclesService; + private final IRptOtherOnlineVehiclesAnalysisService rptOtherOnlineVehiclesAnalysisService; + private final IRptOtherSpecialOverspeedService rptOtherSpecialOverspeedService; + private final IRptOtherSpecialTripsService rptOtherSpecialTripsService; + private final IRptOtherTerminalInstallService rptOtherTerminalInstallService; + + private final CompanyService companyService; + + public List otherSpecialOverspeed(RptOtherParamDTO param) { + Page page = param.page(); + rptOtherSpecialOverspeedService.reportPage(page,param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(),w -> { + RptOtherSpecialOverspeedVO vo = BeanUtil.copyProperties(w, RptOtherSpecialOverspeedVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List otherSpecialTrips(RptOtherParamDTO param) { + VehicleTripsParamDTO vehicleTripsParam = new VehicleTripsParamDTO(); + vehicleTripsParam.setRegionId(param.getRegionId()); + vehicleTripsParam.setStartTime(param.getStartTime()); + vehicleTripsParam.setEndTime(param.getEndTime()); + vehicleTripsParam.setVehicleTypes(Arrays.asList(1,2,3,4)); + PageVo pageList = vehicleTripsManage.lictGroupByCity(vehicleTripsParam); + if(0L == pageList.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(pageList.getRecords(),w -> { + RptOtherSpecialTripsVO vo = BeanUtil.copyProperties(w, RptOtherSpecialTripsVO.class); + vo.setTrips(w.getVehicleTripsNums()); + return vo; + }); + } + + public List otherCompanyTrips(RptOtherParamDTO param) { + VehicleTripsParamDTO vehicleTripsParam = new VehicleTripsParamDTO(); + vehicleTripsParam.setRegionId(param.getRegionId()); + vehicleTripsParam.setStartTime(param.getStartTime()); + vehicleTripsParam.setEndTime(param.getEndTime()); + PageVo pageList = vehicleTripsManage.lictGroupByCompany(vehicleTripsParam); + if(0L == pageList.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(pageList.getRecords(),w -> { + RptOtherCompanyTripsVO vo = BeanUtil.copyProperties(w, RptOtherCompanyTripsVO.class); + vo.setTrips(w.getVehicleTripsNums()); + return vo; + }); + } + + public List otherOnlineVehicles(RptOtherParamDTO param) { + Page page = param.page(); + companyService.pageVehicleNum(page,param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(),w -> { + RptOtherOnlineVehiclesVO vo = BeanUtil.copyProperties(w, RptOtherOnlineVehiclesVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + } + + public List otherCrossDomainVehicles(RptOtherParamDTO param) { + Page page = param.page(); + rptOtherCrossDomainVehiclesService.reportPage(page,param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(),w -> { + RptOtherCrossDomainVehiclesVO vo = new RptOtherCrossDomainVehiclesVO(); + BeanUtils.copyProperties(w, vo); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List otherAlarmCleanVehicles(RptOtherParamDTO param) { + Page page = param.page(); + rptOtherAlarmCleanVehiclesService.reportPage(page,param); + if(0L == page.getTotal()){ + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(),w -> { + RptOtherAlarmCleanVehiclesVO vo = new RptOtherAlarmCleanVehiclesVO(); + BeanUtils.copyProperties(w, vo); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List otherOnlineAnalysisVehicles(RptOtherParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RptOtherOnlineVehiclesAnalysis.class); + wrapper.like(Objects.nonNull(param.getCompanyName()),RptOtherOnlineVehiclesAnalysis::getCompanyName,param.getCompanyName()) + .eq(Objects.nonNull(param.getRegionId()),RptOtherOnlineVehiclesAnalysis::getRegionId,param.getRegionId()) + .eq(Objects.nonNull(param.getOperatorId()),RptOtherOnlineVehiclesAnalysis::getOperatorId,param.getOperatorId()) + .eq(Objects.nonNull(param.getYearMonth()),RptOtherOnlineVehiclesAnalysis::getYearMonthly,param.getYearMonth()) + .like(Objects.nonNull(param.getEnterpriseType()),RptOtherOnlineVehiclesAnalysis::getEnterpriseType,param.getEnterpriseType()) + .orderBy(Boolean.TRUE,Boolean.FALSE, RptOtherOnlineVehiclesAnalysis::getCreateOn); + List list = rptOtherOnlineVehiclesAnalysisService.list(wrapper); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptOtherOnlineVehiclesAnalysisVO.class)); + } + + public List otherCrossDomainAnalysisVehicles(RptOtherParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RptOtherCrossDomainVehiclesAnalysis.class); + wrapper.like(Objects.nonNull(param.getCompanyName()),RptOtherCrossDomainVehiclesAnalysis::getCompanyName,param.getCompanyName()) + .eq(Objects.nonNull(param.getRegionId()),RptOtherCrossDomainVehiclesAnalysis::getRegionId,param.getRegionId()) + .eq(Objects.nonNull(param.getOperatorId()),RptOtherCrossDomainVehiclesAnalysis::getOperatorId,param.getOperatorId()) + .like(Objects.nonNull(param.getEnterpriseType()),RptOtherCrossDomainVehiclesAnalysis::getEnterpriseType,param.getEnterpriseType()) + .eq(Objects.nonNull(param.getYearMonth()),RptOtherCrossDomainVehiclesAnalysis::getYearMonthly,param.getYearMonth()) + .orderBy(Boolean.TRUE,Boolean.FALSE, RptOtherCrossDomainVehiclesAnalysis::getCreateOn); + List list = rptOtherCrossDomainVehiclesAnalysisService.list(wrapper); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptOtherCrossDomainVehiclesAnalysisVO.class)); + } + + public List otherAlarmAnalysisVehicles(RptOtherParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RptOtherAlarmCleanVehiclesAnalysis.class); + wrapper.like(Objects.nonNull(param.getCompanyName()),RptOtherAlarmCleanVehiclesAnalysis::getCompanyName,param.getCompanyName()) + .eq(Objects.nonNull(param.getRegionId()),RptOtherAlarmCleanVehiclesAnalysis::getRegionId,param.getRegionId()) + .eq(Objects.nonNull(param.getOperatorId()),RptOtherAlarmCleanVehiclesAnalysis::getOperatorId,param.getOperatorId()) + .eq(Objects.nonNull(param.getYearMonth()),RptOtherAlarmCleanVehiclesAnalysis::getYearMonthly,param.getYearMonth()) + .like(Objects.nonNull(param.getEnterpriseType()),RptOtherAlarmCleanVehiclesAnalysis::getEnterpriseType,param.getEnterpriseType()) + .orderBy(Boolean.TRUE,Boolean.FALSE, RptOtherAlarmCleanVehiclesAnalysis::getCreateOn); + List list = rptOtherAlarmCleanVehiclesAnalysisService.list(wrapper); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptOtherAlarmCleanVehiclesAnalysisVO.class)); + } + + public List otherTerminalInstall(RptOtherParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RptOtherTerminalInstall.class); + wrapper.like(Objects.nonNull(param.getCompanyName()),RptOtherTerminalInstall::getCompanyName,param.getCompanyName()) + .eq(Objects.nonNull(param.getRegionId()),RptOtherTerminalInstall::getRegionId,param.getRegionId()) + .eq(Objects.nonNull(param.getOperatorId()),RptOtherTerminalInstall::getOperatorId,param.getOperatorId()) + .eq(Objects.nonNull(param.getYearMonth()),RptOtherTerminalInstall::getYearMonthly,param.getYearMonth()) + .like(Objects.nonNull(param.getEnterpriseType()),RptOtherTerminalInstall::getEnterpriseType,param.getEnterpriseType()) + .orderBy(Boolean.TRUE,Boolean.FALSE, RptOtherTerminalInstall::getCreateOn); + List list = rptOtherTerminalInstallService.list(wrapper); + return CollUtils.convert(list,w -> BeanUtil.copyProperties(w,RptOtherTerminalInstallVO.class)); + } + + public void specialVehiclesOverSpeedRecordQueryExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherSpecialOverspeed(param); + String fileName = "专用车辆超速记录查询"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherSpecialOverspeedVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void specialVehiclesTripsRecordQueryExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherSpecialTrips(param); + String fileName = "专用车辆趟次记录查询导出"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherSpecialTripsVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void enterpriseVehiclesTripsRecordQueryExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherCompanyTrips(param); + String fileName = "企业车辆趟次记录查询"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherCompanyTripsVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void vehiclesOnlineStatisticsReportExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherOnlineVehicles(param); + String fileName = "车辆上线情况统计报表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherOnlineVehiclesVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void vehiclesCrossDomainStatisticsReportExport(HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherCrossDomainVehicles(param); + String fileName = "车辆跨域情况统计报表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherCrossDomainVehiclesVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void vehiclesAlarmClearStatisticsReportExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherAlarmCleanVehicles(param); + String fileName = "车辆报警清理统计报表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherAlarmCleanVehiclesVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void vehiclesOnlineSituationAnnulusAnalysisReportExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherOnlineAnalysisVehicles(param); + String fileName = "车辆上线情况同比环比分析"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherOnlineVehiclesAnalysisVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void vehiclesAlarmSituationAnnulusAnalysisReportExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherAlarmAnalysisVehicles(param); + String fileName = "车辆报警情况同比环比分析"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherAlarmCleanVehiclesAnalysisVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void vehiclesCrossDomainSituationAnnulusAnalysisReportExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherCrossDomainAnalysisVehicles(param); + String fileName = "车辆跨域情况同比环比分析"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherCrossDomainVehiclesAnalysisVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void enterpriseVehiclesCarTerminalInstallationRateReportExport + (HttpServletResponse response, RptOtherParamDTO param) { + List collect = otherTerminalInstall(param); + String fileName = "企业车辆车载终端安装率统计"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptOtherTerminalInstallVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + //public void nineAreasVehiclesOnlineStatisticsReportExport + // (HttpServletResponse response, RptOtherParamDTO param) { + // List collect = otherOnlineVehicles(param); + // String fileName = "9地区车辆上线情况统计"; + // ExcelDownUtil.setFileName(fileName, response); + // // 数据导出处理函数 + // try { + // EasyExcel.write(response.getOutputStream(), RptOtherOnlineVehiclesVO.class) + // .autoCloseStream(false) + // .registerWriteHandler(ExcelExportStyle.formalStyle()) + // .sheet(fileName) + // .doWrite(collect); + // } catch (IOException e) { + // throw new RuntimeException(e); + // } + //} +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptTendaysManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptTendaysManage.java new file mode 100644 index 0000000..f4c2480 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/manage/RptTendaysManage.java @@ -0,0 +1,158 @@ +package com.ningdatech.carapi.car.rpt.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.StopWatch; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOfflineWeek; +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedCompany; +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedVehicles; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOfflineWeekSpecialParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOfflineWeekPO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedCompanyPO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.vo.RptTendaysSpecialOfflineWeekVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptTendaysSpecialOverspeedCompanyVO; +import com.ningdatech.carapi.car.rpt.model.vo.RptTendaysSpecialOverspeedVehiclesVO; +import com.ningdatech.carapi.car.rpt.service.IRptTendaysSpecialOfflineWeekService; +import com.ningdatech.carapi.car.rpt.service.IRptTendaysSpecialOverspeedCompanyService; +import com.ningdatech.carapi.car.rpt.service.IRptTendaysSpecialOverspeedVehiclesService; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * @Classname RptManage + * @Description + * @Date 2022/11/8 17:03 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class RptTendaysManage { + private final IRptTendaysSpecialOverspeedCompanyService rptTendaysSpecialOverspeedCompanyService; + private final IRptTendaysSpecialOverspeedVehiclesService rptTendaysSpecialOverspeedVehiclesService; + private final IRptTendaysSpecialOfflineWeekService rptTendaysSpecialOfflineWeekService; + + + public List tendaysSpecialOverspeedCompany(RptTendaysOverspeedSpecialCompanyParamDTO param) { + //包装本旬和上旬时间 + CodeUtil.buildCurrentTendaysStartEnd(param); + CodeUtil.buildLastTendaysStartEnd(param); + List list = rptTendaysSpecialOverspeedCompanyService.report(param); + return CollUtils.convert(list,w -> { + RptTendaysSpecialOverspeedCompanyVO vo = BeanUtil.copyProperties(w, + RptTendaysSpecialOverspeedCompanyVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List tendaysSpecialOverspeedVehicles(RptTendaysOverspeedSpecialVehiclesParamDTO param) { + //包装本旬和上旬时间 + CodeUtil.buildCurrentTendaysStartEnd(param); + CodeUtil.buildLastTendaysStartEnd(param); + List list = rptTendaysSpecialOverspeedVehiclesService.report(param); + return CollUtils.convert(list,w -> { + RptTendaysSpecialOverspeedVehiclesVO vo = BeanUtil.copyProperties(w, + RptTendaysSpecialOverspeedVehiclesVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List tendaysSpecialOfflineWeek(RptTendaysOfflineWeekSpecialParamDTO param) { + //包装本旬和上旬时间 + CodeUtil.buildCurrentTendaysStartEnd(param); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + Page page = param.page(); + Page pageList = rptTendaysSpecialOfflineWeekService.reportPage(page,param); + if(0L == pageList.getTotal()){ + return Collections.emptyList(); + } + stopWatch.stop(); + log.info("时间1 {}",stopWatch.getTotalTimeSeconds()); + return CollUtils.convert(pageList.getRecords(),w -> { + RptTendaysSpecialOfflineWeekVO vo = BeanUtil.copyProperties(w, + RptTendaysSpecialOfflineWeekVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public void specialVehiclesEnterpriseSortingTenDaysReportExport + (HttpServletResponse response, RptTendaysOverspeedSpecialCompanyParamDTO param) { + List collect = tendaysSpecialOverspeedCompany(param); + String fileName = "全省专用车辆企业排序表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptTendaysSpecialOverspeedCompanyVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + public void enterpriseSpecialVehiclesSortingTenDaysReportExport + (HttpServletResponse response, RptTendaysOverspeedSpecialVehiclesParamDTO param) { + List collect = tendaysSpecialOverspeedVehicles(param); + String fileName = "企业专用车辆车辆排序表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptTendaysSpecialOverspeedVehiclesVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void specialVehiclesOfflineWeekTenDaysReportExport + (HttpServletResponse response, RptTendaysOfflineWeekSpecialParamDTO param) { + List collect = tendaysSpecialOfflineWeek(param); + String fileName = "全省一周以上不上线的专用车辆排序"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), RptTendaysSpecialOfflineWeekVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.java new file mode 100644 index 0000000..2e58286 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOperatorVehiclesLaunchRate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOperatorVehiclesLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOperatorVehiclesLaunchRatePO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 运营商车辆上线率日报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface RptDailyOperatorVehiclesLaunchRateMapper extends BaseMapper { + + List report(@Param("po") RptDailyOperatorVehiclesLaunchRateParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.xml new file mode 100644 index 0000000..3be058d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOperatorVehiclesLaunchRateMapper.xml @@ -0,0 +1,39 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.java new file mode 100644 index 0000000..6f0e50b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOverspeedCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOverspeedCompanyPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 超速企业情况日报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface RptDailyOverspeedCompanyMapper extends BaseMapper { + + List report(@Param("param") RptDailyOverspeedCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.xml new file mode 100644 index 0000000..7152176 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedCompanyMapper.xml @@ -0,0 +1,58 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.java new file mode 100644 index 0000000..b25fd9c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOverspeedSpecialVehicles; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOverspeedSpecialVehiclesPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 超速专用车辆日报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface RptDailyOverspeedSpecialVehiclesMapper extends BaseMapper { + + List report(@Param("param") RptDailyOverspeedSpecialVehiclesParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.xml new file mode 100644 index 0000000..a58b461 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailyOverspeedSpecialVehiclesMapper.xml @@ -0,0 +1,62 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.java new file mode 100644 index 0000000..b0a29e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesCompanyLaunchRate60; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesCompanyLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesCompanyLaunchRate60PO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆企业上线率低于60日报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface RptDailySpecialVehiclesCompanyLaunchRate60Mapper extends BaseMapper { + + List report(@Param("param") RptDailySpecialVehiclesCompanyLaunchRateParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.xml new file mode 100644 index 0000000..8712455 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesCompanyLaunchRate60Mapper.xml @@ -0,0 +1,72 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.java new file mode 100644 index 0000000..2716301 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesLaunchRate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesLaunchRatePO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆上线率日报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface RptDailySpecialVehiclesLaunchRateMapper extends BaseMapper { + + List report(@Param("po") RptDailySpecialVehiclesLaunchRateParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.xml new file mode 100644 index 0000000..5311eef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesLaunchRateMapper.xml @@ -0,0 +1,73 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.java new file mode 100644 index 0000000..9de574b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesOverspeed; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesOverspeedParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesOverspeedPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆超速日报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface RptDailySpecialVehiclesOverspeedMapper extends BaseMapper { + + List report(@Param("param") RptDailySpecialVehiclesOverspeedParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.xml new file mode 100644 index 0000000..88f62d3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptDailySpecialVehiclesOverspeedMapper.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.java new file mode 100644 index 0000000..80341c5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedCompanyPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 超速企业情况月报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptMonthOverspeedCompanyMapper extends BaseMapper { + + List report(@Param("param") RptMonthOverspeedCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.xml new file mode 100644 index 0000000..62e6d6a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedCompanyMapper.xml @@ -0,0 +1,72 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.java new file mode 100644 index 0000000..1205ad3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedSpecialCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialVehiclesOverspeedPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆超速企业情况月报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptMonthOverspeedSpecialCompanyMapper extends BaseMapper { + + List report(@Param("param") RptMonthSpecialOverspeedCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.xml new file mode 100644 index 0000000..6efed2a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialCompanyMapper.xml @@ -0,0 +1,70 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.java new file mode 100644 index 0000000..5d00c92 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedSpecialVehicles; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedSpecialVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆超速月对比 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptMonthOverspeedSpecialVehiclesMapper extends BaseMapper { + + List reportPage(Page page, @Param("param") RptMonthSpecialOverspeedVehiclesParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.xml new file mode 100644 index 0000000..4fe7507 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthOverspeedSpecialVehiclesMapper.xml @@ -0,0 +1,56 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.java new file mode 100644 index 0000000..a37f8df --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptMonthSpecialOffline; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOfflineParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆不上线月报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptMonthSpecialOfflineMapper extends BaseMapper { + + List reportPage(Page page, @Param("param") RptMonthSpecialOfflineParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.xml new file mode 100644 index 0000000..5f94365 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptMonthSpecialOfflineMapper.xml @@ -0,0 +1,86 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.java new file mode 100644 index 0000000..0ed385b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherAlarmCleanVehiclesAnalysis; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆报警清理分析表 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherAlarmCleanVehiclesAnalysisMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.xml new file mode 100644 index 0000000..c25b8bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesAnalysisMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.java new file mode 100644 index 0000000..821fe17 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherAlarmCleanVehicles; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherAlarmCleanVehiclesPO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 车辆报警清理表 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherAlarmCleanVehiclesMapper extends BaseMapper { + + Page reportPage(Page page, + @Param("param") RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.xml new file mode 100644 index 0000000..8dd7bac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherAlarmCleanVehiclesMapper.xml @@ -0,0 +1,61 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.java new file mode 100644 index 0000000..ef1a813 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherCrossDomainVehiclesAnalysis; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆跨域情况分析表 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherCrossDomainVehiclesAnalysisMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.xml new file mode 100644 index 0000000..c3eeac9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesAnalysisMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.java new file mode 100644 index 0000000..640bcfa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherCrossDomainVehicles; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherCrossDomainVehiclesPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 车辆跨域情况表 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherCrossDomainVehiclesMapper extends BaseMapper { + + List report(@Param("param") RptOtherParamDTO param); + + Page reportPage(Page page, + @Param("param") RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.xml new file mode 100644 index 0000000..c979bf0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherCrossDomainVehiclesMapper.xml @@ -0,0 +1,103 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.java new file mode 100644 index 0000000..855a3b6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherOnlineVehiclesAnalysis; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 在线车辆统计分析表 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherOnlineVehiclesAnalysisMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.xml new file mode 100644 index 0000000..f9d3a1d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesAnalysisMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.java new file mode 100644 index 0000000..f348020 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherOnlineVehicles; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 在线车辆统计表 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherOnlineVehiclesMapper extends BaseMapper { + + List report(@Param("param") RptOtherParamDTO param); + + Page reportPage(Page page, @Param("param") RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.xml new file mode 100644 index 0000000..f6daa5a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherOnlineVehiclesMapper.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.java new file mode 100644 index 0000000..360a9de --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherSpecialOverspeed; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherSpecialOverspeedPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆超速记录 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherSpecialOverspeedMapper extends BaseMapper { + + List report(@Param("param") RptOtherParamDTO param); + + Page reportPage(Page page,@Param("param") RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.xml new file mode 100644 index 0000000..c7c0b1f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialOverspeedMapper.xml @@ -0,0 +1,119 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.java new file mode 100644 index 0000000..d9ec1a9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherSpecialTrips; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 专用车辆趟次记录 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherSpecialTripsMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.xml new file mode 100644 index 0000000..ec67cac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherSpecialTripsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.java new file mode 100644 index 0000000..d463d48 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherTerminalInstall; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 终端车载安装统计 其它报表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptOtherTerminalInstallMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.xml new file mode 100644 index 0000000..0accaac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptOtherTerminalInstallMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.java new file mode 100644 index 0000000..1c2f95a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOfflineWeek; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOfflineWeekSpecialParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOfflineWeekPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆一周以上不上线旬报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptTendaysSpecialOfflineWeekMapper extends BaseMapper { + + List report(@Param("param") RptTendaysOfflineWeekSpecialParamDTO param); + + Page reportPage(Page page,@Param("param") RptTendaysOfflineWeekSpecialParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.xml new file mode 100644 index 0000000..0b3ccd3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOfflineWeekMapper.xml @@ -0,0 +1,107 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.java new file mode 100644 index 0000000..2969912 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedCompanyPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆超速企业情况旬报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptTendaysSpecialOverspeedCompanyMapper extends BaseMapper { + + List report(@Param("param") RptTendaysOverspeedSpecialCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.xml new file mode 100644 index 0000000..34b512e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedCompanyMapper.xml @@ -0,0 +1,49 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.java new file mode 100644 index 0000000..63cd232 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.mapper; + +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedVehicles; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedVehiclesPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 专用车辆超速车辆情况旬报 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface RptTendaysSpecialOverspeedVehiclesMapper extends BaseMapper { + + List report(@Param("param") RptTendaysOverspeedSpecialVehiclesParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.xml new file mode 100644 index 0000000..ea81ce6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/mapper/RptTendaysSpecialOverspeedVehiclesMapper.xml @@ -0,0 +1,52 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOperatorVehiclesLaunchRateParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOperatorVehiclesLaunchRateParamDTO.java new file mode 100644 index 0000000..5bfbca6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOperatorVehiclesLaunchRateParamDTO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +/** + * @Classname RptDailyOperatorVehiclesLaunchRateParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptDailyOperatorVehiclesLaunchRateParamDTO implements Serializable { + + @ApiModelProperty("日期") + private String date; + + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedCompanyParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedCompanyParamDTO.java new file mode 100644 index 0000000..5173780 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedCompanyParamDTO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.models.auth.In; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedCompanyParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptDailyOverspeedCompanyParamDTO implements Serializable { + + @ApiModelProperty("日期") + private String date; + + @ApiModelProperty("排名") + private Integer rank; + + private Integer startRate; + private Integer endRate; + private String dataScopeSql; + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedSpecialVehiclesParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedSpecialVehiclesParamDTO.java new file mode 100644 index 0000000..97c7083 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailyOverspeedSpecialVehiclesParamDTO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptDailyOverspeedSpecialVehiclesParamDTO implements Serializable { + + @ApiModelProperty("日期") + private String date; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("开始超速率") + private Integer startRate; + + @ApiModelProperty("结束超速率") + private Integer endRate; + + private String dataScopeSql; + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesCompanyLaunchRateParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesCompanyLaunchRateParamDTO.java new file mode 100644 index 0000000..d56d69c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesCompanyLaunchRateParamDTO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @Classname RptDailySpecialVehiclesCompanyLaunchRateParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptDailySpecialVehiclesCompanyLaunchRateParamDTO implements Serializable { + + @ApiModelProperty("日期") + private String date; + + @ApiModelProperty("区域ID") + private Long regionId; + private List regionIds; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("上线率") + private Integer launchRate; + + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesLaunchRateParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesLaunchRateParamDTO.java new file mode 100644 index 0000000..1590616 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesLaunchRateParamDTO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.sys.contants.RegionContant; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +/** + * @Classname RptDailySpecialVehiclesLaunchRateParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptDailySpecialVehiclesLaunchRateParamDTO implements Serializable { + + @ApiModelProperty("日期") + @NotNull(message = "请选择日期") + private String date; + + @ApiModelProperty("区域ID") + private Long regionId; + private Integer regionLevel; + private List regionIds; + + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + + public Long getRegionId(){ + if(Objects.isNull(this.regionId)){ + this.regionId = RegionContant.ZJ_REGION_ID; + return this.regionId; + } + return this.regionId; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesOverspeedParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesOverspeedParamDTO.java new file mode 100644 index 0000000..ecd86ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptDailySpecialVehiclesOverspeedParamDTO.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @Classname RptDailySpecialVehiclesOverspeedParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptDailySpecialVehiclesOverspeedParamDTO implements Serializable { + + @ApiModelProperty("日期") + private String date; + + private String dataScopeSql; + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthOverspeedCompanyParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthOverspeedCompanyParamDTO.java new file mode 100644 index 0000000..c2eb75c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthOverspeedCompanyParamDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptMonthOverspeedCompanyParamDTO implements Serializable { + + @ApiModelProperty("起始时间") + @NotNull(message = "请选择起始时间") + private String startTime; + + @ApiModelProperty("结束时间") + @NotNull(message = "请选择结束时间") + private String endTime; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("开始超速率") + private Integer startRate; + + @ApiModelProperty("结束超速率") + private Integer endRate; + + private String dataScopeSql; + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOfflineParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOfflineParamDTO.java new file mode 100644 index 0000000..94dc85b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOfflineParamDTO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @author CMM + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptMonthSpecialOfflineParamDTO extends PagePo implements Serializable { + + @ApiModelProperty("起始时间") + @NotNull(message = "请选择起始时间") + private String startTime; + + @ApiModelProperty("结束时间") + @NotNull(message = "请选择结束时间") + private String endTime; + + @ApiModelProperty("不上线天数") + private Integer offlineDays; + + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedCompanyParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedCompanyParamDTO.java new file mode 100644 index 0000000..bfd3fff --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedCompanyParamDTO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @author CMM + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptMonthSpecialOverspeedCompanyParamDTO implements Serializable { + + private static final long serialVersionUID = 9172042172933510469L; + + @ApiModelProperty("起始时间") + @NotNull(message = "请选择起始时间") + private String startTime; + + @ApiModelProperty("结束时间") + @NotNull(message = "请选择结束时间") + private String endTime; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("开始超速率") + private Integer startRate; + + @ApiModelProperty("结束超速率") + private Integer endRate; + + private String dataScopeSql; + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedVehiclesParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedVehiclesParamDTO.java new file mode 100644 index 0000000..8d99a4a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptMonthSpecialOverspeedVehiclesParamDTO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptMonthSpecialOverspeedVehiclesParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = -7253421068317400397L; + @ApiModelProperty("起始时间") + @NotNull(message = "请选择起始时间") + private String startTime; + + @ApiModelProperty("结束时间") + @NotNull(message = "请选择结束时间") + private String endTime; + + @ApiModelProperty("上月开始时间") + private String lastMonthStartTime; + + @ApiModelProperty("上月结束时间") + private String lastMonthEndTime; + + @ApiModelProperty("开始超速率") + private Integer startRate; + + @ApiModelProperty("结束超速率") + private Integer endRate; + + private String dataScopeSql; + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptOtherParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptOtherParamDTO.java new file mode 100644 index 0000000..d95cf9b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptOtherParamDTO.java @@ -0,0 +1,85 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.sys.contants.RegionContant; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.*; + +/** + * @Classname RptOtherParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptOtherParamDTO extends PagePo implements Serializable { + + @ApiModelProperty("区域ID") + private Long regionId; + private List regionIds; + private Integer regionLevel; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("车辆类别") + private Integer vehicleType; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("报警类别") + private Integer alarmType; + + @ApiModelProperty("企业类型") + private String enterpriseType; + private List enterpriseTypes; + + @ApiModelProperty("运营商") + private String operatorName; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("开始速率") + private String startRate; + + @ApiModelProperty("结束速率") + private String endRate; + + @ApiModelProperty("年月") + private String yearMonth; + + private String dataScopeSql; + + public Long getRegionId(){ + if(Objects.isNull(this.regionId)){ + this.regionId = RegionContant.ZJ_REGION_ID; + return this.regionId; + } + return this.regionId; + } + + public List getEnterpriseTypes(){ + if(StringUtils.isNotBlank(this.enterpriseType)){ + this.enterpriseTypes = Arrays.asList(this.enterpriseType.split(StrPool.COMMA)); + return this.enterpriseTypes; + } + return Collections.emptyList(); + } + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOfflineWeekSpecialParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOfflineWeekSpecialParamDTO.java new file mode 100644 index 0000000..98b9951 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOfflineWeekSpecialParamDTO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptTendaysOfflineWeekSpecialParamDTO extends PagePo implements Serializable { + + @ApiModelProperty("月份") + @NotNull(message = "请选择月份") + @DateTimeFormat(pattern = "yyyy-MM") + private String month; + + @ApiModelProperty("类型 1上旬 2中旬 3下旬") + @NotNull(message = "请选择旬") + private Integer type; + + private LocalDateTime startTime; + private LocalDateTime endTime; + private LocalDateTime lastStartTime; + private LocalDateTime lastEndTime; + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialCompanyParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialCompanyParamDTO.java new file mode 100644 index 0000000..d02ede0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialCompanyParamDTO.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.checkerframework.checker.formatter.qual.Format; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptTendaysOverspeedSpecialCompanyParamDTO implements Serializable { + + @ApiModelProperty("月份") + @NotNull(message = "请选择月份") + @DateTimeFormat(pattern = "yyyy-MM") + private String month; + + @ApiModelProperty("类型 1上旬 2中旬 3下旬") + @NotNull(message = "请选择旬") + private Integer type; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("开始超速率") + private Integer startRate; + + @ApiModelProperty("结束超速率") + private Integer endRate; + + private LocalDateTime startTime; + private LocalDateTime endTime; + private LocalDateTime lastStartTime; + private LocalDateTime lastEndTime; + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialVehiclesParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialVehiclesParamDTO.java new file mode 100644 index 0000000..a6766f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/dto/RptTendaysOverspeedSpecialVehiclesParamDTO.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.car.rpt.model.dto; + +import com.ningdatech.basic.util.NdDateUtils; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * @Classname RptDailyOverspeedSpecialVehiclesParamDTO + * @Description + * @Date 2022/11/8 17:06 + * @Created by PoffyZhang + */ +@Data +public class RptTendaysOverspeedSpecialVehiclesParamDTO implements Serializable { + + @ApiModelProperty("月份") + @NotNull(message = "请选择月份") + @DateTimeFormat(pattern = "yyyy-MM") + private String month; + + @ApiModelProperty("类型 1上旬 2中旬 3下旬") + @NotNull(message = "请选择旬") + private Integer type; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("开始超速率") + private Integer startRate; + + @ApiModelProperty("结束超速率") + private Integer endRate; + + private LocalDateTime startTime; + private LocalDateTime endTime; + private LocalDateTime lastStartTime; + private LocalDateTime lastEndTime; + private String dataScopeSql; + + private String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOperatorVehiclesLaunchRatePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOperatorVehiclesLaunchRatePO.java new file mode 100644 index 0000000..94006aa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOperatorVehiclesLaunchRatePO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 运营商车辆上线率日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailyOperatorVehiclesLaunchRatePO", description = "运营商车辆上线率日报") +public class RptDailyOperatorVehiclesLaunchRatePO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + @ExcelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("未监控车辆数") + @ExcelProperty("未监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedCompanyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedCompanyPO.java new file mode 100644 index 0000000..4821094 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedCompanyPO.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 超速企业情况日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailyOverspeedCompanyPO", description = "超速企业情况日报") +public class RptDailyOverspeedCompanyPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速车辆总数") + private Long overspeedVehicleNums; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedSpecialVehiclesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedSpecialVehiclesPO.java new file mode 100644 index 0000000..58c2e3d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailyOverspeedSpecialVehiclesPO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 超速专用车辆日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailyOverspeedSpecialVehiclesPO", description = "超速专用车辆日报") +public class RptDailyOverspeedSpecialVehiclesPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速%20-50%次数") + @ExcelProperty("超速20%-50%次数") + private Long overspeed2050Times; + + @ApiModelProperty("超速50以上 次数") + @ExcelProperty("超速50以上 次数") + private Long overspeed50Times; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("总超速次数") + @ExcelProperty("总超速次数") + private Long overspeedTotalTimes; + + @ApiModelProperty("比例") + @ExcelProperty("比例") + private BigDecimal rate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesCompanyLaunchRate60PO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesCompanyLaunchRate60PO.java new file mode 100644 index 0000000..b0b9214 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesCompanyLaunchRate60PO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆企业上线率低于60日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailySpecialVehiclesCompanyLaunchRate60PO", description = "专用车辆企业上线率低于60日报") +public class RptDailySpecialVehiclesCompanyLaunchRate60PO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + @ExcelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("未监控车辆数") + @ExcelProperty("未监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("企业id") + @ExcelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名") + @ExcelProperty("企业名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesLaunchRatePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesLaunchRatePO.java new file mode 100644 index 0000000..dab9072 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesLaunchRatePO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆上线率日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@ApiModel(value = "RptDailySpecialVehiclesLaunchRatePO", description = "专用车辆上线率日报") +@Data +public class RptDailySpecialVehiclesLaunchRatePO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + @ExcelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("未监控车辆数") + @ExcelProperty("未监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商Id") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域Id") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesOverspeedPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesOverspeedPO.java new file mode 100644 index 0000000..cf9d960 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptDailySpecialVehiclesOverspeedPO.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@ApiModel(value = "RptDailySpecialVehiclesOverspeedPO", description = "专用车辆超速日报") +@Data +public class RptDailySpecialVehiclesOverspeedPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("20%-50%车辆数") + @ExcelProperty("20%-50%车辆数") + private Long overspeed2050VehicleNums; + + @ApiModelProperty("超速50%以上的车辆") + @ExcelProperty("超速50%以上的车辆") + private Long overspeed50VehicleNums; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedCompanyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedCompanyPO.java new file mode 100644 index 0000000..a8843b4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedCompanyPO.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 超速企业情况月报 + * @author CMM + * @description + * @since 2022/12/09 17:13 + */ +@Data +public class RptMonthOverspeedCompanyPO { + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速车辆总数") + private Long overspeedVehicleNums; + + @ApiModelProperty("超速次数") + private Long overspeedTimes; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedSpecialVehiclesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedSpecialVehiclesPO.java new file mode 100644 index 0000000..b4c493b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthOverspeedSpecialVehiclesPO.java @@ -0,0 +1,12 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import lombok.Data; + +/** + * @author CMM + * @description + * @since 2022/12/13 15:09 + */ +@Data +public class RptMonthOverspeedSpecialVehiclesPO { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialOfflinePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialOfflinePO.java new file mode 100644 index 0000000..88467dc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialOfflinePO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author CMM + * @description + * @since 2022/12/12 17:46 + */ +@Data +@ApiModel(value = "RptMonthSpecialOfflinePO", description = "专用车辆不上线月报") +public class RptMonthSpecialOfflinePO implements Serializable { + + private static final long serialVersionUID = -5951994953374490890L; + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("未上线天数") + @ExcelProperty("未上线天数") + private Integer offlineDays; + + //@ApiModelProperty("未上线车辆数") + //@ExcelProperty("未上线车辆数") + //private Long offlineVehicleNums; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名称") + @ExcelProperty("运营商名称") + private String operatorName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialVehiclesOverspeedPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialVehiclesOverspeedPO.java new file mode 100644 index 0000000..25cf4f0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptMonthSpecialVehiclesOverspeedPO.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author CMM + * @description + * @since 2022/12/12 12:00 + */ +@Data +public class RptMonthSpecialVehiclesOverspeedPO implements Serializable { + + private static final long serialVersionUID = -1510410272441829172L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速次数") + private Long overspeedTimes; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("最高速率") + private BigDecimal maxSpeed; + + @ApiModelProperty("最高超速率") + private BigDecimal maxOverspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherAlarmCleanVehiclesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherAlarmCleanVehiclesPO.java new file mode 100644 index 0000000..4aac98a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherAlarmCleanVehiclesPO.java @@ -0,0 +1,109 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 车辆报警清理表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherAlarmCleanVehiclesPO", description = "车辆报警清理表 其它报表") +public class RptOtherAlarmCleanVehiclesPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("报警车总数") + @ExcelProperty("报警车总数") + private Long alarmVehicleNums; + + @ApiModelProperty("报警车辆占比") + @ExcelProperty("报警车辆占比") + private BigDecimal alarmVehicleRate; + + @ApiModelProperty("报警处理总数") + @ExcelProperty("报警处理总数") + private Long alarmProcessNums; + + @ApiModelProperty("报警处理占比") + @ExcelProperty("报警处理占比") + private BigDecimal alarmProcessRate; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherCrossDomainVehiclesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherCrossDomainVehiclesPO.java new file mode 100644 index 0000000..9a96ea1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherCrossDomainVehiclesPO.java @@ -0,0 +1,125 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 车辆跨域情况表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherCrossDomainVehiclesPO", description = "车辆跨域情况表 其它报表") +public class RptOtherCrossDomainVehiclesPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("散装水泥车数") + @ExcelProperty("散状水泥车数") + private Long bulkCementTruckNums; + + @ApiModelProperty("散装水泥车占比") + @ExcelProperty("散装水泥车占比") + private BigDecimal bulkCementTruckRate; + + @ApiModelProperty("预拌砂浆车数") + @ExcelProperty("预拌砂浆车数") + private Long readyMixedMortarTruckNums; + + @ApiModelProperty("预拌砂浆车占比") + @ExcelProperty("预拌砂浆车占比") + private BigDecimal readyMixedMortarTruckRate; + + @ApiModelProperty("混凝土搅拌车数") + @ExcelProperty("混凝土搅拌车数") + private Long concreteDeliveryTruckNums; + + @ApiModelProperty("混凝土搅拌车数占比") + @ExcelProperty("混凝土搅拌车数占比") + private BigDecimal concreteDeliveryTruckRate; + + @ApiModelProperty("移动泵车数") + @ExcelProperty("移动泵车数") + private Long mobilePumpTruckNums; + + @ApiModelProperty("移动泵车占比") + @ExcelProperty("移动泵车占比") + private BigDecimal mobilePumpTruckRate; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherOnlineVehiclesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherOnlineVehiclesPO.java new file mode 100644 index 0000000..e46d368 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherOnlineVehiclesPO.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 在线车辆统计表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherOnlineVehiclesPO", description = "在线车辆统计表 其它报表") +public class RptOtherOnlineVehiclesPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherSpecialOverspeedPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherSpecialOverspeedPO.java new file mode 100644 index 0000000..5d32676 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptOtherSpecialOverspeedPO.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速记录 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherSpecialOverspeedPO", description = "专用车辆超速记录 其它报表") +public class RptOtherSpecialOverspeedPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("超速开始时间") + @ExcelProperty("超速开始时间") + private LocalDateTime overspeedStartTime; + + @ApiModelProperty("超速结束时间") + @ExcelProperty("超速结束时间") + private LocalDateTime overspeedEndTime; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("限速") + @ExcelProperty("限速") + private BigDecimal limitSpeed; + + @ApiModelProperty("最高速") + @ExcelProperty("最高速") + private BigDecimal maxSpeed; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private Double overspeedRate; + + @ApiModelProperty("持续时间 秒") + @ExcelProperty("持续时间 秒") + private Integer duration; + + @ApiModelProperty("地点") + @ExcelProperty("地点") + private String address; + + @ApiModelProperty("道路") + @ExcelProperty("道路") + private String road; + + @ApiModelProperty("经纬度") + @ExcelProperty("经纬度") + private String longtitudeLatitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOfflineWeekPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOfflineWeekPO.java new file mode 100644 index 0000000..958ceab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOfflineWeekPO.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆一周以上不上线旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@ApiModel(value = "RptTendaysSpecialOfflineWeekPO", description = "专用车辆一周以上不上线旬报") +@Data +public class RptTendaysSpecialOfflineWeekPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("未上线天数") + @ExcelProperty("未上线天数") + private Integer offlineDays; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedCompanyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedCompanyPO.java new file mode 100644 index 0000000..bf26e8f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedCompanyPO.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速企业情况旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@ApiModel(value = "RptTendaysSpecialOverspeedCompanyPO", description = "专用车辆超速企业情况旬报") +@Data +public class RptTendaysSpecialOverspeedCompanyPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("当前旬超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("上一旬超速次数") + private Long overspeedLastTimes; + + @ApiModelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedVehiclesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedVehiclesPO.java new file mode 100644 index 0000000..0860229 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/po/RptTendaysSpecialOverspeedVehiclesPO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.car.rpt.model.po; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速车辆情况旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@ApiModel(value = "RptTendaysSpecialOverspeedVehiclesPO", description = "专用车辆超速车辆情况旬报") +@Data +public class RptTendaysSpecialOverspeedVehiclesPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("当前旬超速次数") + @ExcelProperty("当前旬超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("上一旬超速次数") + @ExcelProperty("上一旬超速次数") + private Long overspeedLastTimes; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOperatorVehiclesLaunchRateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOperatorVehiclesLaunchRateVO.java new file mode 100644 index 0000000..305932a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOperatorVehiclesLaunchRateVO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 运营商车辆上线率日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailyOperatorVehiclesLaunchRateVO", description = "运营商车辆上线率日报") +public class RptDailyOperatorVehiclesLaunchRateVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + @ExcelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("未监控车辆数") + @ExcelProperty("未监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedCompanyVO.java new file mode 100644 index 0000000..4b568af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedCompanyVO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 超速企业情况日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailyOverspeedCompanyVO", description = "超速企业情况日报") +public class RptDailyOverspeedCompanyVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速车辆总数") + @ExcelProperty("超速车辆总数") + private Long overspeedVehicleNums; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedSpecialVehiclesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedSpecialVehiclesVO.java new file mode 100644 index 0000000..93986f8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailyOverspeedSpecialVehiclesVO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 超速专用车辆日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailyOverspeedSpecialVehiclesVO", description = "超速专用车辆日报") +public class RptDailyOverspeedSpecialVehiclesVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速%20-50%次数") + @ExcelProperty("超速20%-50%次数") + private Long overspeed2050Times; + + @ApiModelProperty("超速50以上 次数") + @ExcelProperty("超速50以上 次数") + private Long overspeed50Times; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("总超速次数") + @ExcelProperty("总超速次数") + private Long overspeedTotalTimes; + + @ApiModelProperty("比例") + @ExcelProperty("比例") + private BigDecimal rate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesCompanyLaunchRate60VO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesCompanyLaunchRate60VO.java new file mode 100644 index 0000000..b30fd65 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesCompanyLaunchRate60VO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆企业上线率低于60日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "RptDailySpecialVehiclesCompanyLaunchRate60VO", description = "专用车辆企业上线率低于60日报") +public class RptDailySpecialVehiclesCompanyLaunchRate60VO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + @ExcelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("未监控车辆数") + @ExcelProperty("未监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("企业id") + @ExcelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名") + @ExcelProperty("企业名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesLaunchRateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesLaunchRateVO.java new file mode 100644 index 0000000..a8da724 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesLaunchRateVO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆上线率日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@ApiModel(value = "RptDailySpecialVehiclesLaunchRateVO", description = "专用车辆上线率日报") +@Data +public class RptDailySpecialVehiclesLaunchRateVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("监控车辆数") + @ExcelProperty("监控车辆数") + private Long monitoredVehicleNums; + + @ApiModelProperty("未监控车辆数") + @ExcelProperty("未监控车辆数") + private Long unmonitoredVehicleNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal launchRate; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商Id") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域Id") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesOverspeedVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesOverspeedVO.java new file mode 100644 index 0000000..b654a45 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptDailySpecialVehiclesOverspeedVO.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速日报 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@ApiModel(value = "RptDailySpecialVehiclesOverspeedVO", description = "专用车辆超速日报") +@Data +public class RptDailySpecialVehiclesOverspeedVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("20%-50%车辆数") + @ExcelProperty("20%-50%车辆数") + private Long overspeed2050VehicleNums; + + @ApiModelProperty("超速50%以上的车辆") + @ExcelProperty("超速50%以上的车辆") + private Long overspeed50VehicleNums; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedCompanyVO.java new file mode 100644 index 0000000..0918e35 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedCompanyVO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 超速企业情况月报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptMonthOverspeedCompanyVO", description = "超速企业情况月报") +public class RptMonthOverspeedCompanyVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速次数") + @ExcelProperty("超速次数") + private Long overspeedTimes; + + @ApiModelProperty("企业车辆数") + @ExcelProperty("企业车辆数") + private Long vehicleNums; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialCompanyVO.java new file mode 100644 index 0000000..43d88fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialCompanyVO.java @@ -0,0 +1,81 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速企业情况月报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptMonthOverspeedSpecialCompanyVO", description = "专用车辆超速企业情况月报") +public class RptMonthOverspeedSpecialCompanyVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("超速次数") + @ExcelProperty("超速次数") + private Long overspeedTimes; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal overspeedRate; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("最高速率") + @ExcelProperty("最高速率") + private BigDecimal maxSpeed; + + @ApiModelProperty("最高超速率") + @ExcelProperty("最高超速率") + private BigDecimal maxOverspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialVehiclesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialVehiclesVO.java new file mode 100644 index 0000000..a241fff --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthOverspeedSpecialVehiclesVO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速月对比 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptMonthOverspeedSpecialVehiclesVO", description = "专用车辆超速月对比") +public class RptMonthOverspeedSpecialVehiclesVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("本月超速次数") + @ExcelProperty("本月超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("企业车辆数") + @ExcelProperty("企业车辆数") + private Long vehicleNums; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal maxOverspeedRate; + + @ApiModelProperty("上月超速次数") + @ExcelProperty("上月超速次数") + private Long overspeedLastTimes; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthSpecialOfflineVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthSpecialOfflineVO.java new file mode 100644 index 0000000..3323d2d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptMonthSpecialOfflineVO.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆不上线月报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptMonthSpecialOffline对象", description = "专用车辆不上线月报") +public class RptMonthSpecialOfflineVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("未上线天数") + @ExcelProperty("未上线天数") + private Integer offlineDays; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesAnalysisVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesAnalysisVO.java new file mode 100644 index 0000000..8c4e099 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesAnalysisVO.java @@ -0,0 +1,145 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 车辆报警清理分析表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherAlarmCleanVehiclesAnalysisVO", description = "车辆报警清理分析表 其它报表") +public class RptOtherAlarmCleanVehiclesAnalysisVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("报警车总数") + @ExcelProperty("报警车总数") + private Long alarmVehicleNums; + + @ApiModelProperty("报警车辆占比") + @ExcelProperty("报警车辆占比") + private BigDecimal alarmVehicleRate; + + @ApiModelProperty("报警处理总数") + @ExcelProperty("报警处理总数") + private Long alarmProcessNums; + + @ApiModelProperty("报警处理占比") + @ExcelProperty("报警处理占比") + private BigDecimal alarmProcessRate; + + @ApiModelProperty("报警车同比") + @ExcelProperty("报警车同比") + private BigDecimal alarmVehicleYoy; + + @ApiModelProperty("报警车环比") + @ExcelProperty("报警车环比") + private BigDecimal alarmVehicleQoq; + + @ApiModelProperty("报警处理同比") + @ExcelProperty("报警处理同比") + private BigDecimal alarmProcessYoy; + + @ApiModelProperty("报警处理环比") + @ExcelProperty("报警处理环比") + private BigDecimal alarmProcessQoq; + + @ApiModelProperty("在线同比") + @ExcelProperty("在线同比") + private BigDecimal onlineYoy; + + @ApiModelProperty("在线环比") + @ExcelProperty("在线环比") + private BigDecimal onlineQoq; + + @ApiModelProperty("离线同比") + @ExcelProperty("离线同比") + private BigDecimal offlineYoy; + + @ApiModelProperty("离线环比") + @ExcelProperty("离线环比") + private BigDecimal offlineQoq; + + @ApiModelProperty("年月") + @ExcelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesVO.java new file mode 100644 index 0000000..94434f8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherAlarmCleanVehiclesVO.java @@ -0,0 +1,109 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 车辆报警清理表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherAlarmCleanVehiclesVO", description = "车辆报警清理表 其它报表") +public class RptOtherAlarmCleanVehiclesVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("报警车总数") + @ExcelProperty("报警车总数") + private Long alarmVehicleNums; + + @ApiModelProperty("报警车辆占比") + @ExcelProperty("报警车辆占比") + private BigDecimal alarmVehicleRate; + + @ApiModelProperty("报警处理总数") + @ExcelProperty("报警处理总数") + private Long alarmProcessNums; + + @ApiModelProperty("报警处理占比") + @ExcelProperty("报警处理占比") + private BigDecimal alarmProcessRate; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCompanyTripsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCompanyTripsVO.java new file mode 100644 index 0000000..6b62ca1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCompanyTripsVO.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆趟次记录 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherSpecialTrips对象", description = "专用车辆趟次记录 其它报表") +public class RptOtherCompanyTripsVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车辆数") + @ExcelProperty("车辆数") + private Integer vehicleNums; + + @ApiModelProperty("趟次") + @ExcelProperty("趟次") + private Long trips; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesAnalysisVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesAnalysisVO.java new file mode 100644 index 0000000..e61753b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesAnalysisVO.java @@ -0,0 +1,177 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 车辆跨域情况分析表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherCrossDomainVehiclesAnalysisVO", description = "车辆跨域情况分析表 其它报表") +public class RptOtherCrossDomainVehiclesAnalysisVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("散装水泥车数") + @ExcelProperty("散状水泥车数") + private Long bulkCementTruckNums; + + @ApiModelProperty("散装水泥车占比") + @ExcelProperty("散装水泥车占比") + private BigDecimal bulkCementTruckRate; + + @ApiModelProperty("预拌砂浆车数") + @ExcelProperty("预拌砂浆车数") + private Long readyMixedMortarTruckNums; + + @ApiModelProperty("预拌砂浆车占比") + @ExcelProperty("预拌砂浆车占比") + private BigDecimal readyMixedMortarTruckRate; + + @ApiModelProperty("混凝土搅拌车数") + @ExcelProperty("混凝土搅拌车数") + private Long concreteDeliveryTruckNums; + + @ApiModelProperty("混凝土搅拌车数占比") + @ExcelProperty("混凝土搅拌车数占比") + private BigDecimal concreteDeliveryTruckRate; + + @ApiModelProperty("移动泵车数") + @ExcelProperty("移动泵车数") + private Long mobilePumpTruckNums; + + @ApiModelProperty("移动泵车占比") + @ExcelProperty("移动泵车占比") + private BigDecimal mobilePumpTruckRate; + + @ApiModelProperty("散装水泥车同比") + @ExcelProperty("散装水泥车同比") + private BigDecimal bulkCementTruckYoy; + + @ApiModelProperty("散装水泥车环比") + @ExcelProperty("散装水泥车环比") + private BigDecimal bulkCementTruckQoq; + + @ApiModelProperty("预拌砂浆车同比") + @ExcelProperty("预拌砂浆车同比") + private BigDecimal readyMixedMortarTruckYoy; + + @ApiModelProperty("预拌砂浆车环比") + @ExcelProperty("预拌砂浆车环比") + private BigDecimal readyMixedMortarTruckQoq; + + @ApiModelProperty("混凝土搅拌车同比") + @ExcelProperty("混凝土搅拌车同比") + private BigDecimal concreteDeliveryTruckYoy; + + @ApiModelProperty("混凝土搅拌车环比") + @ExcelProperty("混凝土搅拌车环比") + private BigDecimal concreteDeliveryTruckQoq; + + @ApiModelProperty("移动泵车同比") + @ExcelProperty("移动泵车同比") + private BigDecimal mobilePumpTruckYoy; + + @ApiModelProperty("移动泵车环比") + @ExcelProperty("移动泵车环比") + private BigDecimal mobilePumpTruckQoq; + + @ApiModelProperty("在线同比") + @ExcelProperty("在线同比") + private BigDecimal onlineYoy; + + @ApiModelProperty("在线环比") + @ExcelProperty("在线环比") + private BigDecimal onlineQoq; + + @ApiModelProperty("离线同比") + @ExcelProperty("离线同比") + private BigDecimal offlineYoy; + + @ApiModelProperty("离线环比") + @ExcelProperty("离线环比") + private BigDecimal offlineQoq; + + @ApiModelProperty("年月") + @ExcelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesVO.java new file mode 100644 index 0000000..0221479 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherCrossDomainVehiclesVO.java @@ -0,0 +1,125 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 车辆跨域情况表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherCrossDomainVehiclesVO", description = "车辆跨域情况表 其它报表") +public class RptOtherCrossDomainVehiclesVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("散装水泥车数") + @ExcelProperty("散状水泥车数") + private Long bulkCementTruckNums; + + @ApiModelProperty("散装水泥车占比") + @ExcelProperty("散装水泥车占比") + private BigDecimal bulkCementTruckRate; + + @ApiModelProperty("预拌砂浆车数") + @ExcelProperty("预拌砂浆车数") + private Long readyMixedMortarTruckNums; + + @ApiModelProperty("预拌砂浆车占比") + @ExcelProperty("预拌砂浆车占比") + private BigDecimal readyMixedMortarTruckRate; + + @ApiModelProperty("混凝土搅拌车数") + @ExcelProperty("混凝土搅拌车数") + private Long concreteDeliveryTruckNums; + + @ApiModelProperty("混凝土搅拌车数占比") + @ExcelProperty("混凝土搅拌车数占比") + private BigDecimal concreteDeliveryTruckRate; + + @ApiModelProperty("移动泵车数") + @ExcelProperty("移动泵车数") + private Long mobilePumpTruckNums; + + @ApiModelProperty("移动泵车占比") + @ExcelProperty("移动泵车占比") + private BigDecimal mobilePumpTruckRate; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesAnalysisVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesAnalysisVO.java new file mode 100644 index 0000000..4ebec18 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesAnalysisVO.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 在线车辆统计分析表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherOnlineVehiclesAnalysisVO", description = "在线车辆统计分析表 其它报表") +public class RptOtherOnlineVehiclesAnalysisVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("年月") + @ExcelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("在线同比") + @ExcelProperty("在线同比") + private BigDecimal onlineYoy; + + @ApiModelProperty("在线环比") + @ExcelProperty("在线环比") + private BigDecimal onlineQoq; + + @ApiModelProperty("离线同比") + @ExcelProperty("离线同比") + private BigDecimal offlineYoy; + + @ApiModelProperty("离线环比") + @ExcelProperty("离线环比") + private BigDecimal offlineQoq; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesVO.java new file mode 100644 index 0000000..e992dad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherOnlineVehiclesVO.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 在线车辆统计表 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherOnlineVehiclesVO", description = "在线车辆统计表 其它报表") +public class RptOtherOnlineVehiclesVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialOverspeedVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialOverspeedVO.java new file mode 100644 index 0000000..736651d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialOverspeedVO.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速记录 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherSpecialOverspeedVO", description = "专用车辆超速记录 其它报表") +public class RptOtherSpecialOverspeedVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("超速开始时间") + @ExcelProperty("超速开始时间") + private LocalDateTime overspeedStartTime; + + @ApiModelProperty("超速结束时间") + @ExcelProperty("超速结束时间") + private LocalDateTime overspeedEndTime; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("限速") + @ExcelProperty("限速") + private BigDecimal limitSpeed; + + @ApiModelProperty("最高速") + @ExcelProperty("最高速") + private BigDecimal maxSpeed; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private Double overspeedRate; + + @ApiModelProperty("持续时间 秒") + @ExcelProperty("持续时间 秒") + private Integer duration; + + @ApiModelProperty("地点") + @ExcelProperty("地点") + private String address; + + @ApiModelProperty("道路") + @ExcelProperty("道路") + private String road; + + @ApiModelProperty("经纬度") + @ExcelProperty("经纬度") + private String longtitudeLatitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialTripsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialTripsVO.java new file mode 100644 index 0000000..f608ad4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherSpecialTripsVO.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆趟次记录 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherSpecialTrips对象", description = "专用车辆趟次记录 其它报表") +public class RptOtherSpecialTripsVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车辆数") + @ExcelProperty("车辆数") + private Integer vehicleNums; + + @ApiModelProperty("趟次") + @ExcelProperty("趟次") + private Long trips; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherTerminalInstallVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherTerminalInstallVO.java new file mode 100644 index 0000000..6c543d2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptOtherTerminalInstallVO.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 终端车载安装统计 其它报表 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "RptOtherTerminalInstallVO", description = "终端车载安装统计 其它报表") +public class RptOtherTerminalInstallVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("在线车辆数") + @ExcelProperty("在线车辆数") + private Long onlineNums; + + @ApiModelProperty("上线率") + @ExcelProperty("上线率") + private BigDecimal onlineRate; + + @ApiModelProperty("离线车辆数") + @ExcelProperty("离线车辆数") + private Long offlineNums; + + @ApiModelProperty("离线率") + @ExcelProperty("离线率") + private BigDecimal offlineRate; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Long vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("安装终端的车辆数") + @ExcelProperty("安装终端的车辆数") + private Long installedNums; + + @ApiModelProperty("安装终端的车辆占比") + @ExcelProperty("安装终端的车辆占比") + private BigDecimal installedRate; + + @ApiModelProperty("年月") + @ExcelProperty("年月") + private String yearMonthly; + + @ApiModelProperty("企业类型") + @ExcelProperty("企业类型") + private String enterpriseType; + + @ApiModelProperty("企业类型名") + @ExcelProperty("企业类型名") + private String enterpriseTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOfflineWeekVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOfflineWeekVO.java new file mode 100644 index 0000000..9eecf0f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOfflineWeekVO.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆一周以上不上线旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@ApiModel(value = "RptTendaysSpecialOfflineWeek对象", description = "专用车辆一周以上不上线旬报") +@Data +public class RptTendaysSpecialOfflineWeekVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("未上线天数") + @ExcelProperty("未上线天数") + private Integer offlineDays; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedCompanyVO.java new file mode 100644 index 0000000..a4f3319 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedCompanyVO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速企业情况旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@ApiModel(value = "RptTendaysSpecialOverspeedCompanyVO", description = "专用车辆超速企业情况旬报") +@Data +public class RptTendaysSpecialOverspeedCompanyVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("当前旬超速次数") + @ExcelProperty("当前旬超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("上一旬超速次数") + @ExcelProperty("上一旬超速次数") + private Long overspeedLastTimes; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedVehiclesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedVehiclesVO.java new file mode 100644 index 0000000..a7c0251 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/model/vo/RptTendaysSpecialOverspeedVehiclesVO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.car.rpt.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 专用车辆超速车辆情况旬报 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@ApiModel(value = "RptTendaysSpecialOverspeedVehiclesVO", description = "专用车辆超速车辆情况旬报") +@Data +public class RptTendaysSpecialOverspeedVehiclesVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("名称") + @ExcelProperty("名称") + private String name; + + @ApiModelProperty("报表时间") + @ExcelProperty("报表时间") + private LocalDateTime rptDate; + + @ApiModelProperty("排名") + @ExcelProperty("排名") + private Integer rank; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("当前旬超速次数") + @ExcelProperty("当前旬超速次数") + private Long overspeedCurrentTimes; + + @ApiModelProperty("上一旬超速次数") + @ExcelProperty("上一旬超速次数") + private Long overspeedLastTimes; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("超速率") + @ExcelProperty("超速率") + private BigDecimal overspeedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOperatorVehiclesLaunchRateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOperatorVehiclesLaunchRateService.java new file mode 100644 index 0000000..df7cc69 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOperatorVehiclesLaunchRateService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOperatorVehiclesLaunchRate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOperatorVehiclesLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOperatorVehiclesLaunchRatePO; + +import java.util.List; + +/** + *

+ * 运营商车辆上线率日报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IRptDailyOperatorVehiclesLaunchRateService extends IService { + + List report(RptDailyOperatorVehiclesLaunchRateParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedCompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedCompanyService.java new file mode 100644 index 0000000..0bd4628 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedCompanyService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOverspeedCompany; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOverspeedCompanyPO; + +import java.util.List; + +/** + *

+ * 超速企业情况日报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IRptDailyOverspeedCompanyService extends IService { + + List report(RptDailyOverspeedCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedSpecialVehiclesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedSpecialVehiclesService.java new file mode 100644 index 0000000..36cd1ac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailyOverspeedSpecialVehiclesService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOverspeedSpecialVehicles; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOverspeedSpecialVehiclesPO; + +import java.util.List; + +/** + *

+ * 超速专用车辆日报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IRptDailyOverspeedSpecialVehiclesService extends IService { + + List report(RptDailyOverspeedSpecialVehiclesParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesCompanyLaunchRate60Service.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesCompanyLaunchRate60Service.java new file mode 100644 index 0000000..e850008 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesCompanyLaunchRate60Service.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesCompanyLaunchRate60; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesCompanyLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesCompanyLaunchRate60PO; + +import java.util.List; + +/** + *

+ * 专用车辆企业上线率低于60日报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IRptDailySpecialVehiclesCompanyLaunchRate60Service extends IService { + + List report(RptDailySpecialVehiclesCompanyLaunchRateParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesLaunchRateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesLaunchRateService.java new file mode 100644 index 0000000..583cd4c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesLaunchRateService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesLaunchRate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesLaunchRatePO; + +import java.util.List; + +/** + *

+ * 专用车辆上线率日报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IRptDailySpecialVehiclesLaunchRateService extends IService { + + List report(RptDailySpecialVehiclesLaunchRateParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesOverspeedService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesOverspeedService.java new file mode 100644 index 0000000..86694e0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptDailySpecialVehiclesOverspeedService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesOverspeed; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesOverspeedParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesOverspeedPO; + +import java.util.List; + +/** + *

+ * 专用车辆超速日报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IRptDailySpecialVehiclesOverspeedService extends IService { + + List report(RptDailySpecialVehiclesOverspeedParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedCompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedCompanyService.java new file mode 100644 index 0000000..668287c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedCompanyService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedCompany; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedCompanyPO; + +import java.util.List; + +/** + *

+ * 超速企业情况月报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptMonthOverspeedCompanyService extends IService { + + List report(RptMonthOverspeedCompanyParamDTO param); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialCompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialCompanyService.java new file mode 100644 index 0000000..94afe10 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialCompanyService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedSpecialCompany; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialVehiclesOverspeedPO; + +import java.util.List; + +/** + *

+ * 专用车辆超速企业情况月报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptMonthOverspeedSpecialCompanyService extends IService { + + List report(RptMonthSpecialOverspeedCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialVehiclesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialVehiclesService.java new file mode 100644 index 0000000..3bbede6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthOverspeedSpecialVehiclesService.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedSpecialVehicles; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedSpecialVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; + +import java.util.List; + +/** + *

+ * 专用车辆超速月对比 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptMonthOverspeedSpecialVehiclesService extends IService { + + List reportPage(Page page, RptMonthSpecialOverspeedVehiclesParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthSpecialOfflineService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthSpecialOfflineService.java new file mode 100644 index 0000000..af8dc0b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptMonthSpecialOfflineService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptMonthSpecialOffline; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOfflineParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; + +import java.util.List; + +/** + *

+ * 专用车辆不上线月报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptMonthSpecialOfflineService extends IService { + + List reportPage(Page page, RptMonthSpecialOfflineParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesAnalysisService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesAnalysisService.java new file mode 100644 index 0000000..55c196a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesAnalysisService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherAlarmCleanVehiclesAnalysis; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆报警清理分析表 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherAlarmCleanVehiclesAnalysisService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesService.java new file mode 100644 index 0000000..e55fb61 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherAlarmCleanVehiclesService.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherAlarmCleanVehicles; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherAlarmCleanVehiclesPO; + +/** + *

+ * 车辆报警清理表 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherAlarmCleanVehiclesService extends IService { + + Page reportPage(Page page, RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesAnalysisService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesAnalysisService.java new file mode 100644 index 0000000..36d2594 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesAnalysisService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherCrossDomainVehiclesAnalysis; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆跨域情况分析表 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherCrossDomainVehiclesAnalysisService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesService.java new file mode 100644 index 0000000..a907e28 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherCrossDomainVehiclesService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherCrossDomainVehicles; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherCrossDomainVehiclesPO; + +import java.util.List; + +/** + *

+ * 车辆跨域情况表 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherCrossDomainVehiclesService extends IService { + + List report(RptOtherParamDTO param); + + Page reportPage(Page page, RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesAnalysisService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesAnalysisService.java new file mode 100644 index 0000000..4be86f8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesAnalysisService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherOnlineVehiclesAnalysis; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 在线车辆统计分析表 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherOnlineVehiclesAnalysisService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesService.java new file mode 100644 index 0000000..630d6e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherOnlineVehiclesService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherOnlineVehicles; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; + +import java.util.List; + +/** + *

+ * 在线车辆统计表 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherOnlineVehiclesService extends IService { + + List report(RptOtherParamDTO param); + + Page reportPage(Page page, RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialOverspeedService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialOverspeedService.java new file mode 100644 index 0000000..32893cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialOverspeedService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherSpecialOverspeed; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherSpecialOverspeedPO; + +import java.util.List; + +/** + *

+ * 专用车辆超速记录 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherSpecialOverspeedService extends IService { + + List report(RptOtherParamDTO param); + + Page reportPage(Page page, RptOtherParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialTripsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialTripsService.java new file mode 100644 index 0000000..4997562 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherSpecialTripsService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherSpecialTrips; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 专用车辆趟次记录 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherSpecialTripsService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherTerminalInstallService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherTerminalInstallService.java new file mode 100644 index 0000000..6ea2055 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptOtherTerminalInstallService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherTerminalInstall; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 终端车载安装统计 其它报表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptOtherTerminalInstallService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOfflineWeekService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOfflineWeekService.java new file mode 100644 index 0000000..102f6a7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOfflineWeekService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOfflineWeek; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOfflineWeekSpecialParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOfflineWeekPO; + +import java.util.List; + +/** + *

+ * 专用车辆一周以上不上线旬报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptTendaysSpecialOfflineWeekService extends IService { + + List report(RptTendaysOfflineWeekSpecialParamDTO param); + + Page reportPage(Page page, RptTendaysOfflineWeekSpecialParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedCompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedCompanyService.java new file mode 100644 index 0000000..26499b5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedCompanyService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedCompany; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedCompanyPO; + +import java.util.List; + +/** + *

+ * 专用车辆超速企业情况旬报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptTendaysSpecialOverspeedCompanyService extends IService { + + List report(RptTendaysOverspeedSpecialCompanyParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedVehiclesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedVehiclesService.java new file mode 100644 index 0000000..ccbeb89 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/IRptTendaysSpecialOverspeedVehiclesService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.car.rpt.service; + +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedVehicles; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedVehiclesPO; + +import java.util.List; + +/** + *

+ * 专用车辆超速车辆情况旬报 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface IRptTendaysSpecialOverspeedVehiclesService extends IService { + + List report(RptTendaysOverspeedSpecialVehiclesParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOperatorVehiclesLaunchRateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOperatorVehiclesLaunchRateServiceImpl.java new file mode 100644 index 0000000..e489413 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOperatorVehiclesLaunchRateServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOperatorVehiclesLaunchRate; +import com.ningdatech.carapi.car.rpt.mapper.RptDailyOperatorVehiclesLaunchRateMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOperatorVehiclesLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOperatorVehiclesLaunchRatePO; +import com.ningdatech.carapi.car.rpt.service.IRptDailyOperatorVehiclesLaunchRateService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 运营商车辆上线率日报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class RptDailyOperatorVehiclesLaunchRateServiceImpl extends ServiceImpl implements IRptDailyOperatorVehiclesLaunchRateService { + + private final RptDailyOperatorVehiclesLaunchRateMapper mapper; + + @Override + @XmlDataScope + public List report(RptDailyOperatorVehiclesLaunchRateParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedCompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedCompanyServiceImpl.java new file mode 100644 index 0000000..708a5fa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedCompanyServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOverspeedCompany; +import com.ningdatech.carapi.car.rpt.mapper.RptDailyOverspeedCompanyMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOverspeedCompanyPO; +import com.ningdatech.carapi.car.rpt.service.IRptDailyOverspeedCompanyService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 超速企业情况日报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class RptDailyOverspeedCompanyServiceImpl extends ServiceImpl implements IRptDailyOverspeedCompanyService { + + private final RptDailyOverspeedCompanyMapper mapper; + + @Override + @XmlDataScope + public List report(RptDailyOverspeedCompanyParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedSpecialVehiclesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedSpecialVehiclesServiceImpl.java new file mode 100644 index 0000000..e7983b6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailyOverspeedSpecialVehiclesServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptDailyOverspeedSpecialVehicles; +import com.ningdatech.carapi.car.rpt.mapper.RptDailyOverspeedSpecialVehiclesMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailyOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailyOverspeedSpecialVehiclesPO; +import com.ningdatech.carapi.car.rpt.service.IRptDailyOverspeedSpecialVehiclesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 超速专用车辆日报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class RptDailyOverspeedSpecialVehiclesServiceImpl extends ServiceImpl implements IRptDailyOverspeedSpecialVehiclesService { + + private final RptDailyOverspeedSpecialVehiclesMapper mapper; + + @Override + @XmlDataScope + public List report(RptDailyOverspeedSpecialVehiclesParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesCompanyLaunchRate60ServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesCompanyLaunchRate60ServiceImpl.java new file mode 100644 index 0000000..d267536 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesCompanyLaunchRate60ServiceImpl.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesCompanyLaunchRate60; +import com.ningdatech.carapi.car.rpt.mapper.RptDailySpecialVehiclesCompanyLaunchRate60Mapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesCompanyLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesCompanyLaunchRate60PO; +import com.ningdatech.carapi.car.rpt.service.IRptDailySpecialVehiclesCompanyLaunchRate60Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆企业上线率低于60日报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class RptDailySpecialVehiclesCompanyLaunchRate60ServiceImpl extends ServiceImpl implements IRptDailySpecialVehiclesCompanyLaunchRate60Service { + + private final RptDailySpecialVehiclesCompanyLaunchRate60Mapper mapper; + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List report(RptDailySpecialVehiclesCompanyLaunchRateParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesLaunchRateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesLaunchRateServiceImpl.java new file mode 100644 index 0000000..1185463 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesLaunchRateServiceImpl.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import java.util.Date; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesLaunchRate; +import com.ningdatech.carapi.car.rpt.mapper.RptDailySpecialVehiclesLaunchRateMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesLaunchRateParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesLaunchRatePO; +import com.ningdatech.carapi.car.rpt.service.IRptDailySpecialVehiclesLaunchRateService; +import com.ningdatech.carapi.common.util.CodeUtil; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 专用车辆上线率日报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class RptDailySpecialVehiclesLaunchRateServiceImpl extends ServiceImpl implements IRptDailySpecialVehiclesLaunchRateService { + + private final RptDailySpecialVehiclesLaunchRateMapper mapper; + + @Override + public List report(RptDailySpecialVehiclesLaunchRateParamDTO param) { + CodeUtil.buildRegionLevel(param); + Date date = NdDateUtils.parseAsDate(param.getDate()); + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(date,"yyyy_MM"); + param.setTableName(tableName); + List res = mapper.report(param); + return res; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesOverspeedServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesOverspeedServiceImpl.java new file mode 100644 index 0000000..366b4bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptDailySpecialVehiclesOverspeedServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptDailySpecialVehiclesOverspeed; +import com.ningdatech.carapi.car.rpt.mapper.RptDailySpecialVehiclesOverspeedMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptDailySpecialVehiclesOverspeedParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptDailySpecialVehiclesOverspeedPO; +import com.ningdatech.carapi.car.rpt.service.IRptDailySpecialVehiclesOverspeedService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆超速日报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class RptDailySpecialVehiclesOverspeedServiceImpl extends ServiceImpl implements IRptDailySpecialVehiclesOverspeedService { + + private final RptDailySpecialVehiclesOverspeedMapper mapper; + + @Override + @XmlDataScope + public List report(RptDailySpecialVehiclesOverspeedParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedCompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedCompanyServiceImpl.java new file mode 100644 index 0000000..d694984 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedCompanyServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedCompany; +import com.ningdatech.carapi.car.rpt.mapper.RptMonthOverspeedCompanyMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedCompanyPO; +import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedCompanyService; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 超速企业情况月报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptMonthOverspeedCompanyServiceImpl extends ServiceImpl implements IRptMonthOverspeedCompanyService { + + private final RptMonthOverspeedCompanyMapper mapper; + + @Override + @XmlDataScope + public List report(RptMonthOverspeedCompanyParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialCompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialCompanyServiceImpl.java new file mode 100644 index 0000000..7d30a08 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialCompanyServiceImpl.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedSpecialCompany; +import com.ningdatech.carapi.car.rpt.mapper.RptMonthOverspeedSpecialCompanyMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialVehiclesOverspeedPO; +import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedSpecialCompanyService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆超速企业情况月报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptMonthOverspeedSpecialCompanyServiceImpl extends ServiceImpl implements IRptMonthOverspeedSpecialCompanyService { + + private final RptMonthOverspeedSpecialCompanyMapper mapper; + + @Override + public List report(RptMonthSpecialOverspeedCompanyParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialVehiclesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialVehiclesServiceImpl.java new file mode 100644 index 0000000..0ef8554 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthOverspeedSpecialVehiclesServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptMonthOverspeedSpecialVehicles; +import com.ningdatech.carapi.car.rpt.mapper.RptMonthOverspeedSpecialVehiclesMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedSpecialVehiclesPO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; +import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedSpecialVehiclesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆超速月对比 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptMonthOverspeedSpecialVehiclesServiceImpl extends ServiceImpl implements IRptMonthOverspeedSpecialVehiclesService { + + private final RptMonthOverspeedSpecialVehiclesMapper mapper; + + @Override + public List reportPage(Page page, RptMonthSpecialOverspeedVehiclesParamDTO param) { + return mapper.reportPage(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthSpecialOfflineServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthSpecialOfflineServiceImpl.java new file mode 100644 index 0000000..ff0805b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptMonthSpecialOfflineServiceImpl.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptMonthSpecialOffline; +import com.ningdatech.carapi.car.rpt.mapper.RptMonthSpecialOfflineMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOfflineParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO; +import com.ningdatech.carapi.car.rpt.service.IRptMonthSpecialOfflineService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆不上线月报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptMonthSpecialOfflineServiceImpl extends ServiceImpl implements IRptMonthSpecialOfflineService { + + private final RptMonthSpecialOfflineMapper mapper; + + @Override + @XmlDataScope + public List reportPage(Page page, RptMonthSpecialOfflineParamDTO param) { + return mapper.reportPage(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesAnalysisServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesAnalysisServiceImpl.java new file mode 100644 index 0000000..c407c27 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesAnalysisServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherAlarmCleanVehiclesAnalysis; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherAlarmCleanVehiclesAnalysisMapper; +import com.ningdatech.carapi.car.rpt.service.IRptOtherAlarmCleanVehiclesAnalysisService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆报警清理分析表 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +public class RptOtherAlarmCleanVehiclesAnalysisServiceImpl extends ServiceImpl implements IRptOtherAlarmCleanVehiclesAnalysisService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesServiceImpl.java new file mode 100644 index 0000000..896d3e3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherAlarmCleanVehiclesServiceImpl.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherAlarmCleanVehicles; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherAlarmCleanVehiclesMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherAlarmCleanVehiclesPO; +import com.ningdatech.carapi.car.rpt.service.IRptOtherAlarmCleanVehiclesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆报警清理表 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptOtherAlarmCleanVehiclesServiceImpl extends ServiceImpl implements IRptOtherAlarmCleanVehiclesService { + + private final RptOtherAlarmCleanVehiclesMapper mapper; + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page reportPage(Page page, + RptOtherParamDTO param) { + return mapper.reportPage(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesAnalysisServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesAnalysisServiceImpl.java new file mode 100644 index 0000000..3fea362 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesAnalysisServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherCrossDomainVehiclesAnalysis; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherCrossDomainVehiclesAnalysisMapper; +import com.ningdatech.carapi.car.rpt.service.IRptOtherCrossDomainVehiclesAnalysisService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆跨域情况分析表 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +public class RptOtherCrossDomainVehiclesAnalysisServiceImpl extends ServiceImpl implements IRptOtherCrossDomainVehiclesAnalysisService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesServiceImpl.java new file mode 100644 index 0000000..5ac81a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherCrossDomainVehiclesServiceImpl.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherCrossDomainVehicles; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherCrossDomainVehiclesMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherCrossDomainVehiclesPO; +import com.ningdatech.carapi.car.rpt.service.IRptOtherCrossDomainVehiclesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + *

+ * 车辆跨域情况表 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptOtherCrossDomainVehiclesServiceImpl extends ServiceImpl implements IRptOtherCrossDomainVehiclesService { + + private final RptOtherCrossDomainVehiclesMapper mapper; + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List report(RptOtherParamDTO param) { + return mapper.report(param); + } + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page reportPage(Page page, RptOtherParamDTO param) { + return mapper.reportPage(page, param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesAnalysisServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesAnalysisServiceImpl.java new file mode 100644 index 0000000..4639d15 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesAnalysisServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherOnlineVehiclesAnalysis; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherOnlineVehiclesAnalysisMapper; +import com.ningdatech.carapi.car.rpt.service.IRptOtherOnlineVehiclesAnalysisService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 在线车辆统计分析表 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +public class RptOtherOnlineVehiclesAnalysisServiceImpl extends ServiceImpl implements IRptOtherOnlineVehiclesAnalysisService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesServiceImpl.java new file mode 100644 index 0000000..56659e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherOnlineVehiclesServiceImpl.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherOnlineVehicles; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherOnlineVehiclesMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; +import com.ningdatech.carapi.car.rpt.service.IRptOtherOnlineVehiclesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 在线车辆统计表 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptOtherOnlineVehiclesServiceImpl extends ServiceImpl implements IRptOtherOnlineVehiclesService { + + private final RptOtherOnlineVehiclesMapper mapper; + + @Override + @XmlDataScope + public List report(RptOtherParamDTO param) { + return mapper.report(param); + } + + @Override + @XmlDataScope + public Page reportPage(Page page, RptOtherParamDTO param) { + return mapper.reportPage(page, param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialOverspeedServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialOverspeedServiceImpl.java new file mode 100644 index 0000000..1daf6a0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialOverspeedServiceImpl.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptOtherSpecialOverspeed; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherSpecialOverspeedMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherSpecialOverspeedPO; +import com.ningdatech.carapi.car.rpt.service.IRptOtherSpecialOverspeedService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆超速记录 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptOtherSpecialOverspeedServiceImpl extends ServiceImpl implements IRptOtherSpecialOverspeedService { + + private final RptOtherSpecialOverspeedMapper mapper; + + @Override + @XmlDataScope + public List report(RptOtherParamDTO param) { + return mapper.report(param); + } + + @Override + @XmlDataScope + public Page reportPage(Page page, RptOtherParamDTO param) { + return mapper.reportPage(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialTripsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialTripsServiceImpl.java new file mode 100644 index 0000000..4e1f178 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherSpecialTripsServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherSpecialTrips; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherSpecialTripsMapper; +import com.ningdatech.carapi.car.rpt.service.IRptOtherSpecialTripsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 专用车辆趟次记录 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +public class RptOtherSpecialTripsServiceImpl extends ServiceImpl implements IRptOtherSpecialTripsService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherTerminalInstallServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherTerminalInstallServiceImpl.java new file mode 100644 index 0000000..bc0a44d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptOtherTerminalInstallServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptOtherTerminalInstall; +import com.ningdatech.carapi.car.rpt.mapper.RptOtherTerminalInstallMapper; +import com.ningdatech.carapi.car.rpt.service.IRptOtherTerminalInstallService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 终端车载安装统计 其它报表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +public class RptOtherTerminalInstallServiceImpl extends ServiceImpl implements IRptOtherTerminalInstallService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOfflineWeekServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOfflineWeekServiceImpl.java new file mode 100644 index 0000000..2116c08 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOfflineWeekServiceImpl.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOfflineWeek; +import com.ningdatech.carapi.car.rpt.mapper.RptTendaysSpecialOfflineWeekMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOfflineWeekSpecialParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOfflineWeekPO; +import com.ningdatech.carapi.car.rpt.service.IRptTendaysSpecialOfflineWeekService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆一周以上不上线旬报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptTendaysSpecialOfflineWeekServiceImpl extends ServiceImpl implements IRptTendaysSpecialOfflineWeekService { + + private final RptTendaysSpecialOfflineWeekMapper mapper; + + @Override + @XmlDataScope + public List report(RptTendaysOfflineWeekSpecialParamDTO param) { + return mapper.report(param); + } + + @Override + @XmlDataScope + public Page reportPage(Page page, RptTendaysOfflineWeekSpecialParamDTO param) { + return mapper.reportPage(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedCompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedCompanyServiceImpl.java new file mode 100644 index 0000000..2d1dea6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedCompanyServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedCompany; +import com.ningdatech.carapi.car.rpt.mapper.RptTendaysSpecialOverspeedCompanyMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialCompanyParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedCompanyPO; +import com.ningdatech.carapi.car.rpt.service.IRptTendaysSpecialOverspeedCompanyService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆超速企业情况旬报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptTendaysSpecialOverspeedCompanyServiceImpl extends ServiceImpl implements IRptTendaysSpecialOverspeedCompanyService { + + private final RptTendaysSpecialOverspeedCompanyMapper mapper; + + @Override + @XmlDataScope + public List report(RptTendaysOverspeedSpecialCompanyParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedVehiclesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedVehiclesServiceImpl.java new file mode 100644 index 0000000..c793114 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/rpt/service/impl/RptTendaysSpecialOverspeedVehiclesServiceImpl.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.rpt.service.impl; + +import com.ningdatech.carapi.car.rpt.entity.RptTendaysSpecialOverspeedVehicles; +import com.ningdatech.carapi.car.rpt.mapper.RptTendaysSpecialOverspeedVehiclesMapper; +import com.ningdatech.carapi.car.rpt.model.dto.RptTendaysOverspeedSpecialVehiclesParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptTendaysSpecialOverspeedVehiclesPO; +import com.ningdatech.carapi.car.rpt.service.IRptTendaysSpecialOverspeedVehiclesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 专用车辆超速车辆情况旬报 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +@RequiredArgsConstructor +public class RptTendaysSpecialOverspeedVehiclesServiceImpl extends ServiceImpl implements IRptTendaysSpecialOverspeedVehiclesService { + + private final RptTendaysSpecialOverspeedVehiclesMapper mapper; + + @Override + @XmlDataScope + public List report(RptTendaysOverspeedSpecialVehiclesParamDTO param) { + return mapper.report(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/controller/VehicleTripsController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/controller/VehicleTripsController.java new file mode 100644 index 0000000..83b8c43 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/controller/VehicleTripsController.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.car.trips.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.monitor.model.dto.LoadMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.vo.SecurityMonitorVO; +import com.ningdatech.carapi.car.trips.manage.VehicleTripsManage; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; +import com.ningdatech.carapi.car.trips.model.vo.VehicleTripsCityVO; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 车辆单趟记录 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Controller +@RestController +@RequestMapping(value = "/api/car-manage/trips") +@Api(tags = "车辆管理-车辆趟次") +@Validated +@RequiredArgsConstructor +public class VehicleTripsController { + + private final VehicleTripsManage vehicleTripsManage; + + @ApiOperation("车辆趟次查询-按城市维度") + @GetMapping("/list-groupby-city") + public PageVo lictGroupByCity(@Valid @ModelAttribute VehicleTripsParamDTO param) { + return vehicleTripsManage.lictGroupByCity(param); + } + + @ApiOperation(value = "车辆趟次导出", notes = "车辆趟次导出") + @GetMapping("/export-list-groupby-city") + public void exportGroupByCity(VehicleTripsParamDTO param, HttpServletResponse response) { + ExcelDownUtil.downXls(response, param, vehicleTripsManage::exportGroupByCity); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTrips.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTrips.java new file mode 100644 index 0000000..82ad498 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTrips.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.car.trips.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆单趟记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_vehicle_trips") +@Data +@ApiModel(value = "VehicleTrips对象", description = "车辆单趟记录") +public class VehicleTrips extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车辆单趟记录流水号") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("发生日期") + private LocalDate happenDate; + + @ApiModelProperty("车辆ID") + private Long vehicleId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("离场经纬度") + private String leaveLngLat; + + @ApiModelProperty("离场日期时间") + private LocalDateTime leaveDateTime; + + @ApiModelProperty("最远停车点经纬度") + private String farStopLnglat; + + @ApiModelProperty("最远停车点日期时间") + private LocalDateTime farStopDateTime; + + @ApiModelProperty("最久停车点经纬度") + private String stayStopLngLat; + + @ApiModelProperty("最久停车点日期时间") + private LocalDateTime stayStopDateTime; + + @ApiModelProperty("离场信息(json数组)") + private String leaveJson; + + @ApiModelProperty("最远停车点信息(json数组)") + private String farStopJson; + + @ApiModelProperty("最久停车点信息(json数组)") + private String stayStopJson; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型 1:泵车 2:混凝土搅拌车 3:散装水泥车 4:预拌砂浆车 5:其他") + private Integer vehicleType; + + @ApiModelProperty("单位完整名称") + private String companyName; + + @ApiModelProperty("轻重车辆类型(根据所属企业距离判断) 0:未知 1:轻车 2:重车") + private Integer weightType; + + @ApiModelProperty("操作时间") + private LocalDateTime updateOn; + + @ApiModelProperty("新增时间") + private LocalDateTime createOn; + + @ApiModelProperty("是否删除 0:删除 1:存在") + private Integer status; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCity.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCity.java new file mode 100644 index 0000000..54b80f2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCity.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.car.trips.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆单趟记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@TableName("nd_vehicle_trips") +@Data +@ApiModel(value = "VehicleTripsCity", description = "车辆趟次记录") +public class VehicleTripsCity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆趟次数") + private Long vehicleTripsNums; + + @ApiModelProperty("发生日期") + @TableField(exist = false) + private LocalDateTime happenDate; + + @ApiModelProperty("区域ID") + @TableField(exist = false) + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCompany.java new file mode 100644 index 0000000..0e2d106 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/entity/VehicleTripsCompany.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.car.trips.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆单趟记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "VehicleTripsCompany", description = "车辆趟次记录") +public class VehicleTripsCompany implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆趟次数") + private Long vehicleTripsNums; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/manage/VehicleTripsManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/manage/VehicleTripsManage.java new file mode 100644 index 0000000..2e8937e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/manage/VehicleTripsManage.java @@ -0,0 +1,117 @@ +package com.ningdatech.carapi.car.trips.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.monitor.entity.AlarmDataLoad; +import com.ningdatech.carapi.car.monitor.entity.SecurityMonitorJoin; +import com.ningdatech.carapi.car.monitor.model.dto.AlarmDataLoadDTO; +import com.ningdatech.carapi.car.monitor.model.dto.LoadMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.dto.SecurityMonitorPageParamDTO; +import com.ningdatech.carapi.car.monitor.model.vo.AlarmDataLoadVO; +import com.ningdatech.carapi.car.monitor.model.vo.SecurityMonitorVO; +import com.ningdatech.carapi.car.monitor.service.IAlarmDataLoadService; +import com.ningdatech.carapi.car.monitor.service.SecurityMonitorService; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCity; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCompany; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsCityExportDTO; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; +import com.ningdatech.carapi.car.trips.model.vo.VehicleTripsCityVO; +import com.ningdatech.carapi.car.trips.model.vo.VehicleTripsCompanyVO; +import com.ningdatech.carapi.car.trips.service.IVehicleTripsCityService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.constant.AlarmTypeEnum; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.sys.entity.dto.CascadeCodeDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @Classname VehicleTripsManage + * @Description + * @Date 2022/11/4 16:30 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class VehicleTripsManage { + + private final IVehicleTripsCityService vehicleTripsCityService; + + //逻辑修改为 从上车记录里取 + public PageVo lictGroupByCity(VehicleTripsParamDTO param) { + Page page = param.page(); + ((VehicleTripsManage)AopContext.currentProxy()).search(page,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleTripsCityVO.class)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public PageVo lictGroupByCompany(VehicleTripsParamDTO param) { + Page page = param.page(); + ((VehicleTripsManage)AopContext.currentProxy()).searchGroupCompany(page,param); + if(0L == page.getTotal()){ + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleTripsCompanyVO.class)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public void search(Page page, VehicleTripsParamDTO param) { + CodeUtil.buildRegionLevel(param); + vehicleTripsCityService.pageCityGetOn(page, param); + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public void searchGroupCompany(Page page, VehicleTripsParamDTO param) { + vehicleTripsCityService.pageCityGetOnCompany(page, param); + } + + public void exportGroupByCity(HttpServletResponse response, VehicleTripsParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = lictGroupByCity(param); + List collect = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleTripsCityVO.class)).collect(Collectors.toList()); + String fileName = "车辆趟次列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), VehicleTripsCityExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.java new file mode 100644 index 0000000..1ced628 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.car.trips.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCity; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCompany; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 车辆单趟记录 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface VehicleTripsCityMapper extends BaseMapper { + Page pageCity(Page page, @Param("regionIds") List regionIds, + @Param("startTime") String startTime,@Param("endTime") String endTime); + + Page pageCityGetOn(Page page, @Param("param") VehicleTripsParamDTO param); + + Page pageCityGetOnCompany(Page page, @Param("param") VehicleTripsParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.xml new file mode 100644 index 0000000..1f707fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsCityMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.java new file mode 100644 index 0000000..1435ad5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.trips.mapper; + +import com.ningdatech.carapi.car.trips.entity.VehicleTrips; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆单趟记录 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface VehicleTripsMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.xml new file mode 100644 index 0000000..62cbd21 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/mapper/VehicleTripsMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsCityExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsCityExportDTO.java new file mode 100644 index 0000000..9733976 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsCityExportDTO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.car.trips.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 车辆单趟记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "VehicleTripsCity", description = "车辆趟次记录") +public class VehicleTripsCityExportDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车辆总数") + @ExcelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆趟次数") + @ExcelProperty("车辆趟次数") + private Long vehicleTripsNums; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsParamDTO.java new file mode 100644 index 0000000..a14139b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/dto/VehicleTripsParamDTO.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.car.trips.model.dto; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.sys.contants.RegionContant; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Objects; + +/** + *

+ * 车辆趟次分页传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@Builder +@ApiModel(value = "VehicleTripsParamDTO", description = "车辆趟次分页传参") +@AllArgsConstructor +@NoArgsConstructor +public class VehicleTripsParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + private List regionIds; + private String regionCode; + private String dataScopeSql; + private Integer regionLevel; + private List vehicleTypes; + + public Long getRegionId(){ + if(Objects.isNull(this.regionId)){ + this.regionId = RegionContant.ZJ_REGION_ID; + return this.regionId; + } + return this.regionId; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCityVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCityVO.java new file mode 100644 index 0000000..8f17b83 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCityVO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.trips.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 车辆单趟记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "VehicleTripsCity", description = "车辆趟次记录") +public class VehicleTripsCityVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆趟次数") + private Long vehicleTripsNums; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCompanyVO.java new file mode 100644 index 0000000..b7523d4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/model/vo/VehicleTripsCompanyVO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.car.trips.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 车辆单趟记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Data +@ApiModel(value = "VehicleTripsCompanyVO", description = "车辆趟次记录") +public class VehicleTripsCompanyVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车辆总数") + private Long vehicleNums; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车辆趟次数") + private Long vehicleTripsNums; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsCityService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsCityService.java new file mode 100644 index 0000000..c1a8b5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsCityService.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.car.trips.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCity; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCompany; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; + +import java.util.List; + +/** + *

+ * 车辆单趟记录 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IVehicleTripsCityService extends IService { + Page pageCity(Page page, List regionIds, + String startTime, String endTime); + + Page pageCityGetOn(Page page, + VehicleTripsParamDTO param); + + Page pageCityGetOnCompany(Page page, + VehicleTripsParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsService.java new file mode 100644 index 0000000..2a4190e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/IVehicleTripsService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.car.trips.service; + +import com.ningdatech.carapi.car.trips.entity.VehicleTrips; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆单趟记录 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +public interface IVehicleTripsService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceCityImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceCityImpl.java new file mode 100644 index 0000000..495a942 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceCityImpl.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.car.trips.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.trips.entity.VehicleTrips; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCity; +import com.ningdatech.carapi.car.trips.entity.VehicleTripsCompany; +import com.ningdatech.carapi.car.trips.mapper.VehicleTripsCityMapper; +import com.ningdatech.carapi.car.trips.mapper.VehicleTripsMapper; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; +import com.ningdatech.carapi.car.trips.service.IVehicleTripsCityService; +import com.ningdatech.carapi.car.trips.service.IVehicleTripsService; +import lombok.RequiredArgsConstructor; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 车辆单趟记录 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class VehicleTripsServiceCityImpl extends ServiceImpl implements IVehicleTripsCityService { + + private final VehicleTripsCityMapper vehicleTripsCityMapper; + + @Override + public Page pageCity(Page page, List regionIds, + String startTime, String endTime) { + return vehicleTripsCityMapper.pageCity(page,regionIds,startTime,endTime); + } + + @Override + public Page pageCityGetOn(Page page, VehicleTripsParamDTO param) { + return vehicleTripsCityMapper.pageCityGetOn(page,param); + } + + @Override + public Page pageCityGetOnCompany(Page page, VehicleTripsParamDTO param) { + return vehicleTripsCityMapper.pageCityGetOnCompany(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceImpl.java new file mode 100644 index 0000000..7097aea --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/trips/service/impl/VehicleTripsServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.car.trips.service.impl; + +import com.ningdatech.carapi.car.trips.entity.VehicleTrips; +import com.ningdatech.carapi.car.trips.mapper.VehicleTripsMapper; +import com.ningdatech.carapi.car.trips.service.IVehicleTripsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆单趟记录 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-08 + */ +@Service +public class VehicleTripsServiceImpl extends ServiceImpl implements IVehicleTripsService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/contants/VehicleContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/contants/VehicleContant.java new file mode 100644 index 0000000..de83b2e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/contants/VehicleContant.java @@ -0,0 +1,10 @@ +package com.ningdatech.carapi.car.vehicle.contants; + +public interface VehicleContant { + + String DEFAULT_CHANNEL_NAME = "通道1"; + + String DEFAULT_NULL_AUDIT = "无"; + + String ADMIN_COMPANY_NAME = "散装中心"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/controller/VehicleController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/controller/VehicleController.java new file mode 100644 index 0000000..f820493 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/controller/VehicleController.java @@ -0,0 +1,150 @@ +package com.ningdatech.carapi.car.vehicle.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.manage.VehicleManage; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleBaseVO; +import com.ningdatech.carapi.car.vehicle.model.dto.*; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/archives/vehicle") +@Api(value = "archives", tags = "车辆管理-档案管理") +@RequiredArgsConstructor +public class VehicleController { + + private final VehicleManage vehicleManage; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + @ApiOperation(value = "车辆列表查询", notes = "车辆列表查询") + @GetMapping("/list") + public PageVo queryList(@Valid @ModelAttribute VehicleArchivesPageQuery vehicleArchivesPageQuery) { + return vehicleManage.queryNewAddList(vehicleArchivesPageQuery); + } + + @ApiOperation(value = "车辆列表导出", notes = "车辆列表导出") + @GetMapping("/exportBase") + public void export(VehicleArchivesPageQuery req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, vehicleManage::exportNewAddBase); + } + + @ApiOperation(value = "车辆档案列表查询", notes = "车辆档案列表查询") + @GetMapping("/archivesList") + public PageVo queryArchivesList(@Valid @ModelAttribute VehicleArchivesPageQuery vehicleArchivesPageQuery) { + return vehicleManage.queryList(vehicleArchivesPageQuery); + } + + @ApiOperation(value = "车辆档案导出", notes = "车辆档案导出") + @GetMapping("/exportArchives") + @WebLog(value = "导出车辆档案") + public void exportArchives(VehicleArchivesPageQuery req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, vehicleManage::exportArchives); + } + + @ApiOperation(value = "车辆待审核列表查询", notes = "车辆待审核列表查询") + @GetMapping("/toBeAuditList") + public PageVo queryToBeAudit(@Valid @ModelAttribute VehicleAuditPageQuery vehicleAuditPageQuery) { + return vehicleManage.queryToBeAudit(vehicleAuditPageQuery); + } + + @ApiOperation(value = "车辆已审核列表查询", notes = "车辆已审核列表查询") + @GetMapping("/auditedList") + public PageVo queryAuditedList(@Valid @ModelAttribute VehicleAuditPageQuery vehicleAuditPageQuery) { + return vehicleManage.queryAuditedList(vehicleAuditPageQuery); + } + + @ApiOperation(value = "车辆审核列表导出", notes = "车辆审核列表导出") + @GetMapping("/exportAudit") + @WebLog + public void exportAudit(VehicleAuditPageQuery req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, vehicleManage::exportAudit); + } + + /** + * 查询车辆基本信息 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询车辆基本信息", notes = "查询车辆基本信息") + @GetMapping("/baseInfo") + public VehicleArchivesQueryDTO getDetails(@Valid @RequestParam Long id) { + return vehicleManage.getDetails(id); + } + + @ApiOperation(value = "保存新车辆", notes = "保存新车辆") + @PostMapping("/save") + @WebLog + public VehicleArchivesQueryDTO handlerSave(@Valid @RequestBody VehicleSaveDTO data) { + NdVehicleBaseInfo entity = vehicleManage.save(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(entity, VehicleArchivesQueryDTO.class); + } + + @ApiOperation(value = "编辑车辆(重新提交)", notes = "编辑车辆(重新提交)") + @PostMapping("/modify") + @WebLog + public VehicleArchivesQueryDTO handlerUpdate(@Valid @RequestBody VehicleUpdateDTO data) { + NdVehicleBaseInfo entity = vehicleManage.update(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(entity, VehicleArchivesQueryDTO.class); + } + + @ApiOperation(value = "删除车辆", notes = "删除车辆") + @PostMapping("/remove") + @WebLog + public Boolean handlerDelete(@Valid @RequestBody List ids) { + return vehicleManage.removeByIdWithCache(ids); + } + + @ApiOperation(value = "车辆审核", notes = "车辆审核") + @PostMapping("/audit") + @WebLog + public Boolean handlerAudit(@Valid @RequestBody VehicleAuditDTO data) { + return vehicleBaseInfoService.audit(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "编辑车辆基本信息", notes = "编辑车辆基本信息") + @PostMapping("/modifyBaseInfo") + @WebLog + public VehicleArchivesQueryDTO modifyUpdate(@Valid @RequestBody VehicleUpdateDTO data) { + NdVehicleBaseInfo entity = vehicleManage.modifyAndUpdate(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(entity, VehicleArchivesQueryDTO.class); + } + + @ApiOperation(value = "更新天表在线时间", notes = "更新天表在线时间") + @GetMapping("/updateOnlineTime") + public String updateOnlineTime() { + vehicleManage.updateOnlineTime(); + return "更新成功"; + } + + @ApiOperation(value = "取消车辆与所属企业、使用企业及区域的绑定") + @GetMapping("/cancel-relevance") + public String cancelRelevance(@Valid @RequestParam Long id){ + return vehicleManage.cancelRelevance(id); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/manage/VehicleManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/manage/VehicleManage.java new file mode 100644 index 0000000..4a85eaf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/manage/VehicleManage.java @@ -0,0 +1,804 @@ +package com.ningdatech.carapi.car.vehicle.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import com.ningdatech.carapi.car.position.model.po.ReqDataPO; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; +import com.ningdatech.carapi.car.vehicle.model.dto.*; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleBaseVO; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleCarPlateVO; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoJoinService; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.*; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.company.enumeration.CompanyTypeEnum; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusDay; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusDayService; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusHourService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.helper.UserCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + * @Classname VehicleManage + * @Description + * @Date 2022/10/14 14:33 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +public class VehicleManage { + + private final IVehicleBaseInfoJoinService vehicleBaseInfoJoinService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + private final UserCacheHelper userCacheHelper; + private final OperatorsCacheHelper operatorsCacheHelper; + private final UserInfoHelper userInfoHelper; + private final RegionsCacheHelper regionsCacheHelper; + private final CompanyService companyService; + private final IVehicleOnlineStatusHourService vehicleOnlineStatusHourService; + private final IVehicleOnlineStatusDayService vehicleOnlineStatusDayService; + private final CompaniesCacheHelper companiesCacheHelper; + + /** + * 车辆档案列表查询 + * @param vehicleArchivesPageQuery + * @return + */ + public PageVo queryList(VehicleArchivesPageQuery vehicleArchivesPageQuery) { + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + // 如果要展示没有所属企业的车 + List baseJoins = Lists.newArrayList(); + if (Boolean.TRUE.equals(vehicleArchivesPageQuery.getShowWithoutCompany())) { + LambdaQueryWrapper otherWrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + buildOtherWrapper(otherWrapper, vehicleArchivesPageQuery); + List baseInfos = vehicleBaseInfoService.list(otherWrapper).stream() + .filter(v -> Objects.isNull(v.getCompanyId())).collect(Collectors.toList()); + // 如果根据所属企业名称查询,结果置为空(因为查出的车辆所属企业不在系统中) + if (Objects.nonNull(vehicleArchivesPageQuery.getCompanyName())) { + baseInfos = Lists.newArrayList(); + } else if (Objects.nonNull(vehicleArchivesPageQuery.getOperatorName())) { + // 所属企业名称查询为空,运营商名称不为空 + baseInfos = baseInfos.stream().filter(b -> { + Long operatorId = b.getOperatorId(); + if (Objects.nonNull(operatorId)) { + OperatorQueryDTO dto = operatorsCacheHelper.getById(operatorId); + String operatorName = dto.getName(); + if (vehicleArchivesPageQuery.getOperatorName().equals(operatorName)) { + return true; + } + } + return false; + }).collect(Collectors.toList()); + } + + baseJoins = CollUtils.convert(baseInfos, r -> { + NdVehicleBaseInfoJoin join = new NdVehicleBaseInfoJoin(); + BeanUtils.copyProperties(r, join); + Long operatorId = r.getOperatorId(); + if (Objects.nonNull(operatorId)) { + OperatorQueryDTO dto = operatorsCacheHelper.getById(operatorId); + join.setOperatorName(dto.getName()); + } + return join; + }); + } + + + Integer pageSize = vehicleArchivesPageQuery.getPageSize(); + Integer pageNumber = vehicleArchivesPageQuery.getPageNumber(); + List joins; + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.eq(NdVehicleBaseInfoJoin::getOperatorId,operatorId); + joins = vehicleBaseInfoJoinService.listCarJoin(wrapper); + } else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + Long companyId = userDetail.getCompanyId(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.and(w -> w.eq(NdVehicleBaseInfoJoin::getCompanyId,companyId).or().eq(NdVehicleBaseInfoJoin::getUseCompanyId,companyId)); + joins = vehicleBaseInfoJoinService.listCarJoinWithUseCompany(wrapper); + } else { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + VehicleManage context = (VehicleManage) AopContext.currentProxy(); + joins = context.searchCar(wrapper, vehicleArchivesPageQuery); + } + joins.addAll(baseJoins); + List records = joins.stream().skip((pageNumber - 1) * pageSize).limit(pageSize).collect(Collectors.toList()); + List data = CollUtils.convert(records, v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + // 根据所属企业的区域Id展示所属区域 + Long companyId = vo.getCompanyId(); + if (Objects.nonNull(companyId)) { + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + Long regionId = companyDto.getRegionId(); + if (Objects.nonNull(regionId)) { + vo.setRegionId(regionId); + vo.setRegionName(regionsCacheHelper.getDisplayName(regionId)); + } + } + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleStatus(v.getVehicleStatus()); + vo.setVehicleStatusName(CarStatusEnum.getDescByCode(v.getVehicleStatus())); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + return vo; + }); + return PageVo.of(data, joins.size()); + } + + /** + * 车辆新增列表查询 + * @param vehicleArchivesPageQuery + * @return + */ + public PageVo queryNewAddList(VehicleArchivesPageQuery vehicleArchivesPageQuery) { + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildNewAddQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.eq(NdVehicleBaseInfoJoin::getOperatorId,operatorId); + vehicleBaseInfoJoinService.pageJoin(page,wrapper); + List data = CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + // 根据所属企业的区域Id展示所属区域 + Long companyId = vo.getCompanyId(); + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + if (Objects.nonNull(companyDto)) { + Long regionId = companyDto.getRegionId(); + if (Objects.nonNull(regionId)) { + vo.setRegionId(regionId); + vo.setRegionName(regionsCacheHelper.getDisplayName(regionId)); + } + } + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleStatus(v.getVehicleStatus()); + vo.setVehicleStatusName(CarStatusEnum.getDescByCode(v.getVehicleStatus())); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + vo.setAuditStateName(AuditStateEnum.getDescByCode(vo.getAuditState())); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + // 如果是企业信息员账号登录,则查询该企业为所属企业和使用企业的所有车辆信息 + else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + Long companyId = userDetail.getCompanyId(); + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + buildNewAddQueryWrapper(wrapper,vehicleArchivesPageQuery); + wrapper.and(w -> w.eq(NdVehicleBaseInfoJoin::getCompanyId,companyId).or().eq(NdVehicleBaseInfoJoin::getUseCompanyId,companyId)); + vehicleBaseInfoJoinService.pageJoinWithUseCompany(page,wrapper); + List data = CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + vo.setVehicleStatus(v.getVehicleStatus()); + vo.setVehicleStatusName(CarStatusEnum.getDescByCode(v.getVehicleStatus())); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + vo.setAuditStateName(AuditStateEnum.getDescByCode(vo.getAuditState())); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } else { + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + VehicleManage context = (VehicleManage) AopContext.currentProxy(); + context.searchNewAddPage(page, wrapper, vehicleArchivesPageQuery); + List data = CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + vo.setVehicleStatus(v.getVehicleStatus()); + vo.setVehicleStatusName(CarStatusEnum.getDescByCode(v.getVehicleStatus())); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + vo.setAuditStateName(AuditStateEnum.getDescByCode(vo.getAuditState())); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchNewAddPage(Page page, LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + buildNewAddQueryWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoJoinService.pageJoin(page,wrapper); + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchPage(Page page, LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoJoinService.pageJoin(page,wrapper); + } + + @BuildChildrenRegionWrapper + public List searchCar(LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + buildQueryWrapper(wrapper,vehicleArchivesPageQuery); + return vehicleBaseInfoJoinService.listCarJoin(wrapper); + } + + + + /** + * 车辆审核列表 + * @param vehicleArchivesPageQuery + * @return + */ + public PageVo queryArchivesList(VehicleArchivesPageQuery vehicleArchivesPageQuery) { + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + VehicleManage context = (VehicleManage)AopContext.currentProxy(); + context.searchArchivesPage(page,wrapper,vehicleArchivesPageQuery); + PageVo pageVo = PageVo.empty(); + VUtils.isTrueOrFalse(0L == page.getTotal()).trueOrFalseHandler( + () -> {}, + () -> { + pageVo.setRecords(CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + return vo; + })); + pageVo.setTotal(page.getTotal()); + } + ); + + return pageVo; + } + + public PageVo queryArchivesListOpen(VehicleArchivesPageQuery vehicleArchivesPageQuery) { + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + buildWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoService.page(page,wrapper); + PageVo pageVo = PageVo.empty(); + VUtils.isTrueOrFalse(0L == page.getTotal()).trueOrFalseHandler( + () -> {}, + () -> { + pageVo.setRecords(CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + return vo; + })); + pageVo.setTotal(page.getTotal()); + } + ); + return pageVo; + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchArchivesPage(Page page, LambdaQueryWrapper wrapper, + VehicleArchivesPageQuery vehicleArchivesPageQuery) { + buildHasEquipmentQueryWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoJoinService.pageJoinWithEquipment(page,wrapper); + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchArchivesPageOpen(Page page, LambdaQueryWrapper wrapper, + VehicleArchivesPageQuery vehicleArchivesPageQuery) { + buildHasEquipmentQueryWrapper(wrapper,vehicleArchivesPageQuery); + vehicleBaseInfoJoinService.pageJoinWithEquipmentOpen(page,wrapper); + } + + /** + * 车辆待审核 + * @param vehicleAuditPageQuery + * @return + */ + public PageVo queryToBeAudit(VehicleAuditPageQuery vehicleAuditPageQuery) { + Page page = vehicleAuditPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + wrapper.eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT.getCode()); + VehicleManage context = (VehicleManage)AopContext.currentProxy(); + context.searchTobeAuditPage(page,wrapper,vehicleAuditPageQuery); + List data = CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + // 根据所属企业的区域Id展示所属区域 + Long companyId = vo.getCompanyId(); + if (Objects.nonNull(companyId)) { + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + if (Objects.nonNull(companyDto)) { + Long regionId = companyDto.getRegionId(); + if (Objects.nonNull(regionId)) { + vo.setRegionId(regionId); + vo.setRegionName(regionsCacheHelper.getDisplayName(regionId)); + } + } + } + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + vo.setVehicleStatus(v.getVehicleStatus()); + vo.setVehicleStatusName(CarStatusEnum.getDescByCode(v.getVehicleStatus())); + // 判断当前登录用户是否可以审核该车辆 + if (!checkCanAudit(vo)){ + vo.setCanAudit(Boolean.FALSE); + } + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + private boolean checkCanAudit(VehicleBaseVO vo) { + // 根据当前登录用户角色判断: + // 如果登录用户是区县散办管理员,且车辆所属区域有区县散办则可以审核; + // 如果登录用户是市级散办管理员,且车辆所属区域没有区县散办则可以审核; + UserBasicInfoVO userFullInfo = userInfoHelper.getUserFullInfo(); + Long roleId = userFullInfo.getRoleId(); + Long userRegionId = userFullInfo.getRegionId(); + Long regionId = vo.getRegionId(); + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId) + && regionId.equals(userRegionId)){ + return true; + } else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) { + // 如果是市级散办 + // 查询车辆所属区域是否为该市下属区域且无区县散办 + List childRegions = regionsCacheHelper.listChild(userRegionId); + if (CollUtil.isNotEmpty(childRegions) && childRegions.contains(regionId)){ + // 获取车辆所属区域的区县散办 + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + if (Objects.nonNull(regionDto)) { + String adminCompanyName = regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME; + // 根据区县散办所属管理企业名称查询管理企业,如果不存在,说明没有相应的区县散办 + Company company = companyService.getCompanyByCompanyNames(adminCompanyName); + if (Objects.isNull(company) || !company.getCompanyType().equals(CompanyTypeEnum.MANAGE_BU.getCode())){ + // 没有下属区县散办,则可以审核 + return true; + }else { + // 有下属区县散办,不可以审核 + return false; + } + } + } + // 该市没有下属子区域,可以审核 + return true; + } + return false; + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchTobeAuditPage(Page page, LambdaQueryWrapper wrapper, + VehicleAuditPageQuery vehicleAuditPageQuery) { + buildAuditQueryWrapper(wrapper,vehicleAuditPageQuery); + vehicleBaseInfoJoinService.pageJoin(page,wrapper); + } + + /** + * 车辆已审核 + * @param vehicleAuditPageQuery + * @return + */ + public PageVo queryAuditedList(VehicleAuditPageQuery vehicleAuditPageQuery) { + Page page = vehicleAuditPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class); + VehicleManage context = (VehicleManage)AopContext.currentProxy(); + context.searchAuditedPage(page,wrapper,vehicleAuditPageQuery); + List data = CollUtils.convert(page.getRecords(), v -> { + VehicleBaseVO vo = BeanUtil.copyProperties(v, VehicleBaseVO.class); + // 根据所属企业的区域Id展示所属区域 + Long companyId = vo.getCompanyId(); + if (Objects.nonNull(companyId)) { + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + if (Objects.nonNull(companyDto)) { + Long regionId = companyDto.getRegionId(); + if (Objects.nonNull(regionId)) { + vo.setRegionId(regionId); + vo.setRegionName(regionsCacheHelper.getDisplayName(regionId)); + } + } + } + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vo.getVehicleType())); + vo.setVehicleStatus(v.getVehicleStatus()); + vo.setVehicleStatusName(CarStatusEnum.getDescByCode(v.getVehicleStatus())); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchAuditedPage(Page page, LambdaQueryWrapper wrapper, + VehicleAuditPageQuery vehicleAuditPageQuery) { + buildAuditQueryWrapper(wrapper,vehicleAuditPageQuery); + wrapper.and(wp -> wp.eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()).or() + .eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_FAIL.getCode())); + vehicleBaseInfoJoinService.pageJoin(page,wrapper); + } + + /** + * 获取车辆详情 + * @param id + * @return + */ + public VehicleArchivesQueryDTO getDetails(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + VehicleManage context = (VehicleManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + NdVehicleBaseInfo ndVehicleBaseInfo = vehicleBaseInfoService.getOne(wrapper); + if (Objects.isNull(ndVehicleBaseInfo)){ + return null; + } + + VehicleArchivesQueryDTO query = BeanUtil.toBean(ndVehicleBaseInfo, VehicleArchivesQueryDTO.class); + Long useCompanyId = ndVehicleBaseInfo.getUseCompanyId(); + if (Objects.nonNull(useCompanyId)){ + CompanyDTO companyDto = companiesCacheHelper.getById(useCompanyId); + if (Objects.nonNull(companyDto)) { + query.setUseCompanyName(companyDto.getName()); + } + } + CodeUtil.searchCompanyNameAndRegionName(query); + NdUserInfo user = userCacheHelper.getById(ndVehicleBaseInfo.getAuditBy()); + query.setAuditBy(Objects.nonNull(user) ? user.getUsername() : (Objects.nonNull(ndVehicleBaseInfo.getAuditBy()) ? ndVehicleBaseInfo.getAuditBy() +StringUtils.EMPTY : VehicleContant.DEFAULT_NULL_AUDIT)); + query.setVehicleStatusName(CarStatusEnum.getDescByCode(ndVehicleBaseInfo.getVehicleStatus())); + Long operatorId = query.getOperatorId(); + if (Objects.nonNull(operatorId)) { + OperatorQueryDTO operatorQueryDto = operatorsCacheHelper.getById(operatorId); + if (Objects.nonNull(operatorQueryDto)) { + query.setOperatorName(operatorQueryDto.getName()); + } + } + return query; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdVehicleBaseInfo::getId,id); + } + + /** + * 查询车牌号 + * @param companyIds + * @return + */ + public List listByCompanyIds(List companyIds) { + List ndVehicleBaseInfos = vehicleBaseInfoJoinService.listJoin( + Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class).in(NdVehicleBaseInfoJoin::getCompanyId,companyIds)); + List query = CollUtils.convert(ndVehicleBaseInfos,w -> BeanUtil.copyProperties(w, VehicleCarPlateVO.class)); + return query; + } + + /** + * 处理 + * @param wrapper + * @param vehicleArchivesPageQuery + */ + private void buildQueryWrapper(LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + + wrapper.eq(NdVehicleBaseInfoJoin::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getCompanyId()),NdVehicleBaseInfoJoin::getCompanyId,vehicleArchivesPageQuery.getCompanyId()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleArchivesPageQuery.getCompanyName()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getUseCompanyName()),NdVehicleBaseInfoJoin::getUseCompanyName,vehicleArchivesPageQuery.getUseCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleStatus()),NdVehicleBaseInfoJoin::getVehicleStatus,vehicleArchivesPageQuery.getVehicleStatus()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getOperatorName()), NdVehicleBaseInfoJoin::getOperatorName, vehicleArchivesPageQuery.getOperatorName()) + //.eq(Objects.nonNull(vehicleArchivesPageQuery.getRegionId()),NdVehicleBaseInfoJoin::getRegionId,vehicleArchivesPageQuery.getRegionId()) + .eq(NdVehicleBaseInfoJoin::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn); + } + + /** + * 处理 + * @param wrapper + * @param vehicleArchivesPageQuery + */ + private void buildOtherWrapper(LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + + wrapper.eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getCompanyId()),NdVehicleBaseInfo::getCompanyId,vehicleArchivesPageQuery.getCompanyId()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfo::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getUseCompanyName()),NdVehicleBaseInfo::getUseCompanyName,vehicleArchivesPageQuery.getUseCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfo::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleStatus()),NdVehicleBaseInfo::getVehicleStatus,vehicleArchivesPageQuery.getVehicleStatus()) + //.eq(Objects.nonNull(vehicleArchivesPageQuery.getRegionId()),NdVehicleBaseInfo::getRegionId,vehicleArchivesPageQuery.getRegionId()) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfo::getUpdateOn); + } + + /** + * 处理 + * @param wrapper + * @param vehicleArchivesPageQuery + */ + private void buildNewAddQueryWrapper(LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + //if(Objects.nonNull(vehicleArchivesPageQuery.getAuditType())){ + // wrapper.eq(AuditStateEnum.AUDIT.getCode().equals(vehicleArchivesPageQuery.getAuditType()), NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT.getCode()) + // .and(AuditStateEnum.AUDIT_SUCCESS.getCode().equals(vehicleArchivesPageQuery.getAuditType()) || + // AuditStateEnum.AUDIT_FAIL.getCode().equals(vehicleArchivesPageQuery.getAuditType()), + // wp -> wp.eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + // .or().eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_FAIL.getCode())); + //} + wrapper.eq(NdVehicleBaseInfoJoin::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getRegionId()),NdVehicleBaseInfoJoin::getRegionId,vehicleArchivesPageQuery.getRegionId()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getAuditType()), NdVehicleBaseInfoJoin::getAuditState,vehicleArchivesPageQuery.getAuditType()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn); + } + + /** + * 处理 + * @param wrapper + * @param vehicleArchivesPageQuery + */ + private void buildWrapper(LambdaQueryWrapper wrapper, VehicleArchivesPageQuery vehicleArchivesPageQuery) { + if(Objects.nonNull(vehicleArchivesPageQuery.getAuditType())){ + wrapper.eq(AuditStateEnum.AUDIT.getCode().equals(vehicleArchivesPageQuery.getAuditType()), NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT.getCode()) + .and(AuditStateEnum.AUDIT_SUCCESS.getCode().equals(vehicleArchivesPageQuery.getAuditType()) || + AuditStateEnum.AUDIT_FAIL.getCode().equals(vehicleArchivesPageQuery.getAuditType()), + wp -> wp.eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .or().eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_FAIL.getCode())); + } + wrapper.eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getCompanyId()),NdVehicleBaseInfo::getCompanyId,vehicleArchivesPageQuery.getCompanyId()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfo::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getUseCompanyName()),NdVehicleBaseInfo::getUseCompanyName,vehicleArchivesPageQuery.getUseCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfo::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfo::getUpdateOn); + } + + private void buildHasEquipmentQueryWrapper(LambdaQueryWrapper wrapper, + VehicleArchivesPageQuery vehicleArchivesPageQuery) { + wrapper.eq(NdVehicleBaseInfoJoin::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleArchivesPageQuery.getCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + //要审核成功 并且审核通过才能进档案 + .eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getCompanyId()),NdVehicleBaseInfoJoin::getCompanyId, vehicleArchivesPageQuery.getCompanyId()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getOperatorName()), NdVehicleBaseInfoJoin::getOperatorName, vehicleArchivesPageQuery.getOperatorName()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn); + } + + /** + * 处理 + * @param wrapper + * @param vehicleAuditPageQuery + */ + private void buildAuditQueryWrapper(LambdaQueryWrapper wrapper, VehicleAuditPageQuery vehicleAuditPageQuery) { + wrapper.eq(NdVehicleBaseInfoJoin::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .like(StringUtils.isNotBlank(vehicleAuditPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleAuditPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleAuditPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleAuditPageQuery.getCompanyName()) + .eq(Objects.nonNull(vehicleAuditPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleAuditPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleAuditPageQuery.getAuditType()),NdVehicleBaseInfoJoin::getAuditState,vehicleAuditPageQuery.getAuditType()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn); + } + + public void exportNewAddBase(HttpServletResponse response, VehicleArchivesPageQuery archivesPageQuery) { + archivesPageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = queryNewAddList(archivesPageQuery); + List collect = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleBaseExportDTO.class)).collect(Collectors.toList()); + String fileName = "车辆信息"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), VehicleBaseExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void exportArchives(HttpServletResponse response, VehicleArchivesPageQuery archivesPageQuery) { + archivesPageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = queryList(archivesPageQuery); + List exportData = page.getRecords().stream() + .map(w -> BeanUtil.copyProperties(w, VehicleBaseVO.class)) + .collect(Collectors.toList()); + String fileName = "车辆档案信息"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), VehicleBaseExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(exportData); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void export(HttpServletResponse response, VehicleArchivesPageQuery archivesPageQuery) { + archivesPageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = queryArchivesList(archivesPageQuery); + List collect = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleBaseVO.class)).collect(Collectors.toList()); + String fileName = "车辆档案信息"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), VehicleBaseExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void exportAudit(HttpServletResponse response, VehicleAuditPageQuery auditPageQuery) { + auditPageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo toBePage = queryToBeAudit(auditPageQuery); + PageVo auditPage = queryAuditedList(auditPageQuery); + List toBeList = toBePage.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleBaseVO.class)).collect(Collectors.toList()); + List auditList = auditPage.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleBaseVO.class)).collect(Collectors.toList()); + String fileName = "车辆审核列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + String sheetNameToBe = "车辆待审核列表"; + String sheetNameAudited = "车辆已审核列表"; + try { + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build(); + //埋点基础信息 sheet + WriteSheet writeSheet = EasyExcel.writerSheet(0, sheetNameToBe) + .head(VehicleBaseExportDTO.class).build(); + excelWriter.write(toBeList, writeSheet); + //埋点数据转换信息 sheet + writeSheet = EasyExcel.writerSheet(1, sheetNameAudited) + .head(VehicleBaseExportDTO.class).build(); + excelWriter.write(auditList, writeSheet); + //埋点触发规则信息 sheet + excelWriter.finish(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + /** + * 根据车牌号和公司ID 获取车辆 信息 是唯一 + * @param carPlate + * @param companyId + * @return + */ + public NdVehicleBaseInfo queryByCarPlateAndCompanyId(String carPlate, Long companyId) { + return vehicleBaseInfoService.getOne(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate) + .eq(NdVehicleBaseInfo::getCompanyId, companyId)); + } + + public NdVehicleBaseInfo update(VehicleUpdateDTO data, Long userId) { + return vehicleBaseInfoService.update(data, userId); + } + + public NdVehicleBaseInfo save(VehicleSaveDTO data, Long userId) { + return vehicleBaseInfoService.save(data, userId); + } + + public Boolean removeByIdWithCache(List ids) { + return vehicleBaseInfoService.removeByIdWithCache(ids); + } + + public NdVehicleBaseInfo modifyAndUpdate(VehicleUpdateDTO data, Long userId) { + return vehicleBaseInfoService.modifyAndUpdate(data, userId); + } + + public void updateOnlineTime() { + // 获取所有车辆信息 + Map timeMap = vehicleBaseInfoService.list().stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 查出天表所有 累计在线的车辆 + VehicleOnlineStatusDay statusday = new VehicleOnlineStatusDay(); + statusday.setYear(String.valueOf(LocalDateTime.now().getYear())); + statusday.setMonth(String.valueOf(LocalDateTime.now().getMonthValue())); + statusday.setDay(String.valueOf(LocalDateTime.now().getDayOfMonth())); + List onlineDays = vehicleOnlineStatusDayService.listByReqInMonthTable(statusday); + Map onlineDayMap = onlineDays.stream().collect(Collectors.toMap(v -> v.getCarPlate() + v.getYear() + + v.getMonth() + v.getDay(), v -> v)); + + // 将天表在线数据按车牌号分组,获取每个车牌号最新的一条在线数据 + Map onlineStatusDayMap = onlineDays.stream().collect(Collectors.groupingBy(VehicleOnlineStatusDay::getCarPlate, + Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(VehicleOnlineStatusDay::getOnlineTime)), Optional::get))); + + // 遍历所有车牌号,如果天表中没有在线数据,需要到对应的GPS表中 + for (String carPlate : timeMap.keySet()) { + VehicleOnlineStatusDay vehicleOnlineStatusDay = onlineStatusDayMap.get(carPlate); + NdVehicleBaseInfo ndVehicleBaseInfo = timeMap.get(carPlate); + if (Objects.isNull(vehicleOnlineStatusDay)) { + ndVehicleBaseInfo.setLastOnlineTime(vehicleOnlineStatusDay.getOnlineTime()); + } + } + } + + public String cancelRelevance(Long id) { + NdVehicleBaseInfo baseInfo = vehicleBaseInfoService.getById(id); + if (Objects.isNull(baseInfo)){ + throw new BizException("车辆信息不存在!"); + } + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(NdVehicleBaseInfo.class); + updateWrapper.set(NdVehicleBaseInfo::getCompanyId, null) + .set(NdVehicleBaseInfo::getUseCompanyId, null) + .set(NdVehicleBaseInfo::getUseCompanyName, null) + .set(NdVehicleBaseInfo::getRegionId, null) + .set(NdVehicleBaseInfo::getRegionName, null) + .eq(NdVehicleBaseInfo::getId, baseInfo.getId()); + boolean update = vehicleBaseInfoService.update(updateWrapper); + if (update){ + return "取消关联成功!"; + } + return "取消关联失败!"; + } + + /** + * 批量查询 车辆信息 用车牌号 + * @param + * @return + */ + public List listByCarplate(ReqDataPO po) { + List carPlates = po.getCarPlates(); + if(CollUtil.isEmpty(carPlates)){ + return Collections.emptyList(); + } + List ndVehicleBaseInfos = vehicleBaseInfoJoinService.listJoin( + Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class).in(NdVehicleBaseInfoJoin::getCarPlate,carPlates)); + List query = CollUtils.convert(ndVehicleBaseInfos,w -> BeanUtil.copyProperties(w, VehicleBaseVO.class)); + return query; + } +} + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoJoinMapper.java new file mode 100644 index 0000000..f4c060e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoJoinMapper.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.car.vehicle.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +public interface VehicleBaseInfoJoinMapper extends BaseMapper { + + String QUERY_SQL = "SELECT b.*, c.name as company_name,o.name as operator_name, " + + "null as equipment_id FROM nd_vehicle_base_info AS b " + + "LEFT JOIN nd_company_info AS c ON b.company_id = c.id " + + "LEFT JOIN nd_operator_info AS o ON b.operator_id = o.id "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + + String QUERY_SQL_WITH_NO_COMPANY = "SELECT b.*, c.name as company_name,o.name as operator_name, " + + "null as equipment_id FROM nd_vehicle_base_info AS b " + + "LEFT JOIN nd_company_info AS c ON b.company_id = c.id " + + "LEFT JOIN nd_operator_info AS o ON b.operator_id = o.id where b.company_id is not null "; + String WRAPPER_NO_COMPANY_SQL = "SELECT * from ( " + QUERY_SQL_WITH_NO_COMPANY + ") AS q ${ew.customSqlSegment}"; + + String QUERY_SQL_WITH_EQUIPMENT = "SELECT" + + " b.*," + + " c.NAME AS company_name," + + " o.NAME AS operator_name," + + " null as equipment_id" + + " FROM " + + " nd_vehicle_base_info AS b" + + " LEFT JOIN nd_company_info AS c ON b.company_id = c.id" + + " LEFT JOIN nd_operator_info AS o ON b.operator_id = o.id" + + " where b.id in (select vehicle_id from nd_vehicle_equipment_info where equipment_function = 'video') "; + String WRAPPER_SQL_WITH_EQUIPMENT = "SELECT * from ( " + QUERY_SQL_WITH_EQUIPMENT + " ) AS q ${ew.customSqlSegment}"; + + String QUERY_SQL_WITH_NOT_EQUIPMENT = "SELECT" + + " b.*," + + " c.NAME AS company_name," + + " o.NAME AS operator_name," + + " null as equipment_id" + + " FROM " + + " nd_vehicle_base_info AS b" + + " LEFT JOIN nd_company_info AS c ON b.company_id = c.id" + + " LEFT JOIN nd_operator_info AS o ON b.operator_id = o.id" + + " where b.car_plate not in (select car_plate from nd_vehicle_equipment_info where equipment_function = 'video') "; + String WRAPPER_SQL_WITH_NOT_EQUIPMENT = "SELECT * from ( " + QUERY_SQL_WITH_NOT_EQUIPMENT + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoin(Page page, @Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + List listJoin(@Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + NdVehicleBaseInfoJoin oneJoin(@Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL_WITH_EQUIPMENT) + Page pageJoinWithEquipment(Page page,@Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL_WITH_EQUIPMENT) + NdVehicleBaseInfoJoin oneJoinWithEquipment(@Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL_WITH_NOT_EQUIPMENT) + Page pageJoinWithNotEquipment(Page page,@Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_NO_COMPANY_SQL) + List listCarJoin(@Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.java new file mode 100644 index 0000000..163a216 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.car.vehicle.mapper; + +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.vehicle.model.po.VehicleCompanyPO; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import com.ningdatech.carapi.homepage.entity.po.VehicleNumPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +public interface VehicleBaseInfoMapper extends BaseMapper { + + /** + * 获取车牌号 通过企业ID + * @param companyIds + * @return + */ + List getCarPlatesByCompanyIds(@Param("companyIds") List companyIds); + + List getZj(@Param("param") DataScreenParam param); + + List getCity(@Param("param") DataScreenParam param); + + List getDistrict(@Param("param") DataScreenParam param); + + VehicleNumPO searchVehicleNum(@Param("param") DataScreenParam param); + + Boolean updateOfflineNotInCarPlates(@Param("cars") List carsOnline); + + boolean batchUpdate(@Param("cars") List batchSaveCars); + + List getCarPlatesByUseCompanyId(Long companyId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.xml new file mode 100644 index 0000000..319282c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/mapper/VehicleBaseInfoMapper.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + update nd_vehicle_base_info + set status = 0,moving = 0 + where car_plate not in ( + + #{item} + + ) + + + + update nd_vehicle_base_info + set status = 0,moving = 0 + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfo.java new file mode 100644 index 0000000..be9e393 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfo.java @@ -0,0 +1,211 @@ +package com.ningdatech.carapi.car.vehicle.model; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import javax.validation.constraints.Size; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@TableName("nd_vehicle_base_info") +@ApiModel(value = "NdVehicleBaseInfo", description = "车辆档案-车辆基本信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleBaseInfo extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("车牌号") + @Size(max = 20, message = "车牌号不能超过20") + @TableField(value = "car_plate") + private String carPlate; + + @ApiModelProperty("自编号") + @Size(max = 30, message = "自编号长度不能超过30") + @TableField(value = "self_no") + private String selfNo; + + @ApiModelProperty("车辆颜色") + @TableField(value = "plate_color") + private String plateColor; + + @ApiModelProperty("所属企业ID") + @TableField(value = "company_id") + private Long companyId; + + @ApiModelProperty("车辆类型") + @TableField(value = "vehicle_type") + private Integer vehicleType; + + @ApiModelProperty("总质量 单位:吨") + @TableField(value = "standard_tonnage") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + @TableField(value = "engine_no") + private String engineNo; + + @ApiModelProperty("底盘号") + @TableField(value = "chassis_no") + private String chassisNo; + + @ApiModelProperty("运营商ID") + @TableField(value = "operator_id") + private Long operatorId; + + @ApiModelProperty("责任驾驶员一") + @TableField(value = "responsible_driver_first") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + @TableField(value = "responsible_driver_first_mobile") + private String responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + @TableField(value = "responsible_driver_second") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + @TableField(value = "responsible_driver_second_mobile") + private String responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + @TableField(value = "fuel_consumption_per") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + @TableField(value = "limited_speed") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + @TableField(value = "standard_oil_quantity") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + @TableField(value = "vehicle_length") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + @TableField(value = "service_time") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + @TableField(value = "service_time_interval") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + @TableField(value = "service_cycle") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + @TableField(value = "service_cycle_interval") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + @TableField(value = "service_fee_start") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + @TableField(value = "service_fee_end") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + @TableField(value = "fuel_level") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + @TableField(value = "road_transportation_num") + private String roadTransportationNum; + + @ApiModelProperty("审核状态 1.审核中 2.审核通过 3.审核不通过") + @TableField(value = "audit_state") + private Integer auditState; + + @ApiModelProperty("审核时间") + @TableField(value = "audit_time") + private LocalDateTime auditTime; + + @ApiModelProperty("审核人") + @TableField(value = "audit_by") + private Long auditBy; + + @ApiModelProperty("审核意见") + @TableField(value = "audit_mind") + private String auditMind; + + @ApiModelProperty("使用年限") + @TableField(value = "useful_life") + private Integer usefulLife; + + @ApiModelProperty("整备质量 吨") + @TableField(value = "self_weight") + private Double selfWeight; + + @ApiModelProperty("排放标准") + private String effluentDischargeStandard; + + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + @ApiModelProperty("车辆状态 0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车辆是否行驶 0没有行驶 1行驶中") + private Integer moving; + + @ApiModelProperty("是否删除 0未删除 1已删除") + private Integer deleted; + + @ApiModelProperty("使用企业ID") + private Long useCompanyId; + + @ApiModelProperty("使用企业名称") + private String useCompanyName; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("上次在线时间") + private LocalDateTime lastOnlineTime; + + @ApiModelProperty("上次修改前所属企业ID") + private Long beforeCompanyId; + + @ApiModelProperty("上次修改前使用企业ID") + private Long beforeUseCompanyId; + + @ApiModelProperty("附件") + private String appendix; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfoJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfoJoin.java new file mode 100644 index 0000000..7cf7eb5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/NdVehicleBaseInfoJoin.java @@ -0,0 +1,226 @@ +package com.ningdatech.carapi.car.vehicle.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@TableName("nd_vehicle_base_info") +@ApiModel(value = "NdVehicleBaseInfo", description = "车辆档案-车辆基本信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleBaseInfoJoin implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long createBy; + + private Long updateBy; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("车牌号") + @Size(max = 20, message = "车牌号不能超过20") + @TableField(value = "car_plate") + private String carPlate; + + @ApiModelProperty("自编号") + @Size(max = 30, message = "自编号长度不能超过30") + @TableField(value = "self_no") + private String selfNo; + + @ApiModelProperty("车辆颜色") + @TableField(value = "plate_color") + private String plateColor; + + @ApiModelProperty("所属企业ID") + @TableField(value = "company_id") + private Long companyId; + + @ApiModelProperty("所属企业名称") +// @TableField(exist = false) + private String companyName; + + @ApiModelProperty("行政区域id") + @TableField(value = "region_id") + private Long regionId; + + @ApiModelProperty("行政区域名称") + @TableField(exist = false) + private String regionName; + + @ApiModelProperty("车辆类型") + @TableField(value = "vehicle_type") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @TableField(exist = false) + private String vehicleTypeName; + + @ApiModelProperty("标准吨位 单位:吨") + @TableField(value = "standard_tonnage") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + @TableField(value = "engine_no") + private String engineNo; + + @ApiModelProperty("底盘号") + @TableField(value = "chassis_no") + private String chassisNo; + + @ApiModelProperty("运营商ID") + @TableField(value = "operator_id") + private Long operatorId; + + @ApiModelProperty("运营商名") +// @TableField(exist = false) + private String operatorName; + + @ApiModelProperty("责任驾驶员一") + @TableField(value = "responsible_driver_first") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + @TableField(value = "responsible_driver_first_mobile") + private String responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + @TableField(value = "responsible_driver_second") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + @TableField(value = "responsible_driver_second_mobile") + private String responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + @TableField(value = "fuel_consumption_per") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + @TableField(value = "limited_speed") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + @TableField(value = "standard_oil_quantity") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + @TableField(value = "vehicle_length") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + @TableField(value = "service_time") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + @TableField(value = "service_time_interval") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + @TableField(value = "service_cycle") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + @TableField(value = "service_cycle_interval") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + @TableField(value = "service_fee_start") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + @TableField(value = "service_fee_end") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + @TableField(value = "fuel_level") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + @TableField(value = "road_transportation_num") + private String roadTransportationNum; + + + @ApiModelProperty("审核状态 1.审核中 2.审核通过 3.审核不通过") + @TableField(value = "audit_state") + private Integer auditState; + + @ApiModelProperty("审核时间") + @TableField(value = "audit_time") + private LocalDateTime auditTime; + + + @ApiModelProperty("审核人") + @TableField(value = "audit_by") + private Long auditBy; + + @ApiModelProperty("审核意见") + @TableField(value = "audit_mind") + private String auditMind; + + @ApiModelProperty("排放标准") + @TableField(value = "effluent_discharge_standard") + private String effluentDischargeStandard; + + @ApiModelProperty("使用年限") + @TableField(value = "useful_life") + private Integer usefulLife; + + @ApiModelProperty("自重 吨") + @TableField(value = "self_weight") + private Double selfWeight; + + @ApiModelProperty("设备ID") + @TableField(value = "equipment_id") + private Long equipmentId; + + @ApiModelProperty("车辆状态 0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车辆是否行驶 0没有行驶 1行驶中") + private Integer moving; + + @ApiModelProperty("是否删除 0未删除 1已删除") + private Integer deleted; + + @ApiModelProperty("使用企业ID") + private Long useCompanyId; + + @ApiModelProperty("使用企业名称") + private String useCompanyName; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("上次在线时间") + private LocalDateTime lastOnlineTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesPageQuery.java new file mode 100644 index 0000000..f8f14ba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesPageQuery.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 车辆档案 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleArchivesPageQuery", description = "车辆档案") +public class VehicleArchivesPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 车牌号 + */ + @ApiModelProperty(value = "车牌号") + private String carPlate; + + /** + * 所属企业名 + */ + @ApiModelProperty(value = "所属企业名") + private String companyName; + + /** + * 使用企业ID + */ + @ApiModelProperty(value = "使用企业ID") + private Long useCompanyId; + + /** + * 使用企业名 + */ + @ApiModelProperty(value = "使用企业名") + private String useCompanyName; + + /** + * 所属企业ID + */ + @ApiModelProperty(value = "所属企业ID") + private Long companyId; + + /** + * 车辆类型 + */ + @ApiModelProperty(value = "车辆类型") + private Integer vehicleType; + + /** + * 所属区域id + */ + @ApiModelProperty(value = "所属区域id") + private Long regionId; + + + /** + * 运营商名 + */ + @ApiModelProperty(value = "运营商名") + private String operatorName; + + @ApiModelProperty("审核类型 1.待审核 2.已审核 3.审核不通过") + private Integer auditType; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("企业列表") + private List companyIdList; + + @ApiModelProperty("是否显示没有所属企业车辆") + private Boolean showWithoutCompany; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesQueryDTO.java new file mode 100644 index 0000000..434576e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleArchivesQueryDTO.java @@ -0,0 +1,166 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 车辆档案 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleArchivesQueryDTO", description = "车辆档案") +public class VehicleArchivesQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("自编号") + private String selfNo; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("所属企业名称") + private String companyName; + + @ApiModelProperty("行政区域id") + private Long regionId; + + @ApiModelProperty("行政区域") + private String regionName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("标准吨位 单位:吨") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + private String engineNo; + + @ApiModelProperty("底盘号") + private String chassisNo; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("责任驾驶员一") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + private Long responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + private Long responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + private String roadTransportationNum; + + @ApiModelProperty("审核状态 1.审核中 2.审核通过 3.审核不通过") + private Integer auditState; + + @ApiModelProperty("审核时间") + private LocalDateTime auditTime; + + @ApiModelProperty("审核人") + private String auditBy; + + @ApiModelProperty("审核意见") + private String auditMind; + + @ApiModelProperty("排放标准") + private String effluentDischargeStandard; + + @ApiModelProperty("使用年限") + private Integer usefulLife; + + @ApiModelProperty("自重 吨") + private Double selfWeight; + + @ApiModelProperty("车辆状态 0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车辆是否行驶 0没有行驶 1行驶中") + private Integer moving; + + @ApiModelProperty("是否删除 0未删除 1已删除") + private Integer deleted; + + @ApiModelProperty("使用企业ID") + private Long useCompanyId; + + @ApiModelProperty("使用企业名称") + private String useCompanyName; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("车辆状态名称") + private String vehicleStatusName; + + @ApiModelProperty("附件") + private String appendix; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditDTO.java new file mode 100644 index 0000000..56e2949 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditDTO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 车辆信息审核 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleAuditDTO", description = "车辆信息审核") +public class VehicleAuditDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "车俩ID",required = true) + @NotNull(message = "请传车辆id!") + private Long id; + + @ApiModelProperty(value = "审核状态 2.审核通过 3.审核不通过",required = true) + @NotNull(message = "请传审核状态!") + private Integer auditState; + + @ApiModelProperty(value = "审核意见") + private String auditMind; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditPageQuery.java new file mode 100644 index 0000000..d3fb5c0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleAuditPageQuery.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 实体类 + * 车辆审核 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleAuditPageQuery", description = "车辆审核") +public class VehicleAuditPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 车牌号 + */ + @ApiModelProperty(value = "车牌号") + private String carPlate; + + /** + * 所属企业名 + */ + @ApiModelProperty(value = "所属企业名") + private String companyName; + + /** + * 车辆类型 + */ + @ApiModelProperty(value = "车辆类型") + private Integer vehicleType; + + /** + * 所属区域id + */ + @ApiModelProperty(value = "所属区域id") + private Long regionId; + + @ApiModelProperty("审核类型 1.待审核 2.已审核 3.审核不通过") + private Integer auditType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleBaseExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleBaseExportDTO.java new file mode 100644 index 0000000..66fe041 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleBaseExportDTO.java @@ -0,0 +1,201 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@ApiModel(value = "VehicleBaseExportDTO", description = "车辆档案-车辆基本信息-导出") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleBaseExportDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @ExcelProperty("ID") + private Long id; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("自编号") + @ExcelProperty("自编号") + private String selfNo; + + @ApiModelProperty("车辆颜色") + @ExcelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("所属企业ID") + @ExcelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("驾驶员ID") + @ExcelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("所属企业名称") + @ExcelProperty("所属企业名称") + private String companyName; + + @ApiModelProperty("行政区域id") + @ExcelProperty("行政区域id") + private Long regionId; + + @ApiModelProperty("行政区域名称") + @ExcelProperty("行政区域名称") + private String regionName; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("标准吨位 单位:吨") + @ExcelProperty("标准吨位 单位:吨") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + @ExcelProperty("发动机号") + private String engineNo; + + @ApiModelProperty("底盘号") + @ExcelProperty("底盘号") + private String chassisNo; + + @ApiModelProperty("运营商ID") + @ExcelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + @ExcelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("责任驾驶员一") + @ExcelProperty("责任驾驶员一") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + @ExcelProperty("责任驾驶员一 电话") + private String responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + @ExcelProperty("责任驾驶员二") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + @ExcelProperty("责任驾驶员二 电话") + private String responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + @ExcelProperty("百公里油耗 单位: L/km") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + @ExcelProperty("限速值 公里/小时") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + @ExcelProperty("标准油量 L") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + @ExcelProperty("车身长度 cm") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + @ExcelProperty("保养时间") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + @ExcelProperty("保养时间周期 天") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + @ExcelProperty("保养里程 km") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + @ExcelProperty("保养时间周期 天") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + @ExcelProperty("服务费开始时间") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + @ExcelProperty("服务费结束时间") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + @ExcelProperty("燃油级别") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + @ExcelProperty("道路运证编号") + private String roadTransportationNum; + + @ApiModelProperty("审核状态 1.审核中 2.审核通过 3.审核不通过") + @ExcelProperty("审核状态 1.审核中 2.审核通过 3.审核不通过") + private Integer auditState; + + @ApiModelProperty("审核时间") + @ExcelProperty("审核时间") + private LocalDateTime auditTime; + + @ApiModelProperty("审核人") + @ExcelProperty("审核人") + private Long auditBy; + + @ApiModelProperty("审核意见") + @ExcelProperty("审核意见") + private String audiMind; + + @ApiModelProperty("排放标准") + @ExcelProperty("排放标准") + private String effluentDischargeStandard; + + @ApiModelProperty("自重 吨") + @ExcelProperty("自重 吨") + private Double selfWeight; + + @ApiModelProperty("车辆状态 0离线 1在线 2异常") + @ExcelProperty("车辆状态 0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车辆是否行驶 0没有行驶 1行驶中") + @ExcelProperty("车辆是否行驶 0没有行驶 1行驶中") + private Integer moving; + + @ApiModelProperty("使用企业") + @ExcelProperty("使用企业") + private String useCompanyName; + + @ApiModelProperty("车辆状态") + @ExcelProperty("车辆状态") + private String vehicleStatusName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleSaveDTO.java new file mode 100644 index 0000000..951febe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleSaveDTO.java @@ -0,0 +1,132 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 车辆信息 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleSaveDTO", description = "车辆信息保存") +public class VehicleSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("车牌号") + @NotEmpty(message = "请输入车牌号!") + private String carPlate; + + @ApiModelProperty("自编号") + private String selfNo; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("车辆类型") + @NotNull(message = "请选择车辆类型!") + private Integer vehicleType; + + @ApiModelProperty("标准吨位 单位:吨") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + private String engineNo; + + @ApiModelProperty("底盘号") + @NotBlank + private String chassisNo; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("责任驾驶员一") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + private String responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + private String responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + private String roadTransportationNum; + + @ApiModelProperty("排放标准") + private String effluentDischargeStandard; + + @ApiModelProperty("使用年限") + private Integer usefulLife; + + @ApiModelProperty("自重 吨") + private Double selfWeight; + + @ApiModelProperty("使用企业ID") + private Long useCompanyId; + + @ApiModelProperty("使用企业名称") + private String useCompanyName; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("附件") + private String appendix; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleUpdateDTO.java new file mode 100644 index 0000000..6af7c89 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleUpdateDTO.java @@ -0,0 +1,132 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 车辆信息 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleUpdateDTO", description = "车辆信编辑") +public class VehicleUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "请传id") + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("自编号") + private String selfNo; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("使用企业ID") + private Long useCompanyId; + + @ApiModelProperty("使用企业名称") + private String useCompanyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("标准吨位 单位:吨") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + private String engineNo; + + @ApiModelProperty("底盘号") + private String chassisNo; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("责任驾驶员一") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + private String responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + private String responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + private String roadTransportationNum; + + @ApiModelProperty("排放标准") + private String effluentDischargeStandard; + + @ApiModelProperty("使用年限") + private Integer usefulLife; + + @ApiModelProperty("自重 吨") + private Double selfWeight; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("附件") + private String appendix; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleViolationDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleViolationDTO.java new file mode 100644 index 0000000..df85e3f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/dto/VehicleViolationDTO.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.car.vehicle.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 车辆违章 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleViolationDTO", description = "车辆违章") +public class VehicleViolationDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "车牌号",required = true) + @NotBlank(message = "车牌号!") + private String carPlate; + + @ApiModelProperty(value = "违章类型 1.无证驾驶 2.闯红灯 3.超载 4.违规路段行驶 5.违规时间行驶") + private String violationType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/po/VehicleCompanyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/po/VehicleCompanyPO.java new file mode 100644 index 0000000..8564e46 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/po/VehicleCompanyPO.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.car.vehicle.model.po; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Classname VehicleCompanyPO + * @Description + * @Date 2022/10/26 11:05 + * @Created by PoffyZhang + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VehicleCompanyPO { + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("使用企业id") + private Long useCompanyId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("自编号") + private String selfNo; + + @ApiModelProperty("状态") + private Integer status; + + @ApiModelProperty("是否行驶") + private Integer moving; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + public String getVechileTypeName(){ + if(Objects.nonNull(this.vehicleType)){ + this.vehicleTypeName = VehicleTypeEnum.getDescByCode(this.vehicleType); + return this.vehicleTypeName; + } + return StringUtils.EMPTY; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleBaseVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleBaseVO.java new file mode 100644 index 0000000..712925e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleBaseVO.java @@ -0,0 +1,172 @@ +package com.ningdatech.carapi.car.vehicle.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@ApiModel(value = "VehicleBaseVO", description = "车辆档案-车辆基本信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleBaseVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("自编号") + private String selfNo; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("所属企业ID") + private Long companyId; + + @ApiModelProperty("使用企业ID") + private Long useCompanyId; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("所属企业名称") + private String companyName; + + @ApiModelProperty("使用企业名称") + private String useCompanyName; + + @ApiModelProperty("行政区域id") + private Long regionId; + + @ApiModelProperty("行政区域名称") + private String regionName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("标准吨位 单位:吨") + private Double standardTonnage; + + @ApiModelProperty("发动机号") + private String engineNo; + + @ApiModelProperty("底盘号") + private String chassisNo; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("责任驾驶员一") + private String responsibleDriverFirst; + + @ApiModelProperty("责任驾驶员一 电话") + private String responsibleDriverFirstMobile; + + @ApiModelProperty("责任驾驶员二") + private String responsibleDriverSecond; + + @ApiModelProperty("责任驾驶员二 电话") + private String responsibleDriverSecondMobile; + + @ApiModelProperty("百公里油耗 单位: L/km") + private Double fuelConsumptionPer; + + @ApiModelProperty("限速值 公里/小时") + private Double limitedSpeed; + + @ApiModelProperty("标准油量 L") + private Double standardOilQuantity; + + @ApiModelProperty("车身长度 cm") + private Double vehicleLength; + + @ApiModelProperty("保养时间") + private LocalDateTime serviceTime; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceTimeInterval; + + @ApiModelProperty("保养里程 km") + private Double serviceCycle; + + @ApiModelProperty("保养时间周期 天") + private Integer serviceCycleInterval; + + @ApiModelProperty("服务费开始时间") + private LocalDateTime serviceFeeStart; + + @ApiModelProperty("服务费结束时间") + private LocalDateTime serviceFeeEnd; + + @ApiModelProperty("燃油级别") + private String fuelLevel; + + @ApiModelProperty("道路运证编号") + private String roadTransportationNum; + + @ApiModelProperty("审核状态 1.审核中 2.审核通过 3.审核不通过") + private Integer auditState; + + @ApiModelProperty("审核状态名称 1.审核中 2.审核通过 3.审核不通过") + private String auditStateName; + + @ApiModelProperty("审核时间") + private LocalDateTime auditTime; + + @ApiModelProperty("审核人") + private Long auditBy; + + @ApiModelProperty("审核意见") + private String audiMind; + + @ApiModelProperty("排放标准") + private String effluentDischargeStandard; + + @ApiModelProperty("自重 吨") + private Double selfWeight; + + @ApiModelProperty("车辆状态 0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车辆是否行驶 0没有行驶 1行驶中") + private Integer moving; + + @ApiModelProperty("车辆状态") + private Integer vehicleStatus; + + @ApiModelProperty("车辆状态名称") + private String vehicleStatusName; + + @ApiModelProperty("是否可以审核") + private Boolean canAudit = Boolean.TRUE; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleCarPlateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleCarPlateVO.java new file mode 100644 index 0000000..1ff3a0b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/model/vo/VehicleCarPlateVO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.car.vehicle.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@ApiModel(value = "VehicleCarPlateVO", description = "车辆") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleCarPlateVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("所属企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoJoinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoJoinService.java new file mode 100644 index 0000000..ae7f97b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoJoinService.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.car.vehicle.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +public interface IVehicleBaseInfoJoinService extends IService { + + Page pageJoin(Page page, LambdaQueryWrapper wrapper); + Page pageJoinWithUseCompany(Page page, LambdaQueryWrapper wrapper); + Page pageOpenJoin(Page page, LambdaQueryWrapper wrapper); + + NdVehicleBaseInfoJoin oneJoin(LambdaQueryWrapper wrapper); + + Page pageJoinWithEquipment(Page page, LambdaQueryWrapper wrapper); + Page pageJoinWithEquipmentAndUseCompany(Page page, LambdaQueryWrapper wrapper); + + Page pageJoinWithEquipmentOpen(Page page, LambdaQueryWrapper wrapper); + + NdVehicleBaseInfoJoin oneJoinWithEquipment(LambdaQueryWrapper wrapper); + + List listJoin(LambdaQueryWrapper in); + + List listCarJoin(LambdaQueryWrapper in); + List listCarJoinWithUseCompany(LambdaQueryWrapper in); + + Page pageJoinWithNotEquipment(Page page, LambdaQueryWrapper wrapper); + Page pageJoinWithNotEquipmentAndUseCompany(Page page, LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoService.java new file mode 100644 index 0000000..b9d7415 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/IVehicleBaseInfoService.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.car.vehicle.service; + +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleAuditDTO; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleSaveDTO; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleUpdateDTO; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.vehicle.model.po.VehicleCompanyPO; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +public interface IVehicleBaseInfoService extends IService { + + NdVehicleBaseInfo save(VehicleSaveDTO vehicleSaveDTO, Long uerId); + + NdVehicleBaseInfo update(VehicleUpdateDTO vehicleUpdateDTO, Long uerId); + + Boolean removeByIdWithCache(List ids); + + Boolean audit(VehicleAuditDTO data, Long userId); + + Map listByCarNo(Collection carNos); + + List getCarPlatesByCompanyIds(List companyIds); + List getCarPlatesByUseCompanyId(Long companyId); + + List getZj(DataScreenParam param); + + List getCity(DataScreenParam param); + + List getDistrict(DataScreenParam param); + + NdVehicleBaseInfo modifyAndUpdate(VehicleUpdateDTO data, Long userId); + + Boolean updateOfflineNotInCarPlates(List carsOnline); + + boolean batchUpdate(List batchSaveCars,Integer batchSize); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoJoinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoJoinServiceImpl.java new file mode 100644 index 0000000..6280b05 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoJoinServiceImpl.java @@ -0,0 +1,104 @@ +package com.ningdatech.carapi.car.vehicle.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoJoinMapper; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoJoinService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class VehicleBaseInfoJoinServiceImpl extends ServiceImpl + implements IVehicleBaseInfoJoinService { + + private final VehicleBaseInfoJoinMapper vehicleBaseInfoJoinMapper; + + @Override + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL,wrapperIndex = 1) + public Page pageJoin(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoin(page,wrapper); + } + + @Override + public Page pageJoinWithUseCompany(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoin(page,wrapper); + } + + @Override + public Page pageOpenJoin(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoin(page,wrapper); + } + + @Override + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public NdVehicleBaseInfoJoin oneJoin(LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.oneJoin(wrapper); + } + + @Override + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL,wrapperIndex = 1) + public Page pageJoinWithEquipment(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoinWithEquipment(page,wrapper); + } + + @Override + public Page pageJoinWithEquipmentAndUseCompany(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoinWithEquipment(page,wrapper); + } + + @Override + public Page pageJoinWithEquipmentOpen(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoinWithEquipment(page,wrapper); + } + + @Override + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public NdVehicleBaseInfoJoin oneJoinWithEquipment(LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.oneJoinWithEquipment(wrapper); + } + + @Override + public List listJoin(LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.listJoin(wrapper); + } + + @Override + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL,wrapperIndex = 1) + public Page pageJoinWithNotEquipment(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoinWithNotEquipment(page,wrapper); + } + + @Override + public Page pageJoinWithNotEquipmentAndUseCompany(Page page, LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.pageJoinWithNotEquipment(page,wrapper); + } + + @Override + @LambdaDataScope + public List listCarJoin(LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.listCarJoin(wrapper); + } + + @Override + public List listCarJoinWithUseCompany(LambdaQueryWrapper wrapper) { + return vehicleBaseInfoJoinMapper.listCarJoin(wrapper); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoServiceImpl.java new file mode 100644 index 0000000..c43ef67 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/service/impl/VehicleBaseInfoServiceImpl.java @@ -0,0 +1,415 @@ +package com.ningdatech.carapi.car.vehicle.service.impl; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import com.ningdatech.carapi.car.equipment.mapper.NdVehicleEquipmentChannelsMapper; +import com.ningdatech.carapi.car.equipment.mapper.NdVehicleEquipmentInfoMapper; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleAuditDTO; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleSaveDTO; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleUpdateDTO; +import com.ningdatech.carapi.car.vehicle.model.po.VehicleCompanyPO; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.car.vehicle.utils.VinUtils; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.scheduler.enums.DataTypeEnum; +import com.ningdatech.carapi.scheduler.enums.OperatorTypeEnum; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class VehicleBaseInfoServiceImpl extends ServiceImpl + implements IVehicleBaseInfoService { + + private final VehicleBaseInfoMapper vehicleBaseInfoMapper; + private final NdVehicleEquipmentInfoMapper vehicleEquipmentInfoMapper; + private final NdVehicleEquipmentChannelsMapper vehicleEquipmentChannelsMapper; + + private final VehiclesCacheHelper vehiclesCacheHelper; + + private final CompaniesCacheHelper companiesCacheHelper; + + private final ApplicationContext applicationContext; + private final RegionsCacheHelper regionCacheHelper; + private final UserRoleService userRoleService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + AtomicReference removeFlag = new AtomicReference<>(true); + //只能删除 审核不成功的车辆 + ids.forEach(id -> { + NdVehicleBaseInfo vehicle = getById(id); + VUtils.isTrueFormat(Objects.isNull(vehicle)) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "该id车辆不存在 {}", id); + + VUtils.isTrueFormat(!AuditStateEnum.AUDIT_FAIL.getCode().equals(vehicle.getAuditState())) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "只有审核失败的车辆才能删除"); + + if (!removeById(id)) { + removeFlag.set(false); + return; + } + + //删除 车辆下的设备 + List ndVehicleEquipmentInfos = vehicleEquipmentInfoMapper.selectList( + Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class).eq(NdVehicleEquipmentInfo::getVehicleId, id)); + if (CollUtil.isNotEmpty(ndVehicleEquipmentInfos)) { + ndVehicleEquipmentInfos.forEach(equipment -> { + vehicleEquipmentChannelsMapper.delete(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class).eq(NdVehicleEquipmentChannels::getEquipmentId, equipment.getId())); + vehicleEquipmentInfoMapper.deleteById(equipment); + }); + } + //更新车辆缓存 + vehiclesCacheHelper.refresh(id); + }); + return removeFlag.get(); + } + + /** + * 车辆审核 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean audit(VehicleAuditDTO data, Long userId) { + VUtils.isTrue(!AuditStateEnum.AUDIT_SUCCESS.getCode().equals(data.getAuditState()) && + !AuditStateEnum.AUDIT_FAIL.getCode().equals(data.getAuditState())).throwMessage("请确认传入的审核code正确"); + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMapper.selectById(data.getId()); + VUtils.isTrueFormat(Objects.isNull(vehicleBaseInfo)) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "修改车辆 {} 为空", data.getId()); + VUtils.isTrueFormat(!AuditStateEnum.AUDIT.getCode().equals(vehicleBaseInfo.getAuditState())) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), "只能审核待审核的车辆 {}", data.getId()); + + vehicleBaseInfo.setAuditState(data.getAuditState()); + vehicleBaseInfo.setAuditBy(userId); + vehicleBaseInfo.setAuditTime(LocalDateTime.now()); + vehicleBaseInfo.setAuditMind(data.getAuditMind()); + //最后修改人 + vehicleBaseInfo.setUpdateBy(userId); + vehicleBaseInfo.setUpdateOn(LocalDateTime.now()); + if(updateById(vehicleBaseInfo)){ + // 如果审核通过 + if (AuditStateEnum.AUDIT_SUCCESS.getCode().equals(data.getAuditState())) { + return Boolean.TRUE; + } else if (AuditStateEnum.AUDIT_FAIL.getCode().equals(data.getAuditState())) { + // 审核不通过,车辆的所属企业和使用企业要恢复到提交审核前的状态, + // 防止使用企业和所属企业更新后,原企业无法重新提交 + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMapper.selectById(data.getId()); + Long beforeCompanyId = baseInfo.getBeforeCompanyId(); + Long beforeUseCompanyId = baseInfo.getBeforeUseCompanyId(); + + baseInfo.setCompanyId(beforeCompanyId); + baseInfo.setUseCompanyId(beforeUseCompanyId); + + if (Objects.nonNull(beforeUseCompanyId)) { + CompanyDTO companyDto = companiesCacheHelper.getById(beforeUseCompanyId); + baseInfo.setUseCompanyName(companyDto.getName()); + } + vehicleBaseInfoMapper.updateById(baseInfo); + } + } + return Boolean.FALSE; + } + + + /** + * 保存车辆 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public NdVehicleBaseInfo save(VehicleSaveDTO data, Long userId) { + Long companyId = LoginUserUtil.loginUserDetail().getCompanyId(); + checkNewCar(data.getCarPlate()); + //VUtils.isTrue(!VinUtils.isLegal(data.getChassisNo())).throwMessage("底盘号错误 请重新填入!"); + NdVehicleBaseInfo vehicleBaseInfo = BeanUtil.toBean(data, NdVehicleBaseInfo.class); + //创建人 最后修改人 + vehicleBaseInfo.setCreateBy(userId); + vehicleBaseInfo.setUpdateBy(userId); + vehicleBaseInfo.setAuditState(AuditStateEnum.AUDIT.getCode()); + vehicleBaseInfo.setCompanyId(companyId); + CompanyDTO company = companiesCacheHelper.getById(companyId); + VUtils.isTrue(Objects.isNull(company)).throwMessage("获取不到当前操作人的公司信息!"); + vehicleBaseInfo.setRegionId(company.getRegionId()); + CodeUtil.searchRegionName(vehicleBaseInfo); + if(save(vehicleBaseInfo)){ + vehiclesCacheHelper.refresh(vehicleBaseInfo.getId()); + } + return vehicleBaseInfo; + } + + private void checkCar(String oldCarPlate, String carPlate) { + // 如果提交的车牌号已经在审核中 + VUtils.isTrue(count(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT.getCode())) > 0) + .throwMessage("该车牌车辆待审核中 请勿重新提交!"); + // 如果修改信息修改了车牌号,校验车牌号是否已经存在 + // 如果提交的车牌号已经审核通过存在于系统中 + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMapper.selectOne(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate)); + String companyName = null; + if (Objects.nonNull(baseInfo)) { + Long companyId = baseInfo.getCompanyId(); + if (Objects.nonNull(companyId)) { + companyName = companiesCacheHelper.getNameById(companyId); + } + } + if (!carPlate.equals(oldCarPlate)) { + VUtils.isTrue(count(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode())) > 0) + .throwMessage("系统企业:" + companyName + "已有该车牌车辆 不能重复添加!"); + } + } + + private void checkNewCar(String carPlate) { + // 如果提交的车牌号已经在审核中 + VUtils.isTrue(count(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT.getCode())) > 0) + .throwMessage("该车牌车辆待审核中 请勿重新提交!"); + // 如果提交的车牌号审核不通过 + VUtils.isTrue(count(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_FAIL.getCode())) > 0) + .throwMessage("该车牌车辆审核不通过 请到车辆新增界面修改信息后重新提交!"); + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMapper.selectOne(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate)); + String companyName = null; + if (Objects.nonNull(baseInfo)) { + Long companyId = baseInfo.getCompanyId(); + if (Objects.nonNull(companyId)) { + companyName = companiesCacheHelper.getNameById(companyId); + } + } + // 如果提交的车牌号已经审核通过存在于系统中 + VUtils.isTrue(count(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).eq(NdVehicleBaseInfo::getCarPlate, carPlate) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode())) > 0) + .throwMessage("系统企业:" + companyName + "已有该车牌车辆 不能重复添加!"); + + } + + @Override + @Transactional(rollbackFor = Exception.class) + public NdVehicleBaseInfo update(VehicleUpdateDTO data, Long userId) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMapper.selectById(data.getId()); + VUtils.isTrueFormat(Objects.isNull(vehicleBaseInfo)) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), String.format("修改车辆%d 为空", data.getId())); + + VUtils.isTrueFormat(!AuditStateEnum.AUDIT_FAIL.getCode().equals(vehicleBaseInfo.getAuditState())) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), String.format("车辆状态为审核失败才能修改", data.getId())); + + VUtils.isTrue(StringUtils.isNotBlank(data.getCarPlate()) && !vehicleBaseInfo.getCarPlate().equals(data.getCarPlate()) && + count(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, data.getCarPlate())) > 0) + .throwMessage("此公司已经有该车牌车辆 不能重复添加!"); + + if(StringUtils.isNotBlank(data.getChassisNo())){ + VUtils.isTrue(!VinUtils.isLegal(data.getChassisNo())).throwMessage("底盘号错误 请重新填入!"); + } + + NdVehicleBaseInfo vehicle = BeanUtil.toBean(data, NdVehicleBaseInfo.class); + + //最后修改人 置为审核中 + vehicle.setAuditState(AuditStateEnum.AUDIT.getCode()); + vehicle.setUpdateBy(userId); + if(updateById(vehicle)){ + vehiclesCacheHelper.refresh(vehicle.getId()); + } + return vehicle; + } + + /** + * 根据企业ids 获取车牌号 + * + * @param companyIds + * @return + */ + @Override + public List getCarPlatesByCompanyIds(List companyIds) { + return vehicleBaseInfoMapper.getCarPlatesByCompanyIds(companyIds); + } + + /** + * 根据企业ID获取所属企业和使用企业为该企业的车牌号 + * + * @param companyId + * @return + */ + @Override + public List getCarPlatesByUseCompanyId(Long companyId) { + return vehicleBaseInfoMapper.getCarPlatesByUseCompanyId(companyId); + } + + @Override + @XmlDataScope + public List getZj(DataScreenParam param) { + return vehicleBaseInfoMapper.getZj(param); + } + + @Override + @XmlDataScope + public List getCity(DataScreenParam param) { + return vehicleBaseInfoMapper.getCity(param); + } + + @Override + @XmlDataScope + public List getDistrict(DataScreenParam param) { + return vehicleBaseInfoMapper.getDistrict(param); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public NdVehicleBaseInfo modifyAndUpdate(VehicleUpdateDTO data, Long userId) { + UserRole userRole = userRoleService.getOne(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getUserId, userId)); + if (Objects.isNull(userRole)){ + throw new BizException("当前登录用户角色不存在!"); + } + Long roleId = userRole.getRoleId(); + + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMapper.selectById(data.getId()); + String oldCarPlate = vehicleBaseInfo.getCarPlate(); + VUtils.isTrueFormat(Objects.isNull(vehicleBaseInfo)) + .throwMessage(ExceptionCode.OPERATION_EX.getCode(), String.format("修改车辆%d 为空", data.getId())); + + //if(StringUtils.isNotBlank(data.getChassisNo())){ + // VUtils.isTrue(!VinUtils.isLegal(data.getChassisNo())).throwMessage("底盘号错误 请重新填入!"); + //} + + //修改车牌号,原车辆的违法违章记录不变,以原车牌号为准,不用更新 + + // 先保存旧的所属企业和使用企业,防止填写错误,审核不通过,回显错误 + vehicleBaseInfo.setBeforeCompanyId(vehicleBaseInfo.getCompanyId()); + vehicleBaseInfo.setBeforeUseCompanyId(vehicleBaseInfo.getUseCompanyId()); + vehicleBaseInfoMapper.updateById(vehicleBaseInfo); + + // 更新编辑过之后的车辆信息 + NdVehicleBaseInfo vehicle = BeanUtil.toBean(data, NdVehicleBaseInfo.class); + // 如果修改了所属企业,车辆所属区域也要更新 + Long oldCompanyId = vehicleBaseInfo.getCompanyId(); + Long newCompanyId = vehicle.getCompanyId(); + if (Objects.isNull(oldCompanyId) || !newCompanyId.equals(oldCompanyId)){ + CompanyDTO companyDto = companiesCacheHelper.getById(newCompanyId); + if (Objects.nonNull(companyDto)) { + Long regionId = companyDto.getRegionId(); + if (Objects.nonNull(regionId)) { + vehicle.setRegionId(regionId); + vehicle.setRegionName(regionCacheHelper.getDisplayName(regionId)); + } + } + } + + String carPlate = vehicle.getCarPlate(); + checkCar(oldCarPlate,carPlate); + // 最后修改人 + // 修改后,车辆审核状态变更为待审核 + // 如果登录用户为超管、市、区县散办不需要更改车辆状态为待审核 + if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId) || + UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)) { + vehicle.setAuditState(AuditStateEnum.AUDIT.getCode()); + }else if(Objects.nonNull(vehicleBaseInfo.getAuditState()) && + AuditStateEnum.AUDIT_FAIL.getCode().equals(vehicleBaseInfo.getAuditState())){ + //另外一种情况 不满足以上情况 但是审核失败需要重新提交的 + vehicle.setAuditState(AuditStateEnum.AUDIT.getCode()); + } + vehicle.setUpdateBy(userId); + if(updateById(vehicle)){ + vehiclesCacheHelper.refresh(vehicle.getId()); + } + return vehicle; + } + + @Override + public Boolean updateOfflineNotInCarPlates(List carsOnline) { + return vehicleBaseInfoMapper.updateOfflineNotInCarPlates(carsOnline); + } + + @Override + public boolean batchUpdate(List batchSaveCars,Integer batchSize) { + if (CollectionUtils.isEmpty(batchSaveCars)) { + return false; + } + List infos = Lists.newArrayList(); + for (NdVehicleBaseInfo batchSaveCar : batchSaveCars) { + NdVehicleBaseInfo car = new NdVehicleBaseInfo(); + car.setId(batchSaveCar.getId()); + car.setCarPlate(batchSaveCar.getCarPlate()); + car.setStatus(batchSaveCar.getStatus()); + car.setLastOnlineTime(batchSaveCar.getLastOnlineTime()); + car.setUpdateOn(batchSaveCar.getUpdateOn()); + infos.add(car); + // 每当达到批次大小时就进行一次更新 + if (infos.size() == batchSize) { + updateBatchById(infos); + infos.clear(); + } + } + // 处理剩余不足批次大小的数据 + if (!infos.isEmpty()) { + updateBatchById(infos); + return true; + } + return false; + } + + @Override + public Map listByCarNo(Collection carNos) { + if (CollectionUtils.isEmpty(carNos)) { + return Collections.emptyMap(); + } + LambdaQueryWrapper query = Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .in(NdVehicleBaseInfo::getCarPlate, carNos) + .eq(NdVehicleBaseInfo::getAuditState, 2); + List list = this.list(query); + return CollUtils.listToMap(this.list(query), NdVehicleBaseInfo::getCarPlate); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/utils/VinUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/utils/VinUtils.java new file mode 100644 index 0000000..5bb77c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/vehicle/utils/VinUtils.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.car.vehicle.utils; + +import java.util.HashMap; +import java.util.Map; + +public class VinUtils { + public static Map kv = new HashMap<>(); + + public static Map wv = new HashMap<>(); + + static{ + kv.put('a',1); + kv.put('b', 2); + kv.put('c', 3); + kv.put('d', 4); + kv.put('e', 5); + kv.put('f', 6); + kv.put('g', 7); + kv.put('h', 8); + kv.put('j', 1); + kv.put('k', 2); + kv.put('l', 3); + kv.put('m', 4); + kv.put('n', 5); + kv.put('p', 7); + kv.put('q', 8); + kv.put('r', 9); + kv.put('s', 2); + kv.put('t', 3); + kv.put('u', 4); + kv.put('v', 5); + kv.put('w', 6); + kv.put('x', 7); + kv.put('y', 8); + kv.put('z', 9); + kv.put('0',0); + kv.put('1',1); + kv.put('2',2); + kv.put('3',4); + kv.put('4',4); + kv.put('5',5); + kv.put('6',6); + kv.put('7',7); + kv.put('8',8); + kv.put('9',9); + + wv.put(1, 8); + wv.put(2, 7); + wv.put(3, 6); + wv.put(4, 5); + wv.put(5, 4); + wv.put(6, 3); + wv.put(7, 2); + wv.put(8, 10); + wv.put(10, 9); + wv.put(11, 8); + wv.put(12, 7); + wv.put(13, 6); + wv.put(14, 5); + wv.put(15, 4); + wv.put(16, 3); + wv.put(17, 2); + }; + + public final static boolean isLegal(String vin) { + if (vin == null) { + return false; + } else if (vin.trim().length() == 17) { + vin = vin.trim().toLowerCase(); + char[] codes = vin.toCharArray(); + int resultInCode = 0; + if ("0123456789".contains(vin.subSequence(8, 9))) { + resultInCode = Integer.valueOf(vin.subSequence(8, 9).toString()); + } else { + return false; + } + int total = 0; + for (int i = 1; i < codes.length + 1; i++) { + char code = codes[i - 1]; + if (kv.containsKey(code)) { + if (i == 9) { + continue; + } else { + total += kv.get(code) * wv.get(i); + } + } else { + return false; + } + } + return resultInCode == total % 11; + } else { + return false; + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/controller/VideoMonitorController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/controller/VideoMonitorController.java new file mode 100644 index 0000000..6b2a7b7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/controller/VideoMonitorController.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.car.video.controller; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.car.position.model.vo.DeviceVO; +import com.ningdatech.carapi.car.video.manage.VideoMonitorManage; +import com.ningdatech.carapi.car.video.model.dto.PlaybackVideoParamDTO; +import com.ningdatech.carapi.car.video.model.dto.PlaybackVideoStartParamDTO; +import com.ningdatech.carapi.car.video.model.vo.PlaybackVideoVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * @author Poffy Zhang + * @date 2022/11/01 上午10:25 + */ + +@RestController +@RequestMapping(value = "/api/v1/car-manage/video-monitor") +@Api(tags = "车辆管理-视频监控") +@Validated +@RequiredArgsConstructor +public class VideoMonitorController { + + private final VideoMonitorManage videoMonitorManage; + + @ApiOperation("获取某辆车在线的设备") + @GetMapping("/get-online-devices/{carPlate}") + public List getOnlineDevices(@Valid @PathVariable String carPlate) { + return videoMonitorManage.getOnlineDevices(carPlate); + } + + @ApiOperation("开始预览设备") + @PostMapping("/start-play/{deviceId}") + @WebLog + public JSONObject startPlay(@Valid @PathVariable String deviceId) { + return videoMonitorManage.startPlay(deviceId); + } + + @ApiOperation("结束预览设备") + @PostMapping("/stop-play/{deviceId}") + @WebLog + public void stopPlay(@Valid @PathVariable String deviceId) { + videoMonitorManage.stopPlay(deviceId); + } + + @ApiOperation("获取回放视频列表") + @GetMapping("/playback-videos") + @WebLog + public List playBackVideos(@Valid @ModelAttribute PlaybackVideoParamDTO param) { + return videoMonitorManage.playBackVideos(param); + } + + @ApiOperation("开始播放回放流视频") + @PostMapping("/start-playback") + @WebLog + public JSONObject startPlayBack(@Valid @RequestBody PlaybackVideoStartParamDTO param) { + return videoMonitorManage.startPlayBack(param); + } + + @ApiOperation("结束播放回放流视频") + @PostMapping("/stop-playback/{streamId}") + @WebLog + public JSONObject stopPlayBack(@Valid @PathVariable String streamId) { + return videoMonitorManage.stopPlayBack(streamId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/manage/VideoMonitorManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/manage/VideoMonitorManage.java new file mode 100644 index 0000000..9f25596 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/manage/VideoMonitorManage.java @@ -0,0 +1,246 @@ +package com.ningdatech.carapi.car.video.manage; + +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.carapi.car.equipment.manage.VehicleEquipmentManage; +import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentQueryDTO; +import com.ningdatech.carapi.car.equipment.service.IVehicleEquipmentNoService; +import com.ningdatech.carapi.car.position.contants.PositionContant; +import com.ningdatech.carapi.car.position.model.vo.DeviceVO; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.car.video.model.dto.PlaybackVideoParamDTO; +import com.ningdatech.carapi.car.video.model.dto.PlaybackVideoStartParamDTO; +import com.ningdatech.carapi.car.video.model.vo.PlaybackVideoVO; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author PoffyZhang + * @date 2022/11/1 上午11:18 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class VideoMonitorManage { + + private final VehicleEquipmentManage vehicleEquipmentManage; + + private final RestTemplate restTemplate; + + private final VehiclesCacheHelper vehiclesCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final IVehicleEquipmentNoService vehicleEquipmentNoService; + + @Value("${vedio.host}") + private String HOST; + + /** + * 实时视频 + * @param carPlate + * @return + */ + public List getOnlineDevices(String carPlate) { + //1.先获取 该车牌号的 所有视频设备 + //List equipmentByCarPlate = vehicleEquipmentManage.getEquipmentByCarPlate(carPlate); + List equipmentByCarPlate = vehicleEquipmentNoService.list(Wrappers.lambdaQuery(VehicleEquipmentNo.class) + .eq(VehicleEquipmentNo::getCarPlate, carPlate)); + if(CollUtil.isEmpty(equipmentByCarPlate)){ + return Collections.emptyList(); + } + String devicesId = equipmentByCarPlate.stream() + .map(VehicleEquipmentNo::getDeviceId) + .collect(Collectors.joining(",")); + return equipmentByCarPlate.stream().map(o -> { + DeviceVO deviceVO = new DeviceVO(); + deviceVO.setDeviceId(o.getDeviceId()); + deviceVO.setName(o.getDeviceName()); + deviceVO.setStatus(o.getStatus()); + return deviceVO; + }).collect(Collectors.toList()); + + //String devicesId = equipmentByCarPlate.stream() + // .map(VehicleEquipmentQueryDTO::getEquipmentNo) + // .collect(Collectors.joining(",")); + + //return equipmentByCarPlate.stream().map(o -> { + // DeviceVO deviceVO = new DeviceVO(); + // deviceVO.setDeviceId(o.getEquipmentNo()); + // deviceVO.setName(o.getName()); + // return deviceVO; + //}).collect(Collectors.toList()); + } + + public JSONObject startPlay(String deviceId) { + String url = String.format("%s%s/start",String.format(PositionContant.STREAM_URL,HOST),deviceId); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.valueOf("application/json")); + HttpEntity requestEntity = new HttpEntity(String.format(""), headers); + log.info("vedio url : {}",url); + try{ + JSONObject response = restTemplate.postForObject(url,requestEntity,JSONObject.class); + log.info("vedio url response : {}",response); + if(Objects.isNull(response)){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),"开始播放流失败 网络异常"); + } + log.info("requst start play datas :{}", JSON.toJSONString(response)); + Integer statusCode = response.getInteger("status_code"); + if(0 != statusCode){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),response.getString("message")); + } + JSONObject jsonObject = response.getJSONObject("result"); + return jsonObject; + }catch (Exception e){ + log.error("此次请求有异常 :" + deviceId,e); + throw new BizException("此设备不在线 :" + deviceId); + } + } + + public void stopPlay(String deviceId) { + String url = String.format( "%s%s/stop",String.format(PositionContant.STREAM_URL,HOST),deviceId); + JSONObject response = restTemplate.postForObject(url,null,JSONObject.class); + if(Objects.isNull(response)){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),"关闭流 网络异常"); + } + log.info("requst stop play datas :{}", JSON.toJSONString(response)); + Integer statusCode = response.getInteger("status_code"); + if (statusCode == 0){ + log.info("关闭流成功"); + }else{ + log.info("关闭流失败"); + } + } + + /** + * 回放视频 + * @param param + * @return + */ + public List playBackVideos(PlaybackVideoParamDTO param) { + List res = Lists.newArrayList(); + // 判断车辆是否在登录用户的区域权限内 + NdVehicleBaseInfo car = vehiclesCacheHelper.getByCarPlate(param.getCarPlate()); + if (Objects.isNull(car)){ + return Collections.emptyList(); + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + VideoMonitorManage context = (VideoMonitorManage) AopContext.currentProxy(); + context.buildQuery(wrapper, car.getId()); + NdVehicleBaseInfo ndVehicleBaseInfo = vehicleBaseInfoService.getOne(wrapper); + if (Objects.isNull(ndVehicleBaseInfo)){ + return Collections.emptyList(); + } + //1.先获取 该车牌号的 所有设备 + List equipmentByCarPlate = vehicleEquipmentManage.getEquipmentByCarPlate(param.getCarPlate()); + if(CollUtil.isEmpty(equipmentByCarPlate)){ + return Collections.emptyList(); + } + //2.请求回放视频接口 + for(VehicleEquipmentQueryDTO equipment : equipmentByCarPlate){ + if(StringUtils.isBlank(equipment.getEquipmentNo())){ + log.info("这个设备 {} 没有设备编号",equipment.getId()); + continue; + } + Map map = Maps.newConcurrentMap(); + map.put("deviceId",equipment.getEquipmentNo()); + map.put("start", param.getStart()); + map.put("end",param.getEnd()); + map.put("host",HOST); + JSONObject response = restTemplate.getForObject(PositionContant.RECORD_LIST_URL,JSONObject.class,map); + if(Objects.isNull(response)){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),"回放视频数据请求失败 网络异常"); + } + log.info("requst playback datas :{}", JSON.toJSONString(response)); + Integer statusCode = response.getInteger("status_code"); + //先不返回异常 + if(0 != statusCode){ + log.warn("运营商的历史回放视频 有异常 {}, :{}",equipment.getEquipmentNo(),response.getString("message")); + } + JSONObject resultJson = response.getJSONObject("result"); + if(Objects.isNull(resultJson)){ + continue; + } + + JSONArray list = resultJson.getJSONArray("list"); + if(Objects.isNull(list) || list.size() == 0){ + continue; + } + + list.stream().forEach(o -> { + LinkedHashMap j = (LinkedHashMap)o; + Object items = j.get("items"); + if(Objects.isNull(items)){ + return; + } + List itemList = (List)items; + itemList.stream().forEach(item -> { + PlaybackVideoVO vo = new PlaybackVideoVO(equipment.getEquipmentNo(),equipment.getName(), VehicleContant.DEFAULT_CHANNEL_NAME + ,Long.valueOf(String.valueOf(item.get("start"))),Long.valueOf(String.valueOf(item.get("end")))); + res.add(vo); + }); + }); + } + return res; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdVehicleBaseInfo::getId,id); + } + + public JSONObject startPlayBack(PlaybackVideoStartParamDTO param) { + String url = String.format("%s%s/start?start=%s&end=%s", + String.format(PositionContant.RECORD_URL,HOST),param.getDeviceId(),param.getStart(),param.getEnd()); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.valueOf("application/json")); + HttpEntity requestEntity = new HttpEntity(String.format(""), headers); + JSONObject response = restTemplate.postForObject(url,requestEntity,JSONObject.class); + if(Objects.isNull(response)){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),"开始播放流失败 网络异常"); + } + log.info("requst start playback datas :{}", JSON.toJSONString(response)); + Integer statusCode = response.getInteger("status_code"); + if(0 != statusCode){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),response.getString("message")); + } + JSONObject jsonObject = response.getJSONObject("result"); + return jsonObject; + } + + public JSONObject stopPlayBack(String streamId) { + String url = String.format("%s%s/stop",String.format(PositionContant.RECORD_URL,HOST),streamId); + JSONObject response = restTemplate.postForObject(url,null,JSONObject.class); + if(Objects.isNull(response)){ + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(),"关闭流 网络异常"); + } + log.info("requst stop playback datas :{}", JSON.toJSONString(response)); + JSONObject jsonObject = response.getJSONObject("result"); + return jsonObject; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoParamDTO.java new file mode 100644 index 0000000..a86c3c9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoParamDTO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.car.video.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * 回放视频传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@Builder +@ApiModel(value = "PlaybackVideoParamDTO", description = "回放视频传参") +public class PlaybackVideoParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间时间戳") + @NotNull(message = "请输入开始时间") + private Long start; + + @ApiModelProperty("结束时间时间戳") + @NotNull(message = "请输入结束时间") + private Long end; + + @ApiModelProperty("车牌号") + @NotBlank(message = "请输入车牌号") + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoStartParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoStartParamDTO.java new file mode 100644 index 0000000..aa3bb9f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/dto/PlaybackVideoStartParamDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.car.video.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * 开始回放视频传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "PlaybackVideoStartParamDTO", description = "开始回放视频传参") +public class PlaybackVideoStartParamDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间时间戳") + @NotNull(message = "请输入开始时间") + private Long start; + + @ApiModelProperty("结束时间时间戳") + @NotNull(message = "请输入结束时间") + private Long end; + + @ApiModelProperty("设备id") + @NotBlank(message = "设备id") + private String deviceId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/vo/PlaybackVideoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/vo/PlaybackVideoVO.java new file mode 100644 index 0000000..9dc25d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/car/video/model/vo/PlaybackVideoVO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.car.video.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author PoffyZhang + * @date 2022/11/07 下午2:10 + */ + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(description = "回放视频-VO") +public class PlaybackVideoVO { + + @ApiModelProperty("设备ID") + private String deviceId; + + @ApiModelProperty("设备名称") + private String deviceName; + + @ApiModelProperty("通道名称") + private String channelName; + + @ApiModelProperty("流开始时间戳") + private Long start; + + @ApiModelProperty("流结束时间戳") + private Long end; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntity.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntity.java new file mode 100644 index 0000000..8cac57f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntity.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.common.aop; + +import java.lang.annotation.*; + +/** + * @Classname BuildChildrenRegion + * @Description + * @Date 2022/11/11 15:34 + * @Created by PoffyZhang + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface BuildChildrenRegionEntity { + + //要生成地区的实体下标 + int entityIndex() default 0; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntityAspect.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntityAspect.java new file mode 100644 index 0000000..f8049f4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionEntityAspect.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.common.aop; + +import cn.hutool.core.collection.CollUtil; +import com.google.common.collect.Lists; +import com.ningdatech.carapi.sys.contants.RegionContant; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Objects; + +/** + * @program: + * @description: 生成子区域 + * BuildChildrenRegionAspect + * @author: PoffyZhang + * @created: 2022/11/11 09:12 + */ +@Aspect +@Component +@Slf4j +@AllArgsConstructor +@Order(10) +public class BuildChildrenRegionEntityAspect { + + @Autowired + private RegionsCacheHelper regionsCacheHelper; + + @Pointcut("@annotation(com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity)") + public void buildChildrenRegionEntityAspect() { + + } + + @Before("buildChildrenRegionEntityAspect() && @annotation(buildChildrenRegionEntity)") + public void before(JoinPoint joinPoint, BuildChildrenRegionEntity buildChildrenRegionEntity) throws Throwable { + + Object entity = joinPoint.getArgs()[buildChildrenRegionEntity.entityIndex()]; + + if (Objects.isNull(entity)) { + return; + } + + Class clazz = entity.getClass(); + Method getRegionId = clazz.getMethod("getRegionId"); + Long regionId = (Long) getRegionId.invoke(entity); + if (Objects.nonNull(regionId)) { + RegionDTO currRegion = regionsCacheHelper.getByRegionId(regionId); + List regionIds; + if (currRegion.getRegionCode().equals(currRegion.getParentCode()) + || currRegion.getRegionLevel().equals(RegionContant.THIRD_LEVEL)) { + regionIds = Lists.newArrayList(regionId); + } else { + regionIds = regionsCacheHelper.listChildRegionId(regionId, false, true); + } + if (CollUtil.isNotEmpty(regionIds)) { + Field field = clazz.getDeclaredField("regionIds"); + field.setAccessible(true); + field.set(entity, regionIds); + } + } + + } + + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapper.java new file mode 100644 index 0000000..a198fa6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapper.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.common.aop; + +import java.lang.annotation.*; + +/** + * @Classname BuildChildrenRegionWrapper + * @Description + * @Date 2022/11/11 15:34 + * @Created by PoffyZhang + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface BuildChildrenRegionWrapper { + + //要生成地区的wrapper下标 + int wrapperIndex() default 0; + + int entityIndex() default 1; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapperAspect.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapperAspect.java new file mode 100644 index 0000000..67d312f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/aop/BuildChildrenRegionWrapperAspect.java @@ -0,0 +1,63 @@ +package com.ningdatech.carapi.common.aop; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ningdatech.carapi.datascope.model.DataScopeEntity; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Objects; + +/** + * @program: + * @description: 生成子区域 + * BuildChildrenRegionAspect + * @author: PoffyZhang + * @created: 2022/11/11 09:12 + */ +@Aspect +@Component +@Slf4j +@AllArgsConstructor +@Order(10) +public class BuildChildrenRegionWrapperAspect { + + @Autowired + private RegionsCacheHelper regionsCacheHelper; + + @Pointcut("@annotation(com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper)") + public void buildChildrenRegionWrapperAspect() { + + } + + @Before("buildChildrenRegionWrapperAspect() && @annotation(buildChildrenRegionWrapper)") + public void before(JoinPoint joinPoint, BuildChildrenRegionWrapper buildChildrenRegionWrapper) throws Throwable { + + LambdaQueryWrapper wrapper = (LambdaQueryWrapper) joinPoint.getArgs()[buildChildrenRegionWrapper.wrapperIndex()]; + Object entity = joinPoint.getArgs()[buildChildrenRegionWrapper.entityIndex()]; + + if(Objects.isNull(wrapper)){ + return; + } + + Class clazz = entity.getClass(); + Method getRegionId = clazz.getMethod("getRegionId"); + Long regionId = (Long) getRegionId.invoke(entity); + if(Objects.nonNull(regionId)){ + List regionIds = regionsCacheHelper.listChildRegionId(regionId); + if (CollUtil.isNotEmpty(regionIds)){ + wrapper.in(CollUtil.isNotEmpty(regionIds), DataScopeEntity::getRegionId,regionIds); + } + } + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseDTO.java new file mode 100644 index 0000000..de976c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.common.base; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.sql.Timestamp; + +/** + * @author qinxianyun + */ +@Getter +@Setter +public class BaseDTO implements Serializable { + + private String createBy; + + private String updateBy; + + private Timestamp createTime; + + private Timestamp updateTime; + + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this); + Field[] fields = this.getClass().getDeclaredFields(); + try { + for (Field f : fields) { + f.setAccessible(true); + builder.append(f.getName(), f.get(this)).append("\n"); + } + } catch (Exception e) { + builder.append("toString builder encounter an error"); + } + return builder.toString(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseEntity.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseEntity.java new file mode 100644 index 0000000..c63f985 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseEntity.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.common.base; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + * 通用字段, is_del 根据需求自行添加 + * @author PoffyZhang + */ +@Getter +@Setter +public class BaseEntity implements Serializable { + + @ApiModelProperty("创建人userId") + protected Long createBy; + + @ApiModelProperty("最后修改人userId") + protected Long updateBy; + + @ApiModelProperty("创建时间") + protected LocalDateTime createOn; + + @ApiModelProperty("修改时间") + protected LocalDateTime updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseMapper.java new file mode 100644 index 0000000..e7a1e50 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/base/BaseMapper.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.common.base; + +import java.util.List; + +/** + * @author qinxianyun + */ +public interface BaseMapper { + + /** + * DTO转Entity + * @param dto / + * @return / + */ + E toEntity(D dto); + + /** + * Entity转DTO + * @param entity / + * @return / + */ + D toDto(E entity); + + /** + * DTO集合转Entity集合 + * @param dtoList / + * @return / + */ + List toEntity(List dtoList); + + /** + * Entity集合转DTO集合 + * @param entityList / + * @return / + */ + List toDto(List entityList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/BeanConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/BeanConfig.java new file mode 100644 index 0000000..146aad5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/BeanConfig.java @@ -0,0 +1,109 @@ +package com.ningdatech.carapi.common.config; + +import com.ningdatech.cache.properties.CustomCacheProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.Header; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicHeader; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.RestTemplate; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @Classname BeanConfig + * @Description + * @Date 2022/10/26 9:42 + * @Created by PoffyZhang + */ +@Configuration +@Slf4j +@RequiredArgsConstructor +public class BeanConfig { + private final CustomCacheProperties cacheProperties; + + @Bean + public RestTemplate restTemplate() { + // 添加内容转换器,使用默认的内容转换器 + RestTemplate restTemplate = new RestTemplate(httpRequestFactory()); + // 设置编码格式为UTF-8,解决中文乱码问题 + List> converterList = restTemplate.getMessageConverters(); + HttpMessageConverter converterTarget = null; + for (HttpMessageConverter item : converterList) { + if (item.getClass() == StringHttpMessageConverter.class) { + converterTarget = item; + break; + } + } + if (converterTarget != null) { + converterList.remove(converterTarget); + } + HttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); + converterList.add(1,converter); + + MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList( + MediaType.TEXT_HTML, + MediaType.TEXT_PLAIN)); + restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter); + + log.info("-----restTemplate-----初始化完成"); + return restTemplate; + } + + @Bean + public ClientHttpRequestFactory httpRequestFactory() { + return new HttpComponentsClientHttpRequestFactory(httpClient()); + } + + @Bean + public HttpClient httpClient() { + // 长连接保持30秒 + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS); + //设置整个连接池最大连接数 根据自己的场景决定 + connectionManager.setMaxTotal(500); + //同路由的并发数,路由是对maxTotal的细分 + connectionManager.setDefaultMaxPerRoute(500); + + //requestConfig + RequestConfig requestConfig = RequestConfig.custom() + //服务器返回数据(response)的时间,超过该时间抛出read timeout + .setSocketTimeout(30000) + //连接上服务器(握手成功)的时间,超出该时间抛出connect timeout + .setConnectTimeout(5000) + //从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool + .setConnectionRequestTimeout(500) + .build(); + //headers + List
headers = new ArrayList<>(); + headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36")); + headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate")); + headers.add(new BasicHeader("Accept-Language", "zh-CN")); + headers.add(new BasicHeader("Connection", "Keep-Alive")); + headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8")); + + return HttpClientBuilder.create() + .setDefaultRequestConfig(requestConfig) + .setConnectionManager(connectionManager) + .setDefaultHeaders(headers) + // 保持长连接配置,需要在头添加Keep-Alive + .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) + //重试次数,默认是3次,没有开启 + .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)) + .build(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/WebConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/WebConfig.java new file mode 100644 index 0000000..e59f46b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/config/WebConfig.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.common.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.ningdatech.basic.config.BaseConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * WebConfig + *

+ * + * @author WendyYang + * @since 14:09 2022/9/30 + */ +@Configuration +public class WebConfig extends BaseConfig { + + /** + * 设置mybatis-plus分页插件 + **/ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmLevelEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmLevelEnum.java new file mode 100644 index 0000000..af34cce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmLevelEnum.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 告警等级 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AlarmLevelEnum", description = "告警等级-枚举") +public enum AlarmLevelEnum { + /** + * 主动抓拍事件 + */ + EARLY_WARNING(1, "预警"), + GIVE_ALARM(2, "报警"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(int code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (AlarmLevelEnum t : AlarmLevelEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmTypeEnum.java new file mode 100644 index 0000000..68d0834 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/AlarmTypeEnum.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 告警类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AlarmTypeEnum", description = "告警类型-枚举") +public enum AlarmTypeEnum { + /** + * 視頻遮擋 + */ + ADAS_ALARM_20102("视频遮挡", "0x00020102"), + ADAS_ALARM_20502("前向碰撞", "0x00020502"), + ADAS_ALARM_20504("车道偏离(左)", "0x00020504"), + ADAS_ALARM_20506("车道偏离(右)", "0x00020506"), + ADAS_ALARM_20508("车距过近", "0x00020508"), + ADAS_ALARM_20510("行人防撞", "0x00020510"), + ADAS_ALARM_20511("不礼让行人", "0x00020511"), + ADAS_ALARM_37005("路口快速通过", "0x00037005"), + ADAS_ALARM_20512("疲劳驾驶预警", "0x00020512"), + ADAS_ALARM_20513("疲劳驾驶", "0x00020513"), + ADAS_ALARM_20514("分神提醒预警", "0x00020514"), + ADAS_ALARM_20515("分神提醒", "0x00020515"), + ADAS_ALARM_20516("接打电话", "0x00020516"), + ADAS_ALARM_20517("抽烟", "0x00020517"), + ADAS_ALARM_20519("驾驶员检测异常", "0x00020519"), + ADAS_ALARM_2051A("驾驶员异常", "0x0002051A"), + ADAS_ALARM_20523("急加速", "0x00020523"), + ADAS_ALARM_20524("急减速", "0x00020524"), + ADAS_ALARM_20525("急左转弯", "0x00020525"), + ADAS_ALARM_20526("急右转弯", "0x00020526"), + ADAS_ALARM_20534("驾驶员身份异常", "0x00020534"), + ADAS_ALARM_20518("未系安全带", "0x00020518"), + ADAS_ALARM_37001("墨镜红外阻断报警", "0x00037001"), + ADAS_ALARM_37002("双手脱离方向盘报警", "0x00037002"), + ADAS_ALARM_37006("单手脱离方向盘报警", "0x00037006"), + ADAS_ALARM_37101("右转弯不停车", "0x00037101"), + ADAS_ALARM_37100("右转弯超速", "0x00037100"), + ADAS_ALARM_20559("紧急告警", "0x00020559"), + ADAS_ALARM_20528("车辆碰撞", "0x00020528"), + ADAS_ALARM_20530("车辆侧翻", "0x00020530"), + ADAS_ALARM_20560("车辆被盗", "0x00020560"), + ADAS_ALARM_20561("车辆非法点火", "0x00020561"), + ADAS_ALARM_20562("车辆非法位移", "0x00020562"), + NA("不支持的报警类型", "999"); + + + + private String desc; + private String code; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(String code) { + if(StringUtils.isBlank(code)){ + return StringUtils.EMPTY; + } + for (AlarmTypeEnum t : AlarmTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ApprovedMotorcycleTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ApprovedMotorcycleTypeEnum.java new file mode 100644 index 0000000..9e76b4d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ApprovedMotorcycleTypeEnum.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.common.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/12 下午2:41 + * 准驾车型 + */ +@AllArgsConstructor +@Getter +public enum ApprovedMotorcycleTypeEnum { + /** + * 搅拌车 + */ + MIXER, + + /** + * 泵车 + */ + PUMP_TRUCK, + + /** + * 散装水泥车 + */ + BULK_CEMENT_TRUCK, + + /** + * 砂浆车 + */ + MORTAR_TRUCK, + + OTHER; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/BgTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/BgTypeEnum.java new file mode 100644 index 0000000..14c2178 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/BgTypeEnum.java @@ -0,0 +1,107 @@ +package com.ningdatech.carapi.common.constant; + +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum.*; + +/** + * 告警类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "BgTypeEnum", description = "告警类型 新-枚举") +public enum BgTypeEnum { + /** + * 主动抓拍事件 + */ + ADAS_DSM_ALARM_100(100, "ADAS主动抓拍事件", adas_initiative_capture_events, false), + ADAS_ALARM_101(101, "前向碰撞报警", forward_collision_warning, false), + ADAS_ALARM_102(102, "车道偏离(左)报警", lane_departure_left_warning, false), + ADAS_ALARM_103(103, "车道偏离(右)报警", lane_departure_right_warning, false), + ADAS_ALARM_104(104, "频繁变道报警", change_lanes_frequently_warning, false), + ADAS_ALARM_105(105, "车距过近(前车)报警", distance_too_close_warning, false), + ADAS_ALARM_106(106, "行人碰撞报警", pedestrian_collisions_warning, false), + ADAS_ALARM_107(107, "不礼让行人", no_comity_pedestrian, false), + ADAS_ALARM_108(108, "道路标志识别事件", road_sign_recognition_event, false), + ADAS_ALARM_109(109, "道路标识超速报警", road_signs_overspeed_warning, false), + ADAS_ALARM_110(110, "路口快速通过报警", crossroads_quickly_through_warning, false), + DSM_ALARM_200(200, "DSM主动抓拍事件", dsm_initiative_capture_events, false), + DSM_ALARM_201(201, "探头遮挡报警", probe_cover_alarm, false), + DSM_ALARM_202(202, "驾驶员人脸身份识别事件", driver_face_identification_events, false), + DSM_ALARM_203(203, "换人驾驶报警", substitution_driving_alarm, false), + DSM_ALARM_204(204, "超时驾驶报警", driver_timeout_alarm, false), + DSM_ALARM_205(205, "疲劳驾驶报警", fatigue_driving_alarm, false), + DSM_ALARM_206(206, "接打手持电话报警", holding_a_call_alarm, false), + DSM_ALARM_207(207, "抽烟报警", smoke_alarm, false), + DSM_ALARM_208(208, "分神驾驶报警", distracted_driving_alarm, false), + DSM_ALARM_209(209, "驾驶员状态异常报警", driver_abnormal_state_alarm, false), + DSM_ALARM_210(210, "未系安全带报警", not_wearing_seatbelt_alarm, false), + DSM_ALARM_211(211, "驾驶员身份异常报警", driver_abnormal_status_alarm, false), + BSD_ALARM_300(300, "后方接近报警", close_behind_alarm, false), + BSD_ALARM_301(301, "左侧后方接近报警", left_rear_near_alarm, false), + BSD_ALARM_302(302, "右侧后方接近报警", right_rear_near_alarm, false); + + private Integer code; + private String desc; + private CodingRuleBehaviorTypeEnum crbType; + private Boolean hidden; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + + public static List listCode(Boolean hidden) { + return Arrays.stream(values()) + .filter(w -> { + if (hidden == null) { + return Boolean.TRUE; + } + return hidden.equals(w.getHidden()); + }) + .map(BgTypeEnum::getCode) + .collect(Collectors.toList()); + } + + + public static String getDescByCode(int code) { + for (BgTypeEnum t : BgTypeEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + + public static CodingRuleBehaviorTypeEnum getCrbTypeByCode(int code) { + for (BgTypeEnum t : BgTypeEnum.values()) { + if (code == t.getCode()) { + return t.crbType; + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CarStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CarStatusEnum.java new file mode 100644 index 0000000..7ecec98 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CarStatusEnum.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.common.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 车辆在线状态 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "CarStatusEnum", description = "车辆状态-枚举") +public enum CarStatusEnum { + /** + * 启用 + */ + ENABLE(1, "启用"), + + /** + *停用 + */ + DISABLE(2, "停用"), + + /** + * 维修 + */ + REPAIR(3, "维修"), + + /** + * 报废 + */ + SCRAP(4,"报废"), + + /** + * 出售 + */ + SELL(5,"出售"); + + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (CarStatusEnum t : CarStatusEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CommonConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CommonConstant.java new file mode 100644 index 0000000..4e04cf8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CommonConstant.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.common.constant; + +/** + * @description: 常量 + * @author: LiuXinXin + * @date: 2022/5/5 17:31 + */ +public class CommonConstant { + + public static final String COOKIE_KEY = "ND_JSESSION"; + + public static final Integer EXPORT_PAGE_NUMBER= 1; + + public static final Integer EXPORT_PAGE_SIZE= 100000; + public static final String CALL_STATUS = "status"; + public static final String CALL_STATUS_OK_VALUE = "ok"; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CompanyTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CompanyTypeEnum.java new file mode 100644 index 0000000..dd82f7d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/CompanyTypeEnum.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 公司类型 + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "CompanyTypeEnum", description = "公司类型-枚举") +public enum CompanyTypeEnum { + /** + * 管理公司 + */ + ADMIN(1, "管理单位"), + + /** + * 企业公司 + */ + ENTERPRISE(2, "企业单位"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (CompanyTypeEnum t : CompanyTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DeletedEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DeletedEnum.java new file mode 100644 index 0000000..ad0d61f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DeletedEnum.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +/** + * 是否删除 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DeletedEnum", description = "是否删除-枚举") +public enum DeletedEnum { + /** + * 是否删除 + */ + NO_DELETED(0, "未删除"), + DELETED(1, "已删除"); + + + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(String code) { + if(StringUtils.isBlank(code)){ + return StringUtils.EMPTY; + } + for (DeletedEnum t : DeletedEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverLicenseTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverLicenseTypeEnum.java new file mode 100644 index 0000000..b3a24d5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverLicenseTypeEnum.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.common.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/12 下午2:26 + * 驾驶员类型 + */ +@AllArgsConstructor +@Getter +public enum DriverLicenseTypeEnum { + /** + * 驾照类型 + */ + A1, + A2, + B1, + B2, + C1, + OTHER +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverVehicleTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverVehicleTypeEnum.java new file mode 100644 index 0000000..8767cc4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/DriverVehicleTypeEnum.java @@ -0,0 +1,108 @@ +package com.ningdatech.carapi.common.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 车辆类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "VehicleTypeEnum", description = "车辆类型-枚举") +public enum DriverVehicleTypeEnum { + /** + * 散装水泥运输车 + */ + BULK_CEMENT_TRUCK(1, "散装水泥车"), + + /** + *预拌砂浆运输车 + */ + READY_MIXED_MORTAR_TRUC(2, "砂浆车"), + + /** + * 混凝土搅拌车 + */ + MIXER(3, "搅拌车"), + + /** + * 移动泵车 + */ + KRHP(4, "泵车"), + + OTHER(99, "其他"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return OTHER.desc; + } + for (DriverVehicleTypeEnum t : DriverVehicleTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return OTHER.desc; + } + + public static Integer getCodeByDesc(String desc) { + if(StringUtils.isBlank(desc)){ + return OTHER.code; + } + for (DriverVehicleTypeEnum t : DriverVehicleTypeEnum.values()) { + if (desc.equals(t.getDesc())) { + return t.code; + } + } + return OTHER.code; + } + + public static DriverVehicleTypeEnum getEnumByValue(Integer code) { + if(Objects.isNull(code)){ + return null; + } + for (DriverVehicleTypeEnum t : DriverVehicleTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t; + } + } + return null; + } + + public static DriverVehicleTypeEnum getEnum(String desc) { + if(Objects.isNull(desc)){ + return null; + } + for (DriverVehicleTypeEnum t : DriverVehicleTypeEnum.values()) { + if (desc.equals(t.getDesc())) { + return t; + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationDegreeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationDegreeEnum.java new file mode 100644 index 0000000..8011453 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationDegreeEnum.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.common.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/12 下午2:28 + * 文化程度 + */ + +@AllArgsConstructor +@Getter +public enum EducationDegreeEnum { + /** + * 小学 + */ + PRIMARY_SCHOOL, + /** + * 初中 + */ + JUNIOR_HIGH_SCHOOL, + /** + * 高中 + */ + HIGH_SCHOOL, + /** + * 大专 + */ + JUNIOR_COLLEGE, + /** + * 本科 + */ + UNDERGRADUATE, + /** + * 硕士 + */ + MASTER, + /** + * 博士 + */ + DOCTOR + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationEnum.java new file mode 100644 index 0000000..3233a9d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/EducationEnum.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.common.constant; + +import java.util.Objects; + +import lombok.Getter; + +/** + * EducationEnum + * @return + * @author CMM + * @since 2023/06/26 12:39 + */ +@Getter +public enum EducationEnum { + + /** + * 学历编码定义 + */ + PRIMARY(0, "小学"), + JUNIOR(1, "初中"), + HIGH(2, "高中"), + TECHNICAL(3, "专科"), + UNDERGRADUATE(4, "本科"), + POSTGRADUATE(5, "研究生"), + DOCTOR(6, "博士"); + + private final int code; + private final String value; + + EducationEnum(int code, String value) { + this.code = code; + this.value = value; + } + + public boolean eq(String val) { + return this.getValue().equals(val); + } + + public boolean eq(int code) { + return this.getCode() == code; + } + + public static EducationEnum getByCode(int code) { + for (EducationEnum genderEnum : EducationEnum.values()) { + if (genderEnum.getCode() == code) { + return genderEnum; + } + } + return null; + } + + public static String getDescByCode(int code) { + for (EducationEnum genderEnum : EducationEnum.values()) { + if (genderEnum.getCode() == code) { + return genderEnum.getValue(); + } + } + return null; + } + + public static EducationEnum getByValue(String value) { + if (Objects.isNull(value)) { + return null; + } + for (EducationEnum genderEnum : EducationEnum.values()) { + if (genderEnum.getValue().contains(value)) { + return genderEnum; + } + } + return null; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GPSDataEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GPSDataEnum.java new file mode 100644 index 0000000..c3d6986 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GPSDataEnum.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.common.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum GPSDataEnum { + + /** + * 高度 + */ + ALTITUDE(0,"altitude"), + /** + * 方向 + */ + + DIRECTION(1,"direction"), + /** + * 方向 + */ + + SPEED(2,"speed"), + /** + * 纬度 + */ + + LATITUDE(3,"latitude"), + /** + * 精度 + */ + + LONGITUDE(4,"longitude"); + + private final int code; + private final String desc; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GenderEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GenderEnum.java new file mode 100644 index 0000000..498c2d8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/GenderEnum.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.common.constant; + +import java.util.Objects; + +import lombok.Getter; + +/** + *

+ * GenderEnum + *

+ * + * @author WendyYang + * @since 15:15 2022/11/4 + */ +@Getter +public enum GenderEnum { + + /** + * 性别编码定义 + */ + WOMAN(0, "女"), + MAN(1, "男"), + UNKNOWN(2, "未知"), + OTHER(3, "其他"); + + private final int code; + private final String value; + + GenderEnum(int code, String value) { + this.code = code; + this.value = value; + } + + public boolean eq(String val) { + return this.getValue().equals(val); + } + + public boolean eq(int code) { + return this.getCode() == code; + } + + public static GenderEnum getByCode(int code) { + for (GenderEnum genderEnum : GenderEnum.values()) { + if (genderEnum.getCode() == code) { + return genderEnum; + } + } + return GenderEnum.UNKNOWN; + } + + public static String getDescByCode(int code) { + for (GenderEnum genderEnum : GenderEnum.values()) { + if (genderEnum.getCode() == code) { + return genderEnum.getValue(); + } + } + return GenderEnum.UNKNOWN.getValue(); + } + + public static GenderEnum getByValue(String value) { + if (Objects.isNull(value)) { + return GenderEnum.UNKNOWN; + } + for (GenderEnum genderEnum : GenderEnum.values()) { + if (genderEnum.getValue().contains(value)) { + return genderEnum; + } + } + return GenderEnum.UNKNOWN; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/InsureCompanyEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/InsureCompanyEnum.java new file mode 100644 index 0000000..6f05878 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/InsureCompanyEnum.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.common.constant; + +import com.google.common.collect.Lists; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Objects; + +/** + * 保险公司 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "InsureCompanyEnum", description = "保险公司-枚举") +public enum InsureCompanyEnum { + /** + * 阳光财产 + */ + SUN(1, "阳光财产"), + + /** + * 人寿财产 + */ + LIFE(2, "人寿财产"), + + /** + * 大地财产 + */ + LAND(3, "大地财产"), + + /** + * 太平洋财产 + */ + PACIFIC(4, "太平洋财产"), + + /** + * 人民财产 + */ + PEOPLE(5, "人民财产"), + + /** + * 中华联合 + */ + CHUT(6, "中华联合"), + + /** + * 其他保险 + */ + OTHER(99, "其他保险"); + + + private Integer code; + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public static String getNameByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (InsureCompanyEnum t : InsureCompanyEnum.values()) { + if (code.equals(t.getCode())) { + return t.name; + } + } + return StringUtils.EMPTY; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + + public static List getNames() { + List res = Lists.newArrayList(); + for(InsureCompanyEnum e : InsureCompanyEnum.values()){ + res.add(e.getName()); + } + return res; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/MissCertEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/MissCertEnum.java new file mode 100644 index 0000000..5947537 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/MissCertEnum.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 丢失证件类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "MissCertEnum", description = "丢失证件类型-枚举") +public enum MissCertEnum { + /** + * 驾驶证 + */ + DRIVER_LINCENSE(1, "驾驶证"), + + /** + * 行驶证 + */ + DRIVE_PERMIT(2, "行驶证"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (MissCertEnum t : MissCertEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/UserRoleTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/UserRoleTypeEnum.java new file mode 100644 index 0000000..b3590ae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/UserRoleTypeEnum.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * @author CMM + * @description + * @since 2022/11/23 16:58 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel("用户角色类型枚举") +public enum UserRoleTypeEnum { + /** + * 系统管理员 + */ + SYSTEM_ADMIN_ROLE_ID("系统管理员",4L), + SYSTEM_ROLE_ID("系统管理员",25L), + REGION_ADMIN_ROLE_ID("本区域管理员",24L), + COMPANY_INFO_OFFICER_ROLE_ID("企业信息员",3L), + OPERATOR_ROLE_ID("运营商",2L), + DRIVER_ROLE_ID("驾驶员",11L), + BULK_CEMENT_ADMIN_ROLE_ID("散办",10L); + + private String desc; + private Long id; + + public String getDesc() { + return desc; + } + public Long getId() { + return id; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescById(Long id){ + if (Objects.isNull(id)){ + return StringUtils.EMPTY; + } + for (UserRoleTypeEnum u : UserRoleTypeEnum.values()){ + if (id.equals(u.getId())){ + return u.desc; + } + } + return StringUtils.EMPTY; + } +} + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleEquipFuncEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleEquipFuncEnum.java new file mode 100644 index 0000000..1cca6de --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleEquipFuncEnum.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.common.constant; + +/** + * 车辆设备功能 + * @author CMM + * @since 2023/05/31 14:27 + */ +public enum VehicleEquipFuncEnum { + + /** + * 视频设备 + */ + video, + + /** + * 定位设备 + */ + gps; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleLimitSpeedEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleLimitSpeedEnum.java new file mode 100644 index 0000000..7f30e59 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleLimitSpeedEnum.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Objects; + +/** + * 车辆类型限速 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "VehicleLimitSpeedEnum", description = "车辆类型限速-枚举") +public enum VehicleLimitSpeedEnum { + /** + * 散装水泥运输车 + */ + BULK_CEMENT_TRUCK_LIMITSPEED(1, "散装水泥运输车",60), + + /** + *预拌砂浆运输车 + */ + READY_MIXED_MORTAR_TRUC(2, "预拌砂浆运输车",60), + + /** + * 混凝土搅拌车 + */ + MIXER(3, "混凝土搅拌车",50), + + /** + * 移动泵车 + */ + KRHP(4, "移动泵车",50); + + + private Integer code; + private String desc; + private Integer limitSpeed; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static Integer getLimitSpeedByCode(Integer code) { + if(Objects.isNull(code)){ + return 60; + } + for (VehicleLimitSpeedEnum t : VehicleLimitSpeedEnum.values()) { + if (code.equals(t.getCode())) { + return t.limitSpeed; + } + } + return 60; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleMovingEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleMovingEnum.java new file mode 100644 index 0000000..3868f8e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleMovingEnum.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 车辆是否行驶 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "VehicleMovingEnum", description = "车辆是否行驶-枚举") +public enum VehicleMovingEnum { + /** + * + */ + MOVING(1, "行驶中"), + + /** + *离线 + */ + NOT_MOVING(0, "不在行驶"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (VehicleMovingEnum t : VehicleMovingEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleStatusEnum.java new file mode 100644 index 0000000..0dc5210 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleStatusEnum.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.common.constant; + +import com.ningdatech.carapi.scheduler.enums.OperatorTypeEnum; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 车辆在线状态 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "VehicleStatusEnum", description = "车辆在线状态-枚举") +public enum VehicleStatusEnum { + /** + * 在线 + */ + ONLINE(1, "在线", OperatorTypeEnum.ONLINE), + + /** + *离线 + */ + OFFLINE(0, "离线",OperatorTypeEnum.OFFLINE), + + /** + * 异常 + */ + EXCEPTIONAL(2, "异常",OperatorTypeEnum.EXCEPTION); + + + private Integer code; + private String desc; + + private OperatorTypeEnum operatorType; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (VehicleStatusEnum t : VehicleStatusEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static OperatorTypeEnum getOperatorTypeByCode(Integer code) { + if(Objects.isNull(code)){ + return null; + } + for (VehicleStatusEnum t : VehicleStatusEnum.values()) { + if (code.equals(t.getCode())) { + return t.operatorType; + } + } + return null; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleTypeEnum.java new file mode 100644 index 0000000..2263e05 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/VehicleTypeEnum.java @@ -0,0 +1,121 @@ +package com.ningdatech.carapi.common.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 车辆类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "VehicleTypeEnum", description = "车辆类型-枚举") +public enum VehicleTypeEnum { + /** + * 散装水泥运输车 + */ + BULK_CEMENT_TRUCK(1, "散装水泥运输车"), + + /** + *预拌砂浆运输车 + */ + READY_MIXED_MORTAR_TRUC(2, "预拌砂浆运输车"), + + /** + * 混凝土搅拌车 + */ + MIXER(3, "混凝土搅拌车"), + + /** + * 移动泵车 + */ + KRHP(4, "移动泵车"), + + OTHER(99, "其他"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return OTHER.desc; + } + for (VehicleTypeEnum t : VehicleTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return OTHER.desc; + } + + public static String getDescByEnum(String e) { + if(StringUtils.isBlank(e)){ + return null; + } + for (VehicleTypeEnum t : VehicleTypeEnum.values()) { + String substring = e.substring(1, e.length() - 1); + if (substring.equals(t.name())) { + return t.desc; + } + } + return null; + } + + public static Integer getCodeByDesc(String desc) { + if(StringUtils.isBlank(desc)){ + return OTHER.code; + } + for (VehicleTypeEnum t : VehicleTypeEnum.values()) { + if (desc.equals(t.getDesc())) { + return t.code; + } + } + return OTHER.code; + } + + public static VehicleTypeEnum getEnumByValue(Integer code) { + if(Objects.isNull(code)){ + return null; + } + for (VehicleTypeEnum t : VehicleTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t; + } + } + return null; + } + + public static VehicleTypeEnum getEnum(String desc) { + if(Objects.isNull(desc)){ + return null; + } + for (VehicleTypeEnum t : VehicleTypeEnum.values()) { + if (desc.equals(t.getDesc())) { + return t; + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ViolationTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ViolationTypeEnum.java new file mode 100644 index 0000000..261c7ac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/constant/ViolationTypeEnum.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.common.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 违章类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "ViolationTypeEnum", description = "违章类型-枚举") +public enum ViolationTypeEnum { + /** + * 无证驾驶 + */ + MISS_CERT(1, "无证驾驶"), + + /** + * 闯红灯 + */ + RED_LIGHT(2, "闯红灯"), + + /** + * 超载 + */ + OVER_LOAD(3, "超载"), + + /** + * 违规路段 + */ + SECTION(4, "违规路段"), + + /** + * 违规时间段 + */ + PERIOD(5, "违规时间段"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (ViolationTypeEnum t : ViolationTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/DefValConstants.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/DefValConstants.java new file mode 100644 index 0000000..6c9ad50 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/DefValConstants.java @@ -0,0 +1,111 @@ +package com.ningdatech.carapi.common.contants; + + +import com.ningdatech.basic.util.StrPool; + +/** + * 默认值 + * + * @author PoffyZhang + */ +public interface DefValConstants { + + /** + * 默认的根节点path + */ + String ROOT_PATH = StrPool.COMMA; + /** + * 默认树层级 + */ + Integer TREE_GRADE = 0; + /** + * 默认的父id + */ + Long PARENT_ID = 0L; + /** + * 默认的排序 + */ + Integer SORT_VALUE = 0; + /** + * 字典占位符 + */ + String DICT_PLACEHOLDER = "###"; + /** + * 浙江省的region_id + */ + Long ZJREGION_ID = 116L; + Long SYSTEM_ID = 1L; + String ZJ_PROVINCE = "浙江省"; + String PROVINCE = "省"; + + /** + * 城市 level + */ + Integer CITY_REGION_LEVEL = 2; + + /** + * 区的 level + */ + Integer QU_REGION_LEVEL = 3; + + /** + * 驾驶员异常数据GPS字符串起始偏移量 + */ + Integer GPS_START_OFFSET = 5; + + /** + * 驾驶员异常数据GPS字符串结尾偏移量 + */ + Integer GPS_END_OFFSET = 69; + + /** + * 新增线下驾驶员培训,发送短信模板 + */ + String OFFLINE_MESSAGE_TEMPLATE = "{%s}您好:{散办名称}组织了关于{培训主题}的{培训模式}培训,培训时间为{培训开始 至 结束时间},培训地点为{培训地点:线下培训时显示},培训链接{生成培训链接,点击后跳转培训页面},请准时参加培训。联系人:{联系人},联系电话:{联系电话},考证号:{准考证号}."; + + /** + * 新增线上驾驶员培训,发送短信模板 + */ + String ONLINE_MESSAGE_TEMPLATE = "{%s}您好:{散办名称}组织了关于{培训主题}的{培训模式}培训,培训时间为{培训开始 至 结束时间},培训链接{生成培训链接,点击后跳转培训页面},请准时参加培训。联系人:{联系人},联系电话:{联系电话},考证号:{准考证号}."; + + /** + * SQL查询一条 + */ + String LIMIT_1 = " limit 1"; + /** + * 随机试卷 + */ + String RANDOM_PAPER = "随机试卷"; + /** + * 随机试卷ID + */ + Long RANDOM_EXAM_PAPER_ID = 0L; + /** + * 线上培训 + */ + String ONLINE = "线上"; + /** + * 线下培训 + */ + String OFFLINE = "线下"; + /** + * 取证培训 + */ + String FORENSIC_REGISTRATION_TRAINING = "取证培训"; + /** + * 继续教育 + */ + String CONTINUING_EDUCATION_TRAINING = "继续教育"; + /** + * 换证培训 + */ + String REPLACEMENT_REGISTRATION_TRAINING = "换证培训"; + /** + * 转码培训 + */ + String TRANSCODING_TRAINING = "转码培训"; + /** + * 通道 + */ + String TONG_DAO = "通道"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/IrsConst.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/IrsConst.java new file mode 100644 index 0000000..01e9fa5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/contants/IrsConst.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.common.contants; + +/** + *

+ * IrsConst + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +public interface IrsConst { + + // 驾驶证查询接口地址 + String DRIVER_LICENSE_URL = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/dataSharing/driverLicenseInfo.htm"; + + String DRIVING_LICENSE_URL = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/dataSharing/vehicleQmInfo.htm"; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/exception/AppErrorCode.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/exception/AppErrorCode.java new file mode 100644 index 0000000..614fc59 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/exception/AppErrorCode.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.common.exception; + +public enum AppErrorCode { + /** + * 用戶 + */ + USER(100), + + AUTH(101); + + private final Integer code; + + AppErrorCode(Integer code) { + this.code = code; + } + + public Integer getCode() { + return code; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/filter/SqlInjectFilter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/filter/SqlInjectFilter.java new file mode 100644 index 0000000..483d04f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/filter/SqlInjectFilter.java @@ -0,0 +1,112 @@ +package com.ningdatech.carapi.common.filter; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Enumeration; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @description: sql注入过滤 + * @author: liushuai + * @date: 2022/3/25 11:42 + */ +@Component +@Configuration +@ConfigurationProperties(prefix = "security.sql") +@WebFilter(filterName = "SqlInjectFilter", urlPatterns = "/*") +public class SqlInjectFilter implements Filter { + /** + * 过滤器配置对象 + */ + FilterConfig filterConfig = null; + + /** + * 忽略的URL + */ + private List excludes; + + public void setExcludes(List excludes) { + this.excludes = excludes; + } + + /** + * 初始化 + */ + @Override + public void init(FilterConfig filterConfig) throws ServletException { + this.filterConfig = filterConfig; + } + + /** + * 拦截 + */ + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + // 已忽略的URL不拦截 + if (isExcludeUrl(request.getServletPath())) { + filterChain.doFilter(servletRequest, servletResponse); + return; + } + + //获得所有请求参数名 + Enumeration names = request.getParameterNames(); + while (names.hasMoreElements()) { + //得到参数名 + String name = names.nextElement(); + //得到参数对应值 + String[] values = request.getParameterValues(name); + for (String value : values) { + if (sqlValidate(value)) { + throw new IOException("您发送请求中的参数中含有非法字符"); + } + } + } + filterChain.doFilter(request, response); + } + + /** + * 销毁 + */ + @Override + public void destroy() { + this.filterConfig = null; + } + + /** + * 判断是否为忽略的URL + * + * @param url URL路径 + * @return true-忽略,false-过滤 + */ + private boolean isExcludeUrl(String url) { + if (excludes == null || excludes.isEmpty()) { + return false; + } + return excludes.stream().map(pattern -> Pattern.compile("^" + pattern)).map(p -> p.matcher(url)) + .anyMatch(Matcher::find); + } + + protected static boolean sqlValidate(String str) { + //统一转为小写 + String s = str.toLowerCase(); + //过滤掉的sql关键字,特殊字符前面需要加\\进行转义 + String badStr = + "select|update|and|or|delete|insert|truncate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|table|" + + "char|declare|sitename|xp_cmdshell|like|from|grant|use|group_concat|column_name|" + + "information_schema.columns|table_schema|union|where|order|by"; + //使用正则表达式进行匹配 + return s.matches(badStr); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalExceptionHandler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..70657da --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalExceptionHandler.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.common.handler; + +import com.ningdatech.basic.enumeration.Status; +import com.ningdatech.basic.model.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.http.HttpStatus; +import org.springframework.validation.BindException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.NoHandlerFoundException; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import java.util.stream.Collectors; + +/** + * @description: 统一错误处理 + * @author: liushuai + * @date: 2022/3/25 11:39 + */ +@Slf4j +@ControllerAdvice +@ResponseStatus(HttpStatus.BAD_REQUEST) +public class GlobalExceptionHandler { + + @ResponseBody + @ExceptionHandler(value = NoHandlerFoundException.class) + public ApiResponse noHandlerFoundException(NoHandlerFoundException e) { + log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", e.getRequestURL(), e.getHttpMethod()); + return ApiResponse.ofStatus(Status.REQUEST_NOT_FOUND); + } + + @ResponseBody + @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class}) + public ApiResponse bindException(BindException e) { + String msg = e.getAllErrors().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(",")); + return ApiResponse.of(Status.BAD_REQUEST.getCode(), msg, null); + } + + @ResponseBody + @ExceptionHandler(value = ConstraintViolationException.class) + public ApiResponse constraintViolationException(ConstraintViolationException e) { + String msg = e.getConstraintViolations().stream() + .map(ConstraintViolation::getMessage) + .collect(Collectors.joining(",")); + return ApiResponse.of(Status.BAD_REQUEST.getCode(), msg, null); + } + + @ResponseBody + @ExceptionHandler(value = Exception.class) + public ApiResponse handlerException(Exception e) { + log.error("【全局异常拦截】: 异常信息 {}: {} ", e.getClass().getSimpleName(), e); + return ApiResponse.of(Status.BAD_REQUEST.getCode(), e.getMessage(), null); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalResponseHandler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalResponseHandler.java new file mode 100644 index 0000000..fd101e9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/handler/GlobalResponseHandler.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.common.handler; + +import cn.hutool.json.JSONUtil; +import com.ningdatech.basic.model.ApiResponse; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +/** + * @Author liuxinxin + * @Date 2021/7/21 11:26 + * @Version 1.0 + **/ +@RestControllerAdvice(basePackages = { + "com.ningdatech.carapi.car.position.controller", + "com.ningdatech.carapi.car.video.controller", + "com.ningdatech.carapi.car.monitor.controller", + "com.ningdatech.carapi.car.rpt.controller", + "com.ningdatech.carapi.car.trips.controller", + "com.ningdatech.carapi.car.datascreen.controller", + "com.ningdatech.carapi.car.vehicle.controller", + "com.ningdatech.carapi.car.equipment.controller", + "com.ningdatech.carapi.meta.controller", + "com.ningdatech.carapi.sys.controller", + "com.ningdatech.carapi.driver.controller", + "com.ningdatech.carapi.archives.controller", + "com.ningdatech.carapi.company.controller", + "com.ningdatech.carapi.analysis.controller", + "com.ningdatech.carapi.safe.controller", + "com.ningdatech.carapi.qrcode.controller", + "com.ningdatech.carapi.open.controller", + "com.ningdatech.carapi.industry.controller", + "com.ningdatech.carapi.homepage.controller" +}) +public class GlobalResponseHandler implements ResponseBodyAdvice { + + private static final String SWAGGER_CLASS_PREFIX = "springfox.documentation"; + + @Override + public boolean supports(MethodParameter methodParameter, Class> aClass) { + return filter(methodParameter); + } + + @Override + public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, + Class> aClass, ServerHttpRequest serverHttpRequest, + ServerHttpResponse serverHttpResponse) { + ApiResponse apiResponse = ApiResponse.ofSuccess(o); + // 处理字符串时,遇到了类型转换的问题,debug一步一步跟踪,原来是对于字符串的ContentType是“text-plain”, + // ConverterType是StringHttpMessageConverter这个类型转换, + // 由于将结果封装成了自定义的ApiResponse类型,所以有ApiResponse转换成String报错 + // 所以需要对String类型的返回值单独进行处理 + if (o instanceof String) { + return JSONUtil.toJsonStr(apiResponse); + } + return ApiResponse.ofSuccess(o); + } + + private Boolean filter(MethodParameter methodParameter) { + Class declaringClass = methodParameter.getDeclaringClass(); + // swagger中的所有返回不进行统一封装 + if (declaringClass.getName().contains(SWAGGER_CLASS_PREFIX)) { + return false; + } + if (methodParameter.hasMethodAnnotation(ExceptionHandler.class)) { + return false; + } + // 如果本身就是使用ApiResponse返回,则不需要进行格式化 + return !methodParameter.getGenericParameterType().equals(ApiResponse.class); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/helper/UserInfoHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/helper/UserInfoHelper.java new file mode 100644 index 0000000..02f13cf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/helper/UserInfoHelper.java @@ -0,0 +1,146 @@ +package com.ningdatech.carapi.common.helper; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeContext; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.sys.convert.UserAuthConverter; +import com.ningdatech.carapi.sys.convert.UserRoleConverter; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.RoleService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/22 上午11:50 + *

+ */ +@Component +@RequiredArgsConstructor +public class UserInfoHelper { + private final CompanyService companyService; + private final INdUserInfoService iNdUserInfoService; + private final IDriverInfoService driverInfoService; + private final CompaniesCacheHelper companiesCacheHelper; + private final INdUserAuthService userAuthService; + private final UserRoleService userRoleService; + private final RoleService roleService; + + public Long getUserCompanyId() { + Long userId = LoginUserUtil.getUserId(); + NdUserInfo userInfo = iNdUserInfoService.getById(userId); + if (Objects.isNull(userInfo.getCompanyId())) { + throw new BizException("当前非公司或驾驶员账号"); + } + return userInfo.getCompanyId(); + } + + public String getUserCompanyName() { + Company company = companyService.getById(getUserCompanyId()); + return company.getName(); + } + + public Long getUserRegionId() { + Company company = companyService.getById(getUserCompanyId()); + return company.getRegionId(); + } + + public UserBasicInfoVO getUserFullInfo() { + UserBasicInfoVO userBasicInfoVO = new UserBasicInfoVO(); + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + Long userId = user.getUserId(); + Long roleId = user.getRoleId(); + Optional dataScope = DataScopeContext.getDataScope(user.getDataScope()); + if(dataScope.isPresent()){ + userBasicInfoVO.setMaxRegion(dataScope.get().getMaxRegion()); + } + userBasicInfoVO.setNickName(user.getNickName()); + // 获取驾驶员信息 + DriverInfo driverInfo = driverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getUserId, userId)); + if (Objects.nonNull(driverInfo)) { + userBasicInfoVO.setDriverId(driverInfo.getId()); + } + userBasicInfoVO.setUserId(userId); + userBasicInfoVO.setRoleId(roleId); + userBasicInfoVO.setCompanyId(user.getCompanyId()); + Company company = companyService.getById(user.getCompanyId()); + userBasicInfoVO.setCompanyName(company.getName()); + userBasicInfoVO.setRegionId(company.getRegionId()); + userBasicInfoVO.setRegionName(company.getRegionName()); + + return userBasicInfoVO; + } + + public UserInfoVO getUserDetailByUserId(Long userId) { + + NdUserInfo user = iNdUserInfoService.getById(userId); + if (Objects.isNull(user)) { + return null; + } + + UserInfoVO query = BeanUtil.toBean(user, UserInfoVO.class); + //查出帐号 + searchAuth(query); + //查出角色 + searchRoleName(query); + return query; + } + + private void searchAuth(UserInfoVO user) { + if(Objects.isNull(user)){ + return; + } + //查出帐号 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdUserAuth.class); + wrapper.in(NdUserAuth::getUserId, user.getId()); + List auths = userAuthService.list(wrapper); + if(CollUtil.isNotEmpty(auths)){ + UserAuthConverter.convert(user,auths); + } + } + + private void searchRoleName(UserInfoVO user) { + if(Objects.isNull(user)){ + return; + } + //查出角色名 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(UserRole.class); + wrapper.in(UserRole::getUserId, user.getId()); + List userRoles = userRoleService.list(wrapper); + if(CollUtil.isEmpty(userRoles)){ + return; + } + List roleIds = userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList()); + List roles = roleService.listByIds(roleIds); + if(CollUtil.isNotEmpty(roles)){ + UserRoleConverter.convert(user,userRoles,roles); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/interceptor/DataPermissionInterceptor.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/interceptor/DataPermissionInterceptor.java new file mode 100644 index 0000000..e63aaa5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/interceptor/DataPermissionInterceptor.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.common.interceptor; + +import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; +import com.baomidou.mybatisplus.core.toolkit.PluginUtils; +import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport; +import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import lombok.*; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectBody; +import net.sf.jsqlparser.statement.select.SetOperationList; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import java.sql.SQLException; +import java.util.List; + +/** + * 数据权限处理器 + * + * @author hubin + * @since 3.4.1 + + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@SuppressWarnings({"rawtypes"}) +public class DataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor { + private DataPermissionHandler dataPermissionHandler; + + @Override + public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { + if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())){ + return; + } + PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); + mpBs.sql(parserSingle(mpBs.sql(), ms.getId())); + } + + @Override + protected void processSelect(Select select, int index, String sql, Object obj) { + SelectBody selectBody = select.getSelectBody(); + if (selectBody instanceof PlainSelect) { + this.setWhere((PlainSelect) selectBody, (String) obj); + } else if (selectBody instanceof SetOperationList) { + SetOperationList setOperationList = (SetOperationList) selectBody; + List selectBodyList = setOperationList.getSelects(); + selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj)); + } + } + + /** + * 设置 where 条件 + * + * @param plainSelect 查询对象 + * @param whereSegment 查询条件片段 + */ + protected void setWhere(PlainSelect plainSelect, String whereSegment) { + Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), whereSegment); + if (null != sqlSegment) { + plainSelect.setWhere(sqlSegment); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/DataChartVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/DataChartVo.java new file mode 100644 index 0000000..232f6fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/DataChartVo.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.common.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * DataChartVo + *

+ * + * @author WendyYang + * @since 09:18 2022/10/26 + */ +@Data +@ApiModel("数据图表视图类") +public class DataChartVo { + + @ApiModelProperty("名称") + private String label; + + @ApiModelProperty("数量") + private Integer value; + + @ApiModelProperty("百分比") + private String percent; + + public DataChartVo(String label, Integer value) { + this.label = label; + this.value = value; + } + + public DataChartVo() { + } + + public DataChartVo(String label, Integer value, String percent) { + this.label = label; + this.value = value; + this.percent = percent; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/FileBasicInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/FileBasicInfo.java new file mode 100644 index 0000000..a2c880b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/FileBasicInfo.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.common.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/7/25 下午1:55 + * 用于包装使用 + */ +@Data +@ApiModel("文件信息基类") +public class FileBasicInfo { + + @ApiModelProperty("文件id") + private Long fileId; + + @ApiModelProperty("文件名") + private String fileName; + + @ApiModelProperty("文件类型") + private Integer fileType; + + @ApiModelProperty("文件路径") + private String filePath; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/GroupByDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/GroupByDto.java new file mode 100644 index 0000000..bb61c61 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/GroupByDto.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.common.model; + +import lombok.Data; + +/** + *

+ * GroupByDto + *

+ * + * @author WendyYang + * @since 16:07 2022/10/25 + */ +@Data +public class GroupByDto { + + private T groupKey; + + private Integer count; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/KeyValueDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/KeyValueDTO.java new file mode 100644 index 0000000..6d3ed66 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/KeyValueDTO.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.common.model; + +import lombok.Data; + +/** + *

+ * + *

+ * + * @author WendyYang + * @since 15:27 2022/10/25 + */ +@Data +public class KeyValueDTO { + + private K key; + + private V value; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/MapDataVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/MapDataVO.java new file mode 100644 index 0000000..2a93824 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/MapDataVO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.common.model; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +/** + *

+ * MapDataVo + *

+ * + * @author WendyYang + * @since 20:09 2022/11/16 + */ +@Data +@Builder +public class MapDataVO { + + @Tolerate + public MapDataVO() { + } + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域编码") + private String regionCode; + + @ApiModelProperty("数量") + private Integer value; + + @ApiModelProperty("百分比") + private String percent; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/RegionContainsBO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/RegionContainsBO.java new file mode 100644 index 0000000..e82dcdb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/RegionContainsBO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.common.model; + +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/7/26 下午4:48 + */ +@Data +public class RegionContainsBO { + + /** + * 最高级节点级别 + */ + private Integer parentRegionTreeLevel; + + /** + * 所有区域码列表 + */ + private List containsRegionCodeList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/po/MapDataPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/po/MapDataPO.java new file mode 100644 index 0000000..526f5df --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/model/po/MapDataPO.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.common.model.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +import java.math.BigDecimal; + +/** + *

+ * MapDataVo + *

+ * + * @author WendyYang + * @since 20:09 2022/11/16 + */ +@Data +@Builder +public class MapDataPO { + + @Tolerate + public MapDataPO() { + } + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域编码") + private String regionCode; + + @ApiModelProperty("数量") + private Integer value; + + @ApiModelProperty("百分比") + private String percent; + + @ApiModelProperty("最高速率") + private BigDecimal maxSpeed; + + @ApiModelProperty("车牌号") + private String carPlate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/BizUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/BizUtils.java new file mode 100644 index 0000000..7d4224f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/BizUtils.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.common.util; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +import cn.hutool.core.util.NumberUtil; + +/** + *

+ * BizUtils + *

+ * + * @author WendyYang + * @since 17:34 2022/12/5 + */ +public class BizUtils { + + public static String percent(Long numerator, Long denominator) { + if (numerator == null || numerator == 0) { + return "0%"; + } + if (denominator == null || denominator == 0 ){ + return NumberUtil.div(numerator, BigDecimal.valueOf(1)).multiply(BigDecimal.valueOf(100)) + .setScale(2, RoundingMode.HALF_UP) + "%"; + } + return NumberUtil.div(numerator, denominator).multiply(BigDecimal.valueOf(100)) + .setScale(2, RoundingMode.HALF_UP) + "%"; + } + + + public static void main(String[] args) { + System.out.println(percent(-1L, 0L)); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/CodeUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/CodeUtil.java new file mode 100644 index 0000000..c1a5711 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/CodeUtil.java @@ -0,0 +1,394 @@ +package com.ningdatech.carapi.common.util; + +import cn.hutool.core.collection.CollUtil; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.datascreen.model.po.OnlineVehicleRegionsPO; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.sys.contants.RegionContant; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * @Classname CodeUtil + * @Description + * @Date 2022/11/22 16:21 + * @Created by PoffyZhang + */ +@RequiredArgsConstructor +@Slf4j +@Component +public class CodeUtil { + + @Autowired + private RegionsCacheHelper regionsCacheHelper; + @Autowired + private CompaniesCacheHelper companiesCacheHelper; + private static CodeUtil codeUtil; + + @PostConstruct + public void init() { + codeUtil = this; + codeUtil.regionsCacheHelper = this.regionsCacheHelper; + codeUtil.companiesCacheHelper = this.companiesCacheHelper; + } + + public static Predicate distinctByKey(Function keyExtractor) { + Set seen = ConcurrentHashMap.newKeySet(); + return t -> seen.add(keyExtractor.apply(t)); + } + + public static void searchCompanyName(T obj) { + try { + Class clazz = obj.getClass(); + Field companyNameField = clazz.getDeclaredField("companyName"); + Field companyIdField = clazz.getDeclaredField("companyId"); + companyNameField.setAccessible(Boolean.TRUE); + companyIdField.setAccessible(Boolean.TRUE); + Long companyId = Objects.nonNull(companyIdField.get(obj)) ? (Long)companyIdField.get(obj) : null; + if (Objects.isNull(companyId)) { + return; + } + String companyName = Objects.nonNull(companyNameField.get(obj)) ? (String)companyNameField.get(obj) : null; + if (Objects.isNull(codeUtil)){ + log.error("codeUtil is null"); + return; + } + companyNameField.set(obj, codeUtil.companiesCacheHelper.getNameById(companyId, companyName)); + } catch (Exception e) { + log.error("searchCompanyName err :",e); + } + } + + public static void searchCompanyNames(List records) { + if (CollUtil.isEmpty(records)) { + return; + } + for (Object obj : records) { + searchCompanyName(obj); + } + } + + public static void searchRegionName(T record) { + try { + Class clazz = record.getClass(); + Field regionNameField = clazz.getDeclaredField("regionName"); + Field regionIdField = clazz.getDeclaredField("regionId"); + regionNameField.setAccessible(Boolean.TRUE); + regionIdField.setAccessible(Boolean.TRUE); + Long regionId = Objects.nonNull(regionIdField.get(record)) ? (Long)regionIdField.get(record) : null; + if (Objects.isNull(regionId)) { + return; + } + if (Objects.isNull(codeUtil)){ + log.error("codeUtil is null"); + return; + } + regionNameField.set(record, codeUtil.regionsCacheHelper.getDisplayName(regionId)); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + + public static void searchRegionNames(List records) { + if (CollUtil.isEmpty(records)) { + return; + } + for (Object obj : records) { + searchRegionName(obj); + } + } + + public static void searchCompanyNameAndRegionName(T record) { + searchCompanyName(record); + searchRegionName(record); + } + + public static void searchCompanyNamesAndRegionNames(List records) { + if (CollUtil.isEmpty(records)) { + return; + } + for (Object obj : records) { + searchCompanyNameAndRegionName(obj); + } + } + + /** + * 字符串是否是json类型 + * + * @param str + * @return + */ + public static boolean getJSONType(String str) { + boolean result = false; + if (StringUtils.isNotBlank(str)) { + str = str.trim(); + if (str.startsWith("{") && str.endsWith("}")) { + result = true; + } else if (str.startsWith("[") && str.endsWith("]")) { + result = true; + } + } + return result; + } + + /** + * 获取 区域等级 + * + * @param record + */ + public static void buildRegionLevel(T record) { + try { + Class clazz = record.getClass(); + Field regionLevelField = clazz.getDeclaredField("regionLevel"); + Field regionIdField = clazz.getDeclaredField("regionId"); + regionLevelField.setAccessible(Boolean.TRUE); + regionIdField.setAccessible(Boolean.TRUE); + Long regionId = Objects.nonNull(regionIdField.get(record)) ? (Long)regionIdField.get(record) : null; + if (Objects.isNull(regionId)) { + regionId = RegionContant.ZJ_REGION_ID; + } + if (Objects.isNull(codeUtil)){ + log.error("codeUtil is null"); + return; + } + RegionDTO regionDto = codeUtil.regionsCacheHelper.getByRegionId(regionId); + if (Objects.nonNull(regionDto)) { + regionLevelField.set(record, regionDto.getRegionLevel()); + } + } catch (Exception e) { + log.error("buildRegionLevel err :",e); + } + } + + /** + * 根据月份 和type 来build 这一旬的起始结束日期 + * + * @param record + * @param + */ + public static void buildCurrentTendaysStartEnd(T record) { + try { + Class clazz = record.getClass(); + Field monthField = clazz.getDeclaredField("month"); + Field typeField = clazz.getDeclaredField("type"); + monthField.setAccessible(Boolean.TRUE); + typeField.setAccessible(Boolean.TRUE); + String month = Objects.nonNull(monthField.get(record)) ? (String)monthField.get(record) : null; + Integer type = Objects.nonNull(typeField.get(record)) ? (Integer)typeField.get(record) : null; + if (StringUtils.isBlank(month) || Objects.isNull(type)) { + return; + } + LocalDateTime date = + LocalDateTime.parse(month + "-01 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + LocalDateTime startTime = date.with(TemporalAdjusters.firstDayOfMonth()); + LocalDateTime endTime = date.plusMonths(1).minusSeconds(1); + // 获取当前月的第一天 + if (type.equals(1)) { + endTime = date.plusDays(10).minusSeconds(1); + } else if (type.equals(2)) { + startTime = startTime.plusDays(10); + endTime = date.plusDays(20).minusSeconds(1); + } else if (type.equals(3)) { + startTime = startTime.plusDays(20); + } + Field startTimeField = clazz.getDeclaredField("startTime"); + Field endTimeField = clazz.getDeclaredField("endTime"); + startTimeField.setAccessible(Boolean.TRUE); + endTimeField.setAccessible(Boolean.TRUE); + startTimeField.set(record, startTime); + endTimeField.set(record, endTime); + } catch (Exception e) { + log.error("buildCurrentTendaysStartEnd err :",e); + } + } + + /** + * 根据月份 和type 来build 上一旬的起始结束日期 + * + * @param record + * @param + */ + public static void buildLastTendaysStartEnd(T record) { + try { + Class clazz = record.getClass(); + Field monthField = clazz.getDeclaredField("month"); + Field typeField = clazz.getDeclaredField("type"); + monthField.setAccessible(Boolean.TRUE); + typeField.setAccessible(Boolean.TRUE); + String month = Objects.nonNull(monthField.get(record)) ? (String)monthField.get(record) : null; + Integer type = Objects.nonNull(typeField.get(record)) ? (Integer)typeField.get(record) : null; + if (StringUtils.isBlank(month) || Objects.isNull(type)) { + return; + } + LocalDateTime date = + LocalDateTime.parse(month + "-01 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + // 上一旬 用type来判断 如果不是1 就减一 + if (!type.equals(1)) { + type = type - 1; + } else if (type.equals(1)) { + // 否则就是上一个月的 下旬 + type = 3; + date = date.minusMonths(1); + } + + LocalDateTime startTime = date.with(TemporalAdjusters.firstDayOfMonth()); + LocalDateTime endTime = date.plusMonths(1).minusSeconds(1); + // 获取当前月的第一天 + if (type.equals(1)) { + endTime = date.plusDays(10).minusSeconds(1); + } else if (type.equals(2)) { + startTime = startTime.plusDays(10); + endTime = date.plusDays(20).minusSeconds(1); + } else if (type.equals(3)) { + startTime = startTime.plusDays(20); + } + Field lastStartTimeField = clazz.getDeclaredField("lastStartTime"); + Field lastEndTimeField = clazz.getDeclaredField("lastEndTime"); + lastStartTimeField.setAccessible(Boolean.TRUE); + lastEndTimeField.setAccessible(Boolean.TRUE); + lastStartTimeField.set(record, startTime); + lastEndTimeField.set(record, endTime); + } catch (Exception e) { + log.error("buildLastTendaysStartEnd err :",e); + } + } + + /** + * Returns the 转换regionCode 成 id + * + * @param record + */ + public static void convertRegionCodeToId(T record) { + try { + Class clazz = record.getClass(); + Field regionIdField = clazz.getDeclaredField("regionId"); + regionIdField.setAccessible(Boolean.TRUE); + String regionCode = + Objects.nonNull(regionIdField.get(record)) ? String.valueOf(regionIdField.get(record)) : null; + Long regionId = codeUtil.regionsCacheHelper.getIdByCode(regionCode); + if (Objects.nonNull(regionId) && !regionId.equals(0L)) { + // 能查得到 说明传入的code 直接转换为id + regionIdField.set(record, regionId); + } + } catch (Exception e) { + log.error("convertRegionCodeToId err :",e); + } + } + + public static Long convertRegionCodeToId(Long regionId) { + try { + String regionCode = String.valueOf(regionId); + if (Objects.isNull(codeUtil)) { + log.error("codeUtil is null"); + return null; + } + Long newRegionId = codeUtil.regionsCacheHelper.getIdByCode(regionCode); + if (Objects.nonNull(newRegionId) && !newRegionId.equals(0L)) { + // 能查得到 说明传入的code 直接转换为id + return newRegionId; + } + } catch (Exception e) { + log.error("convertRegionCodeToId err :",e); + } + return regionId; + } + + /** + * 求一个十进制数的 某个二进制位数上的值 + * + * @param number + * @param index + * @return + */ + public static Integer getBinaryStringIndexValue(Long number, int index) { + char[] chars = Long.toBinaryString(number).toCharArray(); + if (chars.length >= index + 1) { + return Integer.valueOf(String.valueOf(chars[index]), 2); + } + return 0; + } + + public static void complementaryRegion(List list, Long regionId) { + Map dataMap = CollUtils.listToMap(list, m -> m.getRegionId()); + if (Objects.isNull(codeUtil)){ + log.error("codeUtil is null"); + return; + } + List regions = codeUtil.regionsCacheHelper.listChildOnly(regionId); + for (RegionDTO region : regions) { + if (!dataMap.containsKey(region.getId())) { + MapDataVO mapDataVo = new MapDataVO(); + mapDataVo.setRegionId(region.getId()); + mapDataVo.setRegionName(region.getRegionName()); + mapDataVo.setRegionCode(region.getRegionCode()); + mapDataVo.setValue(0); + mapDataVo.setPercent("0%"); + list.add(mapDataVo); + } + } + } + + public static void complementaryRegions(List list, Long regionId) { + Map dataMap = CollUtils.listToMap(list, m -> m.getRegionId()); + if (Objects.isNull(codeUtil)){ + log.error("codeUtil is null"); + return; + } + List regions = codeUtil.regionsCacheHelper.listChildOnly(regionId); + for (RegionDTO region : regions) { + if (!dataMap.containsKey(region.getId())) { + OnlineVehicleRegionsPO onlineVehicleRegions = new OnlineVehicleRegionsPO(); + onlineVehicleRegions.setRegionId(region.getId()); + onlineVehicleRegions.setRegionName(region.getRegionName()); + onlineVehicleRegions.setRegionCode(region.getRegionCode()); + onlineVehicleRegions.setOnlineNum(0); + onlineVehicleRegions.setVehicleNum(0); + onlineVehicleRegions.setRate(BigDecimal.ZERO); + list.add(onlineVehicleRegions); + } + } + } + + // 生成验证码 + public static String codeFen(Integer length) { + String str = "0123456789"; + // 将字符串转换为一个新的字符数组。 + char[] VerificationCodeArray = str.toCharArray(); + Random random = new Random(); + int count = 0;// 计数器 + StringBuilder stringBuilder = new StringBuilder(); + while (true) { + // 随机生成一个随机数 + int index = random.nextInt(VerificationCodeArray.length); + char c = VerificationCodeArray[index]; + // 限制四位不重复数字 + if (stringBuilder.indexOf(c + "") == -1) { + stringBuilder.append(c); + // 计数器加1 + count++; + } + // 当count等于4时结束,随机生成四位数的验证码 + if (count == length) { + break; + } + } + return stringBuilder.toString(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelDownUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelDownUtil.java new file mode 100644 index 0000000..84e1747 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelDownUtil.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.common.util; + +import cn.hutool.poi.excel.ExcelUtil; +import com.alibaba.fastjson.JSON; +import com.ningdatech.basic.model.ApiResponse; +import com.ningdatech.basic.util.StrPool; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpStatus; + +import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.UUID; +import java.util.function.BiConsumer; + +/** + *

+ * ExcelDownUtil + *

+ * + * @author WendyYang + * @since 00:48 2022/11/5 + */ +@Slf4j +public class ExcelDownUtil { + + private static String encodeName(String name) { + String fileName; + try { + fileName = URLEncoder.encode(name, "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.error("文件名编码异常:", e); + fileName = UUID.randomUUID().toString().replace("-", ""); + } + return fileName; + } + + @SneakyThrows + private static void down(HttpServletResponse response, T param, BiConsumer consumer) { + response.setCharacterEncoding("utf-8"); + try { + consumer.accept(response, param); + } catch (Exception e) { + log.error("文件导出失败:", e); + response.reset(); + response.setContentType(StrPool.CONTENT_TYPE); + ApiResponse res = ApiResponse.of(HttpStatus.SC_BAD_REQUEST, "导出失败", null); + response.setStatus(HttpStatus.SC_BAD_REQUEST); + response.getWriter().println(JSON.toJSONString(res)); + } + } + + public static void downXls(HttpServletResponse response, T param, BiConsumer consumer) { + response.setContentType(ExcelUtil.XLS_CONTENT_TYPE); + down(response, param, consumer); + } + + public static void downXlsx(HttpServletResponse response, T param, BiConsumer consumer) { + response.setContentType(ExcelUtil.XLSX_CONTENT_TYPE); + down(response, param, consumer); + } + + public static void setFileName(String fileName, HttpServletResponse response) { + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodeName(fileName) + ".xls"); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelExportStyle.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelExportStyle.java new file mode 100644 index 0000000..798e765 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/ExcelExportStyle.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.common.util; + +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import org.apache.poi.ss.usermodel.*; + +/** + *

+ * ExcelExportStyle + *

+ * + * @author WendyYang + * @since 01:39 2022/11/5 + */ +public class ExcelExportStyle { + + public static HorizontalCellStyleStrategy formalStyle() { + // 表头样式策略 + WriteCellStyle headStyle = new WriteCellStyle(); + // 是否换行 + headStyle.setWrapped(false); + // 水平对齐方式 + headStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); + // 垂直对齐方式 + headStyle.setVerticalAlignment(VerticalAlignment.CENTER); + // 前景色 + headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + // 背景色 + headStyle.setFillBackgroundColor(IndexedColors.AUTOMATIC.getIndex()); + + // 设置为1时,单元格将被前景色填充 + headStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); + // 控制单元格是否应自动调整大小以适应文本过长时的大小 + headStyle.setShrinkToFit(false); + // 单元格边框类型 + headStyle.setBorderBottom(BorderStyle.NONE); + headStyle.setBorderLeft(BorderStyle.NONE); + headStyle.setBorderRight(BorderStyle.NONE); + headStyle.setBorderTop(BorderStyle.NONE); + // 单元格边框颜色 + headStyle.setLeftBorderColor(IndexedColors.BLACK.index); + headStyle.setRightBorderColor(IndexedColors.BLACK.index); + headStyle.setTopBorderColor(IndexedColors.BLACK.index); + headStyle.setBottomBorderColor(IndexedColors.BLACK.index); + // 字体策略 + WriteFont writeFont = new WriteFont(); + // 是否加粗/黑体 + writeFont.setBold(false); + // 字体颜色 + writeFont.setColor(Font.COLOR_NORMAL); + // 字体名称 + writeFont.setFontName("宋体"); + // 字体大小 + writeFont.setFontHeightInPoints((short) 11); + // 是否使用斜体 + writeFont.setItalic(false); + // 是否在文本中使用横线删除 + writeFont.setStrikeout(false); + // 设置要使用的文本下划线的类型 + writeFont.setUnderline(Font.U_NONE); + // 设置要使用的字符集 + writeFont.setCharset((int) Font.DEFAULT_CHARSET); + headStyle.setWriteFont(writeFont); + + // 内容样式策略策略 + WriteCellStyle contentStyle = new WriteCellStyle(); + contentStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); + contentStyle.setHorizontalAlignment(HorizontalAlignment.GENERAL); + contentStyle.setBorderBottom(BorderStyle.NONE); + contentStyle.setBorderLeft(BorderStyle.NONE); + contentStyle.setBorderRight(BorderStyle.NONE); + contentStyle.setBorderTop(BorderStyle.NONE); + contentStyle.setFillPatternType(FillPatternType.NO_FILL); + contentStyle.setWrapped(false); + return new HorizontalCellStyleStrategy(headStyle, contentStyle); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/OssUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/OssUtils.java new file mode 100644 index 0000000..5f95cad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/OssUtils.java @@ -0,0 +1,120 @@ +package com.ningdatech.carapi.common.util; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClient; +import com.aliyun.oss.model.ListObjectsRequest; +import com.aliyun.oss.model.OSSObjectSummary; +import com.aliyun.oss.model.ObjectListing; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/01 15:12 + */ +@Slf4j +public class OssUtils { + private static String ENDPOINT = "oss-cn-hangzhou-zwynet-d01-a.internet.cloud-inner.zj.gov.cn"; + //private fileout String ENDPOINT = "oss-cn-hangzhou.aliyuncs.com"; + private static String ACCESSKEYID = "oZFNfkh9YexqzTED"; + //private fileout String ACCESSKEYID = "LTAI4GL7uypycnBjiRn55rMG"; + private static String ACCESSKEYSECRET = "xewpDvACMzLQAGvY14fcXjkijBKSNH"; + //private fileout String ACCESSKEYSECRET = "qwYC7bW9bkStsko7qkLVnToAzj0Y98"; + private static String NEW_BUCKET = "sanzhuangche2"; + //private fileout String NEW_BUCKET = "devplat"; + + private static OSSClient client = null; + + + /** 创建OSSClient实例 + * + * @return + */ + private static OSSClient getOssClient(){ + client = new OSSClient(ENDPOINT, ACCESSKEYID, ACCESSKEYSECRET); + return client; + } + + /** 关闭OSSClient + * + */ + private static void close(){ + OssUtils.getOssClient().shutdown(); + } + + + /** + * 获取根目录下所有文件大小 + * @param bucketName + * @return + */ + public static Long getOss(String bucketName){ + try { + if (StringUtils.isBlank(bucketName)) { + bucketName = NEW_BUCKET; + } + long sizeTotal = 0L; + ObjectListing objectListing = null; + do { + // 列举bucket所有文件或目录,每次1000个 + ListObjectsRequest request = new ListObjectsRequest(bucketName).withDelimiter("/").withMaxKeys(1000); + // 列举bucket的指定目录(yourPrefix)下文件,每次1000个 + // ListObjectsRequest request = new ListObjectsRequest(bucketName).withMaxKeys(1000).withPrefix("yourPrefix"); + + if (objectListing != null) { + request.setMarker(objectListing.getNextMarker()); + } + objectListing = OssUtils.getOssClient().listObjects(request); + //获取当前文件夹下所有子目录大小 + List folders = objectListing.getCommonPrefixes(); + for (String folder : folders) { + sizeTotal = calculateFolderLength(OssUtils.getOssClient(), bucketName, folder)+sizeTotal; + } + + //获取当前文件夹下所有文件大小 + List sums = objectListing.getObjectSummaries(); + if (sums.size()==0){ + continue; + } + for (OSSObjectSummary s : sums) { + sizeTotal = sizeTotal+s.getSize(); + } + + } while (objectListing.isTruncated()); + //转换为TB + //sizeTotal = sizeTotal/1024/1024/1024/1024; + //转换为GB + sizeTotal = sizeTotal/1024/1024/1024; + //log.info(" 文件夹下所有子目录大小 : [{}] TB",sizeTotal); + log.info(" 文件夹下所有子目录大小 : [{}] GB",sizeTotal); + return sizeTotal; + }catch (Exception e){ + e.printStackTrace(); + return 0L; + }finally { + OssUtils.close(); + } + + } + private static long calculateFolderLength(OSS ossClient, String bucketName, String folder) { + long size = 0L; + ObjectListing objectListing = null; + do { + // MaxKey默认值为100,最大值为1000。 + ListObjectsRequest request = new ListObjectsRequest(bucketName).withPrefix(folder).withMaxKeys(1000); + if (objectListing != null) { + request.setMarker(objectListing.getNextMarker()); + } + objectListing = ossClient.listObjects(request); + List sums = objectListing.getObjectSummaries(); + for (OSSObjectSummary s : sums) { + size += s.getSize(); + } + } while (objectListing.isTruncated()); + return size; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/QrCoder.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/QrCoder.java new file mode 100644 index 0000000..18c7e29 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/QrCoder.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.common.util; + +import cn.hutool.extra.qrcode.QrCodeUtil; +import cn.hutool.extra.qrcode.QrConfig; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; + +/** + * @description: 二维码生成 + * @author: liushuai + * @date: 2022/8/11 15:04 + */ +@Slf4j +public class QrCoder { + /** + * 图片的宽度 + */ + private static final int IMAGE_WIDTH = 150; + /** + * 图片的高度(需按实际内容高度进行调整) + */ + private static final int IMAGE_HEIGHT = 150; + /** + * 二维码的宽度 + */ + private static final int QR_CODE_WIDTH = 145; + /** + * 二维码的高度 + */ + private static final int QR_CODE_HEIGHT = 145; + + + /** + * @param content 内容 + * @param footer 底部文字 + */ + public static BufferedImage createQrCode(String content, String footer) { + // 创建主模板图片 + BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); + Graphics2D main = image.createGraphics(); + // 设置图片的背景色 + main.setColor(Color.white); + main.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); + + // 动态高度 + int height = 0; + + //***************插入二维码图片*********************************************** + Graphics codePic = image.getGraphics(); + BufferedImage codeImg; + QrConfig config = new QrConfig(); + config.setWidth(QR_CODE_WIDTH); + config.setHeight(QR_CODE_HEIGHT); + config.setMargin(0); + codeImg = QrCodeUtil.generate(content, config); + // 绘制二维码 + codePic.drawImage(codeImg, (IMAGE_WIDTH - QR_CODE_WIDTH) / 2, height, QR_CODE_WIDTH, QR_CODE_HEIGHT, null); + codePic.dispose(); + + //**********************底部文字描述****************************************** + Graphics2D typeLeft = image.createGraphics(); + // 设置字体颜色 + typeLeft.setColor(Color.black); + // 设置字体 + Font footerFont = new Font("宋体", Font.PLAIN, 14); + typeLeft.setFont(footerFont); + typeLeft.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + // x开始的位置:(图片宽度-字体大小*字的个数)/2 + int startX = (IMAGE_WIDTH - (footerFont.getSize() * footer.length())) / 2 + 25; + height += QR_CODE_HEIGHT + 2.5; + typeLeft.drawString(footer, startX, height); + + // 返回image方便后续处理是生成图片还是生成base64字符串 + return image; + } + + + /** + * 生成图片文件 + * + * @param image 图片 + * @param fileLocation 地址 + */ + public static void createImage(BufferedImage image, String fileLocation) { + if (image != null) { + try { + ImageIO.write(image, "jpg", new File(fileLocation)); + } catch (IOException e) { + log.error("二维码生成图片失败:", e); + } + } + } + + public static void main(String[] args) { + BufferedImage bufferedImage = createQrCode("https://www.baidu.com", "编码:N20220001"); + createImage(bufferedImage, "/Users/qinxianyun/Downloads/test.jpg"); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/SignUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/SignUtil.java new file mode 100644 index 0000000..06d5c7b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/common/util/SignUtil.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.common.util; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.TreeMap; + +/** + * 签名校验 + * + * @author CMM + * @since 2023/06/05 11:55 + */ +@RequiredArgsConstructor +@Slf4j +@Component +public class SignUtil { + /** + * 生成签名 + * + * @param params 请求参数 + * @param key 密钥 + * @return 签名 + */ + public static String generateSign(Map params, String key) { + // 将参数按照字典序排序 + Map sortedParams = new TreeMap<>(params); + // 拼接参数 + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : sortedParams.entrySet()) { + sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); + } + sb.append("key=").append(key); + // 使用MD5进行加密 + String sign = null; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] bytes = md.digest(sb.toString().getBytes()); + sign = bytesToHexString(bytes); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return sign; + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param bytes 字节数组 + * @return 十六进制字符串 + */ + private static String bytesToHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(b & 0xFF); + if (hex.length() == 1) { + sb.append("0"); + } + sb.append(hex); + } + return sb.toString(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyArchivesController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyArchivesController.java new file mode 100644 index 0000000..62825d9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyArchivesController.java @@ -0,0 +1,155 @@ +package com.ningdatech.carapi.company.controller; + +import java.util.List; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.company.entity.CompanyCertificate; +import com.ningdatech.carapi.company.entity.CompanyCommonCredit; +import com.ningdatech.carapi.company.entity.dto.*; +import com.ningdatech.carapi.company.entity.vo.CompanyEmployeesVO; +import com.ningdatech.carapi.company.service.ICompanyArchivesService; +import com.ningdatech.carapi.company.service.ICompanyCertificateService; +import com.ningdatech.carapi.company.service.ICompanyCommonCreditService; +import com.ningdatech.carapi.company.service.ICompanyVehicleNotGetOnService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * @description: 企业档案管理 + * @author: liushuai + * @date: 2022/10/25 17:58 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-archives") +public class CompanyArchivesController { + private final ICompanyArchivesService iCompanyArchivesService; + private final ICompanyCertificateService iCompanyCertificateService; + private final ICompanyCommonCreditService iCompanyCommonCreditService; + + private final ICompanyVehicleNotGetOnService companyVehicleNotGetOnService; + + @GetMapping + public PageVo getCompanyList(@Valid CompanyListParamDTO param) { + return iCompanyArchivesService.getCompanyList(param); + } + + @GetMapping("/detail") + public ResCompanyArchivesDetailsDTO getCompanyDetail(@RequestParam(value = "companyId", required = false) Long companyId) { + return iCompanyArchivesService.getCompanyDetail(companyId); + } + + @GetMapping("/employees") + public List getCompanyEmployees(@RequestParam(value = "companyId", required = false) Long companyId) { + return iCompanyArchivesService.getCompanyEmployees(companyId); + } + + @PutMapping + public void updateCompanyInfo(@RequestBody ReqCompanyArchivesDetailsDTO reqCompanyArchivesDetailsDTO) { + iCompanyArchivesService.updateCompanyInfo(reqCompanyArchivesDetailsDTO); + } + + @GetMapping("/employees/count") + public PageVo getCompanyEmployeesList(CompanyListParamDTO param) { + return iCompanyArchivesService.getCompanyEmployeesList(param); + } + + @PostMapping("/certificate") + public void saveCertificate(@RequestBody CompanyCertificate companyCertificate) { + iCompanyCertificateService.save(companyCertificate); + } + + @GetMapping("/certificate") + public Page getCompanyCertificateList(@RequestParam(value = "companyId", required = false) Long companyId, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iCompanyCertificateService.getCertificates(new Page<>(pageNum, pageSize),companyId); + } + + @GetMapping("/basic/credit") + public PageVo getCompanyBasicCreditList(CompanyListParamDTO param) { + return iCompanyArchivesService.getCompanyBasicCreditList(param); + } + + @GetMapping("/basic/credit/detail") + public ResCompanyBasicCreditDetailDTO getCompanyBasicCreditDetail(@RequestParam(value = "companyId") Long companyId) { + return iCompanyArchivesService.getCompanyBasicCreditDetail(companyId); + } + + @GetMapping("/common/credit") + public PageVo getCompanyCommonCreditList(CompanyListParamDTO param) { + return iCompanyArchivesService.getCompanyCommonCreditList(param); + } + + @GetMapping("/common/credit/detail") + public Page getCompanyCommonCreditDetailList(@RequestParam(value = "companyId", required = false) Long companyId, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iCompanyCommonCreditService.getCompanyBasicCreditDetail(new Page<>(pageNum, pageSize),companyId); + } + + @ApiOperation("企业列表导出") + @GetMapping("/companyListExport") + public void companyListExport(CompanyListParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, iCompanyArchivesService::companyListExport); + } + + @ApiOperation("企业证书信息列表导出") + @GetMapping("/companyCertificateInformationListExport") + public void companyCertificateInformationListExport(CompanyListParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, iCompanyArchivesService::companyCertificateInformationListExport); + } + + @ApiOperation("企业基本信用列表导出") + @GetMapping("/companyBasicCreditListExport") + public void companyBasicCreditListExport(CompanyListParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, iCompanyArchivesService::companyBasicCreditListExport); + } + + @ApiOperation("企业公共信用列表导出") + @GetMapping("/companyCommonCreditListExport") + public void companyCommonCreditListExport(CompanyListParamDTO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, iCompanyArchivesService::companyCommonCreditListExport); + } + + /** + * 查询车辆未上车行驶记录 + * + * @param param / + * @return / + */ + @ApiOperation(value = "查询车辆未上车行驶记录-驾驶员ID", notes = "查询车辆未上车行驶记录") + @PostMapping("/vehicle/getNotGetOnList") + public PageVo getNotOnCarDriver(@Valid @RequestBody ReqNotGetOnCarDTO param) { + return iCompanyArchivesService.getNotOnCarList(param); + } + + @ApiOperation(value = "企业待审核列表查询", notes = "企业待审核列表查询") + @GetMapping("/toBeAuditList") + public PageVo queryToBeAudit(@Valid @ModelAttribute CompanyAuditPageQuery param) { + return iCompanyArchivesService.queryToBeAudit(param); + } + + @ApiOperation(value = "企业已审核列表查询", notes = "企业已审核列表查询") + @GetMapping("/auditedList") + public PageVo queryAuditedList(@Valid @ModelAttribute CompanyAuditPageQuery param) { + return iCompanyArchivesService.queryAuditedList(param); + } + + @ApiOperation(value = "企业审核", notes = "企业审核") + @PostMapping("/audit") + @WebLog + public Boolean handlerAudit(@Valid @RequestBody CompanyAuditDTO data) { + return iCompanyArchivesService.audit(data, LoginUserUtil.getUserId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyLargeScreenController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyLargeScreenController.java new file mode 100644 index 0000000..961b026 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/CompanyLargeScreenController.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.company.controller; + +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.dto.ResCompanyTotalDTO; +import com.ningdatech.carapi.company.service.ICompanyLargeScreenService; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @description: 企业管理大屏 + * @author: liushuai + * @date: 2022/10/25 10:12 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-large-screen") +public class CompanyLargeScreenController { + private final ICompanyLargeScreenService iCompanyLargeScreenService; + + @GetMapping("/statistics") + @ApiOperation(value = "按区域统计数量",notes = "按区域统计数量") + public List getCompanyCount(@RequestParam(value = "regionId") Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return iCompanyLargeScreenService.getCompanyTotalByRegionId(regionId); + } + + @GetMapping("/enterprise-type") + @ApiOperation(value = "按企业类型统计数量",notes = "按企业类型统计数量") + public List enterpriseType(@RequestParam(value = "regionId") Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return iCompanyLargeScreenService.countEnterpriseType(regionId); + } + + @GetMapping("/dead-accident") + @ApiOperation(value = "半年内发生死亡事故",notes = "半年内发生死亡事故") + public List deadAccident(@RequestParam(value = "regionId") Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return iCompanyLargeScreenService.deadAccident(regionId); + } + + @GetMapping("/mortar-quality") + @ApiOperation(value = "砂浆质量通道",notes = "砂浆质量通道") + public List mortarQuality(@RequestParam(value = "regionId") Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return iCompanyLargeScreenService.mortarQuality(regionId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyBlackListController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyBlackListController.java new file mode 100644 index 0000000..8bd93b0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyBlackListController.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.company.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditBlackListPageParam; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackDetailListDTO; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackListDTO; +import com.ningdatech.carapi.company.service.INdCompanyBlackListService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 企业失信名单 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-black-list") +public class NdCompanyBlackListController { + private final INdCompanyBlackListService iNdCompanyBlackListService; + + @GetMapping + private Page companyBlackList(@ModelAttribute CompanyCreditBlackListPageParam param) { + return iNdCompanyBlackListService.companyBlackList(param); + } + + @GetMapping("/info") + private List companyBlackInfoList(@RequestParam(value = "companyId", required = false) Long companyId) { + return iNdCompanyBlackListService.companyBlackInfoList(companyId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditDeductController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditDeductController.java new file mode 100644 index 0000000..f7ebe9b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditDeductController.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.company.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditDeduct; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditDeductPageParam; +import com.ningdatech.carapi.company.service.INdCompanyCreditDeductService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 平安办扣分 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-credit-deduct") +public class NdCompanyCreditDeductController { + private final INdCompanyCreditDeductService iNdCompanyCreditDeductService; + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + + @PostMapping + private Boolean saveCreditDeduct(@RequestBody NdCompanyCreditDeduct ndCompanyCreditDeduct) { + CompanyDTO company = companiesCacheHelper.getById(ndCompanyCreditDeduct.getCompanyId()); + if (0 != company.getRegionId() && null != company.getRegionId()){ + RegionDTO region = regionsCacheHelper.getByRegionId(company.getRegionId()); + ndCompanyCreditDeduct.setRegionName(region.getRegionName()); + } + return iNdCompanyCreditDeductService.save(ndCompanyCreditDeduct); + } + + @GetMapping + private Page getCreditDeductList(@ModelAttribute CompanyCreditDeductPageParam param) { + return iNdCompanyCreditDeductService.getCreditDeductList(param); + } + + @PutMapping + private Boolean updateCreditDeduct(@RequestBody NdCompanyCreditDeduct ndCompanyCreditDeduct) { + return iNdCompanyCreditDeductService.updateById(ndCompanyCreditDeduct); + } + + @DeleteMapping + private Boolean deleteCreditDeduct(@RequestBody NdCompanyCreditDeduct ndCompanyCreditDeduct) { + return iNdCompanyCreditDeductService.delete(ndCompanyCreditDeduct.getId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditInsideController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditInsideController.java new file mode 100644 index 0000000..3526fe6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditInsideController.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.company.controller; + +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditInside; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditInsidePageParam; +import com.ningdatech.carapi.company.service.INdCompanyCreditInsideService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 内部/联合检查 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-credit-inside") +@Valid +public class NdCompanyCreditInsideController { + private final INdCompanyCreditInsideService iNdCompanyCreditInsideService; + private final RegionsCacheHelper regionsCacheHelper; + + private final CompaniesCacheHelper companiesCacheHelper; + + @PostMapping + private Boolean saveCreditInside(@RequestBody NdCompanyCreditInside ndCompanyCreditInside) { + CompanyDTO company = companiesCacheHelper.getById(ndCompanyCreditInside.getCompanyId()); + if (0 != company.getRegionId() && null != company.getRegionId()){ + ndCompanyCreditInside.setRegionName(regionsCacheHelper.getDisplayName(company.getRegionId())); + } + return iNdCompanyCreditInsideService.save(ndCompanyCreditInside); + } + + @GetMapping + private Page getCreditInsideList(@Valid @ModelAttribute CompanyCreditInsidePageParam param) { + return iNdCompanyCreditInsideService.getList(param); + } + + @PutMapping + private Boolean updateCreditInside(@RequestBody NdCompanyCreditInside ndCompanyCreditInside) { + return iNdCompanyCreditInsideService.updateById(ndCompanyCreditInside); + } + + @DeleteMapping + private Boolean deleteCreditInside(@RequestBody NdCompanyCreditInside ndCompanyCreditInside) { + return iNdCompanyCreditInsideService.delete(ndCompanyCreditInside.getId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditLevelController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditLevelController.java new file mode 100644 index 0000000..c990c10 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditLevelController.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.company.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditLevelPageParam; +import com.ningdatech.carapi.company.service.INdCompanyCreditLevelService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 信用等级 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-credit-level") +public class NdCompanyCreditLevelController { + private final INdCompanyCreditLevelService iNdCompanyCreditLevelService; + + @GetMapping + private Page getCreditLevelList(@ModelAttribute CompanyCreditLevelPageParam param) { + return iNdCompanyCreditLevelService.getCreditLevelList(param); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditRewardController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditRewardController.java new file mode 100644 index 0000000..846af15 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyCreditRewardController.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.company.controller; + +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditReward; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditRewardPageParam; +import com.ningdatech.carapi.company.service.INdCompanyCreditRewardService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; + +import lombok.RequiredArgsConstructor; + + +/** + *

+ * 政府/行业嘉奖 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-credit-reward") +public class NdCompanyCreditRewardController { + private final INdCompanyCreditRewardService iNdCompanyCreditRewardService; + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + + @PostMapping + private Boolean saveCreditReward(@RequestBody NdCompanyCreditReward ndCompanyCreditReward) { + CompanyDTO company = companiesCacheHelper.getById(ndCompanyCreditReward.getCompanyId()); + if (0 != company.getRegionId() && null != company.getRegionId()){ + ndCompanyCreditReward.setRegionName(regionsCacheHelper.getDisplayName(company.getRegionId())); + } + return iNdCompanyCreditRewardService.save(ndCompanyCreditReward); + } + + @GetMapping + private Page getCreditRewardList(@ModelAttribute CompanyCreditRewardPageParam param) { + return iNdCompanyCreditRewardService.getCreditRewardList(param); + } + + @PutMapping + private Boolean updateCreditReward(@RequestBody NdCompanyCreditReward ndCompanyCreditReward) { + return iNdCompanyCreditRewardService.updateById(ndCompanyCreditReward); + } + + @DeleteMapping + private Boolean deleteCreditReward(@RequestBody NdCompanyCreditReward ndCompanyCreditReward) { + return iNdCompanyCreditRewardService.delete(ndCompanyCreditReward.getId()); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyProductManageController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyProductManageController.java new file mode 100644 index 0000000..6e4612c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyProductManageController.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.dto.ResProductManageDTO; +import com.ningdatech.carapi.company.service.INdCompanyProductManageService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 公司生产管理 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequestMapping("/api/v1/company-product-manage") +@RequiredArgsConstructor +public class NdCompanyProductManageController { + private final INdCompanyProductManageService iNdCompanyProductManageService; + + @GetMapping + public Page manageList(@RequestParam(value = "companyName", required = false) String companyName, + @RequestParam(value = "regionId", required = false) Long regionId, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iNdCompanyProductManageService.manageList(companyName, regionId, pageNum, pageSize); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyQualityManageController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyQualityManageController.java new file mode 100644 index 0000000..c358d76 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanyQualityManageController.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.company.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyQualityManage; +import com.ningdatech.carapi.company.entity.dto.ReqQualityManageDTO; +import com.ningdatech.carapi.company.entity.dto.ResQualityManageDTO; +import com.ningdatech.carapi.company.service.INdCompanyQualityManageService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 质量通报 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequestMapping("/api/v1/company-quality-manage") +@RequiredArgsConstructor +public class NdCompanyQualityManageController { + + private final INdCompanyQualityManageService iNdCompanyQualityManageService; + private final RegionsCacheHelper regionsCacheHelper; + + @PostMapping + public Boolean saveQualityManage(@RequestBody ReqQualityManageDTO reqQualityManageDTO) { + NdCompanyQualityManage entity = new NdCompanyQualityManage(); + BeanUtil.copyProperties(reqQualityManageDTO, entity); + entity.setDownloadCount(0); + entity.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + entity.setRegionName(regionsCacheHelper.getDisplayName(reqQualityManageDTO.getRegionId())); + return iNdCompanyQualityManageService.save(entity); + } + + @GetMapping + public Page qualityManageList(@RequestParam(value = "regionId", required = false) Long regionId, + @RequestParam(value = "year", required = false) String year, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iNdCompanyQualityManageService.qualityManageList(regionId, year, pageNum, pageSize); + } + + @DeleteMapping + public Boolean deleteQualityManage(@RequestBody ReqQualityManageDTO reqQualityManageDTO) { + return iNdCompanyQualityManageService.delete(reqQualityManageDTO.getId()); + } + + @ApiOperation("增加下载次数") + @GetMapping("/incrementDownCount/{id}") + public void incrementDownCount(@PathVariable Long id) { + iNdCompanyQualityManageService.incrementDownCount(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductDutyController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductDutyController.java new file mode 100644 index 0000000..26c268b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductDutyController.java @@ -0,0 +1,109 @@ +package com.ningdatech.carapi.company.controller; + +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductDuty; +import com.ningdatech.carapi.company.entity.dto.*; +import com.ningdatech.carapi.company.entity.vo.CompanySecurityCommitmentVO; +import com.ningdatech.carapi.company.entity.vo.CompanySecurityGovernmentVO; +import com.ningdatech.carapi.company.manage.CompanySecurityManage; +import com.ningdatech.carapi.company.service.ICompanySecurityCommitmentService; +import com.ningdatech.carapi.company.service.ICompanySecurityGovernmentService; +import com.ningdatech.carapi.company.service.INdCompanySecurityProductDutyService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 安全生产责任体系 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-security-product-duty") +public class NdCompanySecurityProductDutyController { + + private final INdCompanySecurityProductDutyService iNdCompanySecurityProductDutyService; + private final RegionsCacheHelper regionsCacheHelper; + + private final CompanySecurityManage securityManage; + + private final ICompanySecurityCommitmentService commitmentService; + + private final ICompanySecurityGovernmentService governmentService; + + @PostMapping + private Boolean saveSecurityProductDuty(@RequestBody ReqSecurityProductDutyDTO reqSecurityProductDutyDTO) { + NdCompanySecurityProductDuty entity = new NdCompanySecurityProductDuty(); + BeanUtil.copyProperties(reqSecurityProductDutyDTO, entity); + entity.setRegionName(regionsCacheHelper.getDisplayName(reqSecurityProductDutyDTO.getRegionId())); + return iNdCompanySecurityProductDutyService.save(entity); + } + + @GetMapping + private Page securityProductDutyList(@RequestParam(value = "regionId", required = false) Long regionId, + @RequestParam(value = "companyName", required = false) String companyName, + @RequestParam(value = "startTime", required = false) String startTime, + @RequestParam(value = "endTime", required = false) String endTime, + @RequestParam(value = "fileType") Integer fileType, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iNdCompanySecurityProductDutyService.securityProductDutyList(regionId, companyName,startTime,endTime, fileType, pageNum, pageSize); + } + + @ApiOperation(value = "安全承诺书列表", notes = "安全承诺书列表") + @GetMapping("/list-commitments") + public PageVo listCommitments(@Valid @ModelAttribute CompanySecurityCommitmentParam param) { + return securityManage.pageCommitments(param); + } + + @ApiOperation(value = "管理机构列表", notes = "管理机构列表") + @GetMapping("/list-governments") + public PageVo listGovernments(@Valid @ModelAttribute CompanySecurityCommitmentParam param) { + return securityManage.pageGovernments(param); + } + + @PostMapping("/upload-commitment") + private Boolean uploadCommitment(@Valid @RequestBody UploadCommitmentDTO dto) { + return securityManage.uploadCommitment(dto); + } + + @PostMapping("/upload-government") + private Boolean uploadGovernment(@Valid @RequestBody UploadGovernmentDTO dto) { + return securityManage.uploadGovernment(dto); + } + + @ApiOperation("删除管理机构文件") + @DeleteMapping("/delete-government") + public void deleteGovernmentFile(@RequestParam Long id) { + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + securityManage.deleteGovernmentFile(id,roleId); + } + + @ApiOperation("删除行业企业安全生产责任书") + @DeleteMapping("/delete-commitment") + public void deleteCommitmentFile(@RequestParam Long id) { + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + securityManage.deleteCommitmentFile(id,roleId); + } + + @ApiOperation("增加下载次数") + @GetMapping("/incrementDownCount/{id}") + public void incrementDownCount(@PathVariable Long id) { + securityManage.incrementDownCount(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductExecuteController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductExecuteController.java new file mode 100644 index 0000000..e4c2685 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductExecuteController.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.company.controller; + +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductExecute; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityProductExecuteParam; +import com.ningdatech.carapi.company.entity.dto.ReqSecurityProductExecuteDTO; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductExecuteDTO; +import com.ningdatech.carapi.company.entity.dto.UploadExecutionDTO; +import com.ningdatech.carapi.company.entity.vo.ComSecProExeVO; +import com.ningdatech.carapi.company.manage.CompanySecurityManage; +import com.ningdatech.carapi.company.service.INdCompanySecurityProductExecuteService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + + +/** + *

+ * 安全生产制度执行 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-security-product-execute") +public class NdCompanySecurityProductExecuteController { + + private final INdCompanySecurityProductExecuteService iNdCompanySecurityProductExecuteService; + + private final CompanySecurityManage securityManage; + @PostMapping + private Boolean saveSecurityProductExecute(@RequestBody ReqSecurityProductExecuteDTO reqSecurityProductExecuteDTO) { + NdCompanySecurityProductExecute entity = new NdCompanySecurityProductExecute(); + BeanUtil.copyProperties(reqSecurityProductExecuteDTO, entity); + entity.setRegionId(LoginUserUtil.loginUserDetail().getRegionId()); + entity.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + return iNdCompanySecurityProductExecuteService.save(entity); + } + + @GetMapping + private Page securityProductExecuteList(@RequestParam(value = "name", required = false) String name, + @RequestParam(value = "startTime", required = false) String startTime, + @RequestParam(value = "endTime", required = false) String endTime, + @RequestParam(value = "fileType") Integer fileType, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iNdCompanySecurityProductExecuteService.securityProductExecuteList(name, startTime, endTime,fileType, pageNum, pageSize); + } + + + @ApiOperation(value = "安全生产制度执行情况列表", notes = "安全生产制度执行情况列表") + @GetMapping("/safety-product-execute-list") + public PageVo listExecutes(@Valid @ModelAttribute CompanySecurityProductExecuteParam param) { + return securityManage.pageExecutes(param); + } + + @PostMapping("/upload-execution") + private Boolean uploadExecution(@Valid @RequestBody UploadExecutionDTO dto) { + return securityManage.uploadExecution(dto); + } + + @ApiOperation("删除安全生产制度执行情况文件") + @DeleteMapping("/delete-execute") + public void deleteCommitmentFile(@RequestParam Long id) { + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + securityManage.deleteExecuteFile(id,roleId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductRegulationsController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductRegulationsController.java new file mode 100644 index 0000000..88adc5d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/controller/NdCompanySecurityProductRegulationsController.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.company.controller; + + +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductRegulations; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityProductRegulationParam; +import com.ningdatech.carapi.company.entity.dto.ReqSecurityProductRegulationsDTO; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductRegulationsDTO; +import com.ningdatech.carapi.company.entity.dto.UploadRegulationDTO; +import com.ningdatech.carapi.company.entity.vo.ComSecProRegVO; +import com.ningdatech.carapi.company.manage.CompanySecurityManage; +import com.ningdatech.carapi.company.service.INdCompanySecurityProductRegulationsService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + + +/** + *

+ * 安全生产制度体系 前端控制器 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/company-security-product-regulations") +public class NdCompanySecurityProductRegulationsController { + private final INdCompanySecurityProductRegulationsService iNdCompanySecurityProductRegulationsService; + + private final CompanySecurityManage securityManage; + + @PostMapping + private Boolean saveSecurityProductRegulations(@RequestBody ReqSecurityProductRegulationsDTO reqSecurityProductRegulationsDTO) { + NdCompanySecurityProductRegulations entity = new NdCompanySecurityProductRegulations(); + BeanUtil.copyProperties(reqSecurityProductRegulationsDTO, entity); + entity.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + return iNdCompanySecurityProductRegulationsService.save(entity); + } + + @GetMapping + private Page securityProductRegulationsList(@RequestParam(value = "regulationsName", required = false) String regulationsName, + @RequestParam(value = "competentDepartment", required = false) String competentDepartment, + @RequestParam(value = "startTime", required = false) String startTime, + @RequestParam(value = "endTime", required = false) String endTime, + @RequestParam(value = "fileType") Integer fileType, + @RequestParam(value = "pageNumber") int pageNum, + @RequestParam(value = "pageSize") int pageSize) { + return iNdCompanySecurityProductRegulationsService.securityProductRegulationsList(regulationsName, competentDepartment, startTime, endTime, fileType, pageNum, pageSize); + } + + @ApiOperation(value = "安全生产制度体系列表", notes = "安全生产制度体系列表") + @GetMapping("/safety-education-training-list") + public PageVo listRegulations(@Valid @ModelAttribute CompanySecurityProductRegulationParam param) { + return securityManage.pageRegulations(param); + } + + @PostMapping("/upload-regulation") + private Boolean uploadRegulation(@Valid @RequestBody UploadRegulationDTO dto) { + return securityManage.uploadRegulation(dto); + } + + @ApiOperation("删除安全生产责任体系文件") + @DeleteMapping("/delete-regulation") + public void deleteCommitmentFile(@RequestParam Long id) { + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + securityManage.deleteRegulationFile(id,roleId); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyBasicCredit.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyBasicCredit.java new file mode 100644 index 0000000..ef91416 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyBasicCredit.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.company.entity; + +import java.io.Serializable; +import java.sql.Timestamp; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 企业基础信用信息 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@TableName("nd_company_basic_credit") +@ApiModel(value = "CompanyBasicCredit对象", description = "企业基础信用信息") +@Data +public class CompanyBasicCredit implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("基本管理信用分值") + private Integer basicCreditScore; + + @ApiModelProperty("注册资金") + private String registeredCapital; + + @ApiModelProperty("营业期限") + private String businessTerm; + + @ApiModelProperty("成立日期") + private Timestamp createTime; + + @ApiModelProperty("评价机构") + private String evaluationOrganization; + + @ApiModelProperty("企业网址") + private String website; + + @ApiModelProperty("经营范围") + private String natureBusiness; + + @ApiModelProperty("营业执照地址") + private String businessLicensePath; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("修改人") + private String updateBy; + + @ApiModelProperty("创建日期") + private Timestamp createOn; + + @ApiModelProperty("更新时间") + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCertificate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCertificate.java new file mode 100644 index 0000000..ffd9f5b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCertificate.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.sql.Timestamp; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 企业证书 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@TableName("nd_company_certificate") +@ApiModel(value = "CompanyCertificate对象", description = "企业证书") +@Data +public class CompanyCertificate implements Serializable { + + private static final long serialVersionUID = -2010985253469107704L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("证书名称") + private String certificateName; + + @ApiModelProperty("证书内容") + private String certificateContent; + + @ApiModelProperty("有效日期") + private Timestamp deadlineTime; + + @ApiModelProperty("证书路径") + private String certificatePath; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("修改人") + private String updateBy; + + @ApiModelProperty("创建日期") + private Timestamp createOn; + + @ApiModelProperty("更新时间") + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCommonCredit.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCommonCredit.java new file mode 100644 index 0000000..10758c7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyCommonCredit.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.sql.Timestamp; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 企业公共信用信息 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@TableName("nd_company_common_credit") +@ApiModel(value = "CompanyCommonCredit对象", description = "企业公共信用信息") +@Data +public class CompanyCommonCredit implements Serializable { + + private static final long serialVersionUID = 1260840521011159951L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("项目名称") + private String projectName; + + @ApiModelProperty("失信情况(0-失信,1-否)") + private String blackList; + + @ApiModelProperty("失信内容") + private String blackListContent; + + @ApiModelProperty("纠纷内容") + private String disputeContent; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("修改人") + private String updateBy; + + @ApiModelProperty("创建日期") + private Timestamp createOn; + + @ApiModelProperty("更新时间") + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyEmployees.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyEmployees.java new file mode 100644 index 0000000..b498f6b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyEmployees.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.company.entity; + +import java.io.Serializable; +import java.sql.Timestamp; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@TableName("nd_company_employees") +@ApiModel(value = "CompanyEmployees对象", description = "企业员工信息") +@Data +public class CompanyEmployees implements Serializable { + + private static final long serialVersionUID = 4740513010149140128L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private Timestamp createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private Timestamp updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("员工名称") + private String name; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("电话") + private String mobile; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("出生日期") + private Timestamp birthday; + + @ApiModelProperty("性别(0-女,1-男)") + private Integer sex; + + @ApiModelProperty("身份证号") + private String cardNum; + + @ApiModelProperty("学历(0-小学,1-初中,2-高中,3-专科,4-本科,5-研究生,6-博士)") + private Integer education; + + @ApiModelProperty("职务(1-领导,2车队长)") + private String employeesStatus; + + @ApiModelProperty("区域id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityCommitment.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityCommitment.java new file mode 100644 index 0000000..8faa6dc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityCommitment.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.sql.Timestamp; +import java.time.LocalDateTime; + +/** + * @Classname CompanySecurityCommitment + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +@TableName("nd_company_security_commitment") +@ApiModel(value = "CompanySecurityCommitment", description = "企业 承诺书") +public class CompanySecurityCommitment { + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("承诺对象") + private String commitmentTarget; + + @ApiModelProperty("承诺人") + private String promisee; + + @ApiModelProperty("文件") + private String file; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityGovernment.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityGovernment.java new file mode 100644 index 0000000..33e38e9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityGovernment.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.sql.Timestamp; +import java.time.LocalDateTime; + +/** + * @Classname CompanySecurityCommitment + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +@TableName("nd_company_security_government") +@ApiModel(value = "CompanySecurityGovernment", description = "企业管理机构") +public class CompanySecurityGovernment { + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("文件性质") + private String docNature; + + @ApiModelProperty("部门名称") + private String departmentName; + + @ApiModelProperty("文件") + private String file; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductExecute.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductExecute.java new file mode 100644 index 0000000..bf3faee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductExecute.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.company.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 安全生产制度执行 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("nd_company_security_product_execute_file") +@ApiModel(value = "CompanySecurityProductExecuteFile对象", description = "安全生产制度执行") +public class CompanySecurityProductExecute implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("通报名称") + private String fileName; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("文件ID") + private Long fileId; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("创建日期") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductRegulation.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductRegulation.java new file mode 100644 index 0000000..7359912 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanySecurityProductRegulation.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.company.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 安全生产制度体系 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("nd_company_security_product_regulations_file") +@ApiModel(value = "CompanySecurityProductRegulationsFile对象", description = "安全生产制度体系") +public class CompanySecurityProductRegulation implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("主管企业ID") + private Long companyId; + + @ApiModelProperty("主管企业名称") + private String companyName; + + @ApiModelProperty("制度名称") + private String fileName; + + @ApiModelProperty("文件类型") + private Integer fileType; + + @ApiModelProperty("制度文件ID") + private Long fileId; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("创建日期") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyVehicleNotGetOn.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyVehicleNotGetOn.java new file mode 100644 index 0000000..0a8bedd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/CompanyVehicleNotGetOn.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.company.entity; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 上车表 + *

+ * + * @author CMM + * @since 2023-01-10 + */ +@TableName("nd_company_vehicle_not_get_on") +@ApiModel(value = "CompanyVehicleNotGetOn对象", description = "未上车行驶表") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyVehicleNotGetOn implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("发生时间") + private LocalDate time; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyBlackList.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyBlackList.java new file mode 100644 index 0000000..23184fe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyBlackList.java @@ -0,0 +1,91 @@ +package com.ningdatech.carapi.company.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; + +/** + *

+ * 企业失信名单 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_black_list") +@Data +public class NdCompanyBlackList implements Serializable { + + private static final long serialVersionUID = 5717102444084515804L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 企业id + */ + private Long companyId; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 区域id + */ + private Long regionId; + + /** + * 描述 + */ + private String regionName; + + /** + * 失信类型 + */ + private String type; + + /** + * 失信日期 + */ + private LocalDateTime blackTime; + + /** + * 地点 + */ + private String site; + + /** + * 描述 + */ + private String content; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private LocalDateTime createOn; + + /** + * 更新时间 + */ + private LocalDateTime updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditDeduct.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditDeduct.java new file mode 100644 index 0000000..3c94f2d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditDeduct.java @@ -0,0 +1,90 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 平安办扣分 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_credit_deduct") +@Data +public class NdCompanyCreditDeduct implements Serializable { + + private static final long serialVersionUID = 5515044435449828584L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 企业id + */ + private Long companyId; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 区域id + */ + private Long regionId; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 检查指标类型 + */ + private String type; + + /** + * 备注 + */ + private String remark; + + /** + * 检查日期 + */ + private Timestamp checkTime; + + /** + * 分值 + */ + private Integer score; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditInside.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditInside.java new file mode 100644 index 0000000..b89c47a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditInside.java @@ -0,0 +1,105 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 内部/联合检查 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_credit_inside") +@Data +public class NdCompanyCreditInside implements Serializable { + + private static final long serialVersionUID = -2499448161989294318L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 企业id + */ + private Long companyId; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 区域id + */ + private Long regionId; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 驾驶员id + */ + private Long driverId; + + /** + * 驾驶员名称 + */ + private String driverName; + + /** + * 行政监管类别 + */ + private String type; + + /** + * 车牌号 + */ + private String carNo; + + /** + * 备注 + */ + private String remark; + + /** + * 检查日期 + */ + private Timestamp checkTime; + + /** + * 检查类型(1-联合,0-内部) + */ + private Boolean checkType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditLevel.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditLevel.java new file mode 100644 index 0000000..7725537 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditLevel.java @@ -0,0 +1,88 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 信用等级 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_credit_level") +@Data +public class NdCompanyCreditLevel implements Serializable { + + private static final long serialVersionUID = -9064829467713108944L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("年度") + private String year; + + @ApiModelProperty("信用等级") + private String level; + + @ApiModelProperty("企业信用评价总分") + private Integer score; + + @ApiModelProperty("公共信用评价分值 300分") + private Integer commonCreditScore; + + @ApiModelProperty("基本管理信用分值 120分") + private Integer basicCreditScore; + + @ApiModelProperty("安全生产管理信用分值 240分") + private Integer safeProductCreditScore; + + @ApiModelProperty("行业监管信用分值 240分") + private Integer industryRegulateCreditScore; + + @ApiModelProperty("行业荣誉加分 100分") + private Integer industryHonorBonus; + @ApiModelProperty("政府部门嘉奖分值 50分") + private Integer governmentAwardScore; + @ApiModelProperty("行业标杆分值 50分") + private Integer industryBenchMarkScore; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditReward.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditReward.java new file mode 100644 index 0000000..9419674 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyCreditReward.java @@ -0,0 +1,90 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 政府/行业嘉奖 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_credit_reward") +@Data +public class NdCompanyCreditReward implements Serializable { + + private static final long serialVersionUID = -1797772033801294340L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 企业id + */ + private Long companyId; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 区域id + */ + private Long regionId; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 嘉奖内容 + */ + private String content; + + /** + * 备注 + */ + private String remark; + + /** + * 日期 + */ + private Timestamp rewardTime; + + /** + * 嘉奖类型(1-行业标杆,0-政府) + */ + private Boolean rewardType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyProductManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyProductManage.java new file mode 100644 index 0000000..43691e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyProductManage.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 公司生产管理 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_product_manage") +@Data +public class NdCompanyProductManage implements Serializable { + + private static final long serialVersionUID = -7938578496309798035L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 企业id + */ + private Long companyId; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 区域id + */ + private Long regionId; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 生产线名称 + */ + private String productName; + + /** + * 发车日期 + */ + private Timestamp carStartTime; + + /** + * 设备状态 + */ + private String equipmentStatus; + + /** + * 当天累计生产方量 + */ + private Integer sumProductCount; + + /** + * 当天实际生产方量 + */ + private Integer realProductCount; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyQualityManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyQualityManage.java new file mode 100644 index 0000000..1634737 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanyQualityManage.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 质量通报 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_quality_manage") +@Data +public class NdCompanyQualityManage implements Serializable { + + private static final long serialVersionUID = 7983510778303663592L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域id + */ + private Long regionId; + + private Long companyId; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 通报年月 + */ + private Timestamp fileTime; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 下载次数 + */ + private Integer downloadCount; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductDuty.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductDuty.java new file mode 100644 index 0000000..df7bafa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductDuty.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 安全生产责任体系 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_security_product_duty") +@Data +public class NdCompanySecurityProductDuty implements Serializable { + + private static final long serialVersionUID = 8490965101415954146L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域id + */ + private Long regionId; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 企业id + */ + private Long companyId; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductExecute.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductExecute.java new file mode 100644 index 0000000..f71f9c9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductExecute.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 安全生产制度执行 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_security_product_execute") +@Data +public class NdCompanySecurityProductExecute implements Serializable { + + private static final long serialVersionUID = -1721410303272349639L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 通报名称 + */ + private String name; + + /** + * 区域id + */ + private Long regionId; + + private Long companyId; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductRegulations.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductRegulations.java new file mode 100644 index 0000000..045b3a1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/NdCompanySecurityProductRegulations.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.company.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 安全生产制度体系 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@TableName("nd_company_security_product_regulations") +@Data +public class NdCompanySecurityProductRegulations implements Serializable { + + private static final long serialVersionUID = 2870266919266149636L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域id + */ + private Long regionId; + + private Long companyId; + + /** + * 制度名称 + */ + private String regulationsName; + + /** + * 主管部门 + */ + private String competentDepartment; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 创建日期 + */ + private Timestamp createOn; + + /** + * 更新时间 + */ + private Timestamp updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditDTO.java new file mode 100644 index 0000000..7c2cb6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * 企业信息审核 + * @return + * @author CMM + * @since 2023/06/06 13:36 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CompanyAuditDTO", description = "企业信息审核") +public class CompanyAuditDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "企业ID",required = true) + @NotNull(message = "请传企业id!") + private Long id; + + @ApiModelProperty(value = "审核状态 2.审核通过 3.审核不通过",required = true) + @NotNull(message = "请传审核状态!") + private Integer auditStatus; + + @ApiModelProperty(value = "审核意见") + private String auditMind; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditPageQuery.java new file mode 100644 index 0000000..0dc54a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyAuditPageQuery.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.io.Serializable; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * @author CMM + * @description + * @since 2022/11/17 14:34 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CompanyAuditPageQuery", description = "企业审核") +public class CompanyAuditPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域Id") + private Long regionId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty(value = "公司类型 0管理企业 1生产企业 2物流企业 3其他") + private Integer companyType; + + @ApiModelProperty(value = "生产企业类型 2预拌砂浆生产企业 3预拌混凝土生产企业 4水泥生产企业") + private Integer productCompanyType; + + @ApiModelProperty("审核类型 1待审核 2已审核") + private Integer auditStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditBlackListPageParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditBlackListPageParam.java new file mode 100644 index 0000000..2815254 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditBlackListPageParam.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyCreditBlackListPageParam extends PagePo implements Serializable { + private Long regionId; + + private String companyName; + + private List regionIds; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditDeductPageParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditDeductPageParam.java new file mode 100644 index 0000000..d7cf43b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditDeductPageParam.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyCreditDeductPageParam extends PagePo implements Serializable { + private Long regionId; + + private String companyName; + + private String startTime; + + private String endTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditInsidePageParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditInsidePageParam.java new file mode 100644 index 0000000..edd8054 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditInsidePageParam.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyCreditInsidePageParam extends PagePo implements Serializable { + private Long regionId; + + private List regionIds; + + private String companyName; + + private String type; + + private String startTime; + + private String endTime; + + private Boolean checkType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditLevelPageParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditLevelPageParam.java new file mode 100644 index 0000000..eb106a9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditLevelPageParam.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyCreditLevelPageParam extends PagePo implements Serializable { + private Long regionId; + + private String companyName; + + private String year; + + private String level; + + private Boolean rewardType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditRewardPageParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditRewardPageParam.java new file mode 100644 index 0000000..59db3a6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyCreditRewardPageParam.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyCreditRewardPageParam extends PagePo implements Serializable { + private Long regionId; + + private String companyName; + + private String startTime; + + private String endTime; + + private Boolean rewardType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyListParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyListParamDTO.java new file mode 100644 index 0000000..dcda0a6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanyListParamDTO.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @description + * @since 2022/11/17 14:34 + */ +@Data +public class CompanyListParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域Id") + private Long regionId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty(value = "是否失信") + private Boolean blackList; + + @ApiModelProperty(value = "公司类型 1生产 2物流 3其他") + private Integer companyType; + + @ApiModelProperty(value = "公司类型列表") + private List companyTypeList; + + @ApiModelProperty(value = "生产企业类型") + private Integer productCompanyType; + + @ApiModelProperty("审核类型 0待审核 1已审核") + private Integer auditStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityCommitmentParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityCommitmentParam.java new file mode 100644 index 0000000..3c96961 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityCommitmentParam.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @Classname CompanySecurityCommitmentParam + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +public class CompanySecurityCommitmentParam extends PagePo { + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + private LocalDateTime endTime; + + @ApiModelProperty("文件性质") + private String docNature; + + @ApiModelProperty("部门名称") + private String departmentName; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductExecuteParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductExecuteParam.java new file mode 100644 index 0000000..590049b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductExecuteParam.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * CompanySecurityProductExecuteParam + * @return + * @author CMM + * @since 2023/05/24 21:58 + */ +@Data +public class CompanySecurityProductExecuteParam extends PagePo { + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("文件名称") + private String fileName; + + @ApiModelProperty("开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + private LocalDateTime endTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductRegulationParam.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductRegulationParam.java new file mode 100644 index 0000000..7de6787 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/CompanySecurityProductRegulationParam.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Classname CompanySecurityProductSystemParam + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +public class CompanySecurityProductRegulationParam extends PagePo { + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("文件名称") + private String fileName; + + @ApiModelProperty("主管单位名称") + private String companyName; + + /** + * @link SecurityProductRegulationFileType + */ + @ApiModelProperty("文件类型") + @NotNull(message = "文件类型不能为空!") + private Integer fileType; + + @ApiModelProperty("开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + private LocalDateTime endTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqCompanyArchivesDetailsDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqCompanyArchivesDetailsDTO.java new file mode 100644 index 0000000..011d3b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqCompanyArchivesDetailsDTO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.ningdatech.carapi.company.entity.CompanyBasicCredit; +import com.ningdatech.carapi.company.entity.CompanyEmployees; +import com.ningdatech.carapi.sys.entity.Company; +import lombok.Data; + +import java.util.List; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 09:27 + */ +@Data +public class ReqCompanyArchivesDetailsDTO { + private Company company; + private CompanyBasicCredit companyBasicCredit; + private List companyEmployeesList; + private List enterpriseTypes; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqNotGetOnCarDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqNotGetOnCarDTO.java new file mode 100644 index 0000000..1c5b584 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqNotGetOnCarDTO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.io.Serializable; +import java.time.LocalDate; + +import javax.validation.constraints.NotNull; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 未上车行驶记录查询实体 + * + * @author CMM + * @since 2023/01/10 09:24 + */ +@Data +public class ReqNotGetOnCarDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("公司ID") + @NotNull(message = "公司ID不能为空!") + private Long companyId; + + @ApiModelProperty("车牌") + private String carPlate; + + @ApiModelProperty("查询时间") + private LocalDate queryTime; + + @ApiModelProperty("表名拼接字符串") + private String tableNameStr; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqQualityManageDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqQualityManageDTO.java new file mode 100644 index 0000000..b2f3067 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqQualityManageDTO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: 质量通报 + * @author: liushuai + * @date: 2022/10/10 15:50 + */ +@Data +public class ReqQualityManageDTO { + private Long id; + private Long regionId; + + private Long companyId; + /** + * 通报年月 + */ + private Timestamp fileTime; + + /** + * 文件地址 + */ + private String filePath; + /** + * 文件名称 + */ + private String fileName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductDutyDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductDutyDTO.java new file mode 100644 index 0000000..b85e0b1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductDutyDTO.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +/** + * @description: 生成责任体系请求 + * @author: liushuai + * @date: 2022/10/11 14:55 + */ +@Data +public class ReqSecurityProductDutyDTO { + /** + * 区域id + */ + private Long regionId; + + /** + * 企业id + */ + private Long companyId; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 区域名称 + */ + private String regionName; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 安全生产责任质量通报文件类型 + */ + private Integer fileType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductExecuteDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductExecuteDTO.java new file mode 100644 index 0000000..fee56fe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductExecuteDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/11 15:46 + */ +@Data +public class ReqSecurityProductExecuteDTO { + /** + * 通报名称 + */ + private String name; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; + + /** + * 创建日期 + */ + private Timestamp createOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductRegulationsDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductRegulationsDTO.java new file mode 100644 index 0000000..f8a86d5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ReqSecurityProductRegulationsDTO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/11 15:26 + */ +@Data +public class ReqSecurityProductRegulationsDTO { + /** + * 区域id + */ + private Long regionId; + + /** + * 制度名称 + */ + private String regulationsName; + + /** + * 主管部门 + */ + private String competentDepartment; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDTO.java new file mode 100644 index 0000000..c56a262 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDTO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + * @description: 企业详情 + * @author: liushuai + * @date: 2022/10/26 08:44 + */ +@Data +public class ResCompanyArchivesDTO { + @ExcelProperty("id") + private Long id; + @ExcelProperty("企业名称") + private String name; + @ExcelProperty("区域ID") + private Long regionId; + @ExcelProperty("区域名") + private String regionName; + @ExcelProperty("企业简称") + private String sortName; + @ExcelProperty("企业地址") + private String address; + @ExcelProperty("企业类型") + private String carCompanyType; + @ExcelProperty("法人姓名") + private String legalPerson; + @ExcelProperty("创建时间") + private LocalDateTime createOn; + @ExcelProperty("安全培训人数") + private Long securityDrillPerson; + @ExcelProperty("培训合格证数") + private Long drillPassCount; + @ExcelProperty("企业风险等级") + private String dangerLevel; + @ExcelProperty("企业风险名称") + private String dangerLevelName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDetailsDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDetailsDTO.java new file mode 100644 index 0000000..2424191 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyArchivesDetailsDTO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 08:44 + */ +@Data +public class ResCompanyArchivesDetailsDTO { + private Integer companyType; + private String companyTypeName; + private String carCompanyType; + private String carCompanyTypeName; + private String businessLicense; + private String name; + private String fax; + private String email; + private Long regionId; + private String regionCode; + private String regionName; + private String address; + private Integer employeesNum; + private String bankName; + private String sortName; + private String dutyParagraph; + private String bankCardNo; + private String legalPerson; + private String legalPersonPhone; + private String legalPersonEmail; + private String contactPerson; + private String contactPhone; + private Integer companyStatus; + private String registeredCapital; + private Long securityDrillPerson; + private Long drillPassCount; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDTO.java new file mode 100644 index 0000000..bfa385b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDTO.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 10:15 + */ +@Data +public class ResCompanyBasicCreditDTO { + @ExcelProperty("id") + private Long id; + @ExcelProperty("企业名称") + private String name; + @ExcelProperty("区域名") + private String regionName; + @ExcelProperty("统一社会信用代码") + private String dutyParagraph; + @ExcelProperty("企业类型") + private String carCompanyType; + @ExcelProperty("法人") + private String legalPerson; + @ExcelProperty("联系地址") + private String address; + @ExcelProperty("基本管理信用分值") + private Integer basicCreditScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDetailDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDetailDTO.java new file mode 100644 index 0000000..d5ed36f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBasicCreditDetailDTO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 10:38 + */ +@Data +public class ResCompanyBasicCreditDetailDTO { + private String name; + private String dutyParagraph; + private String carCompanyType; + private String address; + private String legalPerson; + private String registeredCapital; + private Timestamp createTime; + private String businessTerm; + private String evaluationOrganization; + private String website; + private String natureBusiness; + private String contactPhone; + private String fax; + private String businessLicensePath; + private String regionCode; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackDetailListDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackDetailListDTO.java new file mode 100644 index 0000000..2fafa3e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackDetailListDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.time.LocalDateTime; + +import lombok.Data; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/11 16:21 + */ +@Data +public class ResCompanyBlackDetailListDTO { + /** + * 失信类型 + */ + private String type; + + /** + * 失信日期 + */ + private LocalDateTime blackTime; + + /** + * 地点 + */ + private String site; + + /** + * 描述 + */ + private String content; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackListDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackListDTO.java new file mode 100644 index 0000000..e045d64 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyBlackListDTO.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/11 16:07 + */ +@Data +public class ResCompanyBlackListDTO { + private Long regionId; + private String regionName; + + private Long companyId; + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyCommonCreditDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyCommonCreditDTO.java new file mode 100644 index 0000000..380df48 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyCommonCreditDTO.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.company.entity.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 10:21 + */ +@Data +public class ResCompanyCommonCreditDTO { + @ExcelProperty("id") + private Long id; + @ExcelProperty("企业名称") + private String name; + @ExcelProperty("区域名") + private String regionName; + @ExcelProperty("失信情况") + private Boolean blackList; + @ExcelProperty("公共信用评价分值") + private Integer commonCreditScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyEmployeesCountDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyEmployeesCountDTO.java new file mode 100644 index 0000000..9e7ac4c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyEmployeesCountDTO.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +/** + * @description: 员工统计 + * @author: liushuai + * @date: 2022/10/26 09:53 + */ +@Data +public class ResCompanyEmployeesCountDTO { + private Long id; + private String name; + private Long employeesNum; + private Long adminCount; + private Long driverCount; + private Long captainCount; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyTotalDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyTotalDTO.java new file mode 100644 index 0000000..a0223ca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResCompanyTotalDTO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: 公司统计 + * @author: liushuai + * @date: 2022/10/25 10:16 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ResCompanyTotalDTO { + + /** + * 区域名称 + */ + private String regionName; + private String regionCode; + private Long regionId; + private String name; + private Long fileId; + /** + * 企业数量 + */ + private Long companyCount; + private Long count; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResNotGetOnCarRecordDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResNotGetOnCarRecordDTO.java new file mode 100644 index 0000000..bf36b73 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResNotGetOnCarRecordDTO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.company.entity.dto; + +import java.time.LocalDate; + +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * 未上车行驶记录 + * + * @author CMM + * @since 2023/01/09 18:16 + */ +@Data +@ApiModel(value = "ResNotGetOnCarRecordDTO", description = "未上车行驶记录对象") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class ResNotGetOnCarRecordDTO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("时间") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate time; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResProductManageDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResProductManageDTO.java new file mode 100644 index 0000000..65e44cf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResProductManageDTO.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: 生产管理返回 + * @author: liushuai + * @date: 2022/10/10 14:46 + */ +@Data +public class ResProductManageDTO { + private Long regionId; + private String regionName; + private Long companyId; + private String companyName; + private String productName; + private Timestamp carStartTime; + private String equipmentStatus; + private Integer sumProductCount; + private Integer realProductCount; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResQualityManageDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResQualityManageDTO.java new file mode 100644 index 0000000..6cbb15d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResQualityManageDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: 质量通报 + * @author: liushuai + * @date: 2022/10/10 16:03 + */ +@Data +public class ResQualityManageDTO { + private Long id; + private Long regionId; + private String regionName; + /** + * 通报年月 + */ + private Timestamp fileTime; + /** + * 文件地址 + */ + private String filePath; + /** + * 下载次数 + */ + private Integer downloadCount; + /** + * 文件名称 + */ + private String fileName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductDutyDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductDutyDTO.java new file mode 100644 index 0000000..1fccbba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductDutyDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: 生成责任体系响应 + * @author: liushuai + * @date: 2022/10/11 14:55 + */ +@Data +public class ResSecurityProductDutyDTO { + /** + * 区域 + */ + private Long regionId; + private String regionName; + + /** + * 企业 + */ + private Long companyId; + private String companyName; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; + + /** + * 创建日期 + */ + private Timestamp createOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductExecuteDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductExecuteDTO.java new file mode 100644 index 0000000..8c377e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductExecuteDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/11 15:46 + */ +@Data +public class ResSecurityProductExecuteDTO { + /** + * 通报名称 + */ + private String name; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 文件类型 + */ + private Integer fileType; + + /** + * 创建日期 + */ + private Timestamp createOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductRegulationsDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductRegulationsDTO.java new file mode 100644 index 0000000..79a3e98 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/ResSecurityProductRegulationsDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.company.entity.dto; + +import lombok.Data; + +import java.sql.Timestamp; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/11 15:26 + */ +@Data +public class ResSecurityProductRegulationsDTO { + /** + * 制度名称 + */ + private String regulationsName; + + /** + * 主管部门 + */ + private String competentDepartment; + + /** + * 文件地址 + */ + private String filePath; + + /** + * 创建日期 + */ + private Timestamp createOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadCommitmentDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadCommitmentDTO.java new file mode 100644 index 0000000..f488fd6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadCommitmentDTO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.company.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Classname UploadCommitmentDTO + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +public class UploadCommitmentDTO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("承诺对象") + private String commitmentTarget; + + @ApiModelProperty("承诺人") + private String promisee; + + @ApiModelProperty("文件") + private String file; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadExecutionDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadExecutionDTO.java new file mode 100644 index 0000000..e4ddd9b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadExecutionDTO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * UploadRegulationDTO + * @return + * @author CMM + * @since 2023/05/24 21:26 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UploadExecutionDTO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("文件ID") + private Long fileId; + + @ApiModelProperty("上传文件名称") + private String fileName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadGovernmentDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadGovernmentDTO.java new file mode 100644 index 0000000..5fcf2e8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadGovernmentDTO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.company.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Classname UploadCommitmentDTO + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +public class UploadGovernmentDTO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("文件性质") + private String docNature; + + @ApiModelProperty("部门名称") + private String departmentName; + + @ApiModelProperty("文件") + private String file; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadRegulationDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadRegulationDTO.java new file mode 100644 index 0000000..37137ac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/dto/UploadRegulationDTO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.company.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * UploadRegulationDTO + * @return + * @author CMM + * @since 2023/05/24 21:26 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UploadRegulationDTO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("文件ID") + private Long fileId; + + @ApiModelProperty("上传文件名称") + private String fileName; + + @ApiModelProperty("上传文件类型") + private Integer fileType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyProductPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyProductPO.java new file mode 100644 index 0000000..d8a03a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyProductPO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.entity.po; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyProductPO { + + private Long regionId; + + private List regionIds; + + private String companyName; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyQualityPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyQualityPO.java new file mode 100644 index 0000000..34470f3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyQualityPO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.entity.po; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanyQualityPO { + + private Long regionId; + + private List regionIds; + + private String year; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductDutyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductDutyPO.java new file mode 100644 index 0000000..c3e4877 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductDutyPO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.company.entity.po; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @Classname CompanyProductPO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanySecurityProductDutyPO { + + private Long regionId; + + private List regionIds; + + private String companyName; + + private String startTime; + + private String endTime; + + private Integer fileType; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductExecutePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductExecutePO.java new file mode 100644 index 0000000..5741448 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductExecutePO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.entity.po; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Classname CompanySecurityProductExecutePO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanySecurityProductExecutePO { + + private String name; + + private String startTime; + + private String endTime; + + private Integer fileType; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductRegulationPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductRegulationPO.java new file mode 100644 index 0000000..d3ac4de --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanySecurityProductRegulationPO.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.company.entity.po; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Classname CompanySecurityProductExecutePO + * @Description + * @Date 2022/11/20 21:22 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CompanySecurityProductRegulationPO { + + private String regulationsName; + + private String competentDepartment; + + private String startTime; + + private String endTime; + + private Integer fileType; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyVehicleNotGetOnPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyVehicleNotGetOnPO.java new file mode 100644 index 0000000..d5b0bc0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/CompanyVehicleNotGetOnPO.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.company.entity.po; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 公司车辆未上车行驶表对象 + * + * @author CMM + * @since 2023/01/10 15:40 + */ +@Data +public class CompanyVehicleNotGetOnPO { + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("Gps数据车辆状态") + private Long status; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/ResCompanyTotalPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/ResCompanyTotalPO.java new file mode 100644 index 0000000..e517e88 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/po/ResCompanyTotalPO.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.company.entity.po; + +import lombok.Data; + +/** + * @description: 公司统计 + * @author: liushuai + * @date: 2022/10/25 10:16 + */ +@Data +public class ResCompanyTotalPO { + private Long regionId; + /** + * 区域名称 + */ + private String regionName; + private String regionCode; + + private String name; + + /** + * 企业数量 + */ + private Long companyCount; + private Long count; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProExeVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProExeVO.java new file mode 100644 index 0000000..f5a0c1e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProExeVO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.company.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * ComSecProExeVO + * @return + * @author CMM + * @since 2023/05/24 21:56 + */ +@Data +@ApiModel(value = "ComSecProExeVO", description = "企业安全生产制度执行通报列表VO") +public class ComSecProExeVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("通报名称") + private String fileName; + + @ApiModelProperty("通报文件ID") + private String fileId; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProRegVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProRegVO.java new file mode 100644 index 0000000..32717a8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/ComSecProRegVO.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.company.entity.vo; + +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Classname ComSecProRegVO + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +@ApiModel(value = "ComSecProRegVO", description = "企业安全生产制度体系列表VO") +public class ComSecProRegVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("制度名称") + private String fileName; + + @ApiModelProperty("主管企业id") + private Long companyId; + + @ApiModelProperty("主管企业名称") + private String companyName; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("文件类型") + private Integer fileType; + + @ApiModelProperty("文件类型名称") + private String fileTypeName; + + @ApiModelProperty("文件ID") + private Long fileId; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanyEmployeesVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanyEmployeesVO.java new file mode 100644 index 0000000..0f6eb00 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanyEmployeesVO.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.company.entity.vo; + +import java.io.Serializable; +import java.sql.Timestamp; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@ApiModel(value = "CompanyEmployees对象", description = "企业员工信息") +@Data +public class CompanyEmployeesVO implements Serializable { + + private static final long serialVersionUID = 4740513010149140128L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("创建时间") + private Timestamp createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private Timestamp updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("员工名称") + private String name; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("电话") + private String mobile; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("出生日期") + private Timestamp birthday; + + @ApiModelProperty("性别(0-女,1-男)") + private Integer sex; + + @ApiModelProperty("身份证号") + private String cardNum; + + @ApiModelProperty("学历(0-小学,1-初中,2-高中,3-专科,4-本科,5-研究生,6-博士)") + private Integer education; + + @ApiModelProperty("学历(0-小学,1-初中,2-高中,3-专科,4-本科,5-研究生,6-博士)") + private String educationName; + + @ApiModelProperty("职务(1-领导,2车队长)") + private String employeesStatus; + + @ApiModelProperty("区域id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityCommitmentVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityCommitmentVO.java new file mode 100644 index 0000000..b020be8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityCommitmentVO.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.company.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @Classname CompanySecurityCommitment + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +@ApiModel(value = "CompanySecurityCommitment", description = "企业 承诺书") +public class CompanySecurityCommitmentVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业id") + private String companyName; + + @ApiModelProperty("承诺对象") + private String commitmentTarget; + + @ApiModelProperty("承诺人") + private String promisee; + + @ApiModelProperty("文件") + private String file; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityGovernmentVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityGovernmentVO.java new file mode 100644 index 0000000..200f0ec --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/entity/vo/CompanySecurityGovernmentVO.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.company.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @Classname CompanySecurityGovernment + * @Description + * @Date 2023/5/23 16:23 + * @Author PoffyZhang + */ +@Data +@ApiModel(value = "CompanySecurityGovernment", description = "企业管理机构") +public class CompanySecurityGovernmentVO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("企业id") + private Long companyId; + + @ApiModelProperty("企业id") + private String companyName; + + @ApiModelProperty("文件性质") + private String docNature; + + @ApiModelProperty("部门名称") + private String departmentName; + + @ApiModelProperty("文件") + private String file; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyBlackListTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyBlackListTypeEnum.java new file mode 100644 index 0000000..c972d68 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyBlackListTypeEnum.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.company.enumeration; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 企业失信类型枚举 + * @author CMM + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "CompanyBlackListTypeEnum", description = "企业失信类型-枚举") +public enum CompanyBlackListTypeEnum { + /** + * 存在不正当竞争关系 + */ + + UNFAIR_COMPETITION_RELATION(0, "存在不正当竞争关系"), + + /** + * 重大质量事故 + */ + MAJOR_QUALITY_ACCIDENT(1, "重大质量事故"), + + /** + * 严重扰乱市场秩序 + */ + DISRUPT_MARKET_ORDER(2,"严重扰乱市场秩序"), + + /** + * 严重环保问题 + */ + ENVIRONMENTAL_PROBLEMS(3,"严重环保问题"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (CompanyBlackListTypeEnum t : CompanyBlackListTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static CompanyBlackListTypeEnum getEnumByValue(Integer code) { + if(Objects.isNull(code)){ + return null; + } + for (CompanyBlackListTypeEnum t : CompanyBlackListTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t; + } + } + return null; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyCreditLevelEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyCreditLevelEnum.java new file mode 100644 index 0000000..1eae390 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyCreditLevelEnum.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.company.enumeration; + +import org.apache.commons.lang3.StringUtils; + +import lombok.Getter; + +/** + * CompanyCreditLevelEnum + * @return + * @author CMM + * @since 2023/05/26 13:36 + */ +@Getter +public enum CompanyCreditLevelEnum { + /** + * 企业信用等级 + */ + A("A", "信用优秀"), + B("B", "信用良好"), + C("C","信用一般"), + D("D","信用较差"), + E("E","信用差"); + + private final String code; + private final String desc; + + CompanyCreditLevelEnum(String code, String desc) { + this.code = code; + this.desc = desc; + } + + public static String getDescByCode(String code) { + if(StringUtils.isBlank(code)){ + return StringUtils.EMPTY; + } + for (CompanyCreditLevelEnum t : CompanyCreditLevelEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static String getCodeByDesc(String desc) { + if(StringUtils.isBlank(desc)){ + return null; + } + for (CompanyCreditLevelEnum t : CompanyCreditLevelEnum.values()) { + if (desc.equals(t.getDesc())) { + return t.code; + } + } + return null; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyTypeEnum.java new file mode 100644 index 0000000..b65d36d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/CompanyTypeEnum.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.company.enumeration; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + *

+ * CompanyType + *

+ * + * @author WendyYang + * @since 16:43 2022/11/3 + */ +@Getter +public enum CompanyTypeEnum { + /** + * 管理单位 + */ + MANAGE_BU(0, "管理企业"), + PRODUCT_BU(1, "生产企业"), + LOGISTICS_BU(2,"物流企业"), + OTHER(3,"其他"); + + private final Integer code; + private final String desc; + + CompanyTypeEnum(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (CompanyTypeEnum t : CompanyTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static Integer getCodeByDesc(String desc) { + if(Objects.isNull(desc)){ + return null; + } + for (CompanyTypeEnum t : CompanyTypeEnum.values()) { + if (desc.equals(t.getDesc())) { + return t.code; + } + } + return null; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/ProductCompanyType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/ProductCompanyType.java new file mode 100644 index 0000000..03e8c03 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/ProductCompanyType.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.company.enumeration; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + *

+ * ProductCompanyType + *

+ * + * @author WendyYang + * @since 16:43 2022/11/3 + */ +@Getter +public enum ProductCompanyType { + /** + * 生产企业类型 + */ + MORTAR(2L, "预拌砂浆生产企业"), + CONCRETE(3L, "预拌混凝土生产企业"), + CEMENT(4L,"水泥生产企业"); + + private final Long code; + private final String value; + + ProductCompanyType(Long code, String value) { + this.code = code; + this.value = value; + } + + public static String getDescByCode(Long code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (ProductCompanyType t : ProductCompanyType.values()) { + if (code.equals(t.getCode())) { + return t.value; + } + } + return StringUtils.EMPTY; + } + + public static Long getCodeByDesc(String desc) { + if(Objects.isNull(desc)){ + return null; + } + for (ProductCompanyType t : ProductCompanyType.values()) { + if (desc.equals(t.getValue())) { + return t.code; + } + } + return null; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductFileType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductFileType.java new file mode 100644 index 0000000..2f00bf2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductFileType.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.company.enumeration; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 企业安全主体责任-通报文件类型 + * @return + * @author CMM + * @since 2023/05/17 14:42 + */ +@Getter +@AllArgsConstructor +public enum SecurityProductFileType { + + MANAGE_BU(0, "管理部门"), + COMPANY_INNER(1, "企业内部"), + REGULATION_NOTICE(2,"监管通报"), + HIGHER_CHECK(3,"上级检查"); + + + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (SecurityProductFileType t : SecurityProductFileType.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductRegulationFileType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductRegulationFileType.java new file mode 100644 index 0000000..03a0472 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/enumeration/SecurityProductRegulationFileType.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.company.enumeration; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 企业安全主体责任-通报文件类型 + * @return + * @author CMM + * @since 2023/05/17 14:42 + */ +@Getter +@AllArgsConstructor +public enum SecurityProductRegulationFileType { + + ALL_SAFETY_EDUCATION_TRAIN_DATA(0, "全员安全教育培训考试资料"), + DRIVER_SAFETY_EDUCATION_TRAIN_LEDGER(1, "驾驶员安全教育培训台账"), + SAFETY_MANAGE_REGIME(2,"安全管理制度"), + SAFETY_PRODUCT_WORK_PLAN(3,"安全生产工作计划"), + SAFETY_PRODUCT_MEETING_RECORD(4,"安全生产会议记录"), + COMMERCIAL_CONCRETE_COMPANY_ACCIDENT_SUMMARY(5,"商品混凝土企业事故案例汇编"); + + + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (SecurityProductRegulationFileType t : SecurityProductRegulationFileType.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/manage/CompanySecurityManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/manage/CompanySecurityManage.java new file mode 100644 index 0000000..e06d544 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/manage/CompanySecurityManage.java @@ -0,0 +1,431 @@ +package com.ningdatech.carapi.company.manage; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.CompanySecurityCommitment; +import com.ningdatech.carapi.company.entity.CompanySecurityGovernment; +import com.ningdatech.carapi.company.entity.CompanySecurityProductExecute; +import com.ningdatech.carapi.company.entity.CompanySecurityProductRegulation; +import com.ningdatech.carapi.company.entity.dto.*; +import com.ningdatech.carapi.company.entity.vo.ComSecProExeVO; +import com.ningdatech.carapi.company.entity.vo.ComSecProRegVO; +import com.ningdatech.carapi.company.entity.vo.CompanySecurityCommitmentVO; +import com.ningdatech.carapi.company.entity.vo.CompanySecurityGovernmentVO; +import com.ningdatech.carapi.company.service.ICompanySecurityCommitmentService; +import com.ningdatech.carapi.company.service.ICompanySecurityGovernmentService; +import com.ningdatech.carapi.company.service.ICompanySecurityProductExecuteFileService; +import com.ningdatech.carapi.company.service.ICompanySecurityProductRegulationsFileService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname CompanySecurityManage + * @Description + * @Date 2023/5/23 17:32 + * @Author PoffyZhang + */ +@Component +@Slf4j +@AllArgsConstructor +public class CompanySecurityManage { + + private final ICompanySecurityCommitmentService commitmentService; + private final ICompanySecurityGovernmentService governmentService; + private final CompanyService companyService; + private final ICompanySecurityProductRegulationsFileService regulationsFileService; + private final ICompanySecurityProductExecuteFileService executeFileService; + + /** + * 上传安全承诺书 + * @param dto + * @return + */ + public Boolean uploadCommitment(UploadCommitmentDTO dto) { + CompanySecurityCommitment commitment = BeanUtil.copyProperties(dto,CompanySecurityCommitment.class); + commitment.setCreateOn(LocalDateTime.now()); + return commitmentService.save(commitment); + } + + /** + * 上传安全管理机构 + * @param dto + * @return + */ + public Boolean uploadGovernment(UploadGovernmentDTO dto) { + CompanySecurityGovernment government = BeanUtil.copyProperties(dto,CompanySecurityGovernment.class); + government.setCreateOn(LocalDateTime.now()); + return governmentService.save(government); + } + + public PageVo pageCommitments(CompanySecurityCommitmentParam param) { + Page page = param.page(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityCommitment.class) + .ge(Objects.nonNull(param.getStartTime()), CompanySecurityCommitment::getCreateOn, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), CompanySecurityCommitment::getCreateOn, param.getEndTime()) + .eq(Objects.nonNull(param.getRegionId()), CompanySecurityCommitment::getRegionId, param.getRegionId()); + + //如果需要公司名称模糊匹配 + if(StringUtils.isNotBlank(param.getCompanyName())){ + List companies = companyService.list(Wrappers.lambdaQuery(Company.class) + .like(Company::getName, param.getCompanyName())); + if(CollUtil.isEmpty(companies)) { + return PageVo.empty(); + } + List companyIds = companies.stream().map(Company::getId).collect(Collectors.toList()); + wrapper.in(CompanySecurityCommitment::getCompanyId,companyIds); + + } + + commitmentService.pageDataScope(page,wrapper,param); + if(0L == page.getTotal()){ + return PageVo.empty(); + } + List res = page.getRecords().stream().map(data -> { + CompanySecurityCommitmentVO vo = BeanUtil.copyProperties(data,CompanySecurityCommitmentVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res,page.getTotal()); + } + + + + public PageVo pageGovernments(CompanySecurityCommitmentParam param) { + // Page page = param.page(); + + Integer pageNumber = param.getPageNumber(); + Integer pageSize = param.getPageSize(); + + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityGovernment.class) + .ge(Objects.nonNull(param.getStartTime()), CompanySecurityGovernment::getCreateOn, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), CompanySecurityGovernment::getCreateOn, param.getEndTime()) + .like(Objects.nonNull(param.getDocNature()),CompanySecurityGovernment::getDocNature,param.getDocNature()) + .like(Objects.nonNull(param.getDepartmentName()),CompanySecurityGovernment::getDepartmentName,param.getDepartmentName()) + .eq(Objects.nonNull(param.getRegionId()), CompanySecurityGovernment::getRegionId, param.getRegionId()); + //如果需要公司名称模糊匹配 + if(StringUtils.isNotBlank(param.getCompanyName())){ + List companies = companyService.list(Wrappers.lambdaQuery(Company.class) + .like(Company::getName, param.getCompanyName())); + if(CollUtil.isEmpty(companies)) { + return PageVo.empty(); + } + List companyIds = companies.stream().map(Company::getId).collect(Collectors.toList()); + wrapper.in(CompanySecurityGovernment::getCompanyId,companyIds); + } + + List governmentList = governmentService.dataScopeList(wrapper, param); + + // 省级部门上传的文件,下级账号也要能看到 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(CompanySecurityGovernment.class); + if (Objects.nonNull(param.getRegionId())){ + queryWrapper.eq(CompanySecurityGovernment::getRegionId,param.getRegionId()); + }else { + queryWrapper.eq(CompanySecurityGovernment::getRegionId, DefValConstants.ZJREGION_ID); + } + queryWrapper.ge(Objects.nonNull(param.getStartTime()), CompanySecurityGovernment::getCreateOn, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), CompanySecurityGovernment::getCreateOn, param.getEndTime()) + .like(Objects.nonNull(param.getDocNature()),CompanySecurityGovernment::getDocNature,param.getDocNature()) + .like(Objects.nonNull(param.getDepartmentName()),CompanySecurityGovernment::getDepartmentName,param.getDepartmentName()); + //如果需要公司名称模糊匹配 + if(StringUtils.isNotBlank(param.getCompanyName())){ + List companies = companyService.list(Wrappers.lambdaQuery(Company.class) + .like(Company::getName, param.getCompanyName())); + List companyIds = companies.stream().map(Company::getId).collect(Collectors.toList()); + queryWrapper.in(CompanySecurityGovernment::getCompanyId,companyIds); + } + List governments = governmentService.list(queryWrapper); + governmentList.addAll(governments); + } + + if (CollUtil.isEmpty(governmentList)){ + return PageVo.empty(); + } + + List records = governmentList.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + + List res = records.stream().map(data -> { + CompanySecurityGovernmentVO vo = BeanUtil.copyProperties(data,CompanySecurityGovernmentVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res,governmentList.size()); + + + // governmentService.pageDataScope(page,wrapper,param); + //if(0L == page.getTotal()){ + // return PageVo.empty(); + //} + + //List res = page.getRecords().stream().map(data -> { + // CompanySecurityGovernmentVO vo = BeanUtil.copyProperties(data,CompanySecurityGovernmentVO.class); + // CodeUtil.searchCompanyNameAndRegionName(vo); + // return vo; + //}).collect(Collectors.toList()); + //return PageVo.of(res,page.getTotal()); + } + + public PageVo pageRegulations(CompanySecurityProductRegulationParam param) { + // Page page = param.page(); + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + Integer pageNumber = param.getPageNumber(); + Integer pageSize = param.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityProductRegulation.class) + .eq(CompanySecurityProductRegulation::getFileType,param.getFileType()) + .ge(Objects.nonNull(param.getStartTime()), CompanySecurityProductRegulation::getCreateOn, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), CompanySecurityProductRegulation::getCreateOn, param.getEndTime()) + .like(Objects.nonNull(param.getFileName()),CompanySecurityProductRegulation::getFileName,param.getFileName()) + .like(Objects.nonNull(param.getCompanyName()), CompanySecurityProductRegulation::getCompanyName, param.getCompanyName()); + + List regulationList = regulationsFileService.dataScopeList(wrapper, param); + + // 省级部门上传的文件(所属区域为省级),按照文件类型,下级账号也要能看到 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) { + List regulations = regulationsFileService.list(Wrappers.lambdaQuery(CompanySecurityProductRegulation.class) + .eq(CompanySecurityProductRegulation::getRegionId, DefValConstants.ZJREGION_ID) + .eq(CompanySecurityProductRegulation::getFileType,param.getFileType())); + regulationList.addAll(regulations); + } + + if (CollUtil.isEmpty(regulationList)){ + return PageVo.empty(); + } + + List records = regulationList.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + + List res = records.stream() + .map(data -> { + ComSecProRegVO vo = BeanUtil.copyProperties(data, ComSecProRegVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }) + .collect(Collectors.toList()); + return PageVo.of(res,regulationList.size()); + + //regulationsFileService.pageDataScope(page,wrapper,param); + //if(0L == page.getTotal()){ + // return PageVo.empty(); + //} + //List res = page.getRecords().stream().map(data -> { + // ComSecProRegVO vo = BeanUtil.copyProperties(data,ComSecProRegVO.class); + // return vo; + //}).collect(Collectors.toList()); + //return PageVo.of(res,page.getTotal()); + } + + public Boolean uploadRegulation(UploadRegulationDTO dto) { + CompanySecurityProductRegulation regulation = BeanUtil.copyProperties(dto,CompanySecurityProductRegulation.class); + regulation.setCreateOn(LocalDateTime.now()); + regulation.setCreateBy(LoginUserUtil.getUserId()); + regulation.setUpdateOn(LocalDateTime.now()); + regulation.setUpdateBy(LoginUserUtil.getUserId()); + return regulationsFileService.save(regulation); + } + + public PageVo pageExecutes(CompanySecurityProductExecuteParam param) { + //Page page = param.page(); + Integer pageNumber = param.getPageNumber(); + Integer pageSize = param.getPageSize(); + + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityProductExecute.class) + .ge(Objects.nonNull(param.getStartTime()), CompanySecurityProductExecute::getCreateOn, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), CompanySecurityProductExecute::getCreateOn, param.getEndTime()) + .like(Objects.nonNull(param.getFileName()),CompanySecurityProductExecute::getFileName,param.getFileName()); + List executeList = executeFileService.dataScopeList(wrapper, param); + // 省级部门上传的文件(所属区域为省级),下级账号也要能看到 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) { + List executes = executeFileService.list(Wrappers.lambdaQuery(CompanySecurityProductExecute.class) + .eq(CompanySecurityProductExecute::getRegionId, DefValConstants.ZJREGION_ID)); + executeList.addAll(executes); + } + + if (CollUtil.isEmpty(executeList)){ + return PageVo.empty(); + } + + List records = executeList.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + + List res = records.stream() + .map(data -> { + ComSecProExeVO vo = BeanUtil.copyProperties(data, ComSecProExeVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }) + .collect(Collectors.toList()); + return PageVo.of(res,executeList.size()); + + //executeFileService.pageDataScope(page,wrapper,param); + //if(0L == page.getTotal()){ + // return PageVo.empty(); + //} + //List res = page.getRecords().stream().map(data -> { + // ComSecProExeVO vo = BeanUtil.copyProperties(data,ComSecProExeVO.class); + // return vo; + //}).collect(Collectors.toList()); + //return PageVo.of(res,page.getTotal()); + } + + public Boolean uploadExecution(UploadExecutionDTO dto) { + CompanySecurityProductExecute execution = BeanUtil.copyProperties(dto,CompanySecurityProductExecute.class); + execution.setCreateOn(LocalDateTime.now()); + execution.setCreateBy(LoginUserUtil.getUserId()); + execution.setUpdateOn(LocalDateTime.now()); + execution.setUpdateBy(LoginUserUtil.getUserId()); + return executeFileService.save(execution); + } + + public void deleteGovernmentFile(Long id, Long roleId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityGovernment.class); + CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + CompanySecurityGovernment government = governmentService.getOne(wrapper); + if (Objects.isNull(government)){ + throw new BizException("文件无法删除!"); + } + //CompanySecurityGovernment government = governmentService.getById(id); + + // 如果文件是省级部门上传的文件,只有省级管理员角色可以删除 + Long regionId = government.getRegionId(); + if (Objects.nonNull(regionId) && + DefValConstants.ZJREGION_ID.equals(regionId)){ + // 判断登录用户角色是否为省管理员 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){ + throw new BizException("您没有权限删除该文件!"); + } + } + governmentService.deleteById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(CompanySecurityGovernment::getId,id); + } + + public void incrementDownCount(Long id) { + executeFileService.incrementDownCount(id); + } + + public void deleteCommitmentFile(Long id, Long roleId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityCommitment.class); + CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy(); + context.buildCommitmentQuery(wrapper, id); + CompanySecurityCommitment commitment = commitmentService.getOne(wrapper); + if (Objects.isNull(commitment)){ + throw new BizException("文件无法删除!"); + } + //CompanySecurityCommitment commitment = commitmentService.getById(id); + // 如果文件是省级部门上传的文件,只有省级管理员角色可以删除 + Long regionId = commitment.getRegionId(); + if (Objects.nonNull(regionId) && + DefValConstants.ZJREGION_ID.equals(regionId)){ + // 判断登录用户角色是否为省管理员 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){ + throw new BizException("您没有权限删除该文件!"); + } + } + commitmentService.deleteById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildCommitmentQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(CompanySecurityCommitment::getId,id); + } + + public void deleteRegulationFile(Long id, Long roleId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityProductRegulation.class); + CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy(); + context.buildRegulationQuery(wrapper, id); + CompanySecurityProductRegulation regulation = regulationsFileService.getOne(wrapper); + if (Objects.isNull(regulation)){ + throw new BizException("文件无法删除!"); + } + // CompanySecurityProductRegulation regulation = regulationsFileService.getById(id); + + // 如果文件是省级部门上传的文件,只有省级管理员角色可以删除 + Long regionId = regulation.getRegionId(); + if (Objects.nonNull(regionId) && + DefValConstants.ZJREGION_ID.equals(regionId)){ + // 判断登录用户角色是否为省管理员 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){ + throw new BizException("您没有权限删除该文件!"); + } + } + regulationsFileService.deleteById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildRegulationQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(CompanySecurityProductRegulation::getId,id); + } + + public void deleteExecuteFile(Long id, Long roleId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanySecurityProductExecute.class); + CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy(); + context.buildExecuteQuery(wrapper, id); + CompanySecurityProductExecute execute = executeFileService.getOne(wrapper); + if (Objects.isNull(execute)){ + throw new BizException("文件无法删除!"); + } + // CompanySecurityProductExecute execute = executeFileService.getById(id); + // 如果文件是省级部门上传的文件,只有省级管理员角色可以删除 + Long regionId = execute.getRegionId(); + if (Objects.nonNull(regionId) && + DefValConstants.ZJREGION_ID.equals(regionId)){ + // 判断登录用户角色是否为省管理员 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){ + throw new BizException("您没有权限删除该文件!"); + } + } + executeFileService.deleteById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildExecuteQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(CompanySecurityProductExecute::getId,id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.java new file mode 100644 index 0000000..78f25f8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.CompanyBasicCredit; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 企业基础信用信息 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface CompanyBasicCreditMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.xml new file mode 100644 index 0000000..4905d8e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyBasicCreditMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.java new file mode 100644 index 0000000..16daec0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.CompanyCertificate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 企业证书 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface CompanyCertificateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.xml new file mode 100644 index 0000000..3bbc342 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCertificateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.java new file mode 100644 index 0000000..a37b480 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.CompanyCommonCredit; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 企业公共信用信息 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface CompanyCommonCreditMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.xml new file mode 100644 index 0000000..c46beb9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyCommonCreditMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.java new file mode 100644 index 0000000..cc125d9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.CompanyEmployees; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.ResCompanyEmployeesCountDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface CompanyEmployeesMapper extends BaseMapper { + + List countEmployeesByCompanyIds(@Param("companyIds") List companyIds); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.xml new file mode 100644 index 0000000..5bf5837 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyEmployeesMapper.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.java new file mode 100644 index 0000000..edc342a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.CompanySecurityProductExecute; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全生产制度执行 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +public interface CompanySecurityProductExecuteFileMapper extends BaseMapper { + + int incrementDownCount(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.xml new file mode 100644 index 0000000..ca49d21 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductExecuteFileMapper.xml @@ -0,0 +1,8 @@ + + + + + + update nd_security_advisory set download_times = download_times + 1 where id = #{id} + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.java new file mode 100644 index 0000000..3f05eca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.CompanySecurityProductRegulation; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全生产制度体系 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +public interface CompanySecurityProductRegulationsFileMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.xml new file mode 100644 index 0000000..e1f9bf4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanySecurityProductRegulationsFileMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.java new file mode 100644 index 0000000..d9e06a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.mapper; + +import java.time.LocalDateTime; +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.CompanyVehicleNotGetOn; +import com.ningdatech.carapi.company.entity.dto.ReqNotGetOnCarDTO; +import com.ningdatech.carapi.company.entity.po.CompanyVehicleNotGetOnPO; + +/** + *

+ * 上车表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-01-10 + */ +public interface CompanyVehicleNotGetOnMapper extends BaseMapper { + List getNotOnCarList(@Param("param") ReqNotGetOnCarDTO param); + + String checkDataExistByDay(LocalDateTime queryTime); + + void saveBatchNotGetOnList(@Param("singleList") List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.xml new file mode 100644 index 0000000..e6f0ea3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/CompanyVehicleNotGetOnMapper.xml @@ -0,0 +1,38 @@ + + + + + insert into nd_company_vehicle_not_get_on + (id,create_on,create_by,update_on,update_by,car_plate,company_id,time) + values + + (null,now(),null,now(),null,#{notGetOn.carPlate},#{notGetOn.companyId},#{notGetOn.time}) + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.java new file mode 100644 index 0000000..db13985 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyBlackList; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditBlackListPageParam; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackDetailListDTO; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackListDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 企业失信名单 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyBlackListMapper extends BaseMapper { + /** + * 获取失信名单 + * + * @param blackListPage 分页 + * @param param + * @return 失信名单 + */ + Page companyBlackList(Page blackListPage, + @Param("po")CompanyCreditBlackListPageParam param); + + /** + * 获取失信详情 + * + * @param companyId 公司id + * @return 失信详情 + */ + List companyBlackInfoList(@Param("companyId") Long companyId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.xml new file mode 100644 index 0000000..27b99ec --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyBlackListMapper.xml @@ -0,0 +1,42 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.java new file mode 100644 index 0000000..6967157 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.NdCompanyCreditDeduct; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 平安办扣分 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyCreditDeductMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.xml new file mode 100644 index 0000000..62e8ef3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditDeductMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.java new file mode 100644 index 0000000..e6a6937 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.NdCompanyCreditInside; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 内部/联合检查 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyCreditInsideMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.xml new file mode 100644 index 0000000..19b70f3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditInsideMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.java new file mode 100644 index 0000000..8811102 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 信用等级 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyCreditLevelMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.xml new file mode 100644 index 0000000..664cdc8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditLevelMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.java new file mode 100644 index 0000000..164b9f3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.ningdatech.carapi.company.entity.NdCompanyCreditReward; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 政府/行业嘉奖 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyCreditRewardMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.xml new file mode 100644 index 0000000..acdda0a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyCreditRewardMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.java new file mode 100644 index 0000000..81802b3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyProductManage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.ResProductManageDTO; +import com.ningdatech.carapi.company.entity.po.CompanyProductPO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 公司生产管理 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyProductManageMapper extends BaseMapper { + + /** + * 生成管理列表 + * @param managePage 分页 + * @return 分页列表 + */ + Page manageList(Page managePage, + @Param("po") CompanyProductPO po); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.xml new file mode 100644 index 0000000..5186c49 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyProductManageMapper.xml @@ -0,0 +1,35 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.java new file mode 100644 index 0000000..a7cc59b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyQualityManage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.ResQualityManageDTO; +import com.ningdatech.carapi.company.entity.po.CompanyQualityPO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 质量通报 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanyQualityManageMapper extends BaseMapper { + /** + * 获取分页数据 + * + * @param managePage 分页 + * @param + * @return 分页数据 + */ + Page qualityManageList(Page managePage, + @Param("po") CompanyQualityPO po); + + int incrementDownCount(@Param("id") Long id); + + Page qualityAllManageList(Page page, @Param("po") CompanyQualityPO po); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.xml new file mode 100644 index 0000000..5c0d47e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanyQualityManageMapper.xml @@ -0,0 +1,63 @@ + + + + + + + + + update nd_company_quality_manage set download_count = download_count + 1 where id = #{id} + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.java new file mode 100644 index 0000000..4da1839 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.CompanySecurityCommitment; + +/** + *

+ * 安全 安全承诺书 Mapper 接口 + *

+ * + * @author zpf + * @since 2023-05-23 + */ +public interface NdCompanySecurityCommitmentMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.xml new file mode 100644 index 0000000..5740814 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityCommitmentMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.java new file mode 100644 index 0000000..21e7cd8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.CompanySecurityGovernment; + +/** + *

+ * 安全 管理机构 Mapper 接口 + *

+ * + * @author zpf + * @since 2023-05-23 + */ +public interface NdCompanySecurityGovernmentMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.xml new file mode 100644 index 0000000..9d773ce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityGovernmentMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.java new file mode 100644 index 0000000..b11e2d4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductDuty; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.ResQualityManageDTO; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductDutyDTO; +import com.ningdatech.carapi.company.entity.po.CompanySecurityProductDutyPO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 安全生产责任体系 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanySecurityProductDutyMapper extends BaseMapper { + /** + * 获取分页数据 + * + * @param dutyPage 分页 + * @return 列表 + */ + Page securityProductDutyList(Page dutyPage, + @Param("po")CompanySecurityProductDutyPO po); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.xml new file mode 100644 index 0000000..f523e72 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductDutyMapper.xml @@ -0,0 +1,44 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.java new file mode 100644 index 0000000..7a71a6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductExecute; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductExecuteDTO; +import com.ningdatech.carapi.company.entity.po.CompanySecurityProductExecutePO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 安全生产制度执行 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanySecurityProductExecuteMapper extends BaseMapper { + /** + * 获取分页数据 + * + * @param executePage 分页 + * @param + * @return 列表 + */ + Page securityProductExecuteList(Page executePage, + @Param("po")CompanySecurityProductExecutePO po); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.xml new file mode 100644 index 0000000..ae78541 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductExecuteMapper.xml @@ -0,0 +1,34 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.java new file mode 100644 index 0000000..2cdd099 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.company.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductRegulations; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductRegulationsDTO; +import com.ningdatech.carapi.company.entity.po.CompanySecurityProductRegulationPO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 安全生产制度体系 Mapper 接口 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface NdCompanySecurityProductRegulationsMapper extends BaseMapper { + /** + * 获取分页数据 + * + * @param dutyPage 分页 + * @param + * @return 列表 + */ + Page securityProductRegulationsList(Page dutyPage, + @Param("po")CompanySecurityProductRegulationPO po); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.xml new file mode 100644 index 0000000..b519ed3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/mapper/NdCompanySecurityProductRegulationsMapper.xml @@ -0,0 +1,40 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyArchivesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyArchivesService.java new file mode 100644 index 0000000..7fe5bb7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyArchivesService.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.company.service; + +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.company.entity.dto.*; +import com.ningdatech.carapi.company.entity.vo.CompanyEmployeesVO; +import com.ningdatech.carapi.open.model.vo.CompanySecurityInfoVO; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.CompanySaveDTO; + + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 08:50 + */ +public interface ICompanyArchivesService { + + /** + * 获取企业信息 + * + * @param + * @return 企业列表 + */ + PageVo getCompanyList(CompanyListParamDTO param); + + /** + * 获取企业详情 + * + * @param companyId 公司id + * @return 企业详情 + */ + ResCompanyArchivesDetailsDTO getCompanyDetail(Long companyId); + + /** + * 获取企业员工信息 + * + * @param companyId 企业id + * @return 企业员工信息 + */ + List getCompanyEmployees(Long companyId); + + /** + * 修改企业信息 + * + * @param reqCompanyArchivesDetailsDTO {@link ReqCompanyArchivesDetailsDTO} + */ + void updateCompanyInfo(ReqCompanyArchivesDetailsDTO reqCompanyArchivesDetailsDTO); + + /** + * 获取员工统计 + * + * @param param + * @return 分页统计 + */ + PageVo getCompanyEmployeesList(CompanyListParamDTO param); + + /** + * 获取企业基础信用 + * + * @param + * @return 基础信用列表 + */ + PageVo getCompanyBasicCreditList(CompanyListParamDTO param); + + /** + * 获取基础信用详情 + * + * @param companyId 企业id + * @return 信用详情 + */ + ResCompanyBasicCreditDetailDTO getCompanyBasicCreditDetail(Long companyId); + + /** + * 获取企业公共信用 + * + * @param param + * @return 公共信用信息 + */ + PageVo getCompanyCommonCreditList(CompanyListParamDTO param); + + void companyListExport(HttpServletResponse response, CompanyListParamDTO param); + + void companyBasicCreditListExport(HttpServletResponse response, CompanyListParamDTO param); + + void companyCommonCreditListExport(HttpServletResponse response, CompanyListParamDTO param); + + void companyCertificateInformationListExport(HttpServletResponse response, CompanyListParamDTO param); + PageVo getNotOnCarList(ReqNotGetOnCarDTO param); + + CompanySecurityInfoVO getCompanySecurityInfo(Long companyId); + + Company saveCompany(CompanySaveDTO data); + + PageVo queryToBeAudit(CompanyAuditPageQuery param); + + PageVo queryAuditedList(CompanyAuditPageQuery param); + + Boolean audit(CompanyAuditDTO data, Long userId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyBasicCreditService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyBasicCreditService.java new file mode 100644 index 0000000..c9000a4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyBasicCreditService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.company.service; + +import com.ningdatech.carapi.company.entity.CompanyBasicCredit; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 企业基础信用信息 服务类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface ICompanyBasicCreditService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCertificateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCertificateService.java new file mode 100644 index 0000000..d0ee905 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCertificateService.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.CompanyCertificate; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 企业证书 服务类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface ICompanyCertificateService extends IService { + + Page getCertificates(Page page, Long companyId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCommonCreditService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCommonCreditService.java new file mode 100644 index 0000000..0c1d6b0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyCommonCreditService.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.CompanyCommonCredit; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 企业公共信用信息 服务类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface ICompanyCommonCreditService extends IService { + + Page getCompanyBasicCreditDetail(Page page, Long companyId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyEmployeesService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyEmployeesService.java new file mode 100644 index 0000000..f46c11b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyEmployeesService.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.company.service; + +import com.ningdatech.carapi.company.entity.CompanyEmployees; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.ResCompanyEmployeesCountDTO; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +public interface ICompanyEmployeesService extends IService { + + List countEmployeesByCompanyIds(List collect); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyLargeScreenService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyLargeScreenService.java new file mode 100644 index 0000000..175eaa9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyLargeScreenService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.company.service; + +import com.ningdatech.carapi.company.entity.dto.ResCompanyTotalDTO; + +import java.util.List; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/25 10:14 + */ +public interface ICompanyLargeScreenService { + /** + * 根据区域id获取企业数据统计 + * @param regionId 区域id + * @return 企业数据统计 + */ + List getCompanyTotalByRegionId(Long regionId); + + List countEnterpriseType(Long regionId); + + List deadAccident(Long regionId); + + List mortarQuality(Long regionId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityCommitmentService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityCommitmentService.java new file mode 100644 index 0000000..6bccfe8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityCommitmentService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.CompanySecurityCommitment; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityCommitmentParam; + +/** + *

+ * 安全 承诺书 服务类 + *

+ * + * @author zpf + * @since 2023-05-23 + */ +public interface ICompanySecurityCommitmentService extends IService { + + Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityCommitmentParam param); + + void deleteById(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityGovernmentService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityGovernmentService.java new file mode 100644 index 0000000..b07f7c6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityGovernmentService.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.company.service; + +import java.util.List; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.CompanySecurityGovernment; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityCommitmentParam; + +/** + *

+ * 安全 管理机构 服务类 + *

+ * + * @author zpf + * @since 2023-05-23 + */ +public interface ICompanySecurityGovernmentService extends IService { + + Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityCommitmentParam param); + + List dataScopeList(LambdaQueryWrapper wrapper, CompanySecurityCommitmentParam param); + + void deleteById(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductExecuteFileService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductExecuteFileService.java new file mode 100644 index 0000000..7c89d07 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductExecuteFileService.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.CompanySecurityProductExecute; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityProductExecuteParam; + +import java.util.List; + +/** + *

+ * 安全生产制度执行 服务类 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +public interface ICompanySecurityProductExecuteFileService extends IService { + + Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityProductExecuteParam param); + + List dataScopeList(LambdaQueryWrapper wrapper, CompanySecurityProductExecuteParam param); + + void deleteById(Long id); + + Boolean incrementDownCount(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductRegulationsFileService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductRegulationsFileService.java new file mode 100644 index 0000000..daac4dc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanySecurityProductRegulationsFileService.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.CompanySecurityProductRegulation; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityProductRegulationParam; + +import java.util.List; + +/** + *

+ * 安全生产制度体系 服务类 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +public interface ICompanySecurityProductRegulationsFileService extends IService { + + Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityProductRegulationParam param); + + List dataScopeList(LambdaQueryWrapper wrapper, CompanySecurityProductRegulationParam param); + + void deleteById(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyVehicleNotGetOnService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyVehicleNotGetOnService.java new file mode 100644 index 0000000..409e568 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/ICompanyVehicleNotGetOnService.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.company.service; + +import java.time.LocalDateTime; +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.CompanyVehicleNotGetOn; +import com.ningdatech.carapi.company.entity.dto.ReqNotGetOnCarDTO; +import com.ningdatech.carapi.company.entity.po.CompanyVehicleNotGetOnPO; + +/** + *

+ * 上车表 服务类 + *

+ * + * @author CMM + * @since 2023-01-10 + */ +public interface ICompanyVehicleNotGetOnService extends IService { + + /** + * 查询企业车辆未扫码行驶记录 + * @param param + * @return + */ + List getNotOnCarList(ReqNotGetOnCarDTO param); + + String checkDataExistByDay(LocalDateTime queryTime); + + void saveBatchNotGetOnList(List singleList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyBlackListService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyBlackListService.java new file mode 100644 index 0000000..f2ab7db --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyBlackListService.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyBlackList; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditBlackListPageParam; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackDetailListDTO; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackListDTO; + +import java.util.List; + +/** + *

+ * 企业失信名单 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyBlackListService extends IService { + + /** + * 获取失信名单 + * + * @param param + * @return 失信名单 + */ + Page companyBlackList(CompanyCreditBlackListPageParam param); + + /** + * 获取失信详情 + * + * @param companyId 公司id + * @return 失信详情 + */ + List companyBlackInfoList(Long companyId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditDeductService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditDeductService.java new file mode 100644 index 0000000..0d66a2f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditDeductService.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditDeduct; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditDeductPageParam; + +/** + *

+ * 平安办扣分 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyCreditDeductService extends IService { + + /** + * 获取扣分列表 + * + * @param param + * @return 扣分列表 + */ + Page getCreditDeductList(CompanyCreditDeductPageParam param); + + Boolean delete(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditInsideService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditInsideService.java new file mode 100644 index 0000000..e418624 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditInsideService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditInside; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditInsidePageParam; + +/** + *

+ * 内部/联合检查 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyCreditInsideService extends IService { + /** + * 获取列表 + * @param param + * @return 分页信息 + */ + Page getList(CompanyCreditInsidePageParam param); + + Boolean delete(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditLevelService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditLevelService.java new file mode 100644 index 0000000..544fcc0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditLevelService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditLevelPageParam; + +/** + *

+ * 信用等级 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyCreditLevelService extends IService { + + /** + * 获取信用列表 + * + * @param param + * @return 信用等级列表 + */ + Page getCreditLevelList(CompanyCreditLevelPageParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditRewardService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditRewardService.java new file mode 100644 index 0000000..b528ece --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyCreditRewardService.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyCreditReward; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditRewardPageParam; + +/** + *

+ * 政府/行业嘉奖 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyCreditRewardService extends IService { + + /** + * 获取嘉奖列表 + * + * @param param + * @return 嘉奖列表 + */ + Page getCreditRewardList(CompanyCreditRewardPageParam param); + + Boolean delete(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyProductManageService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyProductManageService.java new file mode 100644 index 0000000..b2699d0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyProductManageService.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanyProductManage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.ResProductManageDTO; + +/** + *

+ * 公司生产管理 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyProductManageService extends IService { + + /** + * 获取管理列表 + * + * @param companyName 公司名称 + * @param regionId 区域id + * @param pageNum 当前页 + * @param pageSize 页面大小 + * @return 列表 + */ + Page manageList(String companyName, Long regionId, int pageNum, int pageSize); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyQualityManageService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyQualityManageService.java new file mode 100644 index 0000000..d7672c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanyQualityManageService.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.NdCompanyQualityManage; +import com.ningdatech.carapi.company.entity.dto.ResQualityManageDTO; + +/** + *

+ * 质量通报 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanyQualityManageService extends IService { + /** + * 获取分页 + * @param regionId 区域 + * @param year 年份 + * @param pageNum 当前页 + * @param pageSize 页面大小 + * @return 分页数据 + */ + Page qualityManageList(Long regionId,String year, int pageNum,int pageSize); + + boolean incrementDownCount(Long id); + + Boolean delete(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductDutyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductDutyService.java new file mode 100644 index 0000000..ab6c9e1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductDutyService.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductDuty; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductDutyDTO; + +/** + *

+ * 安全生产责任体系 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanySecurityProductDutyService extends IService { + + /** + * 获取生成责任体系 + * @param regionId 区域id + * @param companyName 公司名称 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param pageNum 当前页 + * @param pageSize 页面大小 + * @return 列表 + */ + Page securityProductDutyList(Long regionId, String companyName, String startTime, + String endTime, Integer fileType, int pageNum, int pageSize); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductExecuteService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductExecuteService.java new file mode 100644 index 0000000..c4ac5da --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductExecuteService.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductExecute; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductExecuteDTO; + +/** + *

+ * 安全生产制度执行 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanySecurityProductExecuteService extends IService { + + /** + * 获取制度执行 + * + * @param name 通报名称 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param pageNum 当前页 + * @param pageSize 页面大小 + * @return 列表 + */ + Page securityProductExecuteList(String name, String startTime, + String endTime, Integer fileType, int pageNum, int pageSize); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductRegulationsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductRegulationsService.java new file mode 100644 index 0000000..ba7be08 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/INdCompanySecurityProductRegulationsService.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.company.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductRegulations; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductRegulationsDTO; + +/** + *

+ * 安全生产制度体系 服务类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +public interface INdCompanySecurityProductRegulationsService extends IService { + + /** + * 获取制度体系 + * @param regulationsName 制度名称 + * @param competentDepartment 主管部门 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param pageNum 当前页 + * @param pageSize 页面大小 + * @return 列表 + */ + Page securityProductRegulationsList(String regulationsName, String competentDepartment, String startTime, + String endTime, Integer fileType, int pageNum, int pageSize); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyBasicCreditServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyBasicCreditServiceImpl.java new file mode 100644 index 0000000..caa61d6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyBasicCreditServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.ningdatech.carapi.company.entity.CompanyBasicCredit; +import com.ningdatech.carapi.company.mapper.CompanyBasicCreditMapper; +import com.ningdatech.carapi.company.service.ICompanyBasicCreditService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 企业基础信用信息 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@Service +public class CompanyBasicCreditServiceImpl extends ServiceImpl implements ICompanyBasicCreditService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCertificateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCertificateServiceImpl.java new file mode 100644 index 0000000..d21ca48 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCertificateServiceImpl.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.company.service.impl; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.company.entity.CompanyCertificate; +import com.ningdatech.carapi.company.mapper.CompanyCertificateMapper; +import com.ningdatech.carapi.company.service.ICompanyCertificateService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +/** + *

+ * 企业证书 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@Service +public class CompanyCertificateServiceImpl extends ServiceImpl implements ICompanyCertificateService { + @Override + public Page getCertificates(Page page, Long companyId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanyCertificate.class); + CompanyCertificateServiceImpl context = (CompanyCertificateServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, companyId); + return page(page,wrapper); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long companyId) { + wrapper.eq(CompanyCertificate::getCompanyId,companyId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCommonCreditServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCommonCreditServiceImpl.java new file mode 100644 index 0000000..3b18d79 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyCommonCreditServiceImpl.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.company.service.impl; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.company.entity.CompanyCommonCredit; +import com.ningdatech.carapi.company.mapper.CompanyCommonCreditMapper; +import com.ningdatech.carapi.company.service.ICompanyCommonCreditService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +/** + *

+ * 企业公共信用信息 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@Service +public class CompanyCommonCreditServiceImpl extends ServiceImpl implements ICompanyCommonCreditService { + + @Override + public Page getCompanyBasicCreditDetail(Page page, Long companyId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanyCommonCredit.class); + CompanyCommonCreditServiceImpl context = (CompanyCommonCreditServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, companyId); + return page(page,wrapper); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long companyId) { + wrapper.eq(CompanyCommonCredit::getCompanyId,companyId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyEmployeesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyEmployeesServiceImpl.java new file mode 100644 index 0000000..3c6dc18 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyEmployeesServiceImpl.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.ningdatech.carapi.company.entity.CompanyEmployees; +import com.ningdatech.carapi.company.entity.dto.ResCompanyEmployeesCountDTO; +import com.ningdatech.carapi.company.mapper.CompanyEmployeesMapper; +import com.ningdatech.carapi.company.service.ICompanyEmployeesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-25 + */ +@Service +@RequiredArgsConstructor +public class CompanyEmployeesServiceImpl extends ServiceImpl implements ICompanyEmployeesService { + + private final CompanyEmployeesMapper companyEmployeesMapper; + + @Override + public List countEmployeesByCompanyIds(List companyIds) { + return companyEmployeesMapper.countEmployeesByCompanyIds(companyIds); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyLargeScreenServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyLargeScreenServiceImpl.java new file mode 100644 index 0000000..2aeb3c4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyLargeScreenServiceImpl.java @@ -0,0 +1,140 @@ +package com.ningdatech.carapi.company.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.company.entity.NdCompanyQualityManage; +import com.ningdatech.carapi.company.entity.dto.ResCompanyTotalDTO; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.company.service.ICompanyLargeScreenService; +import com.ningdatech.carapi.company.service.INdCompanyQualityManageService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.service.IReadyMixedMortarIndustryManageService; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @description: 大屏管理 + * @author: liushuai + * @date: 2022/10/25 10:14 + */ +@Service +@RequiredArgsConstructor +public class CompanyLargeScreenServiceImpl implements ICompanyLargeScreenService { + private final INdVehicleAccidentDeadService accidentDeadService; + private final CompanyService companyService; + private final CompaniesCacheHelper companiesCacheHelper; + private final IReadyMixedMortarIndustryManageService mortarQualityService; + + private final INdCompanyQualityManageService iNdCompanyQualityManageService; + + @Override + public List getCompanyTotalByRegionId(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + List resCompanyTotalList = companyService.countByRegion(param); + if (CollUtil.isEmpty(resCompanyTotalList)) { + return Collections.emptyList(); + } + return resCompanyTotalList.stream().map(w -> { + ResCompanyTotalDTO dto = new ResCompanyTotalDTO(); + BeanUtils.copyProperties(w, dto); + return dto; + }).collect(Collectors.toList()); + } + + @Override + public List countEnterpriseType(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + List resCompanyTotalList = companyService.countEnterpriseType(param); + if (CollUtil.isEmpty(resCompanyTotalList)) { + return Collections.emptyList(); + } + return resCompanyTotalList.stream().map(w -> { + ResCompanyTotalDTO dto = new ResCompanyTotalDTO(); + BeanUtils.copyProperties(w, dto); + return dto; + }).collect(Collectors.toList()); + } + + @Override + public List deadAccident(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + param.setStartTime(LocalDateTime.now().minusMonths(6)); + //半年内 + param.setEndTime(LocalDateTime.now()); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccidentDead.class); + List accidentDeadList = ((CompanyLargeScreenServiceImpl) AopContext.currentProxy()).countDeadCompany(wrapper, param); + + if (CollUtil.isEmpty(accidentDeadList)) { + return Collections.emptyList(); + } + return accidentDeadList.stream().filter(w -> { + if (w.getCompanyId() == null) { + return false; + } + String companyName = companiesCacheHelper.getNameById(w.getCompanyId()); + boolean notBlank = StrUtil.isNotBlank(companyName); + if (notBlank) { + w.setCompanyName(companyName); + } + return notBlank; + }).map(w -> ResCompanyTotalDTO.builder().name(w.getCompanyName()).build()) + .collect(Collectors.toList()); + } + + @Override + public List mortarQuality(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyQualityManage.class); + List list = ((CompanyLargeScreenServiceImpl) AopContext.currentProxy()).mortarQualityies(wrapper, param); + + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + return list.stream().map(w -> { + ResCompanyTotalDTO dto = new ResCompanyTotalDTO(); + dto.setFileId(StringUtils.isNotBlank(w.getFilePath()) ? + Long.parseLong(w.getFilePath()) : null); + dto.setName(w.getFileName()); + return dto; + }).collect(Collectors.toList()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public List mortarQualityies(LambdaQueryWrapper wrapper, DataScreenParam param) { + return iNdCompanyQualityManageService.list(wrapper + .orderBy(Boolean.TRUE, Boolean.FALSE, NdCompanyQualityManage::getUpdateOn)); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public List countDeadCompany(LambdaQueryWrapper wrapper, DataScreenParam param) { + wrapper.select(NdVehicleAccidentDead::getCompanyId) + .ge(Objects.nonNull(param.getStartTime()), NdVehicleAccidentDead::getAccidentTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), NdVehicleAccidentDead::getAccidentTime, param.getEndTime()) + .groupBy(NdVehicleAccidentDead::getCompanyId); + return accidentDeadService.list(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductExecuteFileServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductExecuteFileServiceImpl.java new file mode 100644 index 0000000..fa04123 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductExecuteFileServiceImpl.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.company.entity.CompanySecurityProductExecute; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityProductExecuteParam; +import com.ningdatech.carapi.company.mapper.CompanySecurityProductExecuteFileMapper; +import com.ningdatech.carapi.company.service.ICompanySecurityProductExecuteFileService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +/** + *

+ * 安全生产制度执行 服务实现类 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +@Service +public class CompanySecurityProductExecuteFileServiceImpl extends ServiceImpl implements ICompanySecurityProductExecuteFileService { + + @Override + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + @LambdaDataScope(wrapperIndex = 1,type = LambdaDataScopeTypeEnum.ONLY_REGION) + public Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityProductExecuteParam param) { + return page(page,wrapper); + } + + @Override + @BuildChildrenRegionWrapper + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public List dataScopeList(LambdaQueryWrapper wrapper, CompanySecurityProductExecuteParam param) { + return baseMapper.selectList(wrapper); + } + + @Override + public void deleteById(Long id) { + baseMapper.deleteById(id); + } + + @Override + public Boolean incrementDownCount(Long id) { + return baseMapper.incrementDownCount(id) > 0; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductRegulationsFileServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductRegulationsFileServiceImpl.java new file mode 100644 index 0000000..1ac6f71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanySecurityProductRegulationsFileServiceImpl.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.company.entity.CompanySecurityProductRegulation; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityProductRegulationParam; +import com.ningdatech.carapi.company.mapper.CompanySecurityProductRegulationsFileMapper; +import com.ningdatech.carapi.company.service.ICompanySecurityProductRegulationsFileService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 安全生产制度体系 服务实现类 + *

+ * + * @author CMM + * @since 2023-05-24 + */ +@Service +public class CompanySecurityProductRegulationsFileServiceImpl extends ServiceImpl implements ICompanySecurityProductRegulationsFileService { + + @Override + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + @LambdaDataScope(wrapperIndex = 1) + public Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityProductRegulationParam param) { + return page(page,wrapper); + } + + @Override + @BuildChildrenRegionWrapper + @LambdaDataScope + public List dataScopeList(LambdaQueryWrapper wrapper, CompanySecurityProductRegulationParam param) { + return baseMapper.selectList(wrapper); + } + + @Override + public void deleteById(Long id) { + baseMapper.deleteById(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyVehicleNotGetOnServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyVehicleNotGetOnServiceImpl.java new file mode 100644 index 0000000..ef71e52 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/CompanyVehicleNotGetOnServiceImpl.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.company.entity.CompanyVehicleNotGetOn; +import com.ningdatech.carapi.company.entity.dto.ReqNotGetOnCarDTO; +import com.ningdatech.carapi.company.entity.po.CompanyVehicleNotGetOnPO; +import com.ningdatech.carapi.company.mapper.CompanyVehicleNotGetOnMapper; +import com.ningdatech.carapi.company.service.ICompanyVehicleNotGetOnService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 上车表 服务实现类 + *

+ * + * @author CMM + * @since 2023-01-10 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class CompanyVehicleNotGetOnServiceImpl extends ServiceImpl implements ICompanyVehicleNotGetOnService { + + private final CompanyVehicleNotGetOnMapper companyVehicleNotGetOnMapper; + + @Override + public List getNotOnCarList(ReqNotGetOnCarDTO param) { + return companyVehicleNotGetOnMapper.getNotOnCarList(param); + } + + @Override + public String checkDataExistByDay(LocalDateTime queryTime) { + return companyVehicleNotGetOnMapper.checkDataExistByDay(queryTime); + } + + @Override + public void saveBatchNotGetOnList(List singleList) { + companyVehicleNotGetOnMapper.saveBatchNotGetOnList(singleList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/ICompanyArchivesServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/ICompanyArchivesServiceImpl.java new file mode 100644 index 0000000..aed7e34 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/ICompanyArchivesServiceImpl.java @@ -0,0 +1,810 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.analysis.common.DangerLevelEnum; +import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany; +import com.ningdatech.carapi.analysis.service.IWarnAnalysisCompanyService; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.EducationEnum; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.company.entity.CompanyBasicCredit; +import com.ningdatech.carapi.company.entity.CompanyEmployees; +import com.ningdatech.carapi.company.entity.CompanyVehicleNotGetOn; +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.ningdatech.carapi.company.entity.dto.*; +import com.ningdatech.carapi.company.entity.vo.CompanyEmployeesVO; +import com.ningdatech.carapi.company.enumeration.CompanyCreditLevelEnum; +import com.ningdatech.carapi.company.enumeration.CompanyTypeEnum; +import com.ningdatech.carapi.company.enumeration.ProductCompanyType; +import com.ningdatech.carapi.company.service.*; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.UserCanLoginEnum; +import com.ningdatech.carapi.driver.constants.DriverConstant; +import com.ningdatech.carapi.open.model.vo.CompanySecurityInfoVO; +import com.ningdatech.carapi.scheduler.enums.DataTypeEnum; +import com.ningdatech.carapi.scheduler.enums.OperatorTypeEnum; +import com.ningdatech.carapi.sys.entity.*; +import com.ningdatech.carapi.sys.entity.dto.CompanyPageQuery; +import com.ningdatech.carapi.sys.entity.dto.CompanySaveDTO; +import com.ningdatech.carapi.sys.entity.vo.CompanyVO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.manage.CompanyManage; +import com.ningdatech.carapi.sys.service.*; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.DesensitizedUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @description: + * @author: liushuai + * @date: 2022/10/26 08:50 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class ICompanyArchivesServiceImpl implements ICompanyArchivesService { + private final CompanyManage companyManage; + private final CompanyService companyService; + private final ICompanyBasicCreditService iCompanyBasicCreditService; + private final IRegionService iRegionService; + private final ICompanyEmployeesService iCompanyEmployeesService; + private final CompanyTypeService companyTypeService; + private final CompanyTypeRelatedService companyTypeRelatedService; + private final ApplicationContext applicationContext; + private final ICompanyVehicleNotGetOnService companyVehicleNotGetOnService; + + private final INdCompanyCreditLevelService companyCreditLevelService; + private final IWarnAnalysisCompanyService warnAnalysisCompanyService; + private final RegionsCacheHelper regionCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + private final INdUserInfoService userInfoService; + private final PasswordEncoder passwordEncoder; + private final INdUserAuthService ndUserAuthService; + private final UserRoleService userRoleService; + + @Override + public PageVo getCompanyList(CompanyListParamDTO param) { + CompanyPageQuery companyPageQuery = new CompanyPageQuery(); + + companyPageQuery.setCompanyTypeList(param.getCompanyTypeList()); + companyPageQuery.setCompanyType(param.getCompanyType()); + companyPageQuery.setProductCompanyType(param.getProductCompanyType()); + companyPageQuery.setName(param.getCompanyName()); + + companyPageQuery.setRegionId(param.getRegionId()); + companyPageQuery.setPageSize(param.getPageSize()); + companyPageQuery.setPageNumber(param.getPageNumber()); + PageVo pageVo = companyManage.queryList(companyPageQuery); + if (pageVo.getTotal() != null && 0L != pageVo.getTotal()) { + List res = pageVo.getRecords().stream().map(w -> { + ResCompanyArchivesDTO dto = new ResCompanyArchivesDTO(); + BeanUtil.copyProperties(w, dto); + dto.setCarCompanyType(w.getCompanyTypeName()); + return dto; + }).collect(Collectors.toList()); + return PageVo.of(res, pageVo.getTotal()); + } + return PageVo.empty(); + } + + @Override + public ResCompanyArchivesDetailsDTO getCompanyDetail(Long companyId) { + ResCompanyArchivesDetailsDTO companyArchivesDTO = new ResCompanyArchivesDetailsDTO(); + // 获取企业信息 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, companyId); + Company company = companyService.getOne(wrapper); + if (Objects.isNull(company)) { + throw new BizException("企业不存在"); + } + //Company company = companyService.getById(companyId); + + BeanUtil.copyProperties(company, companyArchivesDTO); + // 对手机号进行脱敏处理 + String contactPhone = company.getContactPhone(); + String legalPersonPhone = company.getLegalPersonPhone(); + String encryptContactPhone = DesensitizedUtil.mobilePhone(contactPhone); + String encryptLegalPersonPhone = DesensitizedUtil.mobilePhone(legalPersonPhone); + companyArchivesDTO.setContactPhone(encryptContactPhone); + companyArchivesDTO.setLegalPersonPhone(encryptLegalPersonPhone); + companyArchivesDTO.setCompanyTypeName(CompanyTypeEnum.getDescByCode(company.getCompanyType())); + // 获取基础信息 + CompanyBasicCredit companyBasicCredit = + iCompanyBasicCreditService.getOne(new QueryWrapper().eq("company_id", companyId)); + BeanUtil.copyProperties(companyBasicCredit, companyArchivesDTO); + // 获取区域信息 + Region region = iRegionService.getById(company.getRegionId()); + companyArchivesDTO.setRegionCode(region.getRegionCode()); + String regionName = regionCacheHelper.getDisplayName(region.getId()); + companyArchivesDTO.setRegionName(regionName); + // 查询企业类型 + List companyTypeRelateds = companyTypeRelatedService + .list(Wrappers.lambdaQuery(CompanyTypeRelated.class).eq(CompanyTypeRelated::getCompanyId, companyId)); + if (CollUtil.isNotEmpty(companyTypeRelateds)) { + companyArchivesDTO.setCarCompanyType(companyTypeRelateds.stream() + .map(c -> String.valueOf(c.getCompanyTypeId())).collect(Collectors.joining(StrPool.COMMA))); + companyArchivesDTO.setCarCompanyTypeName(companyTypeRelateds.stream().map(r -> { + Long companyTypeId = r.getCompanyTypeId(); + CompanyType companyType = companyTypeService.getById(companyTypeId); + return Objects.nonNull(companyType) ? companyType.getName() : StringUtils.EMPTY; + }).filter(StringUtils::isNotBlank).collect(Collectors.joining(StrPool.COMMA))); + } + return companyArchivesDTO; + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildQuery(LambdaQueryWrapper wrapper, Long companyId) { + wrapper.eq(Company::getId,companyId); + } + + @Override + public List getCompanyEmployees(Long companyId) { + List employeesList = iCompanyEmployeesService.list(new QueryWrapper().eq("company_id", companyId)); + return employeesList.stream().map(e -> { + CompanyEmployeesVO vo = new CompanyEmployeesVO(); + BeanUtils.copyProperties(e, vo); + + // 对手机号和身份证号进行脱敏处理 + String mobile = e.getMobile(); + String idCard = e.getCardNum(); + String encryptMobile = DesensitizedUtil.mobilePhone(mobile); + String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END); + vo.setMobile(encryptMobile); + vo.setCardNum(encryptIdCard); + + vo.setEducationName(EducationEnum.getDescByCode(vo.getEducation())); + return vo; + }).collect(Collectors.toList()); + } + + @Override + public void updateCompanyInfo(ReqCompanyArchivesDetailsDTO reqCompanyArchivesDetailsDTO) { + Company company = reqCompanyArchivesDetailsDTO.getCompany(); + // 更新企业信息 + Company companyCache = companyService.getById(company.getId()); + BeanUtil.copyProperties(company, companyCache); + List enterpriseTypes = reqCompanyArchivesDetailsDTO.getEnterpriseTypes(); + if (CollUtil.isNotEmpty(enterpriseTypes)) { + // 先删除原来关联的信息,再保存 + companyTypeRelatedService.remove(Wrappers.lambdaQuery(CompanyTypeRelated.class) + .eq(CompanyTypeRelated::getCompanyId, companyCache.getId())); + for (Long enterpriseType : enterpriseTypes) { + CompanyTypeRelated companyTypeRelated = new CompanyTypeRelated(); + companyTypeRelated.setCompanyId(companyCache.getId()); + companyTypeRelated.setCompanyTypeId(enterpriseType); + companyTypeRelatedService.save(companyTypeRelated); + } + } + companyService.updateById(companyCache); + CompanyBasicCredit companyBasicCredit = reqCompanyArchivesDetailsDTO.getCompanyBasicCredit(); + // 更新企业基础信息 + if (companyBasicCredit != null) { + CompanyBasicCredit companyBasicCreditCache = iCompanyBasicCreditService + .getOne(new QueryWrapper().eq("company_id", company.getId())); + BeanUtil.copyProperties(companyBasicCredit, companyCache); + iCompanyBasicCreditService.updateById(companyBasicCreditCache); + } + // 更新企业员工信息 + List companyEmployeesList = reqCompanyArchivesDetailsDTO.getCompanyEmployeesList(); + if (CollectionUtil.isNotEmpty(companyEmployeesList)) { + // 要先需不需要删除 + List oldEmployees = + iCompanyEmployeesService.list(Wrappers.lambdaQuery(CompanyEmployees.class) + .eq(CompanyEmployees::getCompanyId, companyEmployeesList.get(0).getCompanyId())); + Map employeesMap = CollUtils.listToMap(oldEmployees, CompanyEmployees::getId); + for (CompanyEmployees companyEmployee : companyEmployeesList) { + if (Objects.nonNull(companyEmployee.getId()) && employeesMap.containsKey(companyEmployee.getId())) { + oldEmployees.remove(employeesMap.get(companyEmployee.getId())); + } + iCompanyEmployeesService.saveOrUpdate(companyEmployee); + } + + if (CollUtil.isNotEmpty(oldEmployees)) { + // 说明有要删除的 + for (CompanyEmployees companyEmployee : oldEmployees) { + iCompanyEmployeesService.removeById(companyEmployee.getId()); + log.info("触发删除员工事件 :{}", JSON.toJSONString(companyEmployee)); + } + } + } + // 公司类型 + if (StringUtils.isNotEmpty(company.getCarCompanyType())) { + companyTypeRelatedService.remove( + Wrappers.lambdaQuery(CompanyTypeRelated.class).eq(CompanyTypeRelated::getCompanyId, company.getId())); + String carCompanyType = company.getCarCompanyType(); + for (String enterpriseType : carCompanyType.split(StrPool.COMMA)) { + CompanyType companyType = companyTypeService.getById(enterpriseType); + if (Objects.nonNull(companyType)) { + companyTypeRelatedService.save(new CompanyTypeRelated(null, company.getId(), companyType.getId())); + } + } + } + } + + @Override + public PageVo getCompanyEmployeesList(CompanyListParamDTO param) { + PageVo page = new PageVo<>(); + CompanyPageQuery companyPageQuery = new CompanyPageQuery(); + companyPageQuery.setRegionId(param.getRegionId()); + companyPageQuery.setName(param.getCompanyName()); + companyPageQuery.setPageNumber(param.getPageNumber()); + companyPageQuery.setPageSize(param.getPageSize()); + PageVo pageVo = companyManage.queryList(companyPageQuery); + if (CollUtil.isEmpty(pageVo.getRecords())) { + return PageVo.empty(); + } + List countDtos = iCompanyEmployeesService.countEmployeesByCompanyIds( + pageVo.getRecords().stream().map(CompanyVO::getId).collect(Collectors.toList())); + + page.setTotal(pageVo.getTotal()); + page.setRecords(countDtos); + return page; + } + + @Override + public PageVo getCompanyBasicCreditList(CompanyListParamDTO param) { + PageVo page = new PageVo<>(); + List result = new ArrayList<>(); + CompanyPageQuery companyPageQuery = new CompanyPageQuery(); + companyPageQuery.setRegionId(param.getRegionId()); + companyPageQuery.setName(param.getCompanyName()); + companyPageQuery.setPageNumber(param.getPageNumber()); + companyPageQuery.setPageSize(param.getPageSize()); + // 筛选掉管理企业 + companyPageQuery.setCompanyTypeList(Lists.newArrayList(1, 2, 3)); + PageVo pageVo = companyManage.queryList(companyPageQuery); + // 获取企业信用信息 + Map> listMap = companyCreditLevelService.list().stream() + .collect(Collectors.groupingBy(NdCompanyCreditLevel::getCompanyId)); + if (pageVo.getTotal() != null && 0L != pageVo.getTotal()) { + List companyVOList = new ArrayList<>(pageVo.getRecords()); + for (CompanyVO companyVO : companyVOList) { + ResCompanyBasicCreditDTO resCompanyBasicCreditDTO = new ResCompanyBasicCreditDTO(); + BeanUtil.copyProperties(companyVO, resCompanyBasicCreditDTO); + Company company = companyService.getById(companyVO.getId()); + BeanUtil.copyProperties(company, resCompanyBasicCreditDTO); + resCompanyBasicCreditDTO.setRegionName(companyVO.getRegionName()); + resCompanyBasicCreditDTO.setCarCompanyType(CompanyTypeEnum.getDescByCode(company.getCompanyType())); + resCompanyBasicCreditDTO.setDutyParagraph(company.getBusinessLicense()); + List creditLevelList = listMap.get(companyVO.getId()); + if (CollUtil.isNotEmpty(creditLevelList)) { + String year = String.valueOf(LocalDateTime.now().getYear()); + // 筛选当前年份的数据 + List levels = + creditLevelList.stream().filter(c -> year.equals(c.getYear())).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(levels)) { + NdCompanyCreditLevel creditLevel = levels.get(0); + resCompanyBasicCreditDTO.setBasicCreditScore(creditLevel.getBasicCreditScore()); + } + } else { + // 信用表中不存在该企业,设为0 + log.info("企业信息等级表中不存在该企业{}", companyVO.getId()); + resCompanyBasicCreditDTO.setBasicCreditScore(0); + } + result.add(resCompanyBasicCreditDTO); + } + } + page.setTotal(pageVo.getTotal()); + page.setRecords(result); + return page; + } + + @Override + public ResCompanyBasicCreditDetailDTO getCompanyBasicCreditDetail(Long companyId) { + ResCompanyBasicCreditDetailDTO resCompanyBasicCreditDetailDTO = new ResCompanyBasicCreditDetailDTO(); + // 获取企业信息 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, companyId); + Company company = companyService.getOne(wrapper); + if (Objects.isNull(company)) { + throw new BizException("企业不存在"); + } + //Company company = companyService.getById(companyId); + + BeanUtil.copyProperties(company, resCompanyBasicCreditDetailDTO); + + // 对手机号和身份证号进行脱敏处理 + String contactPhone = company.getContactPhone(); + String encryptPhone = DesensitizedUtil.mobilePhone(contactPhone); + resCompanyBasicCreditDetailDTO.setContactPhone(encryptPhone); + + CompanyBasicCredit companyBasicCredit = + iCompanyBasicCreditService.getOne(new QueryWrapper().eq("company_id", companyId)); + BeanUtil.copyProperties(companyBasicCredit, resCompanyBasicCreditDetailDTO); + if (company.getRegionId() != null && 0L != company.getRegionId()) { + Region region = iRegionService.getById(company.getRegionId()); + resCompanyBasicCreditDetailDTO.setRegionCode(region.getRegionCode()); + } + return resCompanyBasicCreditDetailDTO; + } + + @Override + public PageVo getCompanyCommonCreditList(CompanyListParamDTO param) { + PageVo page = new PageVo<>(); + List result = new ArrayList<>(); + CompanyPageQuery companyPageQuery = new CompanyPageQuery(); + companyPageQuery.setRegionId(param.getRegionId()); + companyPageQuery.setName(param.getCompanyName()); + companyPageQuery.setPageNumber(param.getPageNumber()); + companyPageQuery.setPageSize(param.getPageSize()); + companyPageQuery.setBlackList(param.getBlackList()); + PageVo pageVo = companyManage.queryList(companyPageQuery); + // 获取企业信用信息 + Map> listMap = companyCreditLevelService.list().stream() + .collect(Collectors.groupingBy(NdCompanyCreditLevel::getCompanyId)); + if (pageVo.getTotal() != null && 0L != pageVo.getTotal()) { + List companyVOList = new ArrayList<>(pageVo.getRecords()); + for (CompanyVO companyVO : companyVOList) { + ResCompanyCommonCreditDTO resCompanyCommonCreditDTO = new ResCompanyCommonCreditDTO(); + BeanUtil.copyProperties(companyVO, resCompanyCommonCreditDTO); + List creditLevelList = listMap.get(companyVO.getId()); + if (CollUtil.isNotEmpty(creditLevelList)) { + String year = String.valueOf(LocalDateTime.now().getYear()); + // 筛选当前年份的数据 + List levels = + creditLevelList.stream().filter(c -> year.equals(c.getYear())).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(levels)) { + NdCompanyCreditLevel creditLevel = levels.get(0); + resCompanyCommonCreditDTO.setCommonCreditScore(creditLevel.getCommonCreditScore()); + } + } else { + // 信用表中不存在该企业,设为0 + log.info("企业信息等级表中不存在该企业{}", companyVO.getId()); + resCompanyCommonCreditDTO.setCommonCreditScore(0); + } + result.add(resCompanyCommonCreditDTO); + } + } + page.setTotal(pageVo.getTotal()); + page.setRecords(result); + return page; + } + + @Override + public void companyListExport(HttpServletResponse response, CompanyListParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = getCompanyList(param); + + List collect = (List)page.getRecords(); + + String fileName = "企业列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), ResCompanyArchivesDTO.class).autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void companyBasicCreditListExport(HttpServletResponse response, CompanyListParamDTO param) { + PageVo page = getCompanyBasicCreditList(param); + List collect = (List)page.getRecords(); + String fileName = "企业基本信用列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), ResCompanyBasicCreditDTO.class).autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void companyCommonCreditListExport(HttpServletResponse response, CompanyListParamDTO param) { + PageVo page = getCompanyCommonCreditList(param); + List collect = (List)page.getRecords(); + String fileName = "企业公共信用列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), ResCompanyCommonCreditDTO.class).autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void companyCertificateInformationListExport(HttpServletResponse response, CompanyListParamDTO param) { + param.setPageNumber(1); + param.setPageSize(10000); + PageVo page = getCompanyList(param); + List collect = (List)page.getRecords(); + + String fileName = "企业证书信息列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), ResCompanyArchivesDTO.class).autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public PageVo getNotOnCarList(ReqNotGetOnCarDTO param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(CompanyVehicleNotGetOn.class); + ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl) AopContext.currentProxy(); + context.buildNotOnCarQuery(wrapper,param); + Page notGetOnPage = companyVehicleNotGetOnService.page(page, wrapper); + List resData = notGetOnPage.getRecords().stream().map(c -> { + ResNotGetOnCarRecordDTO res = new ResNotGetOnCarRecordDTO(); + res.setId(c.getId()); + res.setCarPlate(c.getCarPlate()); + res.setTime(c.getTime()); + return res; + }).collect(Collectors.toList()); + return PageVo.of(resData, page.getTotal()); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_COMPANY) + public void buildNotOnCarQuery(LambdaQueryWrapper wrapper, ReqNotGetOnCarDTO param) { + wrapper.eq(CompanyVehicleNotGetOn::getCompanyId, param.getCompanyId()) + .eq(Objects.nonNull(param.getCarPlate()), CompanyVehicleNotGetOn::getCarPlate, param.getCarPlate()) + .eq(Objects.nonNull(param.getQueryTime()), CompanyVehicleNotGetOn::getTime, param.getQueryTime()); + } + + @Override + public CompanySecurityInfoVO getCompanySecurityInfo(Long companyId) { + CompanySecurityInfoVO vo = new CompanySecurityInfoVO(); + // 默认显示查询时间所在年度的信用等级 + String year = String.valueOf(LocalDateTime.now().getYear()); + // 获取企业信用等级信息 + NdCompanyCreditLevel creditLevel = + companyCreditLevelService.getOne(Wrappers.lambdaQuery(NdCompanyCreditLevel.class) + .eq(NdCompanyCreditLevel::getCompanyId, companyId).eq(NdCompanyCreditLevel::getYear, year)); + if (Objects.nonNull(creditLevel)) { + vo.setCreditLevel(creditLevel.getLevel()); + vo.setCreditLevelName(CompanyCreditLevelEnum.getDescByCode(creditLevel.getLevel())); + vo.setCompanyCreditEvaluateTotalScore(creditLevel.getScore()); + vo.setCommonCreditScore(creditLevel.getCommonCreditScore()); + vo.setBasicCreditScore(creditLevel.getBasicCreditScore()); + vo.setSafeProductCreditScore(creditLevel.getSafeProductCreditScore()); + vo.setIndustryRegulateCreditScore(creditLevel.getIndustryRegulateCreditScore()); + vo.setIndustryHonorBonus(creditLevel.getIndustryHonorBonus()); + } + + // 获取企业风险等级信息 + WarnAnalysisCompany warnAnalysisCompany = warnAnalysisCompanyService + .getOne(Wrappers.lambdaQuery(WarnAnalysisCompany.class).eq(WarnAnalysisCompany::getCompanyId, companyId)); + if (Objects.nonNull(warnAnalysisCompany)) { + vo.setDangerLevel(warnAnalysisCompany.getDangerLevel()); + vo.setDangerLevelName(DangerLevelEnum.getDescByCode(warnAnalysisCompany.getDangerLevel())); + vo.setCompanySafeRiskScore(warnAnalysisCompany.getTotalScore()); + vo.setViolationCnt(warnAnalysisCompany.getViolationCount()); + vo.setOutDangerCnt(warnAnalysisCompany.getDangerCount()); + vo.setInjuryCnt(warnAnalysisCompany.getInjuredCount()); + vo.setDeadCnt(warnAnalysisCompany.getDeadCount()); + } + return vo; + } + + public Company saveCompany(CompanySaveDTO data) { + Company company = companyService.save(data, null); + companiesCacheHelper.refresh(company.getId()); + return company; + } + + @Override + public PageVo queryToBeAudit(CompanyAuditPageQuery param) { + + Integer pageNumber = param.getPageNumber(); + Integer pageSize = param.getPageSize(); + Integer productCompanyType = param.getProductCompanyType(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl)AopContext.currentProxy(); + // 判断登录用户的角色 + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + // 如果是区县管理员 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId)) { + context.searchRegionTobeAuditWrapper(wrapper, param); + } else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) { + context.searchCityTobeAuditWrapper(wrapper, param); + } else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(roleId)){ + context.searchAllTobeAuditWrapper(wrapper,param); + } else { + return PageVo.empty(); + } + List companyList = companyService.list(wrapper); + Map> companyTypeRelatedMap = + companyTypeRelatedService.list().stream().collect(Collectors.groupingBy(CompanyTypeRelated::getCompanyId)); + + // 如果具体到生产企业类型筛选 + if (Objects.nonNull(productCompanyType)) { + // 从企业类型关联表中查出对应的企业 + List relatedList = companyTypeRelatedService.list().stream().filter(c -> { + Long value = productCompanyType.longValue(); + Long companyTypeId = c.getCompanyTypeId(); + if (value.equals(companyTypeId)) { + return true; + } + return false; + }).collect(Collectors.toList()); + // 去重 + List companies = + relatedList.stream().map(CompanyTypeRelated::getCompanyId).distinct().collect(Collectors.toList()); + if (CollUtil.isNotEmpty(companies)) { + companyList = + companyList.stream().filter(d -> companies.contains(d.getId())).collect(Collectors.toList()); + } + } + + List records = + companyList.stream().skip((long)(pageNumber - 1) * pageSize).limit(pageSize).collect(Collectors.toList()); + + List res = records.stream().map(w -> { + ResCompanyArchivesDTO dto = new ResCompanyArchivesDTO(); + BeanUtil.copyProperties(w, dto); + CodeUtil.searchRegionName(dto); + if (Objects.nonNull(w.getCompanyType())) { + // 如果是生产企业,展示具体的企业类型 + if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(w.getCompanyType())) { + List relatedList = companyTypeRelatedMap.get(w.getId()); + List nameList = relatedList.stream() + .map(r -> ProductCompanyType.getDescByCode(r.getCompanyTypeId())).collect(Collectors.toList()); + String typeName = nameList.stream().collect(Collectors.joining(StrPool.COMMA)); + dto.setCarCompanyType(typeName); + } else { + dto.setCarCompanyType(CompanyTypeEnum.getDescByCode(w.getCompanyType())); + } + } + return dto; + }).collect(Collectors.toList()); + return PageVo.of(res, companyList.size()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + private void searchAllTobeAuditWrapper(LambdaQueryWrapper wrapper, CompanyAuditPageQuery param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName()) + .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType()) + .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus()) + .and(wp -> wp.eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT.getCode()) + .or() + .eq(Company::getRegionAuditStatus,AuditStateEnum.AUDIT.getCode())) + .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void searchCityTobeAuditWrapper(LambdaQueryWrapper wrapper, CompanyAuditPageQuery param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName()) + .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType()) + .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus()) + .eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT.getCode()) + .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn); + } + + @Override + public PageVo queryAuditedList(CompanyAuditPageQuery param) { + Integer pageNumber = param.getPageNumber(); + Integer pageSize = param.getPageSize(); + Integer productCompanyType = param.getProductCompanyType(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl)AopContext.currentProxy(); + // 判断登录用户的角色 + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + // 如果是区县管理员 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId)) { + context.searchRegionAuditedWrapper(wrapper, param); + } else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) { + context.searchCityAuditedWrapper(wrapper, param); + }else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(roleId)) { + context.searchAllAuditedWrapper(wrapper, param); + } else { + return PageVo.empty(); + } + + List companyList = companyService.list(wrapper); + Map> companyTypeRelatedMap = + companyTypeRelatedService.list().stream().collect(Collectors.groupingBy(CompanyTypeRelated::getCompanyId)); + + // 如果具体到生产企业类型筛选 + if (Objects.nonNull(productCompanyType)) { + // 从企业类型关联表中查出对应的企业 + List relatedList = companyTypeRelatedService.list().stream().filter(c -> { + Long value = productCompanyType.longValue(); + Long companyTypeId = c.getCompanyTypeId(); + if (value.equals(companyTypeId)) { + return true; + } + return false; + }).collect(Collectors.toList()); + // 去重 + List companies = + relatedList.stream().map(CompanyTypeRelated::getCompanyId).distinct().collect(Collectors.toList()); + if (CollUtil.isNotEmpty(companies)) { + companyList = + companyList.stream().filter(d -> companies.contains(d.getId())).collect(Collectors.toList()); + } + } + + List records = + companyList.stream().skip((long)(pageNumber - 1) * pageSize).limit(pageSize).collect(Collectors.toList()); + + List res = records.stream().map(w -> { + ResCompanyArchivesDTO dto = new ResCompanyArchivesDTO(); + BeanUtil.copyProperties(w, dto); + CodeUtil.searchRegionName(dto); + if (Objects.nonNull(w.getCompanyType())) { + // 如果是生产企业,展示具体的企业类型 + if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(w.getCompanyType())) { + List relatedList = companyTypeRelatedMap.get(w.getId()); + List nameList = relatedList.stream() + .map(r -> ProductCompanyType.getDescByCode(r.getCompanyTypeId())).collect(Collectors.toList()); + String typeName = nameList.stream().collect(Collectors.joining(StrPool.COMMA)); + dto.setCarCompanyType(typeName); + } else { + dto.setCarCompanyType(CompanyTypeEnum.getDescByCode(w.getCompanyType())); + } + } + return dto; + }).collect(Collectors.toList()); + return PageVo.of(res, companyList.size()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + private void searchAllAuditedWrapper(LambdaQueryWrapper wrapper, CompanyAuditPageQuery param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName()) + .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType()) + .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus()) + .and(wp -> wp.eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .or() + .eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode()) + .or() + .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .or() + .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode())) + .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void searchCityAuditedWrapper(LambdaQueryWrapper wrapper, CompanyAuditPageQuery param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName()) + .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType()) + .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus()) + .and(wp -> wp.eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode()).or() + .eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode())) + .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean audit(CompanyAuditDTO data, Long userId) { + VUtils.isTrue(!AuditStateEnum.AUDIT_SUCCESS.getCode().equals(data.getAuditStatus()) + && !AuditStateEnum.AUDIT_FAIL.getCode().equals(data.getAuditStatus())).throwMessage("请确认传入的审核code正确"); + Company company = companyService.getById(data.getId()); + VUtils.isTrueFormat(Objects.isNull(company)).throwMessage(ExceptionCode.OPERATION_EX.getCode(), "修改企业 {} 为空", + data.getId()); + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + // 如果是区县散办管理员 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId)) { + company.setRegionAuditStatus(data.getAuditStatus()); + company.setRegionAuditBy(userId); + company.setRegionAuditTime(LocalDateTime.now()); + company.setRegionAuditMind(data.getAuditMind()); + } + // 当且仅当登录用户是市级散办管理员账号,且审核通过,才更新企业审核状态为通过,并创建企业账号信息 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) { + company.setCityAuditStatus(data.getAuditStatus()); + company.setCityAuditBy(userId); + company.setCityAuditTime(LocalDateTime.now()); + company.setCityAuditMind(data.getAuditMind()); + // 市散办审核通过 + if (AuditStateEnum.AUDIT_SUCCESS.getCode().equals(data.getAuditStatus())) { + // 创建企业用户账号 + NdUserInfo userInfo = new NdUserInfo(); + userInfo.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode()); + userInfo.setUsername(company.getName()); + userInfo.setCompanyId(company.getId()); + userInfo.setCreateOn(LocalDateTime.now()); + userInfo.setUpdateOn(LocalDateTime.now()); + userInfoService.save(userInfo); + + Long userInfoId = userInfo.getId(); + NdUserAuth userAuth = new NdUserAuth(); + userAuth.setUserId(userInfoId); + userAuth.setIdentifier(company.getName()); + userAuth.setCredential(passwordEncoder.encode("123456Aa")); + userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + userAuth.setIsAvailable(true); + ndUserAuthService.save(userAuth); + + UserRole userRole = new UserRole(); + userRole.setUserId(userInfoId); + userRole.setRoleId(UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId()); + userRoleService.save(userRole); + } + + } + // 最后修改人 + company.setUpdateBy(userId); + company.setUpdateOn(LocalDateTime.now()); + return companyService.updateById(company); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void searchRegionAuditedWrapper(LambdaQueryWrapper wrapper, CompanyAuditPageQuery param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName()) + .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType()) + .eq(Objects.nonNull(param.getAuditStatus()), Company::getRegionAuditStatus, param.getAuditStatus()) + .and(wp -> wp.eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode()).or() + .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode())) + .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void searchRegionTobeAuditWrapper(LambdaQueryWrapper wrapper, CompanyAuditPageQuery param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName()) + .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType()) + .eq(Objects.nonNull(param.getAuditStatus()), Company::getRegionAuditStatus, param.getAuditStatus()) + .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT.getCode()) + .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyBlackListServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyBlackListServiceImpl.java new file mode 100644 index 0000000..ea9ee3c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyBlackListServiceImpl.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyBlackList; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditBlackListPageParam; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackDetailListDTO; +import com.ningdatech.carapi.company.entity.dto.ResCompanyBlackListDTO; +import com.ningdatech.carapi.company.mapper.NdCompanyBlackListMapper; +import com.ningdatech.carapi.company.service.INdCompanyBlackListService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 企业失信名单 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyBlackListServiceImpl extends ServiceImpl implements INdCompanyBlackListService { + + private final NdCompanyBlackListMapper ndCompanyBlackListMapper; + + @Override + public Page companyBlackList(CompanyCreditBlackListPageParam param) { + Page page = param.page(); + NdCompanyBlackListServiceImpl context = (NdCompanyBlackListServiceImpl) AopContext.currentProxy(); + return context.searchList(page,param); + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page searchList(Page page, CompanyCreditBlackListPageParam param) { + ndCompanyBlackListMapper.companyBlackList(page, param); + CodeUtil.searchCompanyNames(page.getRecords()); + return page; + } + + @Override + public List companyBlackInfoList(Long companyId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyBlackList.class); + NdCompanyBlackListServiceImpl context = (NdCompanyBlackListServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, companyId); + List companyBlackLists = ndCompanyBlackListMapper.selectList(wrapper); + if (CollUtil.isEmpty(companyBlackLists)){ + return Collections.emptyList(); + } + return companyBlackLists.stream().map(c -> { + ResCompanyBlackDetailListDTO dto = new ResCompanyBlackDetailListDTO(); + dto.setType(c.getType()); + dto.setBlackTime(c.getBlackTime()); + dto.setContent(c.getContent()); + dto.setSite(c.getSite()); + return dto; + }).collect(Collectors.toList()); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long companyId) { + wrapper.eq(NdCompanyBlackList::getCompanyId,companyId) + .orderByDesc(NdCompanyBlackList::getId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditDeductServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditDeductServiceImpl.java new file mode 100644 index 0000000..f2f8e75 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditDeductServiceImpl.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyCreditDeduct; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditDeductPageParam; +import com.ningdatech.carapi.company.mapper.NdCompanyCreditDeductMapper; +import com.ningdatech.carapi.company.service.INdCompanyCreditDeductService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 平安办扣分 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyCreditDeductServiceImpl extends ServiceImpl implements INdCompanyCreditDeductService { + + private final NdCompanyCreditDeductMapper ndCompanyCreditDeductMapper; + + @Override + public Page getCreditDeductList(CompanyCreditDeductPageParam param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditDeduct.class); + NdCompanyCreditDeductServiceImpl context = (NdCompanyCreditDeductServiceImpl) AopContext.currentProxy(); + Page ndCompanyCreditDeductPage = context.searchList(page, wrapper, param); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return ndCompanyCreditDeductPage; + } + + @Override + public Boolean delete(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditDeduct.class); + NdCompanyCreditDeductServiceImpl context = (NdCompanyCreditDeductServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + NdCompanyCreditDeduct creditDeduct = ndCompanyCreditDeductMapper.selectOne(wrapper); + if (Objects.isNull(creditDeduct)){ + return false; + } + ndCompanyCreditDeductMapper.deleteById(creditDeduct); + return true; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdCompanyCreditDeduct::getId,id); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public Page searchList(Page page, LambdaQueryWrapper wrapper + , CompanyCreditDeductPageParam param) { + wrapper.like(StringUtils.isNotEmpty(param.getCompanyName()),NdCompanyCreditDeduct::getCompanyName, param.getCompanyName()) + .ge(StringUtils.isNotEmpty(param.getStartTime()),NdCompanyCreditDeduct::getCreateOn, param.getStartTime()) + .le(StringUtils.isNotEmpty(param.getEndTime()),NdCompanyCreditDeduct::getCreateOn, param.getEndTime()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdCompanyCreditDeduct::getUpdateOn); + return ndCompanyCreditDeductMapper.selectPage(page, wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditInsideServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditInsideServiceImpl.java new file mode 100644 index 0000000..c937dab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditInsideServiceImpl.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyCreditInside; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditInsidePageParam; +import com.ningdatech.carapi.company.mapper.NdCompanyCreditInsideMapper; +import com.ningdatech.carapi.company.service.INdCompanyCreditInsideService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 内部/联合检查 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyCreditInsideServiceImpl extends ServiceImpl implements INdCompanyCreditInsideService { + + private final NdCompanyCreditInsideMapper ndCompanyCreditInsideMapper; + + @Override + public Page getList(CompanyCreditInsidePageParam param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditInside.class); + NdCompanyCreditInsideServiceImpl context = (NdCompanyCreditInsideServiceImpl)AopContext.currentProxy(); + return context.searchList(page,wrapper,param); + } + + @Override + public Boolean delete(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditInside.class); + NdCompanyCreditInsideServiceImpl context = (NdCompanyCreditInsideServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + NdCompanyCreditInside creditInside = ndCompanyCreditInsideMapper.selectOne(wrapper); + if (Objects.isNull(creditInside)){ + return false; + } + ndCompanyCreditInsideMapper.deleteById(creditInside); + return true; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdCompanyCreditInside::getId,id); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public Page searchList(Page page,LambdaQueryWrapper wrapper + ,CompanyCreditInsidePageParam param) { + wrapper.eq(NdCompanyCreditInside::getCheckType, param.getCheckType()) + .like(StringUtils.isNotEmpty(param.getCompanyName()),NdCompanyCreditInside::getCompanyName, param.getCompanyName()) + .eq(StringUtils.isNotEmpty(param.getType()),NdCompanyCreditInside::getType, param.getType()) + .ge(StringUtils.isNotEmpty(param.getStartTime()),NdCompanyCreditInside::getCreateOn, param.getStartTime()) + .le(StringUtils.isNotEmpty(param.getEndTime()),NdCompanyCreditInside::getCreateOn, param.getEndTime()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdCompanyCreditInside::getUpdateOn); + Page res = ndCompanyCreditInsideMapper.selectPage(page, wrapper); + CodeUtil.searchCompanyNamesAndRegionNames(res.getRecords()); + return res; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditLevelServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditLevelServiceImpl.java new file mode 100644 index 0000000..293f88e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditLevelServiceImpl.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditLevelPageParam; +import com.ningdatech.carapi.company.mapper.NdCompanyCreditLevelMapper; +import com.ningdatech.carapi.company.service.INdCompanyCreditLevelService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +/** + *

+ * 信用等级 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyCreditLevelServiceImpl extends ServiceImpl implements INdCompanyCreditLevelService { + + private final NdCompanyCreditLevelMapper ndCompanyCreditLevelMapper; + + @Override + public Page getCreditLevelList(CompanyCreditLevelPageParam param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditLevel.class); + NdCompanyCreditLevelServiceImpl context = (NdCompanyCreditLevelServiceImpl) AopContext.currentProxy(); + return context.searchList(page,wrapper,param); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public Page searchList(Page page, + LambdaQueryWrapper wrapper, CompanyCreditLevelPageParam param) { + wrapper.like(StringUtils.isNotEmpty(param.getCompanyName()),NdCompanyCreditLevel::getCompanyName, param.getCompanyName()) + .eq(StringUtils.isNotEmpty(param.getYear()),NdCompanyCreditLevel::getYear, param.getYear()) + .eq(StringUtils.isNotEmpty(param.getLevel()),NdCompanyCreditLevel::getLevel, param.getLevel()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdCompanyCreditLevel::getUpdateOn); + ndCompanyCreditLevelMapper.selectPage(page, wrapper); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return page; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditRewardServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditRewardServiceImpl.java new file mode 100644 index 0000000..f74392f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyCreditRewardServiceImpl.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyCreditReward; +import com.ningdatech.carapi.company.entity.dto.CompanyCreditRewardPageParam; +import com.ningdatech.carapi.company.mapper.NdCompanyCreditRewardMapper; +import com.ningdatech.carapi.company.service.INdCompanyCreditRewardService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 政府/行业嘉奖 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyCreditRewardServiceImpl extends ServiceImpl implements INdCompanyCreditRewardService { + + private final NdCompanyCreditRewardMapper ndCompanyCreditRewardMapper; + + @Override + public Page getCreditRewardList(CompanyCreditRewardPageParam param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditReward.class); + NdCompanyCreditRewardServiceImpl context = (NdCompanyCreditRewardServiceImpl) AopContext.currentProxy(); + return context.searchList(page,wrapper,param); + } + + @Override + public Boolean delete(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyCreditReward.class); + NdCompanyCreditRewardServiceImpl context = (NdCompanyCreditRewardServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + NdCompanyCreditReward creditReward = ndCompanyCreditRewardMapper.selectOne(wrapper); + if (Objects.isNull(creditReward)){ + return false; + } + ndCompanyCreditRewardMapper.deleteById(creditReward); + return true; + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdCompanyCreditReward::getId,id); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public Page searchList(Page page, LambdaQueryWrapper wrapper, CompanyCreditRewardPageParam param) { + wrapper.eq(NdCompanyCreditReward::getRewardType, param.getRewardType()) + .like(StringUtils.isNotEmpty(param.getCompanyName()),NdCompanyCreditReward::getCompanyName, param.getCompanyName()) + .ge(StringUtils.isNotEmpty(param.getStartTime()),NdCompanyCreditReward::getCreateOn, param.getStartTime()) + .le(StringUtils.isNotEmpty(param.getEndTime()),NdCompanyCreditReward::getCreateOn, param.getEndTime()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdCompanyCreditReward::getUpdateOn); + ndCompanyCreditRewardMapper.selectPage(page, wrapper); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return page; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyProductManageServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyProductManageServiceImpl.java new file mode 100644 index 0000000..609971f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyProductManageServiceImpl.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.company.entity.NdCompanyProductManage; +import com.ningdatech.carapi.company.entity.dto.ResProductManageDTO; +import com.ningdatech.carapi.company.entity.po.CompanyProductPO; +import com.ningdatech.carapi.company.mapper.NdCompanyProductManageMapper; +import com.ningdatech.carapi.company.service.INdCompanyProductManageService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +/** + *

+ * 公司生产管理 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyProductManageServiceImpl extends ServiceImpl implements INdCompanyProductManageService { + private final NdCompanyProductManageMapper ndCompanyProductManageMapper; + + @Override + public Page manageList(String companyName, Long regionId, int pageNum, int pageSize) { + NdCompanyProductManageServiceImpl context = (NdCompanyProductManageServiceImpl)AopContext.currentProxy(); + return context.searchList(new Page<>(pageNum, pageSize), + new CompanyProductPO(regionId, null, companyName, null)); + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page searchList(Page page,CompanyProductPO po){ + return ndCompanyProductManageMapper.manageList(page,po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyQualityManageServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyQualityManageServiceImpl.java new file mode 100644 index 0000000..779175c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanyQualityManageServiceImpl.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.company.service.impl; + +import java.util.Objects; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyQualityManage; +import com.ningdatech.carapi.company.entity.dto.ResQualityManageDTO; +import com.ningdatech.carapi.company.entity.po.CompanyQualityPO; +import com.ningdatech.carapi.company.mapper.NdCompanyQualityManageMapper; +import com.ningdatech.carapi.company.service.INdCompanyQualityManageService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 质量通报 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanyQualityManageServiceImpl extends ServiceImpl implements INdCompanyQualityManageService { + + private final NdCompanyQualityManageMapper ndCompanyQualityManageMapper; + + @Override + public Page qualityManageList(Long regionId, String year, int pageNum, int pageSize) { + NdCompanyQualityManageServiceImpl context = (NdCompanyQualityManageServiceImpl)AopContext.currentProxy(); + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + // 非省系统管理员 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) { + return context.searchList(new Page<>(pageNum, pageSize), + new CompanyQualityPO(regionId, null, year, null)); + }else { + return context.searchAllList(new Page<>(pageNum, pageSize), + new CompanyQualityPO(regionId, null, year, null)); + } + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page searchList(Page page, CompanyQualityPO po) { + ndCompanyQualityManageMapper.qualityManageList(page, po); + CodeUtil.searchRegionNames(page.getRecords()); + return page; + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page searchAllList(Page page, CompanyQualityPO po) { + ndCompanyQualityManageMapper.qualityAllManageList(page, po); + CodeUtil.searchRegionNames(page.getRecords()); + return page; + } + + @Override + public boolean incrementDownCount(Long id) { + return ndCompanyQualityManageMapper.incrementDownCount(id) > 0; + } + + @Override + public Boolean delete(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdCompanyQualityManage.class); + NdCompanyQualityManageServiceImpl context = (NdCompanyQualityManageServiceImpl) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + NdCompanyQualityManage qualityManage = ndCompanyQualityManageMapper.selectOne(wrapper); + if (Objects.isNull(qualityManage)){ + return false; + } + ndCompanyQualityManageMapper.deleteById(qualityManage); + return true; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdCompanyQualityManage::getId,id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityCommitmentServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityCommitmentServiceImpl.java new file mode 100644 index 0000000..a3238a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityCommitmentServiceImpl.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.company.entity.CompanySecurityCommitment; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityCommitmentParam; +import com.ningdatech.carapi.company.mapper.NdCompanySecurityCommitmentMapper; +import com.ningdatech.carapi.company.service.ICompanySecurityCommitmentService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全生产责任体系 安全承诺书 + *

+ * + * @author zpf + * @since 2023-05-23 + */ +@Service +@RequiredArgsConstructor +public class NdCompanySecurityCommitmentServiceImpl extends ServiceImpl implements ICompanySecurityCommitmentService { + + @Override + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + @LambdaDataScope(wrapperIndex = 1) + public Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityCommitmentParam param) { + return page(page,wrapper); + } + + @Override + public void deleteById(Long id) { + baseMapper.deleteById(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityGovernmentServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityGovernmentServiceImpl.java new file mode 100644 index 0000000..26bf45e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityGovernmentServiceImpl.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.company.entity.CompanySecurityGovernment; +import com.ningdatech.carapi.company.entity.dto.CompanySecurityCommitmentParam; +import com.ningdatech.carapi.company.mapper.NdCompanySecurityGovernmentMapper; +import com.ningdatech.carapi.company.service.ICompanySecurityGovernmentService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 安全 管理机构 + *

+ * + * @author zpf + * @since 2023-05-23 + */ +@Service +@RequiredArgsConstructor +public class NdCompanySecurityGovernmentServiceImpl extends ServiceImpl implements ICompanySecurityGovernmentService { + + @Override + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + @LambdaDataScope(wrapperIndex = 1) + public Page pageDataScope(Page page, LambdaQueryWrapper wrapper, CompanySecurityCommitmentParam param) { + return page(page,wrapper); + } + + @Override + @BuildChildrenRegionWrapper + @LambdaDataScope + public List dataScopeList(LambdaQueryWrapper wrapper, CompanySecurityCommitmentParam param) { + return baseMapper.selectList(wrapper); + } + + @Override + public void deleteById(Long id) { + baseMapper.deleteById(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductDutyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductDutyServiceImpl.java new file mode 100644 index 0000000..eab42d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductDutyServiceImpl.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductDuty; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductDutyDTO; +import com.ningdatech.carapi.company.entity.po.CompanySecurityProductDutyPO; +import com.ningdatech.carapi.company.mapper.NdCompanySecurityProductDutyMapper; +import com.ningdatech.carapi.company.service.INdCompanySecurityProductDutyService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全生产责任体系 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanySecurityProductDutyServiceImpl extends ServiceImpl implements INdCompanySecurityProductDutyService { + + private final NdCompanySecurityProductDutyMapper ndCompanySecurityProductDutyMapper; + + @Override + public Page securityProductDutyList(Long regionId, String companyName, String startTime, String endTime, Integer fileType, int pageNum, int pageSize) { + NdCompanySecurityProductDutyServiceImpl context = (NdCompanySecurityProductDutyServiceImpl)AopContext.currentProxy(); + return context.searchList(new Page<>(pageNum, pageSize), + new CompanySecurityProductDutyPO(regionId,null, companyName, startTime, endTime, fileType,null)); + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page searchList(Page page, + CompanySecurityProductDutyPO po) { + ndCompanySecurityProductDutyMapper.securityProductDutyList(page,po); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return page; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductExecuteServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductExecuteServiceImpl.java new file mode 100644 index 0000000..24d3a43 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductExecuteServiceImpl.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductExecute; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductExecuteDTO; +import com.ningdatech.carapi.company.entity.po.CompanySecurityProductExecutePO; +import com.ningdatech.carapi.company.mapper.NdCompanySecurityProductExecuteMapper; +import com.ningdatech.carapi.company.service.INdCompanySecurityProductExecuteService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全生产制度执行 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanySecurityProductExecuteServiceImpl extends ServiceImpl implements INdCompanySecurityProductExecuteService { + + private final NdCompanySecurityProductExecuteMapper ndCompanySecurityProductExecuteMapper; + + @Override + public Page securityProductExecuteList(String name, String startTime, String endTime, Integer fileType, int pageNum, int pageSize) { + NdCompanySecurityProductExecuteServiceImpl context = (NdCompanySecurityProductExecuteServiceImpl)AopContext.currentProxy(); + return context.searchList(new Page<>(pageNum, pageSize),new CompanySecurityProductExecutePO(name, startTime, endTime,fileType,null)); + + } + + @XmlDataScope(entityIndex = 1) + public Page searchList(Page page, + CompanySecurityProductExecutePO po) { + return ndCompanySecurityProductExecuteMapper.securityProductExecuteList(page, po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductRegulationsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductRegulationsServiceImpl.java new file mode 100644 index 0000000..dbcb9e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/company/service/impl/NdCompanySecurityProductRegulationsServiceImpl.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.company.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.company.entity.NdCompanySecurityProductRegulations; +import com.ningdatech.carapi.company.entity.dto.ResSecurityProductRegulationsDTO; +import com.ningdatech.carapi.company.entity.po.CompanySecurityProductRegulationPO; +import com.ningdatech.carapi.company.mapper.NdCompanySecurityProductRegulationsMapper; +import com.ningdatech.carapi.company.service.INdCompanySecurityProductRegulationsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全生产制度体系 服务实现类 + *

+ * + * @author liushuai + * @since 2022-10-10 + */ +@Service +@RequiredArgsConstructor +public class NdCompanySecurityProductRegulationsServiceImpl extends ServiceImpl implements INdCompanySecurityProductRegulationsService { + + private final NdCompanySecurityProductRegulationsMapper ndCompanySecurityProductRegulationsMapper; + + @Override + public Page securityProductRegulationsList(String regulationsName, String competentDepartment, String startTime, String endTime, Integer fileType, int pageNum, int pageSize) { + NdCompanySecurityProductRegulationsServiceImpl context = (NdCompanySecurityProductRegulationsServiceImpl)AopContext.currentProxy(); + return context.searchList(new Page<>(pageNum, pageSize), + new CompanySecurityProductRegulationPO(regulationsName, competentDepartment, startTime, endTime, fileType,null)); + } + + @XmlDataScope(entityIndex = 1) + public Page searchList(Page page, CompanySecurityProductRegulationPO po) { + return ndCompanySecurityProductRegulationsMapper.securityProductRegulationsList(page,po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScope.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScope.java new file mode 100644 index 0000000..6e03582 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScope.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.datascope.aop; + +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; + +import java.lang.annotation.*; + +/** + * @Classname LambdaDataScope + * @Description + * @Date 2022/11/11 15:34 + * @Created by PoffyZhang + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface LambdaDataScope { + LambdaDataScopeTypeEnum type() default LambdaDataScopeTypeEnum.ALL; + + //wrapper的下标位置 如果是分页的话 可能是第二个 + int wrapperIndex() default 0; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScopeAspect.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScopeAspect.java new file mode 100644 index 0000000..6f3a7e7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/LambdaDataScopeAspect.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.datascope.aop; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.model.DataScopeEntity; +import com.ningdatech.carapi.datascope.provider.DataScopeContext; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Optional; + +/** + * @program: + * @description: 数据权限切面 + * LambdaDataScopeAspect + * @author: PoffyZhang + * @created: 2022/11/11 09:12 + */ +@Aspect +@Component +@Slf4j +@AllArgsConstructor +@Order(10) +public class LambdaDataScopeAspect { + + @Pointcut("@annotation(com.ningdatech.carapi.datascope.aop.LambdaDataScope)") + public void lambdaDataScopeAspect() { + + } + + @Before("lambdaDataScopeAspect() && @annotation(lambdaDataScope)") + public void before(JoinPoint joinPoint, LambdaDataScope lambdaDataScope) throws Throwable { + Optional currentUserDataScoper = getCurrentUserDataScoper(); + if (!currentUserDataScoper.isPresent()) { + return; + } + DataScopeDto dataScopeDto = currentUserDataScoper.get(); + LambdaQueryWrapper wrapper = + (LambdaQueryWrapper) joinPoint.getArgs()[lambdaDataScope.wrapperIndex()]; + + if (Objects.isNull(wrapper)) { + return; + } + + switch (lambdaDataScope.type()) { + case ALL: + wrapper.in(CollUtil.isNotEmpty(dataScopeDto.getRegionIds()), DataScopeEntity::getRegionId, dataScopeDto.getRegionIds()) + .in(CollUtil.isNotEmpty(dataScopeDto.getCompanyIds()), DataScopeEntity::getCompanyId, dataScopeDto.getCompanyIds()); + break; + case ONLY_REGION: + wrapper.in(CollUtil.isNotEmpty(dataScopeDto.getRegionIds()), DataScopeEntity::getRegionId, dataScopeDto.getRegionIds()); + break; + case ONLY_COMPANY: + wrapper.in(CollUtil.isNotEmpty(dataScopeDto.getCompanyIds()), DataScopeEntity::getCompanyId, dataScopeDto.getCompanyIds()); + break; + case REGION_TABLE: + wrapper.in(CollUtil.isNotEmpty(dataScopeDto.getRegionIds()), DataScopeEntity::getId, dataScopeDto.getRegionIds()); + break; + case COMPANY_TABLE: + wrapper.in(CollUtil.isNotEmpty(dataScopeDto.getCompanyIds()), DataScopeEntity::getId, dataScopeDto.getCompanyIds()) + .in(CollUtil.isNotEmpty(dataScopeDto.getRegionIds()), DataScopeEntity::getRegionId, dataScopeDto.getRegionIds()); + break; + case NONE: + break; + default: + wrapper.in(CollUtil.isNotEmpty(dataScopeDto.getRegionIds()), DataScopeEntity::getRegionId, dataScopeDto.getRegionIds()) + .in(CollUtil.isNotEmpty(dataScopeDto.getCompanyIds()), DataScopeEntity::getCompanyId, dataScopeDto.getCompanyIds()); + } + + } + + public Optional getCurrentUserDataScoper() { + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + if (Objects.isNull(loginUser) || Objects.isNull(loginUser.getDataScope())) { + return Optional.empty(); + } + return DataScopeContext.getDataScope(loginUser.getDataScope()); + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScope.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScope.java new file mode 100644 index 0000000..5f126bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScope.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.datascope.aop; + +import java.lang.annotation.*; + +/** + * @Classname XmlDataScope + * xml 可以join 所以要设置 别名 + * @Description + * @Date 2022/11/11 15:34 + * @Created by PoffyZhang + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface XmlDataScope { + + String regionAlias() default "r"; + + String companyAlias() default "c"; + + //实体的位置 默认0 如果有分页 那么可能是第二个 + int entityIndex() default 0; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScopeAspect.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScopeAspect.java new file mode 100644 index 0000000..eb42349 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/aop/XmlDataScopeAspect.java @@ -0,0 +1,101 @@ +package com.ningdatech.carapi.datascope.aop; + +import cn.hutool.core.collection.CollUtil; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeContext; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +; + +/** + * @program: + * @description: xml sql方式 + * 数据权限切面 + * @author: PoffyZhang + * @created: 2022/11/11 09:12 + */ +@Aspect +@Component +@Slf4j +@AllArgsConstructor +@Order(10) +public class XmlDataScopeAspect { + + @Pointcut("@annotation(com.ningdatech.carapi.datascope.aop.XmlDataScope)") + public void xmlDataScopeAspect() { + + } + + @Before("xmlDataScopeAspect() && @annotation(xmlDataScope)") + public void before(JoinPoint joinPoint, XmlDataScope xmlDataScope) throws Throwable { + Optional currentUserDataScoper = getCurrentUserDataScoper(); + if(!currentUserDataScoper.isPresent()){ + return; + } + DataScopeDto dataScopeDto = currentUserDataScoper.get(); + Object entity = joinPoint.getArgs()[xmlDataScope.entityIndex()]; + + if(Objects.isNull(entity)){ + return; + } + + StringBuilder sql = new StringBuilder(); + if(CollUtil.isEmpty(dataScopeDto.getCompanyIds()) + && CollUtil.isEmpty(dataScopeDto.getRegionIds())){ + return; + } + + if(CollUtil.isNotEmpty(dataScopeDto.getCompanyIds())){ + sql.append(" AND " + xmlDataScope.companyAlias() + ".id in (" + + convertForStr(dataScopeDto.getCompanyIds()) + ")"); + } + + + if(CollUtil.isNotEmpty(dataScopeDto.getRegionIds())){ + sql.append(" AND " + xmlDataScope.regionAlias() + ".id in (" + + convertForStr(dataScopeDto.getRegionIds()) + ")"); + } + + if(sql.length() > 0){ + Class clazz = entity.getClass(); + Field dataScopeSql = clazz.getDeclaredField("dataScopeSql"); + dataScopeSql.setAccessible(true); + dataScopeSql.set(entity, sql.toString()); + } + } + + private String convertForStr(List companyIds) { + if(CollUtil.isEmpty(companyIds)){ + return StringUtils.EMPTY; + } + StringBuilder sql = new StringBuilder(); + for(Long companyId : companyIds){ + sql.append(companyId + ","); + } + sql.delete(sql.length()-1,sql.length()); + return sql.toString(); + } + + public Optional getCurrentUserDataScoper(){ + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + if(Objects.isNull(loginUser) || Objects.isNull(loginUser.getDataScope())){ + return Optional.empty(); + } + return DataScopeContext.getDataScope(loginUser.getDataScope()); + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeColumnConst.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeColumnConst.java new file mode 100644 index 0000000..868972e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeColumnConst.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.datascope.contants; + +/** + *

+ * DataScopeColumnConst + *

+ * + * @author WendyYang + * @since 16:24 2022/11/3 + */ +public interface DataScopeColumnConst { + + String REGION_ID = "region_id"; + + String COMPANY_ID = "company_id"; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeEnum.java new file mode 100644 index 0000000..630cd5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/DataScopeEnum.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.datascope.contants; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.stream.Stream; + +/** + *

+ * 数据权限枚举类 + *

+ * + * @author WendyYang + * @since 2019-07-21 + */ +@Getter +@AllArgsConstructor +public enum DataScopeEnum { + + /** + * 数据权限枚举 + */ + ALL(1, "全部"), + + SELF_REGION(2, "本区域"), + + SELF_CHILD_REGION(3, "本区域及下级区域"), + + SELF_COMPANY(4, "本单位"); + + private final int val; + + private final String desc; + + + public static DataScopeEnum match(String val) { + return Stream.of(values()) + .filter((item) -> item.name().equalsIgnoreCase(val)) + .findAny() + .orElse(SELF_COMPANY); + } + + public static DataScopeEnum get(String val) { + return match(val); + } + + public boolean eq(final DataScopeEnum val) { + return val != null && this.name().equals(val.name()); + } + + public int getCode() { + return this.val; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/LambdaDataScopeTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/LambdaDataScopeTypeEnum.java new file mode 100644 index 0000000..11ecef0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/contants/LambdaDataScopeTypeEnum.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.datascope.contants; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * @Classname DataScopeTypeEnum + * @Description + * @Date 2022/11/18 11:15 + * @Created by PoffyZhang + */ +@ApiModel(value = "DataScopeTypeEnum", description = "数据范围类型-枚举") +public enum LambdaDataScopeTypeEnum { + /** + * 一般场景 此表有 ragion_id company_id + */ + ALL, + + /** + * 该表数据 只有地区 没有公司 + */ + ONLY_REGION, + + /** + * 只有公司 + */ + ONLY_COMPANY, + + /** + * 该表刚好是地区表 字段是id + */ + REGION_TABLE, + + /** + * 该表刚好是公司表 字段是id + */ + COMPANY_TABLE, + + /** + * 企业 公司都没有 + */ + NONE; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeDto.java new file mode 100644 index 0000000..882659f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeDto.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.datascope.model; + +import com.ningdatech.carapi.datascope.contants.DataScopeEnum; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import lombok.Data; + +import java.util.List; + +/** + *

+ * DataScopeDto + *

+ * + * @author WendyYang + * @since 13:42 2022/11/4 + */ +@Data +public class DataScopeDto { + + private DataScopeEnum dataScope; + + private List regionIds; + + private List companyIds; + + //该用户权限所能查询到的最大区域 + private RegionDTO maxRegion; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeEntity.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeEntity.java new file mode 100644 index 0000000..1ef39ad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/model/DataScopeEntity.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.datascope.model; + +import lombok.Data; + +import java.util.Map; + +/** + * @Classname DataScopEntity + * @Description + * @Date 2022/11/11 16:25 + * @Created by PoffyZhang + */ +@Data +public class DataScopeEntity { + + protected Long id; + + protected Long regionId; + + protected Long companyId; + + protected String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeContext.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeContext.java new file mode 100644 index 0000000..2cffdac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeContext.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.datascope.provider; + +import com.ningdatech.basic.util.SpringUtils; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import lombok.RequiredArgsConstructor; + +import java.util.Map; +import java.util.Optional; + +/** + *

+ * 数据权限获取 + *

+ * + * @author WendyYang + * @since 2022/1/9 23:28 + */ +@RequiredArgsConstructor +public class DataScopeContext { + + private static final String WARN_MSG = "请先创建数据权限[%s]的实现类,使其实现 DataScopeProvider"; + + private static final Map DSP_MAP; + + static { + DSP_MAP = SpringUtils.getBeansOfType(DataScopeProvider.class); + } + + public static Optional getDataScope(int type) { + String key = "DATA_SCOPE_" + type; + DataScopeProvider dataScopeProvider = DSP_MAP.get(key); + if (dataScopeProvider == null) { + throw new IllegalArgumentException(String.format(WARN_MSG, key)); + } + return dataScopeProvider.findDataFieldProperty(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeProvider.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeProvider.java new file mode 100644 index 0000000..7ff6428 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/DataScopeProvider.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.datascope.provider; + + +import com.ningdatech.carapi.datascope.model.DataScopeDto; + +import java.util.List; +import java.util.Optional; + +/** + *

+ * 数据权限获取接口 + *

+ * + * @author WendyYang + * @since 2022/1/9 23:28 + */ +public interface DataScopeProvider { + + /** + * 获取登录人的数据权限 + * + * @return 数据权限 + **/ + Optional findDataFieldProperty(); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/AllDataScopeProviderImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/AllDataScopeProviderImpl.java new file mode 100644 index 0000000..d9c2772 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/AllDataScopeProviderImpl.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.datascope.provider.impl; + +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.contants.DataScopeEnum; +import com.ningdatech.carapi.datascope.provider.DataScopeProvider; +import com.ningdatech.carapi.sys.contants.RegionContant; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Optional; + + +/** + *

+ * 数据权限{@link DataScopeEnum#ALL} + *

+ * + * @author WendyYang + * @since 2022/1/9 23:29 + */ +@Slf4j +@RequiredArgsConstructor +@Component("DATA_SCOPE_1") +public class AllDataScopeProviderImpl implements DataScopeProvider { + + private final RegionsCacheHelper regionsCacheHelper; + @Override + public Optional findDataFieldProperty() { + DataScopeDto dataScopeDto = new DataScopeDto(); + //全部权限的话 最大是浙江 + dataScopeDto.setMaxRegion(regionsCacheHelper.getByRegionId(RegionContant.ZJ_REGION_ID)); + return Optional.ofNullable(dataScopeDto); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfChildRegionDataScopeProviderImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfChildRegionDataScopeProviderImpl.java new file mode 100644 index 0000000..5cdada8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfChildRegionDataScopeProviderImpl.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.datascope.provider.impl; + +import com.ningdatech.carapi.datascope.contants.DataScopeEnum; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeProvider; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; + +/** + *

+ * 数据权限{@link DataScopeEnum#SELF_CHILD_REGION} + *

+ * + * @author WendyYang + * @since 2022/1/9 23:29 + */ +@Slf4j +@RequiredArgsConstructor +@Component("DATA_SCOPE_3") +public class SelfChildRegionDataScopeProviderImpl implements DataScopeProvider { + + private final RegionsCacheHelper regionsCacheHelper; + private final INdUserInfoService userInfoService; + private final CompaniesCacheHelper companiesCacheHelper; + + @Override + public Optional findDataFieldProperty() { + NdUserInfo user = userInfoService.getById(LoginUserUtil.getUserId()); + CompanyDTO company = companiesCacheHelper.getById(user.getCompanyId()); + List regionIds = regionsCacheHelper.listChildRegionId(company.getRegionId()); + DataScopeDto ds = new DataScopeDto(); + ds.setRegionIds(regionIds); + //最大的区域权限是 公司所在的区域 用于大屏地图 + ds.setMaxRegion(regionsCacheHelper.getByRegionId(company.getRegionId())); + return Optional.ofNullable(ds); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfCompanyDataScopeProviderImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfCompanyDataScopeProviderImpl.java new file mode 100644 index 0000000..e59b11c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfCompanyDataScopeProviderImpl.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.datascope.provider.impl; + +import com.ningdatech.carapi.datascope.contants.DataScopeEnum; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeProvider; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + *

+ * 数据权限{@link DataScopeEnum#SELF_COMPANY} + *

+ * + * @author WendyYang + * @since 2022/1/9 23:29 + */ +@Slf4j +@RequiredArgsConstructor +@Component("DATA_SCOPE_4") +public class SelfCompanyDataScopeProviderImpl implements DataScopeProvider { + + private final RegionsCacheHelper regionsCacheHelper; + + private final CompaniesCacheHelper companiesCacheHelper; + + private final INdUserInfoService userInfoService; + + @Override + public Optional findDataFieldProperty() { + Long userId = LoginUserUtil.getUserId(); + NdUserInfo user = userInfoService.getById(userId); + List companyIds = Collections.singletonList(user.getCompanyId()); + DataScopeDto ds = new DataScopeDto(); + ds.setCompanyIds(companyIds); + CompanyDTO company = companiesCacheHelper.getById(user.getCompanyId()); + //最大的区域权限是 公司所在的区域 用于大屏地图 + ds.setMaxRegion(regionsCacheHelper.getByRegionId(company.getRegionId())); + return Optional.ofNullable(ds); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfRegionDataScopeProviderImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfRegionDataScopeProviderImpl.java new file mode 100644 index 0000000..00686e4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/datascope/provider/impl/SelfRegionDataScopeProviderImpl.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.datascope.provider.impl; + +import com.ningdatech.carapi.datascope.contants.DataScopeEnum; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeProvider; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + *

+ * 数据权限{@link DataScopeEnum#SELF_REGION} + *

+ * + * @author WendyYang + * @since 2022/1/9 23:29 + */ +@Slf4j +@RequiredArgsConstructor +@Component("DATA_SCOPE_2") +public class SelfRegionDataScopeProviderImpl implements DataScopeProvider { + + private final INdUserInfoService userInfoService; + private final CompaniesCacheHelper companiesCacheHelper; + + private final RegionsCacheHelper regionsCacheHelper; + + @Override + public Optional findDataFieldProperty() { + Long userId = LoginUserUtil.getUserId(); + NdUserInfo user = userInfoService.getById(userId); + CompanyDTO company = companiesCacheHelper.getById(user.getCompanyId()); + Long regionId; + regionId = company.getRegionId(); + List regionIds = Collections.singletonList(regionId); + DataScopeDto ds = new DataScopeDto(); + ds.setRegionIds(regionIds); + //最大的区域权限是 公司所在的区域 用于大屏地图 + ds.setMaxRegion(regionsCacheHelper.getByRegionId(company.getRegionId())); + return Optional.ofNullable(ds); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/assembler/TrainingAssembler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/assembler/TrainingAssembler.java new file mode 100644 index 0000000..d4f9e2f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/assembler/TrainingAssembler.java @@ -0,0 +1,97 @@ +package com.ningdatech.carapi.driver.assembler; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.*; +import com.ningdatech.carapi.driver.entity.TrainingMaterial; +import com.ningdatech.carapi.driver.entity.TrainingOrganization; +import com.ningdatech.carapi.driver.entity.TrainingOrganizationTrainer; +import com.ningdatech.carapi.driver.model.TrainingBasicInfo; +import com.ningdatech.carapi.driver.model.TrainingMaterialInfo; +import com.ningdatech.carapi.driver.model.TrainingMaterialOverviewInfo; +import com.ningdatech.carapi.driver.model.vo.OrganizationTrainingTrainersInfo; + +/** + * @author liuxinxin + * @date 2022/10/22 下午3:59 + */ + +public class TrainingAssembler { + + public static TrainingBasicInfo buildTrainingBasicInfo(TrainingOrganization trainingOrganization) { + // 装配培训基本信息 + TrainingBasicInfo trainingBasicInfo = new TrainingBasicInfo(); + trainingBasicInfo.setAddress(trainingOrganization.getAddress()); + trainingBasicInfo.setContactNumber(trainingOrganization.getContactNumber()); + trainingBasicInfo.setContacts(trainingOrganization.getContacts()); + trainingBasicInfo.setRemark(trainingOrganization.getRemark()); + trainingBasicInfo.setTrainingStartTime(trainingOrganization.getTrainingStartTime()); + trainingBasicInfo.setTrainingEndTime(trainingOrganization.getTrainingEndTime()); + if (Objects.nonNull(trainingOrganization.getTrainingMode())){ + trainingBasicInfo.setTrainingMode(TrainingModeEnum.valueOf(trainingOrganization.getTrainingMode())); + } + if (Objects.nonNull(trainingOrganization.getTrainingStatus())) { + trainingBasicInfo.setTrainingStatus(TrainingStatusEnum.valueOf(trainingOrganization.getTrainingStatus())); + } + trainingBasicInfo.setTrainingTopic(trainingOrganization.getTrainingTopic()); + if (Objects.nonNull(trainingOrganization.getTrainingType())) { + trainingBasicInfo.setTrainingType(TrainingTypeEnum.valueOf(trainingOrganization.getTrainingType())); + } + return trainingBasicInfo; + } + + public static TrainingMaterialOverviewInfo buildTrainingMaterialOverviewInfo(List materialList) { + List trainingMaterialInfoList = buildTrainingMaterialInfoList(materialList); + Map> trainingMaterialMap = trainingMaterialInfoList.stream() + .collect(Collectors.groupingBy(TrainingMaterialInfo::getMaterialType)); + TrainingMaterialOverviewInfo trainingMaterialOverviewInfo = new TrainingMaterialOverviewInfo(); + trainingMaterialOverviewInfo.setRuleSystemMaterialList(trainingMaterialMap.get(MaterialTypeEnum.rule_system)); + trainingMaterialOverviewInfo.setPolicyDocumentsMaterialInfoList(trainingMaterialMap.get(MaterialTypeEnum.policy_documents)); + trainingMaterialOverviewInfo.setSafetyKnowledgeMaterialInfoList(trainingMaterialMap.get(MaterialTypeEnum.safety_knowledge)); + trainingMaterialOverviewInfo.setAccidentCaseMaterialInfoList(trainingMaterialMap.get(MaterialTypeEnum.accident_case)); + trainingMaterialOverviewInfo.setTrainingVideoMaterialInfoList(trainingMaterialMap.get(MaterialTypeEnum.training_video)); + trainingMaterialOverviewInfo.setOtherMaterialInfoList(trainingMaterialMap.get(MaterialTypeEnum.other)); + return trainingMaterialOverviewInfo; + } + + public static OrganizationTrainingTrainersInfo buildOrganizationTrainingTrainersInfo(TrainingOrganizationTrainer trainer) { + OrganizationTrainingTrainersInfo organizationTrainingTrainersInfo = new OrganizationTrainingTrainersInfo(); + organizationTrainingTrainersInfo.setId(trainer.getId()); + organizationTrainingTrainersInfo.setDriverId(trainer.getDriverId()); + organizationTrainingTrainersInfo.setDriverName(trainer.getDriverName()); + organizationTrainingTrainersInfo.setCompanyId(trainer.getCompanyId()); + organizationTrainingTrainersInfo.setCompanyName(trainer.getCompanyName()); + organizationTrainingTrainersInfo.setDriverId(trainer.getDriverId()); + organizationTrainingTrainersInfo.setDriverUserId(trainer.getDriverUserId()); + if (StringUtils.isNotBlank(trainer.getExaminationStatus())) { + organizationTrainingTrainersInfo.setExaminationStatus(ExaminationStatusEnum.valueOf(trainer.getExaminationStatus())); + } + organizationTrainingTrainersInfo.setExamPaperId(trainer.getExamPaperId()); + organizationTrainingTrainersInfo.setExamPaperName(trainer.getExamPaperName()); + organizationTrainingTrainersInfo.setExamRegistrationNo(trainer.getExamRegistrationNo()); + organizationTrainingTrainersInfo.setScore(trainer.getScore()); + organizationTrainingTrainersInfo.setIsQualified(trainer.getIsQualified()); + return organizationTrainingTrainersInfo; + } + + public static List buildTrainingMaterialInfoList(List materialList) { + return materialList.stream().map(r -> { + TrainingMaterialInfo trainingMaterialInfo = new TrainingMaterialInfo(); + String appendixListJson = r.getAppendixListJson(); + List appendixList = JSONObject.parseArray(appendixListJson,FileBasicInfo.class); + trainingMaterialInfo.setTitle(r.getTitle()); + trainingMaterialInfo.setContent(r.getContent()); + trainingMaterialInfo.setMaterialType(MaterialTypeEnum.valueOf(r.getMaterialType())); + trainingMaterialInfo.setTrainingMaterialId(r.getId()); + trainingMaterialInfo.setAppendixList(appendixList); + return trainingMaterialInfo; + }).collect(Collectors.toList()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/call/RestTemplateToInterface.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/call/RestTemplateToInterface.java new file mode 100644 index 0000000..af4f390 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/call/RestTemplateToInterface.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.driver.call; + +import com.ningdatech.carapi.driver.entity.OverseeInterfaceCallDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import javax.xml.transform.Result; + +/** + * @author CMM + * @description + * @since 2022/12/08 14:27 + */ +@Component +public class RestTemplateToInterface { + @Autowired + private RestTemplate restTemplate; + + /** + * 以get方式请求第三方http接口 getForEntity + * + * @param url + * @return + */ + public Result doGetWith1(String url) { + ResponseEntity responseEntity = restTemplate.getForEntity(url, Result.class); + Result result = responseEntity.getBody(); + return result; + } + + /** + * 以get方式请求第三方http接口 getForObject 返回值返回的是响应体,省去了我们再去getBody() + * + * @param url + * @return + */ + public Result doGetWith2(String url) { + Result result = restTemplate.getForObject(url, Result.class); + return result; + } + + + /** + * 以post方式请求第三方http接口 postForEntity + * @param url + * @param req + * @return + */ + public String doPostWith1(String url, OverseeInterfaceCallDTO req) { + ResponseEntity responseEntity = restTemplate.postForEntity(url, req, String.class); + String body = responseEntity.getBody(); + return body; + } + + /** + * 以post方式请求第三方http接口 postForEntity 返回值返回的是响应体,省去了我们再去getBody() + * + * @param url + * @param req + * @return + */ + public String doPostWith2(String url, OverseeInterfaceCallDTO req) { + String body = restTemplate.postForObject(url, req, String.class); + return body; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ApplicantTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ApplicantTypeEnum.java new file mode 100644 index 0000000..94fee39 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ApplicantTypeEnum.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.driver.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 驾驶员培训报名申请类型 + * @return + * @author CMM + * @since 2023/02/07 13:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "ApplicantTypeEnum", description = "驾驶员培训报名申请类型-枚举") +public enum ApplicantTypeEnum { + + /** + * 材料审核 + */ + MATERIAL_APPLICANT(1, "材料审核"), + + /** + * 跳槽审核 + */ + JOB_CHANGE_APPLICANT(2, "跳槽审核"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(int code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (ApplicantTypeEnum t : ApplicantTypeEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ArticleTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ArticleTypeEnum.java new file mode 100644 index 0000000..5565bd4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ArticleTypeEnum.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/9 下午4:40 + */ +@AllArgsConstructor +@Getter +public enum ArticleTypeEnum { + + /** + * 规章制度 + */ + RULES_AND_REGULATIONS +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/CurrentUserOrganizationEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/CurrentUserOrganizationEnum.java new file mode 100644 index 0000000..7288281 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/CurrentUserOrganizationEnum.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/11/3 下午6:27 + * 当前驾驶与参与培训组织状态 + */ + +public enum CurrentUserOrganizationEnum { + + // 已完成 + completed, + + // 未完成 + incomplete, + + // 未参加 + uncommitted +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorAppendixTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorAppendixTypeEnum.java new file mode 100644 index 0000000..f9c606a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorAppendixTypeEnum.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +@Getter +@AllArgsConstructor +public enum DriverAbnormalBehaviorAppendixTypeEnum { + PICTURE(0,"图片"), + + VIDEO(1,"视频"), + + OTHER(2,"其他"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(String code) { + if(StringUtils.isBlank(code)){ + return StringUtils.EMPTY; + } + for (DriverAbnormalBehaviorAppendixTypeEnum t : DriverAbnormalBehaviorAppendixTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorOverseeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorOverseeEnum.java new file mode 100644 index 0000000..9de1c24 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorOverseeEnum.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.driver.constant; + +import org.apache.commons.lang3.StringUtils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author CMM + * @description + * @since 2022/12/05 15:31 + */ +@AllArgsConstructor +@Getter +public enum DriverAbnormalBehaviorOverseeEnum { + + UN_OVERSEE(0,"待督办"), + + OVERSEE(1,"已督办"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(String code) { + if(StringUtils.isBlank(code)){ + return StringUtils.EMPTY; + } + for (DriverAbnormalBehaviorOverseeEnum t : DriverAbnormalBehaviorOverseeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorProcessingEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorProcessingEnum.java new file mode 100644 index 0000000..0a97446 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAbnormalBehaviorProcessingEnum.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * @author CMM + * @description + * @since 2022/12/05 15:31 + */ +@AllArgsConstructor +@Getter +public enum DriverAbnormalBehaviorProcessingEnum { + + UN_DEAL(0,"待处理"), + DEAL(1,"已处理"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.nonNull(code)){ + return StringUtils.EMPTY; + } + for (DriverAbnormalBehaviorProcessingEnum t : DriverAbnormalBehaviorProcessingEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAgeRangeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAgeRangeEnum.java new file mode 100644 index 0000000..381fb4c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverAgeRangeEnum.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.Getter; + +import java.util.Arrays; + +/** + *

+ * DriverAgeRangeEnum + *

+ * + * @author WendyYang + * @since 14:52 2022/10/27 + */ +@Getter + +public enum DriverAgeRangeEnum { + + /** + * 年龄范围 + */ + AGE_20_25(20, 25, 20, "20-25岁"), + AGE_26_30(26, 30, 26, "26-30岁"), + AGE_31_35(31, 35, 31, "31-35岁"), + AGE_36_40(36, 40, 36, "36-40岁"), + AGE_41_45(41, 45, 41, "41-45岁"), + AGE_46_50(46, 50, 46, "46-50岁"), + AGE_51(51, -1, 51, "50岁以上"); + + /** + * 无效的值 + */ + public static final int UNDEFINED = -1; + private final int start; + private final int end; + private final int key; + private final String label; + + DriverAgeRangeEnum(int start, int end, int key, String label) { + this.start = start; + this.end = end; + this.key = key; + this.label = label; + } + + public static DriverAgeRangeEnum getByKey(int key){ + return Arrays.stream(values()) + .filter(w -> w.getKey() == key) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("无效的年龄编码")); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverContinuingEducationRegistrationStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverContinuingEducationRegistrationStatusEnum.java new file mode 100644 index 0000000..dd274c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverContinuingEducationRegistrationStatusEnum.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/20 下午2:28 + * 驾驶员继续教育报名状态 + */ + +public enum DriverContinuingEducationRegistrationStatusEnum { + // 初审/复核阶段 + review_stage, + + // 考试培训阶段 + exam_training_stage, + + // 已完成 + available +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverJobChangeStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverJobChangeStatusEnum.java new file mode 100644 index 0000000..65bd4cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverJobChangeStatusEnum.java @@ -0,0 +1,15 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/20 下午2:28 + * 驾驶员跳槽审核报名状态 + */ + +public enum DriverJobChangeStatusEnum { + // 初审/复核阶段 + review_stage, + + // 已完成 + available +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverMaterialAuditStatus.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverMaterialAuditStatus.java new file mode 100644 index 0000000..42d9a2a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverMaterialAuditStatus.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/14 上午11:14 + * 驾驶员材料审核状态 + */ +@AllArgsConstructor +@Getter +public enum DriverMaterialAuditStatus { + + /** + * 材料初审中 + */ + IN_PRELIMINARY_TRIAL, + + /** + * 材料初审通过 + */ + PRELIMINARY_TRIAL_PASS, + + /** + * 材料初审驳回 + */ + PRELIMINARY_TRIAL_REJECTION, + + /** + * 材料复核中 + */ + IN_REVIEWING, + + /** + * 材料复核通过 + */ + REVIEWING_PASS, + + /** + * 材料复核驳回 + */ + REVIEWING_REJECTION +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverRegistrationStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverRegistrationStatusEnum.java new file mode 100644 index 0000000..e6afc29 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverRegistrationStatusEnum.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/20 下午2:28 + * 驾驶员取证报名状态 + */ + +public enum DriverRegistrationStatusEnum { + // 初审/复核阶段 + review_stage, + + // 考试培训阶段 + exam_training_stage, + + // 上传培训合格证书阶段 + upload_training_certificate_stage, + + // 已完成 + available +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverReplacementRegistrationStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverReplacementRegistrationStatusEnum.java new file mode 100644 index 0000000..6fad9ef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverReplacementRegistrationStatusEnum.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/20 下午2:28 + * 驾驶员换证报名状态 + */ + +public enum DriverReplacementRegistrationStatusEnum { + // 初审/复核阶段 + review_stage, + + // 考试培训阶段 + exam_training_stage, + + // 上传培训合格证书阶段 + upload_training_certificate_stage, + + // 已完成 + available +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverStatusEnum.java new file mode 100644 index 0000000..293c1ef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DriverStatusEnum.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/9 下午5:47 + */ + +@AllArgsConstructor +@Getter +public enum DriverStatusEnum { + + // 入职 + induction, + + // 离职 + quit + + // 未入职 + //un_induction + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DrivingExperienceRangeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DrivingExperienceRangeEnum.java new file mode 100644 index 0000000..4dc8968 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/DrivingExperienceRangeEnum.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.Getter; + +/** + *

+ * DrivingExperienceRangeEnum + *

+ * + * @author WendyYang + * @since 19:22 2022/10/28 + */ +@Getter +public enum DrivingExperienceRangeEnum { + + /** + * 驾驶证超时范围 + */ + RANGE_0(-1, 0, 0, "1年已下"), + RANGE_1_5(1, 5, 5, "1-5年"), + RANGE_6_10(6, 10, 10, "5-10年"), + RANGE_11(11, -1, 11, "10年以上"); + + private final int start; + private final int end; + private final int key; + private final String label; + + public static final int UNDEFINED = -1; + + DrivingExperienceRangeEnum(int start, int end, int key, String label) { + this.start = start; + this.end = end; + this.key = key; + this.label = label; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamQualifiedEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamQualifiedEnum.java new file mode 100644 index 0000000..efc3cc6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamQualifiedEnum.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/26 下午3:15 + * 考试是否合格枚举 + */ + +public enum ExamQualifiedEnum { + + // 合格 + qualified, + + // 不合格 + unqualified +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamTypeEnum.java new file mode 100644 index 0000000..5ddda13 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExamTypeEnum.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/26 下午3:01 + * 考试类型id + */ + +public enum ExamTypeEnum { + + // 取证报名 + forensic_registration_training, + + // 换证报名 + replacement_registration_training, + + // 继续教育 + continuing_education_training, + + // 转码培训 + transcoding_training + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExaminationStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExaminationStatusEnum.java new file mode 100644 index 0000000..929e9d6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ExaminationStatusEnum.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/22 上午10:32 + * 培训考试状态 + */ +@AllArgsConstructor +@Getter +public enum ExaminationStatusEnum { + // 已考试 + examined, + + // 未考试 + waiting_examination +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialStatusEnum.java new file mode 100644 index 0000000..947dd50 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialStatusEnum.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/21 下午5:06 + */ +@AllArgsConstructor +@Getter +public enum MaterialStatusEnum { + // 启用 + enable, + + // 禁用 + disable +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialTypeEnum.java new file mode 100644 index 0000000..17fdfc2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/MaterialTypeEnum.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/21 下午5:09 + */ +@AllArgsConstructor +@Getter +public enum MaterialTypeEnum { + // 规则制度 + rule_system, + + // 政策文件 + policy_documents, + + // 安全知识 + safety_knowledge, + + // 事故案例 + accident_case, + + // 培训视频 + training_video, + + // 其他 + other +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/QuestionTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/QuestionTypeEnum.java new file mode 100644 index 0000000..aee9cc0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/QuestionTypeEnum.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/11 上午11:11 + */ +@AllArgsConstructor +@Getter +public enum QuestionTypeEnum { + + /** + * 单项选择题 + */ + SINGLE_CHOICE, + + /** + * 多项选择题 + */ + MULTIPLE_CHOICE, + + /** + * 判断题 + */ + JUDGMENTAL; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ScoreOperateType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ScoreOperateType.java new file mode 100644 index 0000000..2fe7674 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/ScoreOperateType.java @@ -0,0 +1,15 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/11/4 上午9:37 + */ + +public enum ScoreOperateType { + + // 加分 + add, + + // 减分 + reduce +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/StarManageDisplayTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/StarManageDisplayTypeEnum.java new file mode 100644 index 0000000..061078a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/StarManageDisplayTypeEnum.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/11/15 下午1:59 + */ + +public enum StarManageDisplayTypeEnum { + /** + * 公司ID + */ + company_id, + + region_id, + + driver_id +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingModeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingModeEnum.java new file mode 100644 index 0000000..c9c289b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingModeEnum.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/21 下午2:40 + * 驾驶员培训组织 培训模式枚举 + */ +@AllArgsConstructor +@Getter +public enum TrainingModeEnum { + + // 线上 + online, + + // 线下 + offline + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationFlagEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationFlagEnum.java new file mode 100644 index 0000000..9e40ec0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationFlagEnum.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.driver.constant; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 驾驶员是否能够参加培训报名-枚举 + * @return + * @author CMM + * @since 2023/02/15 16:03 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "TrainingRegistrationFlagEnum", description = "驾驶员是否能够参加培训报名-枚举") +public enum TrainingRegistrationFlagEnum { + CAN_NOT_TAKE(0, "false"), + + CAN_TAKE(1, "true"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(int code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (TrainingRegistrationFlagEnum t : TrainingRegistrationFlagEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationTypeEnum.java new file mode 100644 index 0000000..c406df9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingRegistrationTypeEnum.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/19 下午4:43 + * 培训报名类型 + */ +@AllArgsConstructor +@Getter +public enum TrainingRegistrationTypeEnum { + + // 取证报名 + FORENSIC_REGISTRATION, + + // 换证报名 + REPLACEMENT_REGISTRATION, + + // 继续教育 + CONTINUING_EDUCATION, + + // 申请跳槽 + JOB_APPLICATION +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingStatusEnum.java new file mode 100644 index 0000000..2db4e9e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingStatusEnum.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/21 下午2:44 + */ + +@AllArgsConstructor +@Getter +public enum TrainingStatusEnum { + + // 启用 + enable, + + // 禁用 + disable +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingTypeEnum.java new file mode 100644 index 0000000..68c79e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/TrainingTypeEnum.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.driver.constant; + +/** + * @author liuxinxin + * @date 2022/10/21 下午2:46 + * 培训类型 取证培训/继续教育/换证培训/转码培训 + */ + +public enum TrainingTypeEnum { + + + // 取证报名 + forensic_registration_training, + + // 换证报名 + replacement_registration_training, + + // 继续教育 + continuing_education_training, + + // 转码培训 + transcoding_training + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/UserCanLoginEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/UserCanLoginEnum.java new file mode 100644 index 0000000..8485998 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constant/UserCanLoginEnum.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.driver.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 用户是否可登录 + * @return + * @author CMM + * @since 2023/02/07 13:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "UserCanLoginEnum", description = "用户是否可登录-枚举") +public enum UserCanLoginEnum { + + CAN_NOT_LOGIN(0, "false"), + + CAN_LOGIN(1, "true"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(int code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (UserCanLoginEnum t : UserCanLoginEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constants/DriverConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constants/DriverConstant.java new file mode 100644 index 0000000..a808927 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/constants/DriverConstant.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.driver.constants; + +/** + * @return + * @author CMM + * @since 2023/06/07 10:27 + */ +public interface DriverConstant { + + String FILE_ID = "fileId"; + + String FILE_NAME = "fileName"; + Integer ID_CARD_DESENSITIZED_FRONT = 1; + Integer ID_CARD_DESENSITIZED_END = 2; + String NO_5 = "%05d"; + Long YEAR_3 = 3L; + String MANAGE_UNIT = "散装中心"; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ArticleInfoController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ArticleInfoController.java new file mode 100644 index 0000000..b5a4cff --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ArticleInfoController.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.ArticleInfoManage; +import com.ningdatech.carapi.driver.model.po.ReqArticleInfoListPO; +import com.ningdatech.carapi.driver.model.vo.ResArticleInfoListVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@RequestMapping("/api/v1/article-info") +@RestController +@Api(tags = "文章管理") +@Validated +@RequiredArgsConstructor +public class ArticleInfoController { + + private final ArticleInfoManage articleInfoManage; + + @PostMapping("/list") + @ApiOperation("文章列表查询") + public PageVo articleInfoList(@Valid @RequestBody ReqArticleInfoListPO reqArticleInfoListPo) { + return articleInfoManage.articleInfoList(reqArticleInfoListPo); + } + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/BehaviourManageController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/BehaviourManageController.java new file mode 100644 index 0000000..4a7d89c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/BehaviourManageController.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.driver.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.driver.entity.BehaviorAnalysisProcessingMode; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisNoticeDTO; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisOverseeDTO; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisPageParamDTO; +import com.ningdatech.carapi.driver.manage.BehaviourAnalysisManage; +import com.ningdatech.carapi.driver.model.vo.BehaviourAnalysisVO; +import com.ningdatech.carapi.driver.model.vo.DriverAbnormalBehaviorAnalysisDetailVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; + +/** + * @author CMM + * @Classname BehaviourManageController + * @Description + * @Date 2022/11/07 16:30 + */ +@RestController +@RequestMapping(value = "/api/v1/driver/behaviour") +@Api(tags = "驾驶员管理-行为管理") +@Validated +@RequiredArgsConstructor +public class BehaviourManageController { + + private final BehaviourAnalysisManage behaviourAnalysisManage; + + @ApiOperation("行为分析") + @GetMapping("/behaviour-analysis-list") + public PageVo behaviourAnalysisList( + @Valid @ModelAttribute DriverAbnormalBehaviorAnalysisPageParamDTO param) { + return behaviourAnalysisManage.behaviorAnalysisList(param); + } + + @ApiOperation("驾驶员异常行为分析详情") + @GetMapping("/analysis-info/detail/{id}") + public DriverAbnormalBehaviorAnalysisDetailVO behaviourAnalysisDetail(@Valid @PathVariable Long id){ + return behaviourAnalysisManage.getBehaviourAnalysisDetail(id); + } + + @ApiOperation("驾驶员异常行为分析督办") + @PostMapping("/analysis/oversee") + public Boolean behaviorAnalysisOversee(@Valid @RequestBody DriverAbnormalBehaviorAnalysisOverseeDTO param){ + return behaviourAnalysisManage.oversee(param, LoginUserUtil.getUserId()); + } + + @ApiOperation("获取驾驶员异常行为分析处理方式-全局配置") + @GetMapping("/analysis/get/processing-mode") + public List processingModeDetail(){ + return behaviourAnalysisManage.processingModeDetail(); + } + + @ApiModelProperty("添加驾驶员异常行为分析处理方式") + @GetMapping("/addProcessingMode") + public Boolean addProcessingMode(@Valid String req){ + return behaviourAnalysisManage.addProcessingMode(req); + } + + @ApiModelProperty("删除驾驶员异常行为分析处理方式") + @DeleteMapping("/deleteProcessingMode/{id}") + public Boolean addProcessingMode(@Valid @PathVariable Integer id){ + return behaviourAnalysisManage.deleteProcessingMode(id); + } + + @ApiOperation("驾驶员异常行为分析处理详情") + @PostMapping("/analysis/deal") + public Boolean behaviorAnalysisNotice(@Valid @RequestBody DriverAbnormalBehaviorAnalysisNoticeDTO param){ + return behaviourAnalysisManage.deal(param,LoginUserUtil.getUserId()); + } + + @ApiOperation("行为分析列表导出") + @GetMapping("/behaviour-analysis-list-export") + public void exportBehaviourAnalysisList(DriverAbnormalBehaviorAnalysisPageParamDTO req, HttpServletResponse response){ + ExcelDownUtil.downXls(response,req,behaviourAnalysisManage::driverAbnormalBehaviorAnalysisListExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/CertificateController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/CertificateController.java new file mode 100644 index 0000000..2f8d565 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/CertificateController.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.carapi.driver.manage.CertificateManage; +import com.ningdatech.carapi.driver.model.po.ReqUploadCertificatePO; +import com.ningdatech.carapi.driver.model.vo.ResCertificateVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author Liuxinxin + * @since 2022-10-24 + */ +@RequestMapping("/api/v1/certificate") +@RestController +@Api(tags = "合格证管理") +@Validated +@RequiredArgsConstructor +public class CertificateController { + + private final CertificateManage certificateManage; + + @PostMapping("/upload") + @ApiOperation("上传合格证书") + public void uploadCertificate(@Valid @RequestBody ReqUploadCertificatePO request) { + certificateManage.uploadCertificate(request); + } + + @PostMapping("/get") + @ApiOperation("登陆者获取合格证书(移动端使用)") + public ResCertificateVO getCertificate() { + return certificateManage.getCertificate(); + } + + @PostMapping("/get/web/{driverId}") + @ApiOperation("根据驾驶员id获取合格证书") + public ResCertificateVO getCertificate(@PathVariable("driverId") Long driverId) { + return certificateManage.getCertificate(driverId); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverArchivesController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverArchivesController.java new file mode 100644 index 0000000..dd33527 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverArchivesController.java @@ -0,0 +1,188 @@ +package com.ningdatech.carapi.driver.controller; + + +import java.util.List; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.driver.manage.DriverArchivesManage; +import com.ningdatech.carapi.driver.model.dto.DriverBasicInfoDTO; +import com.ningdatech.carapi.driver.model.po.*; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoDetailVO; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoSearchListVO; +import com.ningdatech.carapi.driver.model.vo.ResDriverTrainingRegistrationListVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * @author LiuXinXin + * @since 2022-10-09 + */ +@RequestMapping("/api/v1/driver/archives") +@RestController +@Api(tags = "驾驶员管理-档案管理(新接口)") +@Validated +@RequiredArgsConstructor +public class DriverArchivesController { + + private final DriverArchivesManage driverArchivesManage; + + @PostMapping("/archival-info/search") + @ApiOperation("档案管理查询") + public PageVo archivalInfoSearch(@Valid @RequestBody ReqArchivalInfoSearchPO po) { + return driverArchivesManage.archivalInfoSearch(po); + } + + @PostMapping("/training/registration") + @ApiOperation("驾驶员培训报名/申请跳槽/继续教育报名/换证培训报名(新接口)") + @WebLog(value = "驾驶员培训报名/申请跳槽/继续教育报名/换证培训报名", modular = "驾驶员管理-档案管理") + public void driverTrainingRegistration + (@Valid @RequestBody ReqDriverTrainingRegistrationPO po) { + driverArchivesManage.driverTrainingRegistration(po); + } + + @PostMapping("/training/registration/un-deal/list") + @ApiOperation("驾驶员培训报名-审核列表筛选(新接口)") + public PageVo driverTrainingRegistrationUnDealList + (@Valid @RequestBody ReqDriverTrainingRegistrationListPO po) { + return driverArchivesManage.driverTrainingRegistrationUnDealList(po); + } + + @PostMapping("/archival-info/detail/review") + @ApiOperation("驾驶员档案审核详情(新接口)") + public ResArchivalInfoDetailVO getArchivalInfoReviewDetail(@Valid @RequestBody ReqGetArchivalInfoReviewDetailPO request) { + return driverArchivesManage.getArchivalInfoReviewDetail(request); + } + + @PostMapping("/archival-info/detail/{driverId}") + @ApiOperation("获取驾驶员档案详情") + public ResArchivalInfoDetailVO getArchivalInfoReviewDetail(@PathVariable("driverId") Long driverId) { + return driverArchivesManage.getDriverArchivalInfo(driverId); + } + + @PostMapping("/archival-info/detail/id-card/{idCard}") + @ApiOperation("根据身份证号获取驾驶员档案详情") + public ResArchivalInfoDetailVO getArchivalInfoReviewDetailByIdCard(@PathVariable("idCard") String idCard) { + return driverArchivesManage.getDriverArchivalInfoByIdCard(idCard); + } + + @PostMapping("/training/preliminary-trial") + @ApiOperation("驾驶员材料初审(新接口)") + public void driverTrainingPreliminaryTrial(@Valid @RequestBody ReqDriverTrainingPreliminaryTrialPO po) { + driverArchivesManage.driverTrainingPreliminaryTrial(po); + } + + @PostMapping("/training/in-review") + @ApiOperation("驾驶员材料复审(新接口)") + @WebLog(value = "驾驶员材料复审", modular = "驾驶员管理-档案管理") + public void driverTrainingInReview(@Valid @RequestBody ReqDriverInReviewingPO po) { + driverArchivesManage.driverTrainingInReview(po); + } + + @PostMapping("/quit/{driverId}") + @ApiOperation("驾驶员离职") + public void driverQuit(@PathVariable("driverId") Long driverId) { + driverArchivesManage.driverQuit(driverId); + } + + @PostMapping("/induction") + @ApiOperation("驾驶员入职") + public void driverInduction(@Valid @RequestBody ReqDriverInductionPO po) { + driverArchivesManage.driverInduction(po); + } + + @PostMapping("/changed-job") + @ApiOperation("驾驶员跳槽") + public void changedJob(@Valid @RequestBody ReqChangedJobPO request) { + driverArchivesManage.changedJob(request); + } + + /** + * 查询驾驶员违章记录档案 + * + * @param driverId,violationType + * @return + */ + @ApiOperation(value = "查询驾驶员违章记录档案", notes = "查询驾驶员违章记录档案") + @GetMapping("/violation") + public List getViolation(@Valid @RequestParam Long driverId, @Valid @RequestParam Integer violationType) { + return driverArchivesManage.getViolation(driverId, violationType); + } + + /** + * 查询驾驶员事故记录档案 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询驾驶员事故记录档案", notes = "查询驾驶员事故记录档案") + @GetMapping("/accident-driver/{driverId}") + public List getAccidentVehicle(@Valid @PathVariable Long driverId) { + return driverArchivesManage.getAccidentVehicle(driverId); + } + + /** + * 查询驾驶员死亡事故记录档案 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询驾驶员死亡事故记录档案", notes = "查询驾驶员死亡事故记录档案") + @GetMapping("/accident-dead/{driverId}") + public List getAccidentDead(@Valid @PathVariable Long driverId) { + return driverArchivesManage.getAccidentDead(driverId); + } + + /** + * 查询驾驶员事故分析记录档案 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询驾驶员事故分析记录档案", notes = "查询驾驶员事故分析记录档案") + @GetMapping("/accident-analysis/{driverId}") + public List getAccidentAnalysis(@Valid @PathVariable Long driverId) { + return driverArchivesManage.getAccidentAnalysis(driverId); + } + + @ApiOperation("驾驶员模版数据导入") + @PostMapping("/importTemplateData") + @WebLog(value = "驾驶员模版数据导入", modular = "驾驶员管理-档案管理") + public String importTemplateData(@RequestParam("template") ImportTemplateEnum template, MultipartFile file, HttpServletResponse response) { + return driverArchivesManage.importDriverArchivesData(template, file, response); + } + + @ApiOperation(value = "驾驶员档案列表导出", notes = "驾驶员档案列表导出") + @GetMapping("/exportDriverArchives") + @WebLog + public void exportDriverArchives(@Valid @ModelAttribute ReqArchivalInfoSearchPO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, driverArchivesManage::exportDriverArchives); + } + + @ApiOperation(value = "驾驶员档案数据录入", notes = "驾驶员档案数据录入") + @PostMapping("/addDriverArchives") + public Boolean addDriverArchives(@Valid @RequestBody ReqAddDriverArchivesPO param) { + return driverArchivesManage.addDriverArchives(param); + } + + @ApiOperation(value = "驾驶员基本信息编辑", notes = "驾驶员基本信息编辑") + @PostMapping("/modifyDriverBasicInfo") + public ResArchivalInfoDetailVO modifyDriverBasicInfo(@Valid @RequestBody DriverBasicInfoDTO data) { + return driverArchivesManage.modifyDriverBasicInfo(data); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverBlackListController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverBlackListController.java new file mode 100644 index 0000000..2cc14ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverBlackListController.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.DriverBlackListManage; +import com.ningdatech.carapi.driver.model.po.ReqDriverBlackListSearchPO; +import com.ningdatech.carapi.driver.model.vo.ResDriverBlackListVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@RequestMapping("/api/v1/driver/black-list") +@RestController +@Api(tags = "驾驶员管理-黑名单列表") +@Validated +@RequiredArgsConstructor +public class DriverBlackListController { + + private final DriverBlackListManage driverBlackListManage; + + @PostMapping("/search") + @ApiOperation("黑名单列表查询") + public PageVo driverBlackListSearch(@Valid @RequestBody ReqDriverBlackListSearchPO po) { + return driverBlackListManage.driverBlackListSearch(po); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverManageDataViewController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverManageDataViewController.java new file mode 100644 index 0000000..31c0237 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverManageDataViewController.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.driver.controller; + +import com.ningdatech.carapi.common.model.DataChartVo; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.driver.manage.DriverManageDataViewManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * DriverManageDataViewController + *

+ * + * @author WendyYang + * @since 15:28 2022/10/26 + */ +@AllArgsConstructor +@RestController +@Api(tags = "驾驶员管理-数据大屏") +@RequestMapping("/api/v1/driver-manage/data-view") +public class DriverManageDataViewController { + + private final DriverManageDataViewManage driverManageDataViewManage; + + @ApiOperation("驾驶员比例/驾驶员分布") + @GetMapping("/driverStatisticsByRegion/{regionId}") + public List driverStatisticsByRegion(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return driverManageDataViewManage.driverStatisticsByRegion(regionId); + } + + @ApiOperation("驾驶员年龄统计") + @GetMapping("/driverAgeStatisticsByRegion/{regionId}") + public List driverAgeStatisticsByRegion(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return driverManageDataViewManage.driverAgeStatisticsByRegion(regionId); + } + + @ApiOperation("驾驶员驾龄统计") + @GetMapping("/drivingExperienceStatisticsByRegion/{regionId}") + public List drivingExperienceStatisticsByRegion(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return driverManageDataViewManage.drivingExperienceStatisticsByRegion(regionId); + } + + @ApiOperation("驾驶员籍贯统计") + @GetMapping("/driverNativePlaceStatisticsByRegion/{regionId}") + public List driverNativePlaceStatisticsByRegion(@PathVariable Long regionId) { + regionId = CodeUtil.convertRegionCodeToId(regionId); + return driverManageDataViewManage.driverNativePlaceStatisticsByRegion(regionId); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreInfoController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreInfoController.java new file mode 100644 index 0000000..95499bf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreInfoController.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +@Controller +@RequestMapping("/carapi.driver/driver-score-info") +public class DriverScoreInfoController { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreRecordController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreRecordController.java new file mode 100644 index 0000000..93deb6d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/DriverScoreRecordController.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.DriverScoreRecordManage; +import com.ningdatech.carapi.driver.model.po.ReqScoreBonusPO; +import com.ningdatech.carapi.driver.model.po.ReqScoreListPO; +import com.ningdatech.carapi.driver.model.vo.ResDriverScoreRecordListVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +@Controller +@RequestMapping("/api/v1/score") +@RestController +@Api(tags = "驾驶员分数记录列表") +@Validated +@RequiredArgsConstructor +public class DriverScoreRecordController { + + private final DriverScoreRecordManage driverScoreRecordManage; + + @PostMapping("/list") + @ApiOperation("驾驶员分数记录") + public List list() { + return driverScoreRecordManage.list(); + } + + @PostMapping("/page-list") + @ApiOperation("驾驶员分页分数记录") + public PageVo pageList(@Valid @RequestBody ReqScoreListPO request) { + return driverScoreRecordManage.pageList(request); + } + + @PostMapping("/score/{driverId}") + @ApiOperation("获取驾驶员分数") + public Integer getScore(@PathVariable("driverId") Long driverId) { + return driverScoreRecordManage.getScore(driverId); + } + + @PostMapping("/score/bonus") + @ApiOperation("培训奖励分数") + public void bonus(@Valid @RequestBody ReqScoreBonusPO request) { + driverScoreRecordManage.bonus(request); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ExamRecordController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ExamRecordController.java new file mode 100644 index 0000000..d78d373 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/ExamRecordController.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.ExamRecordManage; +import com.ningdatech.carapi.driver.model.po.ReqListExamRecordPO; +import com.ningdatech.carapi.driver.model.vo.ResListExamRecordVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +@RequestMapping("/api/v1/exam-record") +@RestController +@Api(tags = "考试记录") +@Validated +@RequiredArgsConstructor +public class ExamRecordController { + private final ExamRecordManage examRecordManage; + + @PostMapping("/list") + @ApiOperation("培训考试列表筛选") + public PageVo listExamRecord(@Valid @RequestBody ReqListExamRecordPO request) { + return examRecordManage.listExamRecord(request); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/StarManageController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/StarManageController.java new file mode 100644 index 0000000..989945c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/StarManageController.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.DriverStarManage; +import com.ningdatech.carapi.driver.model.po.ReqCompanyStarPO; +import com.ningdatech.carapi.driver.model.po.ReqDriverStarListPO; +import com.ningdatech.carapi.driver.model.po.ReqRegionStarPO; +import com.ningdatech.carapi.driver.model.vo.ResCompanyStarListVO; +import com.ningdatech.carapi.driver.model.vo.ResDriverStarListVO; +import com.ningdatech.carapi.driver.model.vo.ResRegionStarVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author Liuxinxin + * @since 2022-11-15 + */ +@RequestMapping("/api/v1/start-manage") +@RestController +@Api(tags = "驾驶员星级管理") +@Validated +@RequiredArgsConstructor +public class StarManageController { + + public final DriverStarManage driverStarManage; + + @PostMapping("/driver-star-list") + @ApiOperation("驾驶员星级列表筛选") + public PageVo driverStarList(@Valid @RequestBody ReqDriverStarListPO request) { + return driverStarManage.driverStarList(request); + } + + @PostMapping("/region-star-summary") + @ApiOperation("区域列表筛选") + public PageVo regionStarList(@Valid @RequestBody ReqRegionStarPO request) { + return driverStarManage.regionStarList(request); + } + + @PostMapping("/company-star-summary") + @ApiOperation("公司星级列表筛选") + public PageVo companyStarList(@Valid @RequestBody ReqCompanyStarPO request) { + return driverStarManage.companyStarList(request); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingMaterialController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingMaterialController.java new file mode 100644 index 0000000..120187a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingMaterialController.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.driver.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.TrainingMaterialManage; +import com.ningdatech.carapi.driver.model.po.ReqSaveTrainingMaterialPO; +import com.ningdatech.carapi.driver.model.po.ReqTrainingMaterialListPO; +import com.ningdatech.carapi.driver.model.vo.ResSaveTrainingMaterialVO; +import com.ningdatech.carapi.driver.model.vo.ResTrainingMaterialListVO; +import com.ningdatech.carapi.driver.model.vo.ResTrainingMaterialVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@RequestMapping("/api/v1/driver/training-materials") +@RestController +@Api(tags = "驾驶员管理-培训管理-培训材料") +@Validated +@RequiredArgsConstructor +public class TrainingMaterialController { + + private final TrainingMaterialManage trainingMaterialManage; + + @PostMapping("/list") + @ApiOperation("培训材料-列表查询(新接口)") + public PageVo trainingMaterialsList(@Valid @RequestBody ReqTrainingMaterialListPO po) { + return trainingMaterialManage.trainingMaterialsList(po); + } + + @PostMapping("/save") + @ApiOperation("保存培训材料(新接口)") + public ResSaveTrainingMaterialVO saveTrainingMaterial(@Valid @RequestBody ReqSaveTrainingMaterialPO request) { + return trainingMaterialManage.saveTrainingMaterial(request); + } + + @PostMapping("/detail/{trainingMaterialId}") + @ApiOperation("培训材料详情") + public ResTrainingMaterialVO getTrainingMaterialDetail(@PathVariable("trainingMaterialId") Long trainingMaterialId) { + return trainingMaterialManage.getTrainingMaterialDetail(trainingMaterialId); + } + + @PostMapping("remove/{trainingMaterialId}") + @ApiOperation("删除培训材料") + public void removeTrainingMaterial(@PathVariable("trainingMaterialId") Long trainingMaterialId) { + trainingMaterialManage.removeTrainingMaterial(trainingMaterialId); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingOrganizationController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingOrganizationController.java new file mode 100644 index 0000000..447b328 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/controller/TrainingOrganizationController.java @@ -0,0 +1,127 @@ +package com.ningdatech.carapi.driver.controller; + + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.driver.manage.TrainingOrganizationManage; +import com.ningdatech.carapi.driver.model.po.*; +import com.ningdatech.carapi.driver.model.query.TrainingOrgTrainersQuery; +import com.ningdatech.carapi.driver.model.vo.*; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 前端控制器 + *

+ * + * @author LiuXinXin + * @since 2022-10-10 + */ +@RequestMapping("/api/v1/driver/training-organization") +@RestController +@Api(tags = "驾驶员管理-培训管理-培训组织") +@Validated +@RequiredArgsConstructor +public class TrainingOrganizationController { + + private final TrainingOrganizationManage trainingOrganizationManage; + + @PostMapping("/save") + @ApiOperation("保存培训组织(新接口)") + public ResCreateTrainingOrgVO saveTrainingOrganization(@Valid @RequestBody ReqCreateTrainingOrgPO request) { + return trainingOrganizationManage.saveTrainingOrganization(request); + } + + @PostMapping("/list") + @ApiOperation("培训组织-列表查询(新接口)") + public PageVo trainingOrganizationList(@Valid @RequestBody ReqTrainingOrganizationListPO request) { + return trainingOrganizationManage.trainingOrganizationList(request); + } + + @PostMapping("/status-modify") + @ApiOperation("培训组织状态变更") + public void trainingOrganizationStatusModify(@Valid @RequestBody ReqTrainingOrganizationStatusModifyPO request) { + trainingOrganizationManage.trainingOrganizationStatusModify(request); + } + + @PostMapping("/detail/{organizationId}") + @ApiOperation("培训组织-详情") + public ResTrainingOrganizationDetailVO trainingOrganizationDetail(@Valid @PathVariable("organizationId") Long organizationId) { + return trainingOrganizationManage.trainingOrganizationDetail(organizationId); + } + + @PostMapping("/delete/{organizationId}") + @ApiOperation("培训组织-删除培训组织") + public void deleteTrainingOrganization(@Valid @PathVariable("organizationId") Long organizationId) { + trainingOrganizationManage.deleteTrainingOrganization(organizationId); + } + + @PostMapping("/upload/exam-result") + @ApiOperation("培训考试-上传考试结果") + public void uploadExamResult(@Valid @RequestBody ReqUploadExamResultPO request) { + trainingOrganizationManage.uploadExamResult(request); + } + + @PostMapping("/upload/exam-result-generate-certificate") + @ApiOperation("培训考试-上传考试结果并生成电子合格证") + public void uploadExamResultAndGenerateCertificate(@Valid @RequestBody ReqUploadExamResultPO request) { + trainingOrganizationManage.uploadExamResultAndGenerateCertificate(request); + } + + @PostMapping("/make-up-exam") + @ApiOperation("补考") + public void makeUpExam(@Valid @RequestBody ReqMakeUpExamPO request) { + trainingOrganizationManage.makeUpExam(request); + } + + @PostMapping("/get/current-user-organization") + @ApiOperation("获取当前用户培训组织") + public ResCurrentUserOrganizationVO getCurrentUserOrganization(@Valid @RequestBody ReqCurrentUserOrganizationPO request) { + return trainingOrganizationManage.getCurrentUserOrganization(request); + } + + @PostMapping("/sign/{organizationId}") + @ApiOperation("培训签到") + public void organizationSign(@PathVariable("organizationId") Long organizationId) { + trainingOrganizationManage.organizationSign(organizationId); + } + + @PostMapping("/sign/check/{organizationId}") + @ApiOperation("培训签到校验 已签到返回 true 否则返回false") + public Boolean organizationSignCheck(@PathVariable("organizationId") Long organizationId) { + return trainingOrganizationManage.organizationSignCheck(organizationId); + } + + @PostMapping("/driver-training/list") + @ApiOperation("驾驶员培训记录列表") + public PageVo driverTrainingList(@Valid @RequestBody ReqDriverTrainingListPO request) { + return trainingOrganizationManage.driverTrainingList(request); + } + + @GetMapping("/getTrainers") + @ApiOperation("获取培训组织关联的培训人员信息") + public PageVo trainerList(@Valid @ModelAttribute TrainingOrgTrainersQuery request){ + return trainingOrganizationManage.trainerList(request); + } + + @PostMapping("/set/exam-time") + @ApiOperation("培训考试-设置考试时间") + public String setExamTime(@Valid @RequestBody ReqSetExamTimePO request) { + return trainingOrganizationManage.setExamTime(request); + } + + @PostMapping("/trainer/export") + @ApiOperation("培训人员信息导出") + public void exportTrainer(@Valid @ModelAttribute ReqTrainerExportPO req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, trainingOrganizationManage::exportTrainer); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ArticleInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ArticleInfo.java new file mode 100644 index 0000000..f4cd5da --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ArticleInfo.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author LiuXinXin + * @since 2022-10-09 + */ +@TableName("nd_article_info") +@Data +public class ArticleInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String createOn; + + private LocalDateTime updateOn; + + /** + * 制定时间 + */ + private LocalDateTime formulationTime; + + /** + * 标题 + */ + private String title; + + /** + * 文章类型 + */ + private String articleType; + + /** + * 文章状态 + */ + private String articleStatus; + + /** + * 文件内容 + */ + private String content; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviorAnalysisProcessingMode.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviorAnalysisProcessingMode.java new file mode 100644 index 0000000..fa2b8ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviorAnalysisProcessingMode.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author CMM + * @description + * @since 2022/12/14 17:29 + */ +@Data +@TableName("nd_driver_abnormal_behavior_processing_mode") +public class BehaviorAnalysisProcessingMode implements Serializable { + + private static final long serialVersionUID = 5422041381526432689L; + + @ApiModelProperty("处理方式ID") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("处理方式名称") + private String processingModeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviourAnalysisExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviourAnalysisExportDTO.java new file mode 100644 index 0000000..474f13f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/BehaviourAnalysisExportDTO.java @@ -0,0 +1,98 @@ +package com.ningdatech.carapi.driver.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.constant.BgTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author CMM + * @Classname SecurityMonitorJoin + * @Description + * @Date 2022/11/6 20:59 + */ +@Data +public class BehaviourAnalysisExportDTO implements Serializable { + + private static final long serialVersionUID = 498564167561863385L; + + @ApiModelProperty("告警事件id") + @ExcelProperty("ID") + private Long id; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("驾驶员姓名") + @ExcelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶员ID") + @ExcelProperty("驾驶员ID") + private Long driverId; + + /** + * {@link BgTypeEnum} + */ + @ApiModelProperty("告警类型") + @ExcelProperty("告警类型") + private Integer alarmType; + + @ApiModelProperty("告警类型名称") + @ExcelProperty("告警类型名称") + private String alarmTypeName; + + @ApiModelProperty(value = "告警级别",allowableValues = "1 预警,2 报警") + @ExcelProperty("告警级别") + private Integer alarmLevel; + + @ApiModelProperty("告警级别名称") + @ExcelProperty("告警级别名称") + private String alarmLevelName; + + @ApiModelProperty("车辆速度") + @ExcelProperty("车辆速度") + private Integer speed; + + @ApiModelProperty("告警时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ExcelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("告警地址") + @ExcelProperty("告警地址") + private String alarmAddress; + + @ApiModelProperty("告警图片附件") + @ExcelProperty("告警图片附件网址") + private String alarmPictureAppendix; + + @ApiModelProperty("告警视频附件") + @ExcelProperty("告警视频附件网址") + private String alarmVideoAppendix; + + @ApiModelProperty("处理状态") + @ExcelProperty("处理状态") + private Integer processingStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/Certificate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/Certificate.java new file mode 100644 index 0000000..5d93d97 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/Certificate.java @@ -0,0 +1,97 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-24 + */ +@Data +@TableName("nd_certificate") +@ApiModel(value = "Certificate对象", description = "") +public class Certificate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("驾驶员合格证表") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员用户id") + private Long userId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("出生年月") + private LocalDateTime birth; + + @ApiModelProperty("性别") + private Integer gender; + + @ApiModelProperty("籍贯") + private String nativePlace; + + @ApiModelProperty("健康状况") + private String health; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("驾驶证类型") + private String driverLicenseType; + + @ApiModelProperty("驾驶证号") + private String driverLicenseNo; + + @ApiModelProperty("合格证编号") + private String certificateNo; + + @ApiModelProperty("发证单位") + private String issuedBy; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("有效期至") + private LocalDateTime expiryDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysis.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysis.java new file mode 100644 index 0000000..97a67a6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysis.java @@ -0,0 +1,139 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import com.ningdatech.carapi.common.constant.BgTypeEnum; +import com.ningdatech.carapi.driver.constant.DriverAbnormalBehaviorOverseeEnum; +import com.ningdatech.carapi.driver.constant.DriverAbnormalBehaviorProcessingEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author CMM + * @Description + * @Date 2022/11/6 20:59 + */ +@TableName("nd_driver_abnormal_behavior_analysis") +@Data +@ApiModel(value = "DriverAbnormalBehaviorAnalysis",description = "驾驶员行为分析") +@NoArgsConstructor +@AllArgsConstructor +public class DriverAbnormalBehaviorAnalysis extends BaseEntity implements Serializable { + private static final long serialVersionUID = 4998442662608188657L; + + @ApiModelProperty("告警事件id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + /** + * {@link BgTypeEnum} + */ + @ApiModelProperty("告警类型") + private Integer alarmType; + + @ApiModelProperty(value = "告警级别",allowableValues = "1 预警,2 报警") + private Integer alarmLevel; + + @ApiModelProperty("告警级别名称") + private String alarmLevelName; + + @ApiModelProperty("车辆速度") + private Integer speed; + + @ApiModelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("告警地点") + private String alarmAddress; + + @ApiModelProperty("告警图片附件") + private String alarmPictureAppendix; + + @ApiModelProperty("告警视频附件") + private String alarmVideoAppendix; + + /** + * {@link DriverAbnormalBehaviorProcessingEnum} + */ + @ApiModelProperty(value = "处理状态",allowableValues = "0 待处理,1 已处理") + private Integer processingStatus; + + /** + * {@link DriverAbnormalBehaviorOverseeEnum} + */ + @ApiModelProperty(value = "处理状态",allowableValues = "0 待督办,1 已督办") + private Integer overseeStatus; + + @ApiModelProperty("处理方式") + private String processingMode; + + @ApiModelProperty("处理描述") + private String processingDescription; + + @ApiModelProperty("处理用户") + private String processingUser; + + @ApiModelProperty("处理时间") + private LocalDateTime processingTime; + + @ApiModelProperty("地址信息") + private String addressInfo; + + @ApiModelProperty("供应商数据关联id") + private Integer supplierDataId; + + @ApiModelProperty("告警类型名称") + private String alarmTypeName; + + @ApiModelProperty("供应商报警唯一序号") + private Long alarmMsgSn; + + @ApiModelProperty("平台ID") + private Long gnssCenterId; + + @ApiModelProperty("告警GPS高度") + private BigDecimal altitude; + + @ApiModelProperty("告警GPS经度") + private BigDecimal longitude; + + @ApiModelProperty("告警GPS纬度") + private BigDecimal latitude; + + @ApiModelProperty("督办处理结果") + private String overseeResult; + + @ApiModelProperty("督办时间") + private LocalDateTime overseeTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisNoticeDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisNoticeDTO.java new file mode 100644 index 0000000..8652353 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisNoticeDTO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.driver.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +/** + * @author CMM + * @description + * @since 2022/12/08 10:55 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DriverAbnormalBehaviorAnalysisNoticeDTO",description = "驾驶员异常行为分析通知") +public class DriverAbnormalBehaviorAnalysisNoticeDTO implements Serializable { + + private static final long serialVersionUID = 4549243904173062235L; + + @ApiModelProperty(value = "驾驶员异常行为数据ID",required = true) + @NotNull(message = "驾驶员异常行为数据ID不能为空!") + private Long id; + + @ApiModelProperty(value = "处理方式",required = true) + @NotNull(message = "驾驶员异常行为处理方式不能为空!") + private List processingMode; + + @ApiModelProperty(value = "处理描述内容",required = true) + @NotNull(message = "请传入处理描述的内容!") + @Size(max = 100) + private String processingDescription; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisOverseeDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisOverseeDTO.java new file mode 100644 index 0000000..1c4bbb3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisOverseeDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.driver.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author CMM + * @description + * @since 2022/12/06 23:33 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DriverAbnormalBehaviorAnalysisOverseeDTO",description = "驾驶员异常行为分析处理") +public class DriverAbnormalBehaviorAnalysisOverseeDTO implements Serializable { + + private static final long serialVersionUID = 8267690499784450167L; + + @ApiModelProperty(value = "驾驶员异常行为数据ID",required = true) + @NotNull(message = "驾驶员异常行为数据ID不能为空!") + private Long id; + + @ApiModelProperty(value = "督办状态 0 不督办告警 1 督办告警",required = true) + @NotNull(message = "请传入督办状态!") + private Integer overseeStatus; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisPageParamDTO.java new file mode 100644 index 0000000..8c8f57d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverAbnormalBehaviorAnalysisPageParamDTO.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.driver.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @description + * @since 2022/12/02 17:08 + */ +@Data +@ApiModel(description = "驾驶员异常行为分析PARAM DTO") +public class DriverAbnormalBehaviorAnalysisPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = -7881235564388790588L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty(value = "告警级别",allowableValues = "1 预警,2 报警") + private Integer level; + + @ApiModelProperty("告警级别名称") + private Integer alarmLevelName; + + @ApiModelProperty(value = "告警类型") + private List alarmType; + + @ApiModelProperty("开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + private LocalDateTime endTime; + + @ApiModelProperty(value = "处理状态",allowableValues = "0 待处理,1 已处理") + private Integer processingStatus; + + @ApiModelProperty(value = "督办状态",allowableValues = "0 待督办,1 已督办") + private Integer overseeStatus; + + @ApiModelProperty("系统车牌号列表") + private Set carPlateList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverArchivesDataImportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverArchivesDataImportDTO.java new file mode 100644 index 0000000..ae2d548 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverArchivesDataImportDTO.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.driver.entity; + +import com.ningdatech.carapi.common.constant.ApprovedMotorcycleTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author CMM + * @description + * @since 2022/11/30 11:59 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DriverArchivesDataImportDTO { + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("性别") + private String gender; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("出生年月") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + private String nativePlace; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("健康状况") + private String health; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("驾驶证号") + private String driverLicenseNo; + + @ApiModelProperty("准驾车型") + private String driverLicenseType; + + @ApiModelProperty("初次领证时间") + private LocalDateTime initialLicenseTime; + + /** + * {@link ApprovedMotorcycleTypeEnum} + */ + @ApiModelProperty("拟驾车型列表") + private String motorcycleTypeList; + + @ApiModelProperty("违法违规信息") + private String illegalAndIllegalInfo; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverBlackList.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverBlackList.java new file mode 100644 index 0000000..39842cf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverBlackList.java @@ -0,0 +1,86 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@Data +@TableName("nd_driver_black_list") +public class DriverBlackList implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 驾驶员ID + */ + private Long driverId; + + /** + * 驾驶员姓名 + */ + private String driverName; + + /** + * 年度 + */ + private String year; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + /** + * 超速累计次数 + */ + private Long accumulatedOverspeedCnt; + + /** + * 出险累计次数 + */ + private Long accumulatedAccidentsCnt; + + /** + * 违章累计次数 + */ + private Long accumulatedViolationsCnt; + + /** + * 区域ID + */ + private Long regionId; + + /** + * 公司ID + */ + private Long companyId; + + /** + * 公司名 + */ + private String companyName; + + /** + * 累计伤人次数 + */ + private Long accumulatedHurtCnt; + + /** + * 累计亡人次数 + */ + private Long accumulatedDeathCnt; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverInfo.java new file mode 100644 index 0000000..e00cd38 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverInfo.java @@ -0,0 +1,147 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.constant.ApprovedMotorcycleTypeEnum; +import com.ningdatech.carapi.driver.constant.DriverContinuingEducationRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverReplacementRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverStatusEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@TableName("nd_driver_info") +@Data +public class DriverInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶头像文件") + private String avatarFile; + + @ApiModelProperty("性别") + private Integer gender; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("出生年月") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + private String nativePlace; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯编码") + private String nativePlaceRegionCode; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("健康状况") + private String health; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty("驾驶证类型") + private String driverLicenseType; + + @ApiModelProperty("服务企业唯一标识id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + /** + * {@link DriverStatusEnum} + */ + @ApiModelProperty(value = "驾驶员状态", + allowableValues = " induction 入职,quit 离职") + private String driverStatus; + + @ApiModelProperty("系统用户ID") + private Long userId; + + @ApiModelProperty("区域id") + private Long regionId; + + /** + * {@link DriverRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员取证报名状态") + private String driverRegistrationStatus; + + @ApiModelProperty("违法违规信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty("初次领证时间") + private LocalDateTime initialLicenseTime; + + @ApiModelProperty("离职时间") + private LocalDateTime quitTime; + + @ApiModelProperty("入职时间") + private LocalDateTime inductionTime; + + /** + * {@link DriverReplacementRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员换证培训报名状态") + private String replacementRegistrationStatus; + + /** + * {@link DriverContinuingEducationRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员继续教育报名状态") + private String continuingEducationStatus; + + /** + * {@link DriverContinuingEducationRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员跳槽审核报名状态") + private String jobChangeStatus; + + /** + * {@link ApprovedMotorcycleTypeEnum} + */ + @ApiModelProperty("拟驾车型列表") + private String motorcycleTypeList; + + @ApiModelProperty("驾驶员是否可以参加取证报名") + private Integer driverRegistrationFlag; + + @ApiModelProperty("驾驶员是否可以参加继续教育报名") + private Integer continuingEducationFlag; + + @ApiModelProperty("驾驶员是否可以参加换证培训报名") + private Integer replacementRegistrationFlag; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreInfo.java new file mode 100644 index 0000000..69a61de --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreInfo.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +@TableName("nd_driver_score_info") +@Data +@ApiModel(value = "DriverScoreInfo对象", description = "") +public class DriverScoreInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员分数") + private Integer driverScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreRecord.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreRecord.java new file mode 100644 index 0000000..6b4bb2d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverScoreRecord.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +@Data +@TableName("nd_driver_score_record") +@ApiModel(value = "DriverScoreRecord对象", description = "") +public class DriverScoreRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("操作分数") + private Integer operateScore; + + @ApiModelProperty("操作类型 加分减分") + private String operateType; + + @ApiModelProperty("加分减分原因") + private String operateReason; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverTrainingMaterials.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverTrainingMaterials.java new file mode 100644 index 0000000..daf311f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverTrainingMaterials.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@TableName("nd_driver_training_materials") +@Data +public class DriverTrainingMaterials implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * oss文件id + */ + private Long fileId; + + private String fileName; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverWorkRecordInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverWorkRecordInfo.java new file mode 100644 index 0000000..8b3f87f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/DriverWorkRecordInfo.java @@ -0,0 +1,131 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.constant.ApprovedMotorcycleTypeEnum; +import com.ningdatech.carapi.driver.constant.DriverContinuingEducationRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverReplacementRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverStatusEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.time.LocalDateTime; + + +@TableName("nd_driver_work_record") +@Data +public class DriverWorkRecordInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶头像文件") + private String avatarFile; + + @ApiModelProperty("性别") + private Integer gender; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("出生年月") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + private String nativePlace; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯编码") + private String nativePlaceRegionCode; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("健康状况") + private String health; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty("驾驶证类型") + private String driverLicenseType; + + @ApiModelProperty("服务企业唯一标识id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + /** + * {@link DriverStatusEnum} + */ + @ApiModelProperty("驾驶员状态:入职/离职") + private String driverStatus; + + @ApiModelProperty("系统用户ID") + private Long userId; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域") + private String regionName; + + /** + * {@link DriverRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员取证报名状态") + private String driverRegistrationStatus; + + @ApiModelProperty("违法违规信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty("初次领证时间") + private LocalDateTime initialLicenseTime; + + @ApiModelProperty("离职时间") + private LocalDateTime quitTime; + + @ApiModelProperty("入职时间") + private LocalDateTime inductionTime; + + /** + * {@link DriverReplacementRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员换证培训报名状态") + private String replacementRegistrationStatus; + + /** + * {@link DriverContinuingEducationRegistrationStatusEnum} + */ + @ApiModelProperty("驾驶员继续教育报名状态") + private String continuingEducationStatus; + + /** + * {@link ApprovedMotorcycleTypeEnum} + */ + @ApiModelProperty("拟驾车型列表") + private String motorcycleTypeList; + + @ApiModelProperty("驾驶员Id") + private Long driverId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecord.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecord.java new file mode 100644 index 0000000..6aca399 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecord.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +@Data +@TableName("nd_exam_record") +@ApiModel(value = "ExamRecord对象", description = "") +public class ExamRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @NotNull(message = "培训类型不能为空") + @ApiModelProperty(value = "考试类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private String examType; + + @ApiModelProperty("训练组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("考试试卷id") + private Long examPaperId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecordDetail.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecordDetail.java new file mode 100644 index 0000000..5a1f1dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/ExamRecordDetail.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +@Data +@TableName("nd_exam_record_detail") +@ApiModel(value = "ExamRecordDetail对象", description = "") +public class ExamRecordDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员用户id") + private Long driverUserId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("考试分数") + private Integer score; + + @ApiModelProperty("考试结果") + private String examResult; + + @ApiModelProperty("考试时间") + private LocalDateTime examTime; + + @ApiModelProperty("所属区域") + private Long regionId; + + @ApiModelProperty("考试类型") + private String examType; + + @ApiModelProperty("考试记录id") + private Long examRecordId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/OverseeInterfaceCallDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/OverseeInterfaceCallDTO.java new file mode 100644 index 0000000..e1b7975 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/OverseeInterfaceCallDTO.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.driver.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author CMM + * @description + * @since 2022/12/08 14:35 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class OverseeInterfaceCallDTO implements Serializable { + + private static final long serialVersionUID = 3881169002010057397L; + + @ApiModelProperty("平台ID") + private Long GnssCenterId; + + @ApiModelProperty("告警唯一序号") + private Long MSgSn; + + @ApiModelProperty("督办截止时间") + private Integer SupervisionEndTime; + + @ApiModelProperty("督办等级") + private Integer SupervisionLevel; + + @ApiModelProperty("督办人") + private String Supervisor; + + @ApiModelProperty("督办人手机号") + private String SupervisorTel; + + @ApiModelProperty("督办人邮箱") + private String SupervisorEmail; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/RegionStarDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/RegionStarDTO.java new file mode 100644 index 0000000..aec0879 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/RegionStarDTO.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.driver.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author CMM + * @description + * @since 2022/11/22 17:10 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class RegionStarDTO { + private List regionIdList; + private String companyName; + private Long companyId; + private String driverName; + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/StarManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/StarManage.java new file mode 100644 index 0000000..4fd7d61 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/StarManage.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-11-15 + */ +@Data +@TableName("nd_star_manage") +@ApiModel(value = "StarManage对象", description = "") +public class StarManage implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("受伤人数") + private Integer injuredCnt; + + @ApiModelProperty("事故次数") + private Integer accidentsCnt; + + @ApiModelProperty("出险次数") + private Integer insuranceCnt; + + @ApiModelProperty("死亡人数") + private Integer deathCnt; + + @ApiModelProperty("当前星级") + private Double currentStar; + + @ApiModelProperty("扣除星级") + private Double deductStar; + + @ApiModelProperty("当前分数") + private Integer currentScore; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingBonusRecord.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingBonusRecord.java new file mode 100644 index 0000000..92980c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingBonusRecord.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-31 + */ +@Data +@TableName("nd_training_bonus_record") +@ApiModel(value = "TrainingBonusRecord对象", description = "") +public class TrainingBonusRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("继续教育培训奖励表") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("材料类型") + private String materialType; + + @ApiModelProperty("培训材料id") + private Long trainingMaterialId; + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("行为类型") + private String behaviorType; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("公司ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingMaterial.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingMaterial.java new file mode 100644 index 0000000..428d51e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingMaterial.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.driver.constant.MaterialStatusEnum; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-21 + */ +@TableName("nd_training_material") +@Data +@ApiModel(value = "TrainingMaterial对象", description = "") +public class TrainingMaterial implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("培训材料表") + private Long id; + + @ApiModelProperty("标题") + private String title; + + /** + * {@link MaterialTypeEnum} + */ + @ApiModelProperty("材料类型") + private String materialType; + + /** + * {@link MaterialStatusEnum} + */ + @ApiModelProperty("材料状态") + private String materialStatus; + + @ApiModelProperty("内容") + private String content; + + @ApiModelProperty("附件json list") + private String appendixListJson; + + private Long regionId; + private Long companyId; + + private LocalDateTime updateOn; + + private LocalDateTime createOn; + + private Long createBy; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganization.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganization.java new file mode 100644 index 0000000..6d51656 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganization.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.driver.constant.TrainingModeEnum; +import com.ningdatech.carapi.driver.constant.TrainingStatusEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author LiuXinXin + * @since 2022-10-10 + */ +@TableName("nd_training_organization") +@Data +public class TrainingOrganization implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + /** + * 培训主题 + */ + private String trainingTopic; + + /** + * 培训开始时间 + */ + private LocalDateTime trainingStartTime; + + /** + * 培训结束时间 + */ + private LocalDateTime trainingEndTime; + + /** + * 培训地点 + */ + private String address; + + + /** + * 培训模式 线上/线下 + * {@link TrainingModeEnum} + */ + private String trainingMode; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + private String trainingType; + + /** + * 联系人 + */ + private String contacts; + + /** + * 联系电话 + */ + private String contactNumber; + + /** + * 培训状态 启用/禁用 + * {@link TrainingStatusEnum} + */ + private String trainingStatus; + + /** + * 备注 + */ + private String remark; + + /** + * 区域id + */ + private Long regionId; + + /** + * 考试试卷id + */ + private Long examPaperId; + + /** + * 考试试卷名称 + */ + private String examPaperName; + + /** + * 随机试卷id + */ + private String randomExamPaperId; + + @ApiModelProperty("考试开始时间") + private LocalDateTime examStartTime; + + @ApiModelProperty("考试结束时间") + private LocalDateTime examEndTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationMaterial.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationMaterial.java new file mode 100644 index 0000000..8cbf6dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationMaterial.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +@Data +@TableName("nd_training_organization_material") +@ApiModel(value = "TrainingOrganizationMaterial对象", description = "") +public class TrainingOrganizationMaterial implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("培训材料id") + private Long trainingMaterialId; + + @ApiModelProperty("培训材料类型") + private String materialType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationTrainer.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationTrainer.java new file mode 100644 index 0000000..6847a15 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingOrganizationTrainer.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.driver.constant.ExamQualifiedEnum; +import com.ningdatech.carapi.driver.constant.ExaminationStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +@Data +@TableName("nd_training_organization_trainer") +@ApiModel(value = "TrainingOrganizationTrainer对象", description = "") +public class TrainingOrganizationTrainer implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶员用户id") + private Long driverUserId; + + @ApiModelProperty("分数") + private Integer score; + + /** + * {@link ExamQualifiedEnum} + */ + @ApiModelProperty("是否合格") + private String isQualified; + + @ApiModelProperty("试卷id") + private Long examPaperId; + + @ApiModelProperty("试卷名称") + private String examPaperName; + + @ApiModelProperty("准考证号") + private String examRegistrationNo; + + /** + * {@link ExaminationStatusEnum} + */ + @ApiModelProperty("考试状态") + private String examinationStatus; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("签到时间") + private LocalDateTime signTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingRegistrationReview.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingRegistrationReview.java new file mode 100644 index 0000000..8396d21 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/entity/TrainingRegistrationReview.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.driver.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Data +@TableName("nd_training_registration_review") +@ApiModel(value = "TrainingRegistrationReview对象", description = "") +public class TrainingRegistrationReview implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + private Long updateBy; + + @ApiModelProperty("驾驶员用户id") + private Long driverUserId; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员姓名冗余字段") + private String driverName; + + @ApiModelProperty("身份证号") + private String driverIdCard; + + @ApiModelProperty("驾驶员手机号") + private String driverPhoneNo; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("公司所属区域") + private Long regionId; + + @ApiModelProperty("培训类型") + private String registrationType; + + @ApiModelProperty("审核状态") + private String approvalStatus; + + @ApiModelProperty("附件信息json") + private String appendixListJson; + + @ApiModelProperty("meta审核id") + private Long metaApplyId; + + @ApiModelProperty("meta审核类型") + private String metaApplyType; + + @ApiModelProperty("审核员结果意见附件") + private String auditAppendixListJson; + + @ApiModelProperty("初复审关联ID") + private Long preliminaryReviewAssociatedId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverBehaviorScoreHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverBehaviorScoreHelper.java new file mode 100644 index 0000000..42fd4c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverBehaviorScoreHelper.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.driver.helper; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.driver.model.bo.CodingRuleBO; +import com.ningdatech.carapi.sys.entity.CodingRule; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import com.ningdatech.carapi.sys.entity.enumeration.RuleOperationTypeEnum; +import com.ningdatech.carapi.sys.service.ICodingRuleService; +import com.ningdatech.carapi.sys.service.IExamRuleService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/11/14 上午11:27 + */ +@Component +@RequiredArgsConstructor +public class DriverBehaviorScoreHelper { + + private final IExamRuleService iExamRuleService; + private final ICodingRuleService iCodingRuleService; + +// public Integer getExamScoreValue() { +// iExamRuleService.getById() +// } + + /** + * 行为类型 + * + * @param behaviorType + * @return + */ + public CodingRuleBO getCodingRuleBehaviorScore(CodingRuleBehaviorTypeEnum behaviorType, VehicleTypeEnum vehicleTypeEnum) { + CodingRule codingRule = null; + if (Objects.nonNull(vehicleTypeEnum)) { + codingRule = iCodingRuleService.getOne(Wrappers.lambdaQuery(CodingRule.class) + .eq(CodingRule::getVehicleType, vehicleTypeEnum.name()) + .eq(CodingRule::getBehaviorType, behaviorType.name())); + }else { + codingRule = iCodingRuleService.getOne(Wrappers.lambdaQuery(CodingRule.class) + .eq(CodingRule::getBehaviorType, behaviorType.name())); + } + Integer operationScore = codingRule.getOperationScore(); + String ruleOperationType = codingRule.getRuleOperationType(); + + CodingRuleBO codingRuleBO = new CodingRuleBO(); + codingRuleBO.setOperationScore(operationScore); + codingRuleBO.setRuleOperationType(RuleOperationTypeEnum.valueOf(ruleOperationType)); + return codingRuleBO; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverInfoHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverInfoHelper.java new file mode 100644 index 0000000..e19fd2b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/DriverInfoHelper.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.driver.helper; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/11/14 下午2:44 + */ +@Component +@RequiredArgsConstructor +public class DriverInfoHelper { + private final UserInfoHelper userInfoHelper; + private final IDriverInfoService iDriverInfoService; + private final ICertificateService iCertificateService; + + /** + * 判断驾驶员是否拥有合格证书判断 + * + * @param userId + */ + public void driverCertificateValidCheck(Long userId) { + DriverInfo driverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getUserId, userId)); + if (Objects.isNull(driverInfo)) { + throw new BizException("当前账号无驾驶员信息"); + } else { + Certificate certificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, userId)); + if (Objects.isNull(certificate)) { + throw new BizException("当前驾驶员无证书信息"); + } else { + LocalDateTime expiryDate = certificate.getExpiryDate(); + if (expiryDate.isBefore(LocalDateTime.now())) { + throw new BizException("当前驾驶员合格证书已过期"); + } + } + } + } + + /** + * 判断驾驶员是否拥有有效的合格证书 + * + * @param userId + */ + public Boolean hasDriverAvailableCertificate(Long userId) { + DriverInfo driverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getUserId, userId)); + if (Objects.isNull(driverInfo)) { + return false; + } else { + Certificate certificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, userId)); + if (Objects.isNull(certificate)) { + return false; + } else { + LocalDateTime expiryDate = certificate.getExpiryDate(); + if (expiryDate.isBefore(LocalDateTime.now())) { + return false; + } + } + } + return true; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/RegistrationAvailableCheckHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/RegistrationAvailableCheckHelper.java new file mode 100644 index 0000000..69b71d0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/helper/RegistrationAvailableCheckHelper.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.driver.helper; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.driver.constant.DriverContinuingEducationRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverReplacementRegistrationStatusEnum; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.model.po.ReqDriverTrainingRegistrationPO; +import com.ningdatech.carapi.driver.service.ICertificateService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/11/11 下午1:58 + */ +@Component +@RequiredArgsConstructor +public class RegistrationAvailableCheckHelper { + private final ICertificateService iCertificateService; + + public void forensicRegistration(DriverInfo driverInfo) { + String driverRegistrationStatus = driverInfo.getDriverRegistrationStatus(); + Boolean hasAlreadySignUp = StringUtils.isNotBlank(driverRegistrationStatus); + if (hasAlreadySignUp) { + throw new BizException("该驾驶员已经报名,无需重复报名"); + } + } + + public void replacementRegistrationValidCheck(ReqDriverTrainingRegistrationPO request, DriverInfo driverInfo) { + // 校验驾驶员当前是否有换证培训的权限 + String driverRegistrationStatus = driverInfo.getDriverRegistrationStatus(); + if (!DriverRegistrationStatusEnum.available.name().equals(driverRegistrationStatus)) { + throw new BizException("请先通过驾驶员取证培训!"); + } + String replacementRegistrationStatus = driverInfo.getReplacementRegistrationStatus(); + // 此次提交的报名信息为重新提交的换证报名 + if (Objects.nonNull(request.getDriverId())){ + return; + } + Boolean hasAlreadySignUp = (!DriverReplacementRegistrationStatusEnum.available.name().equals(replacementRegistrationStatus) + && StringUtils.isNotBlank(replacementRegistrationStatus)); + if (hasAlreadySignUp) { + throw new BizException("该驾驶员已经报名,无需重复报名"); + } + Certificate certificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class).eq(Certificate::getDriverId, driverInfo.getId())); + LocalDateTime expiryDate = certificate.getExpiryDate(); + if (expiryDate.isAfter(LocalDateTime.now())) { + throw new BizException("该合格证尚未过期,无需重复办理"); + } + } + + public void continuingEducationRegistrationValidCheck(ReqDriverTrainingRegistrationPO request, DriverInfo driverInfo) { + String driverRegistrationStatus = driverInfo.getDriverRegistrationStatus(); + if (!DriverRegistrationStatusEnum.available.name().equals(driverRegistrationStatus)) { + throw new BizException("请先通过驾驶员取证培训报名"); + } + // 此次提交的报名信息为重新提交的继续教育报名 + if (Objects.nonNull(request.getDriverId())){ + return; + } + String continuingEducationStatus = driverInfo.getContinuingEducationStatus(); + Boolean hasAlreadySignUp = (!DriverContinuingEducationRegistrationStatusEnum.available.name().equals(continuingEducationStatus) + && StringUtils.isNotBlank(continuingEducationStatus)); + if (hasAlreadySignUp) { + throw new BizException("该驾驶员已经报名,无需重复报名"); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ArticleInfoManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ArticleInfoManage.java new file mode 100644 index 0000000..c69f745 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ArticleInfoManage.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.driver.manage; + +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.constant.ArticleTypeEnum; +import com.ningdatech.carapi.driver.entity.ArticleInfo; +import com.ningdatech.carapi.driver.model.po.ReqArticleInfoListPO; +import com.ningdatech.carapi.driver.model.vo.ResArticleInfoListVO; +import com.ningdatech.carapi.driver.service.IArticleInfoService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author liuxinxin + * @date 2022/10/9 下午4:34 + */ + +@Component +@RequiredArgsConstructor +public class ArticleInfoManage { + + private final IArticleInfoService iArticleInfoService; + + public PageVo articleInfoList(ReqArticleInfoListPO reqArticleInfoListPo) { + ArticleTypeEnum articleType = reqArticleInfoListPo.getArticleType(); + String title = reqArticleInfoListPo.getTitle(); + LocalDateTime startTime = reqArticleInfoListPo.getStartTime(); + LocalDateTime endTime = reqArticleInfoListPo.getEndTime(); + Integer pageNumber = reqArticleInfoListPo.getPageNumber(); + Integer pageSize = reqArticleInfoListPo.getPageSize(); + + Page page = iArticleInfoService.page(new Page<>(pageNumber, pageSize) + , Wrappers.lambdaQuery(ArticleInfo.class) + .eq(Objects.nonNull(articleType), ArticleInfo::getArticleType, articleType.name()) + .like(StringUtils.isNotBlank(title), ArticleInfo::getTitle, title) + .gt(Objects.nonNull(startTime), ArticleInfo::getFormulationTime, startTime) + .lt(Objects.nonNull(endTime), ArticleInfo::getFormulationTime, endTime)); + + PageVo pageVo = new PageVo<>(); + long total = page.getTotal(); + pageVo.setTotal(total); + if (total == 0) { + return pageVo; + } + + List records = page.getRecords(); + List resArticleInfoListVOList = records.stream().map(r -> { + ResArticleInfoListVO resArticleInfoListVO = new ResArticleInfoListVO(); + resArticleInfoListVO.setArticleId(r.getId()); + resArticleInfoListVO.setArticleStatus(r.getArticleStatus()); + String currentArticleType = r.getArticleType(); + if (StringUtils.isNotBlank(currentArticleType)) { + resArticleInfoListVO.setArticleType(ArticleTypeEnum.valueOf(currentArticleType)); + } + resArticleInfoListVO.setFormulationTime(r.getFormulationTime()); + resArticleInfoListVO.setTitle(r.getTitle()); + return resArticleInfoListVO; + }).collect(Collectors.toList()); + + pageVo.setRecords(resArticleInfoListVOList); + return pageVo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/BehaviourAnalysisManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/BehaviourAnalysisManage.java new file mode 100644 index 0000000..e78a8dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/BehaviourAnalysisManage.java @@ -0,0 +1,257 @@ +package com.ningdatech.carapi.driver.manage; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.DriverAbnormalBehaviorAppendixTypeEnum; +import com.ningdatech.carapi.driver.constant.DriverAbnormalBehaviorProcessingEnum; +import com.ningdatech.carapi.driver.entity.*; +import com.ningdatech.carapi.driver.model.vo.BehaviourAnalysisVO; +import com.ningdatech.carapi.driver.model.vo.DriverAbnormalBehaviorAnalysisDetailVO; +import com.ningdatech.carapi.driver.model.vo.DriverDailyAlarmEvent; +import com.ningdatech.carapi.driver.service.IBehaviorAnalysisProcessingModeService; +import com.ningdatech.carapi.driver.service.IBehaviourAnalysisService; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @Classname BehaviourAnalysisManage + * @Description + * @Date 2022/11/7 16:30 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class BehaviourAnalysisManage { + + private final IBehaviourAnalysisService behaviourAnalysisService; + private final IDriverInfoService driverInfoService; + private final IBehaviorAnalysisProcessingModeService behaviorAnalysisProcessingModeService; + private final CompanyService companyService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + + public PageVo behaviorAnalysisList(DriverAbnormalBehaviorAnalysisPageParamDTO param) { + Page page = param.page(); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + Map companyMap = companyService.list(Wrappers.lambdaQuery(Company.class) + .select(Company::getId,Company::getName)).stream().collect(Collectors.toMap(Company::getId, c -> c)); + Map vehicleBaseInfoMap = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getCompanyId)).stream() + .collect(Collectors.toMap(v -> v.getCarPlate() + v.getCompanyId(), v -> v)); + stopWatch.stop(); + log.info("1共耗时 {}s", stopWatch.getTotalTimeSeconds()); + + StopWatch stopWatch2 = new StopWatch(); + stopWatch2.start(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverAbnormalBehaviorAnalysis.class); + BehaviourAnalysisManage context = (BehaviourAnalysisManage) AopContext.currentProxy(); + context.buildBehaviourAnalysisQuery(wrapper, param); + behaviourAnalysisService.page(page, wrapper); + stopWatch2.stop(); + log.info("2共耗时 {}s", stopWatch2.getTotalTimeSeconds()); + + // 驾驶员异常行为列表查询 + if (0L == page.getTotal()) { + return PageVo.empty(); + } + + List behaviourAnalysisVOList = page.getRecords().stream().map(b -> { + BehaviourAnalysisVO resVo = new BehaviourAnalysisVO(); + BeanUtil.copyProperties(b, resVo); + BigDecimal speed = BigDecimal.valueOf(b.getSpeed()).multiply(TaskContant.Math.SPEED_UNITS) + .setScale(BigDecimal.ROUND_CEILING, RoundingMode.HALF_UP); + resVo.setSpeed(speed); + String alarmPictureAppendix = b.getAlarmPictureAppendix(); + String alarmVideoAppendix = b.getAlarmVideoAppendix(); + List list = getFileBasicInfos(alarmPictureAppendix, alarmVideoAppendix); + resVo.setAlarmAppendix(list); + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(b.getCarPlate() + b.getCompanyId()); + if (Objects.nonNull(vehicleBaseInfo)) { + resVo.setCompanyId(vehicleBaseInfo.getCompanyId()); + Company company = companyMap.get(vehicleBaseInfo.getCompanyId()); + resVo.setCompanyName(company.getName()); + } + return resVo; + }).collect(Collectors.toList()); + return PageVo.of(behaviourAnalysisVOList, page.getTotal()); + } + + private List getFileBasicInfos(String alarmPic, String alarmVideo) { + List list = new ArrayList<>(); + if (StrUtil.isNotBlank(alarmPic) && !HttpUtil.isHttps(alarmPic) && !HttpUtil.isHttp(alarmPic)) { + FileBasicInfo filePictureBasicInfo = new FileBasicInfo(); + filePictureBasicInfo.setFileType(DriverAbnormalBehaviorAppendixTypeEnum.PICTURE.getCode()); + filePictureBasicInfo.setFilePath(alarmPic); + list.add(filePictureBasicInfo); + } + if (StrUtil.isNotBlank(alarmVideo) && !HttpUtil.isHttps(alarmVideo) && !HttpUtil.isHttp(alarmVideo)) { + FileBasicInfo fileVideoBasicInfo = new FileBasicInfo(); + fileVideoBasicInfo.setFileType(DriverAbnormalBehaviorAppendixTypeEnum.VIDEO.getCode()); + fileVideoBasicInfo.setFilePath(alarmVideo); + list.add(fileVideoBasicInfo); + } + return list; + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildBehaviourAnalysisQuery(LambdaQueryWrapper wrapper, DriverAbnormalBehaviorAnalysisPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCarPlate()), DriverAbnormalBehaviorAnalysis::getCarPlate, param.getCarPlate()) + .eq(Objects.nonNull(param.getLevel()), DriverAbnormalBehaviorAnalysis::getAlarmLevel, param.getLevel()) + .ge(Objects.nonNull(param.getStartTime()), DriverAbnormalBehaviorAnalysis::getAlarmTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), DriverAbnormalBehaviorAnalysis::getAlarmTime, param.getEndTime()) + .in(Objects.nonNull(param.getAlarmType()), DriverAbnormalBehaviorAnalysis::getAlarmType, param.getAlarmType()) + .eq(Objects.nonNull(param.getProcessingStatus()), DriverAbnormalBehaviorAnalysis::getProcessingStatus, param.getProcessingStatus()) + .eq(Objects.nonNull(param.getOverseeStatus()), DriverAbnormalBehaviorAnalysis::getOverseeStatus, param.getOverseeStatus()) + .orderBy(Boolean.TRUE, Boolean.FALSE, DriverAbnormalBehaviorAnalysis::getAlarmTime); + } + + public Boolean oversee(DriverAbnormalBehaviorAnalysisOverseeDTO param, Long userId) { + return behaviourAnalysisService.oversee(param, userId); + } + + public DriverAbnormalBehaviorAnalysisDetailVO getBehaviourAnalysisDetail(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverAbnormalBehaviorAnalysis.class); + BehaviourAnalysisManage context = (BehaviourAnalysisManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + DriverAbnormalBehaviorAnalysis driverAbnormalBehaviorAnalysis = behaviourAnalysisService.getOne(wrapper); + if (Objects.isNull(driverAbnormalBehaviorAnalysis)) { + throw new BizException("异常行为不存在"); + } + //DriverAbnormalBehaviorAnalysis driverAbnormalBehaviorAnalysis = behaviourAnalysisService.getById(id); + DriverAbnormalBehaviorAnalysisDetailVO resVo = BeanUtil.copyProperties(driverAbnormalBehaviorAnalysis, DriverAbnormalBehaviorAnalysisDetailVO.class); + Optional.ofNullable(driverAbnormalBehaviorAnalysis.getSpeed()).ifPresent(c -> resVo.setSpeed(BigDecimal.valueOf(c).multiply(TaskContant.Math.SPEED_UNITS) + .setScale(BigDecimal.ROUND_CEILING, RoundingMode.HALF_UP).intValue())); + + //统计该驾驶员当日异常行为告警事件 + //获取当前日期的起始时间和结束时间 + LocalDateTime startTime = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endTime = NdDateUtils.endOfDay(LocalDateTime.now()); + + LambdaQueryWrapper query = Wrappers.lambdaQuery(DriverAbnormalBehaviorAnalysis.class); + query.eq(DriverAbnormalBehaviorAnalysis::getDriverId, driverAbnormalBehaviorAnalysis.getDriverId()) + .ge(DriverAbnormalBehaviorAnalysis::getAlarmTime, startTime) + .le(DriverAbnormalBehaviorAnalysis::getAlarmTime, endTime) + .orderByDesc(DriverAbnormalBehaviorAnalysis::getAlarmTime); + List driverAbnormalBehaviorAnalysisList = behaviourAnalysisService.list(query); + List data = new ArrayList<>(); + for (DriverAbnormalBehaviorAnalysis abnormalBehaviorAnalysis : driverAbnormalBehaviorAnalysisList) { + DriverDailyAlarmEvent driverDailyAlarmEvent = BeanUtil.copyProperties(abnormalBehaviorAnalysis, DriverDailyAlarmEvent.class); + List fileBasicInfos = getFileBasicInfos(abnormalBehaviorAnalysis.getAlarmPictureAppendix(), + abnormalBehaviorAnalysis.getAlarmVideoAppendix()); + driverDailyAlarmEvent.setAlarmAppendix(fileBasicInfos); + data.add(driverDailyAlarmEvent); + } + resVo.setAlarmEventList(data); + return resVo; + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(DriverAbnormalBehaviorAnalysis::getId,id); + } + + public Boolean deal(DriverAbnormalBehaviorAnalysisNoticeDTO param, Long userId) { + //根据异常行为数据ID查询驾驶员信息 + DriverAbnormalBehaviorAnalysis driverAbnormalBehaviorAnalysis = behaviourAnalysisService.getById(param.getId()); + String processingDescription = param.getProcessingDescription(); + String processingMode = param.getProcessingMode().toString(); + + driverAbnormalBehaviorAnalysis.setProcessingDescription(processingDescription); + driverAbnormalBehaviorAnalysis.setProcessingMode(processingMode); + driverAbnormalBehaviorAnalysis.setProcessingStatus(DriverAbnormalBehaviorProcessingEnum.DEAL.getCode()); + driverAbnormalBehaviorAnalysis.setProcessingTime(LocalDateTime.now()); + driverAbnormalBehaviorAnalysis.setProcessingUser(LoginUserUtil.getUsername()); + driverAbnormalBehaviorAnalysis.setUpdateOn(LocalDateTime.now()); + driverAbnormalBehaviorAnalysis.setUpdateBy(userId); + behaviourAnalysisService.updateById(driverAbnormalBehaviorAnalysis); + return Boolean.TRUE; + } + + public void driverAbnormalBehaviorAnalysisListExport(HttpServletResponse response, DriverAbnormalBehaviorAnalysisPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = behaviorAnalysisList(param); + Collection records = page.getRecords(); + List collect = records.stream().map(c -> { + BehaviourAnalysisExportDTO exportDTO = BeanUtil.copyProperties(c, BehaviourAnalysisExportDTO.class); + List alarmAppendix = c.getAlarmAppendix(); + for (FileBasicInfo fileBasicInfo : alarmAppendix) { + if (DriverAbnormalBehaviorAppendixTypeEnum.PICTURE.getCode().equals(fileBasicInfo.getFileType())) { + exportDTO.setAlarmPictureAppendix(fileBasicInfo.getFilePath()); + } else { + exportDTO.setAlarmVideoAppendix(fileBasicInfo.getFilePath()); + } + } + return exportDTO; + }).collect(Collectors.toList()); + String fileName = "驾驶员异常行为分析列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), BehaviourAnalysisExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public List processingModeDetail() { + return behaviorAnalysisProcessingModeService.list(); + } + + public Boolean addProcessingMode(String req) { + BehaviorAnalysisProcessingMode behaviorAnalysisProcessingMode = new BehaviorAnalysisProcessingMode(); + behaviorAnalysisProcessingMode.setProcessingModeName(req); + behaviorAnalysisProcessingModeService.save(behaviorAnalysisProcessingMode); + return Boolean.TRUE; + } + + public Boolean deleteProcessingMode(Integer id) { + behaviorAnalysisProcessingModeService.removeById(id); + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/CertificateManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/CertificateManage.java new file mode 100644 index 0000000..6c13cc9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/CertificateManage.java @@ -0,0 +1,154 @@ +package com.ningdatech.carapi.driver.manage; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.driver.constant.*; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.model.po.ReqUploadCertificatePO; +import com.ningdatech.carapi.driver.model.vo.ResCertificateVO; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/26 下午4:20 + */ +@Component +@RequiredArgsConstructor +public class CertificateManage { + + private final ICertificateService iCertificateService; + private final IDriverInfoService iDriverInfoService; + + private final CompaniesCacheHelper companiesCacheHelper; + private final UserInfoHelper userInfoHelper; + + @Transactional(rollbackFor = Exception.class) + public void uploadCertificate(ReqUploadCertificatePO request) { + + // 按照登录用户,如果是驾驶员登录,只展示该驾驶员信息 + UserBasicInfoVO userFullInfo = userInfoHelper.getUserFullInfo(); + Long roleId = userFullInfo.getRoleId(); + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)){ + throw new BizException("当前登录用户不能上传合格证!"); + } + // 获取入参 + String certificateNo = request.getCertificateNo(); + Long driverId = request.getDriverId(); + LocalDateTime expiryDate = request.getExpiryDate(); + LocalDateTime issueDate = request.getIssueDate(); + String issuedBy = request.getIssuedBy(); + String examType = request.getExamType(); + + // 校验合格证号是否可用 + Certificate oldCertificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getCertificateNo, certificateNo)); + + if (Objects.nonNull(oldCertificate)) { + throw new BizException("证书编号重复!"); + } + + List certificateList = iCertificateService.list(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getDriverId, driverId) + .gt(Certificate::getExpiryDate, LocalDateTime.now())); + if (CollectionUtil.isNotEmpty(certificateList)) { + throw new BizException("该驾驶员证书已上传"); + } + + // 获取驾驶员信息 + DriverInfo driverInfo = iDriverInfoService.getById(driverId); + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + // 保存合格证信息 + Certificate saveRecord = new Certificate(); + saveRecord.setCertificateNo(certificateNo); + saveRecord.setDriverId(driverId); + saveRecord.setDriverName(driverInfo.getDriverName()); + saveRecord.setExpiryDate(expiryDate); + saveRecord.setIssueDate(issueDate); + saveRecord.setIssuedBy(issuedBy); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setCreateBy(user.getUserId()); + saveRecord.setUserId(driverInfo.getUserId()); + saveRecord.setBirth(driverInfo.getBirth()); + saveRecord.setGender(driverInfo.getGender()); + saveRecord.setNativePlace(driverInfo.getNativePlace()); + saveRecord.setHealth(driverInfo.getHealth()); + saveRecord.setPhoneNo(driverInfo.getPhoneNo()); + saveRecord.setAddress(driverInfo.getAddress()); + saveRecord.setDriverLicenseType(driverInfo.getDriverLicenseType()); + saveRecord.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + saveRecord.setRemark(request.getRemark()); + saveRecord.setRegionId(user.getRegionId()); + saveRecord.setRegionName(user.getRegionName()); + saveRecord.setCompanyId(user.getCompanyId()); + saveRecord.setCompanyName(user.getCompanyName()); + // 如果是换证培训,替换原来过期的取证培训合格证信息 + if (examType.equals(TrainingTypeEnum.replacement_registration_training.name())){ + Certificate certificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, driverInfo.getUserId())); + saveRecord.setId(certificate.getId()); + } + iCertificateService.saveOrUpdate(saveRecord); + + // 取证报名和换证报名上传合格证之后,更新驾驶员状态并将对应的培训报名类型的可参加培训标志更改为可参加 + if (examType.equals(TrainingTypeEnum.forensic_registration_training.name())){ + driverInfo.setDriverRegistrationStatus(DriverRegistrationStatusEnum.available.name()); + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + }else if (examType.equals(TrainingTypeEnum.replacement_registration_training.name())){ + driverInfo.setReplacementRegistrationStatus(DriverReplacementRegistrationStatusEnum.available.name()); + driverInfo.setReplacementRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } + driverInfo.setUpdateOn(LocalDateTime.now()); + // 更新驾驶员为入职 + driverInfo.setDriverStatus(DriverStatusEnum.induction.name()); + iDriverInfoService.updateById(driverInfo); + } + + public ResCertificateVO getCertificate(Long driverId) { + DriverInfo driverInfo = iDriverInfoService.getById(driverId); + if (Objects.isNull(driverInfo)) { + throw new BizException("驾驶员信息不存在"); + } + Certificate certificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, driverInfo.getUserId())); + + ResCertificateVO resCertificateVO = new ResCertificateVO(); + resCertificateVO.setIdCard(driverInfo.getIdCard()); + resCertificateVO.setPhoneNo(driverInfo.getPhoneNo()); + resCertificateVO.setAddress(driverInfo.getAddress()); + BeanUtil.copyProperties(certificate, resCertificateVO); + CodeUtil.searchCompanyName(resCertificateVO); + return resCertificateVO; + } + + public ResCertificateVO getCertificate() { + Long userId = LoginUserUtil.getUserId(); + Certificate certificate = iCertificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, userId)); + + ResCertificateVO resCertificateVO = new ResCertificateVO(); + BeanUtil.copyProperties(certificate, resCertificateVO); + CodeUtil.searchCompanyName(resCertificateVO); + return resCertificateVO; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverArchivesManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverArchivesManage.java new file mode 100644 index 0000000..706490e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverArchivesManage.java @@ -0,0 +1,2204 @@ +package com.ningdatech.carapi.driver.manage; + +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import com.ningdatech.carapi.car.position.model.po.ReqDataPO; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.*; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.*; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.*; +import com.ningdatech.carapi.driver.constants.DriverConstant; +import com.ningdatech.carapi.driver.entity.*; +import com.ningdatech.carapi.driver.helper.RegistrationAvailableCheckHelper; +import com.ningdatech.carapi.driver.model.DriverArchivesExportDTO; +import com.ningdatech.carapi.driver.model.dto.DriverBasicInfoDTO; +import com.ningdatech.carapi.driver.model.po.*; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoDetailVO; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoSearchListVO; +import com.ningdatech.carapi.driver.model.vo.ResDriverTrainingRegistrationListVO; +import com.ningdatech.carapi.driver.service.*; +import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn; +import com.ningdatech.carapi.qrcode.service.VehicleGetOnService; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; +import com.ningdatech.carapi.safe.manage.VehicleAccidentManage; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentAnalysisService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; +import com.ningdatech.carapi.sys.contants.UserLoginConstant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.MetaApply; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.constant.ImportTemplateConstant; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.enumeration.BooleanDisplayEnum; +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; +import com.ningdatech.carapi.sys.entity.enumeration.MetaApplyStatusEnum; +import com.ningdatech.carapi.sys.entity.enumeration.MetaApplyTypeEnum; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.IMetaApplyService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.DesensitizedUtil; +import cn.hutool.core.util.IdcardUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.ExcelReader; +import cn.hutool.poi.excel.ExcelUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author liuxinxin + * @date 2022/10/9 上午10:33 + */ + +@Component +@RequiredArgsConstructor +@Slf4j +public class DriverArchivesManage { + + private final IDriverInfoService iDriverInfoService; + private final CompanyService companyService; + private final IMetaApplyService iMetaApplyService; + private final RegionsCacheHelper regionsCacheHelper; + private final INdUserInfoService iNdUserInfoService; + private final INdUserAuthService iNdUserAuthService; + private final UserRoleService userRoleService; + private final PasswordEncoder passwordEncoder; + private final ITrainingRegistrationReviewService iTrainingRegistrationReviewService; + private final UserInfoHelper userInfoHelper; + private final INdVehicleAccidentService vehicleAccidentService; + private final INdVehicleAccidentDeadService vehicleAccidentDeadService; + private final INdVehicleAccidentAnalysisService vehicleAccidentAnalysisService; + private final INdVehicleViolationService vehicleViolationService; + private final CompaniesCacheHelper companiesCacheHelper; + private final RegistrationAvailableCheckHelper registrationAvailableCheckHelper; + private final Logger LOG = LoggerFactory.getLogger(DriverArchivesManage.class); + private final IDriverWorkRecordService iDriverWorkRecordService; + private final ICertificateService certificateService; + private final IDriverScoreInfoService iDriverScoreInfoService; + private final VehicleAccidentManage vehicleAccidentManage; + private final VehicleGetOnService vehicleGetOnService; + private final IDriverInfoService driverInfoService; + + public PageVo archivalInfoSearch(ReqArchivalInfoSearchPO request) { + + // 按照登录用户,如果是驾驶员登录,只展示该驾驶员信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + Page page = request.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverInfo.class); + DriverStatusEnum driverStatus = request.getDriverStatus(); + // 不是离职列表,要加数据权限 + if (Objects.nonNull(driverStatus) && DriverStatusEnum.quit.name().equals(driverStatus.name())) { + buildQuitInfoSearchQuery(wrapper,request); + }else { + // 不是离职列表,要加数据权限 + DriverArchivesManage context = (DriverArchivesManage) AopContext.currentProxy(); + context.buildArchivalInfoSearchQuery(wrapper, request); + } + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)) { + Long userId = userDetail.getUserId(); + DriverInfo driverInfo = driverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class).eq(DriverInfo::getUserId, userId)); + if (Objects.nonNull(driverInfo)) { + Long driverId = driverInfo.getId(); + wrapper.eq(DriverInfo::getId, driverId); + } + } + + iDriverInfoService.page(page, wrapper); + // 培训审核列表查询 + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List records = page.getRecords(); + List returnVoList = records.stream().map(r -> { + ResArchivalInfoSearchListVO resVo = new ResArchivalInfoSearchListVO(); + BeanUtils.copyProperties(r, resVo); + resVo.setDriverId(r.getId()); + resVo.setInductionTime(r.getInitialLicenseTime()); + CodeUtil.searchCompanyNameAndRegionName(resVo); + // 对手机号和身份证号进行脱敏处理 + String phoneNo = r.getPhoneNo(); + String idCard = r.getIdCard(); + String encryptPhone = DesensitizedUtil.mobilePhone(phoneNo); + String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END); + resVo.setPhoneNo(encryptPhone); + resVo.setIdCard(encryptIdCard); + return resVo; + }).collect(Collectors.toList()); + return PageVo.of(returnVoList, page.getTotal()); + } + + public PageVo archivalInfoSearchOpen(ReqArchivalInfoSearchPO request) { + Page page = request.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverInfo.class); + buildArchivalInfoSearchQuery(wrapper, request); + iDriverInfoService.page(page, wrapper); + // 培训审核列表查询 + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List records = page.getRecords(); + List returnVoList = records.stream().map(r -> { + ResArchivalInfoSearchListVO resVo = BeanUtil.copyProperties(r, ResArchivalInfoSearchListVO.class); + resVo.setDriverId(r.getId()); + resVo.setInductionTime(r.getInitialLicenseTime()); + CodeUtil.searchCompanyNameAndRegionName(resVo); + return resVo; + }).collect(Collectors.toList()); + return PageVo.of(returnVoList, page.getTotal()); + } + + public List archivalInfoSearchBatchOpen(ReqDataPO po) { + List idCards = po.getIdCards(); + if(CollUtil.isEmpty(idCards)){ + return Collections.emptyList(); + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverInfo.class); + buildArchivalInfoSearchQuery(wrapper, idCards); + List list = iDriverInfoService.list(wrapper); + // 培训审核列表查询 + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + return list.stream().map(r -> { + ResArchivalInfoSearchListVO resVo = BeanUtil.copyProperties(r, ResArchivalInfoSearchListVO.class); + resVo.setDriverId(r.getId()); + resVo.setInductionTime(r.getInitialLicenseTime()); + CodeUtil.searchCompanyNameAndRegionName(resVo); + return resVo; + }).collect(Collectors.toList()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildArchivalInfoSearchQuery(LambdaQueryWrapper wrapper, ReqArchivalInfoSearchPO request) { + // 获取入参 + String companyName = request.getCompanyName(); + String driverName = request.getDriverName(); + String idCard = request.getIdCard(); + DriverStatusEnum driverStatus = request.getDriverStatus(); + Long companyId = request.getCompanyId(); + + // 查询 + String driverStatusStr = Objects.nonNull(driverStatus) ? driverStatus.name() : null; + wrapper.like(StringUtils.isNotBlank(companyName), DriverInfo::getCompanyName, companyName) + .like(StringUtils.isNotBlank(driverName), DriverInfo::getDriverName, driverName) + .ge(request.getStartTime() != null, DriverInfo::getCreateOn, request.getStartTime()) + .le(request.getEndTime() != null, DriverInfo::getCreateOn, request.getEndTime()) + .eq(StringUtils.isNotBlank(idCard), DriverInfo::getIdCard, idCard) + .eq(StringUtils.isNotBlank(driverStatusStr), DriverInfo::getDriverStatus, driverStatus) + .eq(Objects.nonNull(companyId), DriverInfo::getCompanyId, companyId) + .orderByDesc(DriverInfo::getCreateOn) + .isNotNull(DriverInfo::getCompanyId); + if (StrUtil.isNotBlank(request.getTrainingRegistrationType())) { + if (request.getTrainingRegistrationType().equals(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name())) { + wrapper.eq(DriverInfo::getDriverRegistrationStatus, DriverRegistrationStatusEnum.exam_training_stage.name()); + wrapper.eq(DriverInfo::getDriverRegistrationFlag, TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + + } else if (request.getTrainingRegistrationType().equals(TrainingRegistrationTypeEnum.CONTINUING_EDUCATION.name())) { + wrapper.eq(DriverInfo::getContinuingEducationStatus, DriverRegistrationStatusEnum.exam_training_stage.name()); + wrapper.eq(DriverInfo::getContinuingEducationFlag, TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (request.getTrainingRegistrationType().equals(TrainingRegistrationTypeEnum.REPLACEMENT_REGISTRATION.name())) { + wrapper.eq(DriverInfo::getReplacementRegistrationStatus, DriverRegistrationStatusEnum.exam_training_stage.name()); + wrapper.eq(DriverInfo::getReplacementRegistrationFlag, TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } + } + } + + public void buildArchivalInfoSearchQuery(LambdaQueryWrapper wrapper, List idCards) { + if(CollUtil.isEmpty(idCards)){ + //查不到 + wrapper.eq(DriverInfo::getId,0L); + return; + } + // 查询 + wrapper.in(DriverInfo::getIdCard, idCards) + .orderByDesc(DriverInfo::getCreateOn) + .isNotNull(DriverInfo::getCompanyId); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildQuitInfoSearchQuery(LambdaQueryWrapper wrapper, ReqArchivalInfoSearchPO request) { + // 获取入参 + String companyName = request.getCompanyName(); + String driverName = request.getDriverName(); + String idCard = request.getIdCard(); + // 查询 + wrapper.like(StringUtils.isNotBlank(companyName), DriverInfo::getCompanyName, companyName) + .like(StringUtils.isNotBlank(driverName), DriverInfo::getDriverName, driverName) + .eq(StringUtils.isNotBlank(idCard), DriverInfo::getIdCard, idCard) + .eq(DriverInfo::getDriverStatus,DriverStatusEnum.quit.name()) + .orderByDesc(DriverInfo::getCreateOn); + } + + public ResArchivalInfoDetailVO getDriverArchivalInfo(Long driverId) { + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + // 获取公司信息 + Long companyId = driverInfo.getCompanyId(); + CompanyDTO company = null; + if (Objects.nonNull(companyId)) { + company = companiesCacheHelper.getById(companyId); + } + // 装配返回信息 + ResArchivalInfoDetailVO resVo = new ResArchivalInfoDetailVO(); + resVo.setDriverId(driverInfo.getId()); + resVo.setDriverName(driverInfo.getDriverName()); + resVo.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + if (StringUtils.isNotBlank(driverInfo.getDriverLicenseType())) { + List strings = Arrays.stream(DriverLicenseTypeEnum.values()).map(String::valueOf).collect(Collectors.toList()); + if (strings.contains(driverInfo.getDriverLicenseType())) { + resVo.setDriverLicenseType(DriverLicenseTypeEnum.valueOf(driverInfo.getDriverLicenseType())); + }else { + resVo.setDriverLicenseType(DriverLicenseTypeEnum.OTHER); + } + } + if (StringUtils.isNotBlank(driverInfo.getMotorcycleTypeList())) { + resVo.setMotorcycleTypeList(JSONObject.parseArray(driverInfo.getMotorcycleTypeList(), String.class)); + } + + // 对手机号和身份证号进行脱敏处理 + String phoneNo = driverInfo.getPhoneNo(); + String idCard = driverInfo.getIdCard(); + String encryptPhone = DesensitizedUtil.mobilePhone(phoneNo); + String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END); + resVo.setDriverPhoneNo(encryptPhone); + resVo.setIdCard(encryptIdCard); + + String avatarFile = driverInfo.getAvatarFile(); + if (StringUtils.isNotBlank(avatarFile)) { + resVo.setAvatarFile(JSONObject.parseObject(avatarFile, FileBasicInfo.class)); + } + resVo.setBirth(driverInfo.getBirth()); + resVo.setNativePlace(driverInfo.getNativePlace()); + resVo.setDriverAddress(driverInfo.getAddress()); + resVo.setIllegalAndIllegalInfo(driverInfo.getIllegalAndIllegalInfo()); + resVo.setInitialLicenseTime(driverInfo.getInitialLicenseTime()); + resVo.setHealth(driverInfo.getHealth()); + resVo.setNativePlaceRegionCode(driverInfo.getNativePlaceRegionCode()); + resVo.setGender(driverInfo.getGender()); + if (Objects.nonNull(company)) { + resVo.setCompanyId(company.getId()); + resVo.setCompanyName(company.getName()); + resVo.setCompanyAddress(company.getAddress()); + String contactPhone = company.getContactPhone(); + String encryptContactPhone = DesensitizedUtil.mobilePhone(contactPhone); + resVo.setCompanyContactPhone(encryptContactPhone); + resVo.setCompanyContactPerson(company.getContactPerson()); + } + // 取证报名的信息作为驾驶员档案基本信息 + resVo.setTrainingRegistrationType(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION); + + // 装配初审信息 + TrainingRegistrationTypeEnum trainingRegistrationType = TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION; + TrainingRegistrationReview preliminaryReviewInfo = iTrainingRegistrationReviewService.getOne( + Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getRegistrationType, trainingRegistrationType.name()) + .eq(TrainingRegistrationReview::getMetaApplyType, MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()) + .eq(TrainingRegistrationReview::getDriverUserId, driverInfo.getUserId()) + .eq(TrainingRegistrationReview::getApprovalStatus, MetaApplyStatusEnum.FIRST_TRIAL_APPROVED.name())); + if (Objects.nonNull(preliminaryReviewInfo)) { + AuditInfo auditInfo = assemblerAuditInfo(preliminaryReviewInfo); + resVo.setPreliminaryReviewInfo(auditInfo); + + assemblerAppendixInfo(resVo, preliminaryReviewInfo); + } + + // 装配复核信息 + if (Objects.nonNull(preliminaryReviewInfo) + && MetaApplyStatusEnum.FIRST_TRIAL_APPROVED.name().equals(preliminaryReviewInfo.getApprovalStatus())) { + TrainingRegistrationReview inReviewInfo = iTrainingRegistrationReviewService.getOne( + Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getRegistrationType, trainingRegistrationType.name()) + .eq(TrainingRegistrationReview::getMetaApplyType, MetaApplyTypeEnum.IN_REVIEW.name()) + .eq(TrainingRegistrationReview::getDriverUserId, driverInfo.getUserId()) + .eq(TrainingRegistrationReview::getApprovalStatus, MetaApplyStatusEnum.REEXAMINATION_APPROVED.name())); + if (Objects.nonNull(inReviewInfo)) { + AuditInfo auditInfo = assemblerAuditInfo(inReviewInfo); + resVo.setReviewInfo(auditInfo); + } + } + + // 获取培训合格证信息 + Certificate certificate = certificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getDriverId, driverId) + .orderBy(Boolean.TRUE, Boolean.TRUE, Certificate::getCreateOn) + .last(DefValConstants.LIMIT_1)); + if (Objects.nonNull(certificate)){ + resVo.setCertificateNo(certificate.getCertificateNo()); + } + resVo.setDriverUserId(driverInfo.getUserId()); + return resVo; + } + + public ResArchivalInfoDetailVO getArchivalInfoReviewDetail(ReqGetArchivalInfoReviewDetailPO request) { + Long driverId = request.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + Long metaApplyId = request.getMetaApplyId(); + MetaApply metaApply = iMetaApplyService.getById(metaApplyId); + VUtils.isTrue(Objects.isNull(metaApply)).throwMessage("审核记录不存在!"); + // 获取公司信息 + Long companyId = driverInfo.getCompanyId(); + CompanyDTO company = companiesCacheHelper.getById(companyId); + // 装配返回信息 + ResArchivalInfoDetailVO resVo = new ResArchivalInfoDetailVO(); + resVo.setDriverId(driverInfo.getId()); + resVo.setDriverName(driverInfo.getDriverName()); + resVo.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + if (StringUtils.isNotBlank(driverInfo.getDriverLicenseType())) { + resVo.setDriverLicenseType(DriverLicenseTypeEnum.valueOf(driverInfo.getDriverLicenseType())); + } + if (StringUtils.isNotBlank(driverInfo.getDriverLicenseType())) { + resVo.setDriverLicenseType(DriverLicenseTypeEnum.valueOf(driverInfo.getDriverLicenseType())); + } + if (StringUtils.isNotBlank(driverInfo.getMotorcycleTypeList())) { + resVo.setMotorcycleTypeList(JSONObject.parseArray(driverInfo.getMotorcycleTypeList(), String.class)); + } + + resVo.setDriverAddress(driverInfo.getAddress()); + + // 对手机号和身份证号进行脱敏处理 + String phoneNo = driverInfo.getPhoneNo(); + String idCard = driverInfo.getIdCard(); + //String encryptPhone = DesensitizedUtil.mobilePhone(phoneNo); + //String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END); + //resVo.setDriverPhoneNo(encryptPhone); + //resVo.setIdCard(encryptIdCard); + resVo.setDriverPhoneNo(phoneNo); + resVo.setIdCard(idCard); + + String avatarFile = driverInfo.getAvatarFile(); + if (StringUtils.isNotBlank(avatarFile)) { + resVo.setAvatarFile(JSONObject.parseObject(avatarFile, FileBasicInfo.class)); + } + resVo.setDriverAddress(driverInfo.getAddress()); + resVo.setBirth(driverInfo.getBirth()); + resVo.setNativePlace(driverInfo.getNativePlace()); + resVo.setHealth(driverInfo.getHealth()); + resVo.setGender(driverInfo.getGender()); + resVo.setCompanyId(company.getId()); + resVo.setCompanyName(company.getName()); + resVo.setCompanyAddress(company.getAddress()); + resVo.setCompanyContactPhone(company.getContactPhone()); + resVo.setCompanyContactPerson(company.getContactPerson()); + resVo.setTrainingRegistrationType(request.getTrainingRegistrationType()); + resVo.setNativePlaceRegionCode(driverInfo.getNativePlaceRegionCode()); + resVo.setInitialLicenseTime(driverInfo.getInitialLicenseTime()); + resVo.setIllegalAndIllegalInfo(driverInfo.getIllegalAndIllegalInfo()); + resVo.setDriverAddress(driverInfo.getAddress()); + resVo.setDriverPhoneNo(driverInfo.getPhoneNo()); + if (Objects.nonNull(metaApply.getJobChangeCompanyId())) { + resVo.setJobChangeCompanyId(metaApply.getJobChangeCompanyId()); + CompanyDTO companyDto = companiesCacheHelper.getById(metaApply.getJobChangeCompanyId()); + resVo.setJobChangeCompanyName(companyDto.getName()); + } + + // 根据id获取当前查看的培训报名记录的信息 + Long reviewId = request.getTrainingRegistrationReviewId(); + + TrainingRegistrationReview trainingRegistrationReview + = iTrainingRegistrationReviewService.getById(reviewId); + if (Objects.isNull(trainingRegistrationReview)) { + throw new BizException("培训报名信息不存在!"); + } + if (MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name() + .equals(trainingRegistrationReview.getApprovalStatus())) { + assemblerAppendixInfo(resVo, trainingRegistrationReview); + } + // 如果是材料初审信息-已初审列表中的数据或者是材料复审信息-待复核列表中的数据,获取审核详情 + if (MetaApplyStatusEnum.FIRST_TRIAL_APPROVED.name() + .equals(trainingRegistrationReview.getApprovalStatus()) + || MetaApplyStatusEnum.FIRST_TRIAL_APPROVAL_REJECTION.name() + .equals(trainingRegistrationReview.getApprovalStatus()) + || MetaApplyStatusEnum.REEXAMINATION_UNDER_REVIEW.name() + .equals(trainingRegistrationReview.getApprovalStatus())) { + // 装配初审信息 + AuditInfo auditInfo = assemblerAuditInfo(trainingRegistrationReview); + resVo.setPreliminaryReviewInfo(auditInfo); + // 装配附件信息 + assemblerAppendixInfo(resVo, trainingRegistrationReview); + } + // 材料复审列表中已复审列表中的数据,获取审核详情 + if (MetaApplyStatusEnum.REEXAMINATION_APPROVED.name() + .equals(trainingRegistrationReview.getApprovalStatus()) + || MetaApplyStatusEnum.REEXAMINATION_APPROVAL_REJECTION.name() + .equals(trainingRegistrationReview.getApprovalStatus())) { + // 装配初审信息和复审信息 + // 获取该复审信息对应的初审报名信息(这两种状态下的复审信息对应的初审状态一定是审核通过的) + Long preliminaryReviewId = trainingRegistrationReview.getPreliminaryReviewAssociatedId(); + TrainingRegistrationReview preliminaryTrainingRegistrationReview = iTrainingRegistrationReviewService.getById(preliminaryReviewId); + // 装配初审信息 + AuditInfo preliminaryAuditInfo = assemblerAuditInfo(preliminaryTrainingRegistrationReview); + resVo.setPreliminaryReviewInfo(preliminaryAuditInfo); + assemblerAppendixInfo(resVo, preliminaryTrainingRegistrationReview); + // 装配复审信息 + AuditInfo reviewAuditInfo = assemblerAuditInfo(trainingRegistrationReview); + resVo.setReviewInfo(reviewAuditInfo); + } + + return resVo; + } + + private void assemblerAppendixInfo(ResArchivalInfoDetailVO resVo, TrainingRegistrationReview trainingRegistrationReview) { + String appendixListJson = trainingRegistrationReview.getAppendixListJson(); + if (StringUtils.isNotBlank(appendixListJson)) { + List appendixList = JSONObject.parseArray(appendixListJson, FileBasicInfo.class); + resVo.setAppendixList(appendixList); + } + } + + /** + * 只获取驾驶员基本信息 + * + * @param request + * @return ResArchivalInfoDetailVO + */ + public ResArchivalInfoDetailVO getDriverDetail(ReqGetArchivalInfoReviewDetailPO request) { + Long driverId = request.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + // 获取公司信息 + Long companyId = driverInfo.getCompanyId(); + CompanyDTO company = companiesCacheHelper.getById(companyId); + // 装配返回信息 + ResArchivalInfoDetailVO resVo = new ResArchivalInfoDetailVO(); + resVo.setDriverId(driverInfo.getId()); + resVo.setDriverName(driverInfo.getDriverName()); + resVo.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + if (StringUtils.isNotBlank(driverInfo.getDriverLicenseType())) { + resVo.setDriverLicenseType(DriverLicenseTypeEnum.valueOf(driverInfo.getDriverLicenseType())); + } + resVo.setDriverPhoneNo(driverInfo.getPhoneNo()); + resVo.setDriverAddress(driverInfo.getAddress()); + resVo.setIdCard(driverInfo.getIdCard()); + String avatarFile = driverInfo.getAvatarFile(); + if (StringUtils.isNotBlank(avatarFile)) { + resVo.setAvatarFile(JSONObject.parseObject(avatarFile, FileBasicInfo.class)); + } + resVo.setBirth(driverInfo.getBirth()); + resVo.setNativePlace(driverInfo.getNativePlace()); + resVo.setHealth(driverInfo.getHealth()); + resVo.setGender(driverInfo.getGender()); + resVo.setCompanyId(company.getId()); + resVo.setCompanyName(company.getName()); + resVo.setCompanyAddress(company.getAddress()); + resVo.setCompanyContactPhone(company.getContactPhone()); + resVo.setCompanyContactPerson(company.getContactPerson()); + return resVo; + } + + public AuditInfo assemblerAuditInfo(TrainingRegistrationReview trainingRegistrationReview) { + Long metaApplyId = trainingRegistrationReview.getMetaApplyId(); + String auditAppendixListJson = trainingRegistrationReview.getAuditAppendixListJson(); + MetaApply metaApply = validateGetMetaApplyBySerializableId(metaApplyId); + AuditInfo auditInfo = new AuditInfo(); + auditInfo.setAuditorId(metaApply.getApproverUserId()); + auditInfo.setAuditorName(metaApply.getApprover()); + auditInfo.setAuditTime(metaApply.getReviewTime()); + auditInfo.setReviewComments(metaApply.getAuditOpinion()); + if (StringUtils.isNotBlank(auditAppendixListJson)) { + auditInfo.setAppendixList(JSONObject.parseArray(auditAppendixListJson, FileBasicInfo.class)); + } + return auditInfo; + } + + public void driverInduction(ReqDriverInductionPO request) { + Long driverId = request.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + Long newCompanyId = request.getNewCompanyId(); + Company newCompany = companyService.getById(newCompanyId); + if ((Objects.isNull(newCompany))) { + throw new BizException("公司信息不存在"); + } + //驾驶员重新入职,将其关联到新的公司 + driverInfo.setCompanyId(newCompany.getId()); + driverInfo.setCompanyName(newCompany.getName()); + driverInfo.setRegionId(newCompany.getRegionId()); + driverInfo.setDriverStatus(DriverStatusEnum.induction.name()); + driverInfo.setInductionTime(LocalDateTime.now()); + driverInfo.setUpdateOn(LocalDateTime.now()); + iDriverInfoService.updateById(driverInfo); + } + + /** + * 装配驾驶员工作记录保存对象 + * + * @param driverInfo + * @return DriverWorkRecordInfo + */ + private DriverWorkRecordInfo assembleDriverWorkRecordInfo(DriverInfo driverInfo) { + DriverWorkRecordInfo driverWorkRecordInfo = new DriverWorkRecordInfo(); + driverWorkRecordInfo.setDriverId(driverInfo.getId()); + driverWorkRecordInfo.setDriverName(driverInfo.getDriverName()); + driverWorkRecordInfo.setAvatarFile(driverInfo.getAvatarFile()); + driverWorkRecordInfo.setGender(driverInfo.getGender()); + driverWorkRecordInfo.setIdCard(driverInfo.getIdCard()); + driverWorkRecordInfo.setBirth(driverInfo.getBirth()); + driverWorkRecordInfo.setNativePlace(driverInfo.getNativePlace()); + driverWorkRecordInfo.setNativePlaceRegionCode(driverInfo.getNativePlaceRegionCode()); + driverWorkRecordInfo.setPhoneNo(driverInfo.getPhoneNo()); + driverWorkRecordInfo.setHealth(driverInfo.getHealth()); + driverWorkRecordInfo.setAddress(driverInfo.getAddress()); + driverWorkRecordInfo.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + driverWorkRecordInfo.setDriverLicenseType(driverInfo.getDriverLicenseType()); + driverWorkRecordInfo.setCompanyId(driverInfo.getCompanyId()); + driverWorkRecordInfo.setCreateOn(LocalDateTime.now()); + driverWorkRecordInfo.setUpdateOn(LocalDateTime.now()); + driverWorkRecordInfo.setQuitTime(LocalDateTime.now()); + driverWorkRecordInfo.setReplacementRegistrationStatus(driverInfo.getReplacementRegistrationStatus()); + driverWorkRecordInfo.setContinuingEducationStatus(driverInfo.getContinuingEducationStatus()); + driverWorkRecordInfo.setMotorcycleTypeList(driverInfo.getMotorcycleTypeList()); + driverWorkRecordInfo.setDriverStatus(DriverStatusEnum.quit.name()); + driverWorkRecordInfo.setUserId(driverInfo.getUserId()); + driverWorkRecordInfo.setRegionId(driverInfo.getRegionId()); + driverWorkRecordInfo.setDriverRegistrationStatus(driverInfo.getDriverRegistrationStatus()); + driverWorkRecordInfo.setIllegalAndIllegalInfo(driverInfo.getIllegalAndIllegalInfo()); + driverWorkRecordInfo.setInitialLicenseTime(driverInfo.getInitialLicenseTime()); + CodeUtil.searchCompanyNameAndRegionName(driverWorkRecordInfo); + return driverWorkRecordInfo; + } + + public void driverQuit(Long driverId) { + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + // 驾驶员离职 更新驾驶员状态 + driverInfo.setDriverStatus(DriverStatusEnum.quit.name()); + driverInfo.setQuitTime(LocalDateTime.now()); + iDriverInfoService.updateById(driverInfo); + // 删除驾驶员关联的企业和区域信息 + LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(DriverInfo.class); + wrapper.set(DriverInfo::getCompanyId,null) + .set(DriverInfo::getCompanyName,null) + .set(DriverInfo::getRegionId,null) + .eq(DriverInfo::getId,driverInfo.getId()); + iDriverInfoService.update(wrapper); + //保存驾驶员工作记录 + DriverWorkRecordInfo driverWorkRecordInfo = assembleDriverWorkRecordInfo(driverInfo); + iDriverWorkRecordService.save(driverWorkRecordInfo); + } + + public void changedJob(ReqChangedJobPO request) { + Long driverId = request.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + Long newCompanyId = request.getNewCompanyId(); + if (newCompanyId.equals(driverInfo.getCompanyId())) { + throw new BizException("跳槽公司与当前公司相同,请重新选择!"); + } + Company newCompany = companyService.getById(newCompanyId); + if (Objects.isNull(newCompany)) { + throw new BizException("公司信息不存在"); + } + //保存跳槽前的工作记录 + DriverWorkRecordInfo driverWorkRecordInfo = assembleDriverWorkRecordInfo(driverInfo); + iDriverWorkRecordService.save(driverWorkRecordInfo); + //更新跳槽后的驾驶员档案信息 + driverInfo.setInductionTime(LocalDateTime.now()); + driverInfo.setCompanyId(newCompany.getId()); + driverInfo.setCompanyName(newCompany.getName()); + driverInfo.setRegionId(newCompany.getRegionId()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfo.setDriverStatus(DriverStatusEnum.induction.name()); + iDriverInfoService.updateById(driverInfo); + } + + @Transactional(rollbackFor = Exception.class) + public void driverTrainingRegistration(ReqDriverTrainingRegistrationPO request) { + // 获取培训报名类型 + TrainingRegistrationTypeEnum trainingRegistrationType = request.getTrainingRegistrationType(); + switch (trainingRegistrationType) { + // 取证报名 + case FORENSIC_REGISTRATION: { + forensicRegistration(request); + } + break; + // 申请跳槽 + case JOB_APPLICATION: { + jobApplication(request); + } + break; + // 继续教育 + case CONTINUING_EDUCATION: { + continuingEducation(request); + } + break; + // 换证报名 + case REPLACEMENT_REGISTRATION: { + replacementRegistration(request); + } + break; + default: + break; + } + } + + private void jobApplication(ReqDriverTrainingRegistrationPO request) { + + // 获取录入用户信息 + UserBasicInfoVO loginUser = userInfoHelper.getUserFullInfo(); + // 获取对应身份证驾驶员的用户ID + Long driverUserId = request.getDriverUserId(); + VUtils.isTrue(Objects.isNull(driverUserId)).throwMessage("该身份证号驾驶员用户不存在!"); + // 校验提交的身份证号是否正确 + // 查询驾驶员信息 + DriverInfo driverInfo = driverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class).eq(DriverInfo::getUserId, driverUserId)); + VUtils.isTrue(Objects.isNull(driverInfo)).throwMessage("该身份证号驾驶员信息不存在!"); + String idCard = request.getIdCard(); + VUtils.isTrue(!driverInfo.getIdCard().equals(idCard)).throwMessage("请填写正确的身份证号!"); + // 校验该驾驶员是否可以进行跳槽申请 + String driverRegistrationStatus = driverInfo.getDriverRegistrationStatus(); + if (!DriverRegistrationStatusEnum.available.name().equals(driverRegistrationStatus)) { + throw new BizException("请先通过驾驶员取证培训报名"); + } + Long companyId = driverInfo.getCompanyId(); + Company company = companyService.getById(companyId); + + Long driverId = request.getDriverId(); + if (Objects.nonNull(driverId)){ + // 如果 driverId不为空则为修改信息(重新提交),必须审核状态为初审/复审阶段(驳回状态)时才能修改 + DriverInfo driver = validateGetDriverInfoBySerializableId(driverId); + String jobChangeStatus = driver.getJobChangeStatus(); + boolean modifyAvailable = + DriverRegistrationStatusEnum.review_stage.name().equals(jobChangeStatus); + if (!modifyAvailable) { + // 只有驾驶员跳槽审核报名状态 为初审/复核阶段时 才能修改信息 + throw new BizException("当前状态不能重新提交跳槽申请!"); + } + // 根据驾驶员id获取审核表信息及审核id,重新提交并更新审核状态 + updateApprovalStatus(request, driverId); + }else { + // 提交审核申请 + MetaApply metaApply = new MetaApply(); + metaApply.setCreateOn(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setUserId(driverInfo.getUserId()); + metaApply.setApplyType(MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()); + metaApply.setApplyStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + metaApply.setApplyTime(LocalDateTime.now()); + metaApply.setApplicantId(loginUser.getUserId()); + metaApply.setApplicant(loginUser.getNickName()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + JSONObject extraMaterial = new JSONObject(); + extraMaterial.put("driverInfoId", driverInfo.getId()); + metaApply.setExtraMaterial(NdJsonUtil.toJson(extraMaterial)); + metaApply.setDisplayEnable(BooleanDisplayEnum.Y.name()); + metaApply.setApplicantType(ApplicantTypeEnum.JOB_CHANGE_APPLICANT.getCode()); + metaApply.setJobChangeCompanyId(loginUser.getCompanyId()); + + iMetaApplyService.save(metaApply); + + // 补充驾驶员报名审核表信息 + TrainingRegistrationReview trainingRegistrationReviewSaveRecord = new TrainingRegistrationReview(); + trainingRegistrationReviewSaveRecord.setMetaApplyId(metaApply.getId()); + trainingRegistrationReviewSaveRecord.setMetaApplyType(metaApply.getApplyType()); + trainingRegistrationReviewSaveRecord.setApprovalStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + + // 填意向跳槽企业 + trainingRegistrationReviewSaveRecord.setCompanyId(loginUser.getCompanyId()); + trainingRegistrationReviewSaveRecord.setCompanyName(loginUser.getCompanyName()); + trainingRegistrationReviewSaveRecord.setRegionId(loginUser.getRegionId()); + + trainingRegistrationReviewSaveRecord.setDriverUserId(driverInfo.getUserId()); + trainingRegistrationReviewSaveRecord.setDriverId(driverInfo.getId()); + trainingRegistrationReviewSaveRecord.setDriverIdCard(request.getIdCard()); + trainingRegistrationReviewSaveRecord.setDriverName(request.getDriverName()); + trainingRegistrationReviewSaveRecord.setDriverPhoneNo(request.getPhoneNo()); + trainingRegistrationReviewSaveRecord.setCreateBy(loginUser.getUserId()); + trainingRegistrationReviewSaveRecord.setCreateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setUpdateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord + .setRegistrationType(TrainingRegistrationTypeEnum.JOB_APPLICATION.name()); + List appendixList = request.getAppendixList(); + if (CollectionUtil.isNotEmpty(appendixList)) { + trainingRegistrationReviewSaveRecord.setAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord); + + // 更新驾驶员跳槽审核状态为审核阶段 + driverInfo.setJobChangeStatus(DriverJobChangeStatusEnum.review_stage.name()); + driverInfoService.updateById(driverInfo); + } + + } + + + /** + * 驾驶员培训报名-未处理列表筛选(新接口) + * + * @return PageVo + */ + public PageVo driverTrainingRegistrationUnDealList + (ReqDriverTrainingRegistrationListPO request) { + + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + + LambdaQueryWrapper wrapper + = Wrappers.lambdaQuery(TrainingRegistrationReview.class); + DriverArchivesManage context = (DriverArchivesManage) AopContext.currentProxy(); + context.buildDriverTrainingRegistrationUnDealQuery(wrapper, request); + Page page + = iTrainingRegistrationReviewService.page(new Page<>(pageNumber, pageSize), wrapper); + + // 培训审核列表查询 + PageVo pageVo = new PageVo<>(); + long total = page.getTotal(); + pageVo.setTotal(total); + if (total == 0) { + pageVo.setRecords(new ArrayList<>()); + return pageVo; + } + List records = page.getRecords(); + List returnVoList = records.stream().map(r -> { + ResDriverTrainingRegistrationListVO resVo = new ResDriverTrainingRegistrationListVO(); + resVo.setTrainingRegistrationReviewId(r.getId()); + resVo.setCompanyId(r.getCompanyId()); + resVo.setCompanyName(r.getCompanyName()); + // 装配所属区域 + Long companyRegionId = r.getRegionId(); + if (Objects.nonNull(companyRegionId)) { + String displayRegionName = regionsCacheHelper.getDisplayName(companyRegionId); + resVo.setRegionId(companyRegionId); + resVo.setRegionName(displayRegionName); + } + resVo.setDriverName(r.getDriverName()); + resVo.setDriverId(r.getDriverId()); + resVo.setMetaApplyId(r.getMetaApplyId()); + if (StringUtils.isNotBlank(r.getApprovalStatus())) { + resVo.setMetaApplyStatus(MetaApplyStatusEnum.valueOf(r.getApprovalStatus()).name()); + } + // 对驾驶员手机号和身份证号做脱敏处理 + String phoneNo = r.getDriverPhoneNo(); + String idCard = r.getDriverIdCard(); + String encryptPhone = DesensitizedUtil.mobilePhone(phoneNo); + String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END); + resVo.setPhoneNo(encryptPhone); + resVo.setIdCard(encryptIdCard); + resVo.setCreateTime(r.getCreateOn()); + resVo.setTrainingRegistrationType(TrainingRegistrationTypeEnum.valueOf(r.getRegistrationType())); + return resVo; + }).collect(Collectors.toList()); + pageVo.setRecords(returnVoList); + return pageVo; + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildDriverTrainingRegistrationUnDealQuery(LambdaQueryWrapper wrapper, ReqDriverTrainingRegistrationListPO request) { + String companyName = request.getCompanyName(); + String driverName = request.getDriverName(); + MetaApplyTypeEnum metaApplyType = request.getMetaApplyType(); + TrainingRegistrationTypeEnum trainingRegistrationType = request.getTrainingRegistrationType(); + List metaApplyStatusList = request.getMetaApplyStatusList(); + String metaApplyTypeStr = Objects.nonNull(metaApplyType) ? metaApplyType.name() : null; + String trainingRegistrationTypeStr = Objects.nonNull(trainingRegistrationType) ? trainingRegistrationType.name() : null; + wrapper.like(StringUtils.isNotBlank(companyName), TrainingRegistrationReview::getCompanyName, companyName) + .like(StringUtils.isNotBlank(driverName), TrainingRegistrationReview::getDriverName, driverName) + .eq(StringUtils.isNotBlank(metaApplyTypeStr), TrainingRegistrationReview::getMetaApplyType, metaApplyTypeStr) + .eq(StringUtils.isNotBlank(trainingRegistrationTypeStr), TrainingRegistrationReview::getRegistrationType, trainingRegistrationTypeStr) + .in(CollectionUtil.isNotEmpty(metaApplyStatusList), TrainingRegistrationReview::getApprovalStatus, metaApplyStatusList) + .orderByDesc(TrainingRegistrationReview::getUpdateOn); + } + + /** + * 获取唯一的登陆username + * + * @param driverName + * @return + */ + private String generateNotDuplicateLoginIdentifier(String driverName) { + String pinYinUserName = PinyinUtils.toPinyin(driverName); + int count = 1; + String returnUserName = pinYinUserName; + while (true) { + List ndUserAuthList = iNdUserAuthService.list(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getIdentifier, returnUserName) + .eq(NdUserAuth::getAuthType, AuthTypeEnum.ACCOUNT_PASSWORD.name())); + + if (CollectionUtils.isEmpty(ndUserAuthList)) { + return returnUserName; + } else { + returnUserName = pinYinUserName + count++; + } + } + } + + /** + * 生产密码 + * + * @param phoneNo + * @param driverName + * @return + */ + private String generateCredential(String phoneNo, String driverName) { + String driverNamePinYin = PinyinUtils.toPinyin(driverName); + String password = driverNamePinYin + phoneNo.substring(phoneNo.length() - 4); + LOG.error("-------password : " + password); + return passwordEncoder.encode(password); + } + + private void continuingEducation(ReqDriverTrainingRegistrationPO request) { + // 获取当前登陆账户id + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + // 校验驾驶员当前是否有继续教育审核的资格 + // 查询驾驶员信息 + String idCard = request.getIdCard(); + DriverInfo driverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getIdCard, idCard)); + if (Objects.isNull(driverInfo)) { + throw new BizException("该驾驶员信息不存在"); + } + // 校验驾驶员当前是否有继续教育的权限,只有取证报名完成状态下才能继续另外两种培训报名 + registrationAvailableCheckHelper.continuingEducationRegistrationValidCheck(request, driverInfo); + + Long driverId = request.getDriverId(); + if (Objects.nonNull(driverId)) { + // 如果 driverId不为空则为修改信息(重新提交),必须审核状态为初审/复审阶段(驳回状态)时才能修改 + DriverInfo driver = validateGetDriverInfoBySerializableId(driverId); + String continuingEducationStatus = driver.getContinuingEducationStatus(); + boolean modifyAvailable = + DriverRegistrationStatusEnum.review_stage.name().equals(continuingEducationStatus); + if (!modifyAvailable) { + // 只有驾驶员取证报名状态 为初审/复核阶段时 才能修改信息 + throw new BizException("当前状态不能修改驾驶员信息"); + } + // 根据驾驶员id获取审核表信息及审核id,重新提交并更新审核状态 + updateApprovalStatus(request, driverId); + // 校验 获取公司信息是否存在 获取当前登陆用户信息公司 + Long companyId = userInfoHelper.getUserCompanyId(); + DriverInfo newDriverInfo = assemblerSaveRecord(request); + // 重新提交后,获取系统用户ID,装配驾驶员信息,更新驾驶员信息 + newDriverInfo.setContinuingEducationStatus(continuingEducationStatus); + Long userId = iDriverInfoService.selectUserIdById(driverId); + newDriverInfo.setUserId(userId); + newDriverInfo.setId(driverInfo.getId()); + iDriverInfoService.updateById(newDriverInfo); + } else { + Company company = companyService.getById(driverInfo.getCompanyId()); + // 提交审核申请 + MetaApply metaApply = new MetaApply(); + metaApply.setCreateOn(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setUserId(driverInfo.getUserId()); + metaApply.setApplyType(MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()); + metaApply.setApplyStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + metaApply.setApplyTime(LocalDateTime.now()); + metaApply.setApplicantId(loginUser.getUserId()); + metaApply.setApplicant(loginUser.getNickName()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + JSONObject extraMaterial = new JSONObject(); + extraMaterial.put("driverInfoId", driverInfo.getId()); + metaApply.setExtraMaterial(NdJsonUtil.toJson(extraMaterial)); + metaApply.setDisplayEnable(BooleanDisplayEnum.Y.name()); + metaApply.setApplicantType(ApplicantTypeEnum.MATERIAL_APPLICANT.getCode()); + iMetaApplyService.save(metaApply); + + // 补充驾驶员报名审核表信息 + TrainingRegistrationReview trainingRegistrationReviewSaveRecord = new TrainingRegistrationReview(); + trainingRegistrationReviewSaveRecord.setMetaApplyId(metaApply.getId()); + trainingRegistrationReviewSaveRecord.setMetaApplyType(metaApply.getApplyType()); + trainingRegistrationReviewSaveRecord.setApprovalStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + trainingRegistrationReviewSaveRecord.setCompanyId(company.getId()); + trainingRegistrationReviewSaveRecord.setCompanyName(company.getName()); + trainingRegistrationReviewSaveRecord.setRegionId(company.getRegionId()); + trainingRegistrationReviewSaveRecord.setDriverUserId(driverInfo.getUserId()); + trainingRegistrationReviewSaveRecord.setDriverId(driverInfo.getId()); + trainingRegistrationReviewSaveRecord.setDriverIdCard(request.getIdCard()); + trainingRegistrationReviewSaveRecord.setDriverName(request.getDriverName()); + trainingRegistrationReviewSaveRecord.setDriverPhoneNo(request.getPhoneNo()); + trainingRegistrationReviewSaveRecord.setCreateBy(loginUser.getUserId()); + trainingRegistrationReviewSaveRecord.setCreateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setUpdateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord + .setRegistrationType(TrainingRegistrationTypeEnum.CONTINUING_EDUCATION.name()); + List appendixList = request.getAppendixList(); + if (CollectionUtil.isNotEmpty(appendixList)) { + trainingRegistrationReviewSaveRecord.setAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord); + + // 更新驾驶员状态 + driverInfo.setContinuingEducationStatus(DriverContinuingEducationRegistrationStatusEnum.review_stage.name()); + iDriverInfoService.updateById(driverInfo); + } + } + + private void replacementRegistration(ReqDriverTrainingRegistrationPO request) { + // 获取当前登陆账户id + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + + // 查询驾驶员信息 + String idCard = request.getIdCard(); + DriverInfo driverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getIdCard, idCard)); + if (Objects.isNull(driverInfo)) { + throw new BizException("该驾驶员信息不存在"); + } + // 校验驾驶员是否能参加换证报名培训 + registrationAvailableCheckHelper.replacementRegistrationValidCheck(request, driverInfo); + Long driverId = request.getDriverId(); + if (Objects.nonNull(driverId)) { + // 如果 driverId不为空则为修改信息(重新提交),必须审核状态为初审/复审阶段(驳回状态)时才能修改 + DriverInfo driver = validateGetDriverInfoBySerializableId(driverId); + String replacementRegistrationStatus = driver.getReplacementRegistrationStatus(); + boolean modifyAvailable = DriverRegistrationStatusEnum.review_stage.name().equals(replacementRegistrationStatus); + if (!modifyAvailable) { + // 只有驾驶员换证报名状态 为初审/复核阶段时 才能修改信息 + throw new BizException("当前状态不能修改驾驶员信息"); + } + //根据驾驶员id获取审核表信息及审核id,重新提交并更新审核状态 + updateApprovalStatus(request, driverId); + // 校验 获取公司信息是否存在 获取当前登陆用户信息公司 + Long companyId = userInfoHelper.getUserCompanyId(); + DriverInfo newDriverInfo = assemblerSaveRecord(request); + // 重新提交后,获取系统用户ID,装配驾驶员信息,更新驾驶员信息 + newDriverInfo.setReplacementRegistrationStatus(replacementRegistrationStatus); + Long userId = iDriverInfoService.selectUserIdById(driverId); + newDriverInfo.setUserId(userId); + newDriverInfo.setId(driverInfo.getId()); + iDriverInfoService.updateById(newDriverInfo); + } else { + // 装配审核信息 + Company company = companyService.getById(driverInfo.getCompanyId()); + + // 提交审核申请 + MetaApply metaApply = new MetaApply(); + metaApply.setCreateOn(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setUserId(driverInfo.getUserId()); + metaApply.setApplyType(MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()); + metaApply.setApplyStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + metaApply.setApplyTime(LocalDateTime.now()); + metaApply.setApplicantId(loginUser.getUserId()); + metaApply.setApplicant(loginUser.getNickName()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + JSONObject extraMaterial = new JSONObject(); + extraMaterial.put("driverInfoId", driverInfo.getId()); + metaApply.setExtraMaterial(NdJsonUtil.toJson(extraMaterial)); + metaApply.setDisplayEnable(BooleanDisplayEnum.Y.name()); + metaApply.setApplicantType(ApplicantTypeEnum.MATERIAL_APPLICANT.getCode()); + iMetaApplyService.save(metaApply); + + // 补充驾驶员报名审核表信息 + TrainingRegistrationReview trainingRegistrationReviewSaveRecord = new TrainingRegistrationReview(); + trainingRegistrationReviewSaveRecord.setMetaApplyId(metaApply.getId()); + trainingRegistrationReviewSaveRecord.setMetaApplyType(metaApply.getApplyType()); + trainingRegistrationReviewSaveRecord.setApprovalStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + trainingRegistrationReviewSaveRecord.setCompanyId(company.getId()); + trainingRegistrationReviewSaveRecord.setCompanyName(company.getName()); + trainingRegistrationReviewSaveRecord.setRegionId(company.getRegionId()); + trainingRegistrationReviewSaveRecord.setDriverUserId(driverInfo.getUserId()); + trainingRegistrationReviewSaveRecord.setDriverId(driverInfo.getId()); + trainingRegistrationReviewSaveRecord.setDriverIdCard(request.getIdCard()); + trainingRegistrationReviewSaveRecord.setDriverName(request.getDriverName()); + trainingRegistrationReviewSaveRecord.setDriverPhoneNo(request.getPhoneNo()); + trainingRegistrationReviewSaveRecord.setCreateBy(loginUser.getUserId()); + trainingRegistrationReviewSaveRecord.setCreateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setUpdateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setRegistrationType(TrainingRegistrationTypeEnum.REPLACEMENT_REGISTRATION.name()); + List appendixList = request.getAppendixList(); + if (CollectionUtil.isNotEmpty(appendixList)) { + trainingRegistrationReviewSaveRecord.setAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord); + + // 更新驾驶员状态 + driverInfo.setReplacementRegistrationStatus(DriverReplacementRegistrationStatusEnum.review_stage.name()); + iDriverInfoService.updateById(driverInfo); + } + } + + /** + * 驾驶员培训报名(取证培训报名) + * + * @return + */ + private void forensicRegistration(ReqDriverTrainingRegistrationPO request) { + // 获取录入用户信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + + Long driverId = request.getDriverId(); + if (Objects.nonNull(driverId)) { + // 如果 driverId不为空则为修改信息(重新提交),必须审核状态为初审/复审阶段(驳回状态)时才能修改 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + String driverRegistrationStatus = driverInfo.getDriverRegistrationStatus(); + boolean modifyAvailable = DriverRegistrationStatusEnum.review_stage.name().equals(driverRegistrationStatus); + if (!modifyAvailable) { + // 只有驾驶员取证报名状态 为初审/复核阶段时 才能修改信息 + throw new BizException("当前状态不能修改驾驶员信息"); + } + //根据驾驶员id获取审核表信息及审核id,重新提交并更新审核状态 + updateApprovalStatus(request, driverId); + // 校验 获取公司信息是否存在 获取当前登陆用户信息公司 + Long companyId = userInfoHelper.getUserCompanyId(); + DriverInfo newDriverInfo = assemblerSaveRecord(request); + // 重新提交后,获取系统用户ID,装配驾驶员信息,更新驾驶员信息 + newDriverInfo.setDriverRegistrationStatus(driverRegistrationStatus); + Long userId = iDriverInfoService.selectUserIdById(driverId); + newDriverInfo.setUserId(userId); + newDriverInfo.setId(driverInfo.getId()); + iDriverInfoService.updateById(newDriverInfo); + } else { + // 创建驾驶员信息 + // 校验驾驶员 手机号/身份证号是否可用 + String idCard = request.getIdCard(); + String phoneNo = request.getPhoneNo(); + validateDriverInfoIdCardAvailable(null, idCard); + validateDriverInfoPhoneNoAvailable(null, phoneNo); + // 校验 获取公司信息是否存在 + Long companyId = userInfoHelper.getUserCompanyId(); + CompanyDTO company = companiesCacheHelper.getById(companyId); + + // 创建唯一标识用户不可登陆用户账号 并获取用户id + Long driverUserId = createUniqAccountAndGetUserId(request, loginUser.getUserId()); + + // 装配驾驶员信息 保存驾驶员信息 + DriverInfo saveDriverInfoRecord = assemblerSaveRecord(request); + saveDriverInfoRecord.setCreateOn(LocalDateTime.now()); + saveDriverInfoRecord.setUserId(driverUserId); + saveDriverInfoRecord.setDriverRegistrationStatus(DriverRegistrationStatusEnum.review_stage.name()); + iDriverInfoService.save(saveDriverInfoRecord); + + driverId = saveDriverInfoRecord.getId(); + + // 提交审核申请 + MetaApply metaApply = new MetaApply(); + metaApply.setCreateOn(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setUserId(driverUserId); + metaApply.setApplyType(MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()); + metaApply.setApplyStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + metaApply.setApplyTime(LocalDateTime.now()); + metaApply.setApplicantId(loginUser.getUserId()); + metaApply.setApplicant(loginUser.getNickName()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + JSONObject extraMaterial = new JSONObject(); + extraMaterial.put("driverInfoId", driverId); + metaApply.setExtraMaterial(NdJsonUtil.toJson(extraMaterial)); + metaApply.setDisplayEnable(BooleanDisplayEnum.Y.name()); + metaApply.setApplicantType(ApplicantTypeEnum.MATERIAL_APPLICANT.getCode()); + iMetaApplyService.save(metaApply); + + // 补充驾驶员报名审核表信息 + TrainingRegistrationReview trainingRegistrationReviewSaveRecord = new TrainingRegistrationReview(); + trainingRegistrationReviewSaveRecord.setMetaApplyId(metaApply.getId()); + trainingRegistrationReviewSaveRecord.setMetaApplyType(metaApply.getApplyType()); + trainingRegistrationReviewSaveRecord.setApprovalStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + trainingRegistrationReviewSaveRecord.setCompanyId(companyId); + trainingRegistrationReviewSaveRecord.setCompanyName(company.getName()); + trainingRegistrationReviewSaveRecord.setRegionId(company.getRegionId()); + trainingRegistrationReviewSaveRecord.setDriverUserId(driverUserId); + trainingRegistrationReviewSaveRecord.setDriverId(driverId); + trainingRegistrationReviewSaveRecord.setDriverIdCard(request.getIdCard()); + trainingRegistrationReviewSaveRecord.setDriverName(request.getDriverName()); + trainingRegistrationReviewSaveRecord.setDriverPhoneNo(request.getPhoneNo()); + trainingRegistrationReviewSaveRecord.setCreateBy(loginUser.getUserId()); + trainingRegistrationReviewSaveRecord.setCreateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setUpdateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setRegistrationType(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name()); + List appendixList = request.getAppendixList(); + if (CollectionUtil.isNotEmpty(appendixList)) { + trainingRegistrationReviewSaveRecord.setAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord); + } + + } + + private void updateApprovalStatus(ReqDriverTrainingRegistrationPO request, Long driverId) { + TrainingRegistrationReview firstTrailReview = iTrainingRegistrationReviewService.getOne(Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getDriverId, driverId) + .eq(TrainingRegistrationReview::getId, request.getTrainingRegistrationReviewId()) + .eq(TrainingRegistrationReview::getApprovalStatus, MetaApplyStatusEnum.FIRST_TRIAL_APPROVAL_REJECTION.name())); + + TrainingRegistrationReview reexaminationReview = iTrainingRegistrationReviewService.getOne(Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getDriverId, driverId) + .eq(TrainingRegistrationReview::getId, request.getTrainingRegistrationReviewId()) + .eq(TrainingRegistrationReview::getApprovalStatus, MetaApplyStatusEnum.REEXAMINATION_APPROVAL_REJECTION.name())); + if (Objects.nonNull(firstTrailReview)) { + Long firstTrailMetaApplyId = firstTrailReview.getMetaApplyId(); + //根据审核id获取审核状态 + MetaApply firstTrailMetaApply = iMetaApplyService.getOne(Wrappers.lambdaQuery(MetaApply.class) + .eq(MetaApply::getId, firstTrailMetaApplyId)); + //更新培训审核表信息,及审核意见表信息 + if (Objects.nonNull(firstTrailMetaApply) && + MetaApplyStatusEnum.FIRST_TRIAL_APPROVAL_REJECTION.name().equals(firstTrailMetaApply.getApplyStatus())) { + firstTrailMetaApply.setApplyStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + firstTrailReview.setDriverIdCard(request.getIdCard()); + firstTrailReview.setDriverId(request.getDriverId()); + firstTrailReview.setDriverName(request.getDriverName()); + firstTrailReview.setDriverPhoneNo(request.getPhoneNo()); + firstTrailReview.setRegistrationType(request.getTrainingRegistrationType().name()); + firstTrailReview.setApprovalStatus(MetaApplyStatusEnum.FIRST_TRIAL_UNDER_REVIEW.name()); + firstTrailReview.setCreateOn(LocalDateTime.now()); + firstTrailReview.setUpdateOn(LocalDateTime.now()); + List appendixList = request.getAppendixList(); + if (CollectionUtil.isNotEmpty(appendixList)) { + firstTrailReview.setAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.updateById(firstTrailReview); + iMetaApplyService.updateById(firstTrailMetaApply); + } + } + if (Objects.nonNull(reexaminationReview)) { + Long reexaminationMetaApplyId = reexaminationReview.getMetaApplyId(); + MetaApply reexaminationMetaApply = iMetaApplyService.getOne(Wrappers.lambdaQuery(MetaApply.class) + .eq(MetaApply::getId, reexaminationMetaApplyId)); + if (Objects.nonNull(reexaminationMetaApply) && + MetaApplyStatusEnum.REEXAMINATION_APPROVAL_REJECTION.name().equals(reexaminationMetaApply.getApplyStatus())) { + reexaminationMetaApply.setApplyStatus(MetaApplyStatusEnum.REEXAMINATION_UNDER_REVIEW.name()); + reexaminationReview.setDriverIdCard(request.getIdCard()); + reexaminationReview.setDriverId(request.getDriverId()); + reexaminationReview.setDriverName(request.getDriverName()); + reexaminationReview.setDriverPhoneNo(request.getPhoneNo()); + reexaminationReview.setRegistrationType(request.getTrainingRegistrationType().name()); + reexaminationReview.setApprovalStatus(MetaApplyStatusEnum.REEXAMINATION_UNDER_REVIEW.name()); + reexaminationReview.setCreateOn(LocalDateTime.now()); + reexaminationReview.setUpdateOn(LocalDateTime.now()); + List appendixList = request.getAppendixList(); + if (CollectionUtil.isNotEmpty(appendixList)) { + reexaminationReview.setAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.updateById(reexaminationReview); + iMetaApplyService.updateById(reexaminationMetaApply); + } + } + } + + /** + * 校验驾驶员身份证信息是否可用 + */ + private void validateDriverInfoIdCardAvailable(Long driverId, String idCard) { + DriverInfo currentIdCardDriverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getIdCard, idCard) + .ne(Objects.nonNull(driverId), DriverInfo::getId, driverId)); + if (Objects.nonNull(currentIdCardDriverInfo)) { + throw new BizException("该驾驶员身份信息已录入"); + } + } + + /** + * 校验驾驶员手机号信息是否可用 + */ + private void validateDriverInfoPhoneNoAvailable(Long driverId, String phoneNo) { + DriverInfo currentPhoneNoDriverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getPhoneNo, phoneNo) + .ne(Objects.nonNull(driverId), DriverInfo::getId, driverId)); + if (Objects.nonNull(currentPhoneNoDriverInfo)) { + throw new BizException("该驾驶员手机号信息已录入"); + } + } + + /** + * 根据公司id 校验获取公司信息 + * + * @param companyId + * @return + */ + private Company validateGetCompanyBySerializableId(Long companyId) { + Company company = companyService.getById(companyId); + if (Objects.isNull(company)) { + throw new BizException("公司信息不存在"); + } + return company; + } + + /** + * 根据驾驶员id 校验获取驾驶员信息 + * + * @return + */ + private DriverInfo validateGetDriverInfoBySerializableId(Long driverId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverInfo.class); + DriverArchivesManage context = (DriverArchivesManage) AopContext.currentProxy(); + context.buildQuery(wrapper, driverId); + DriverInfo driverInfo = iDriverInfoService.getOne(wrapper); + //DriverInfo driverInfo = iDriverInfoService.getById(driverId); + if (Objects.isNull(driverInfo)) { + throw new BizException("该驾驶员信息不存在"); + } + return driverInfo; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long driverId) { + wrapper.eq(DriverInfo::getId,driverId); + } + + /** + * 根据驾驶员id 校验获取审核信息 + * + * @return + */ + private MetaApply validateGetMetaApplyBySerializableId(Long metaApplyId) { + MetaApply metaApply = iMetaApplyService.getById(metaApplyId); + if (Objects.isNull(metaApply)) { + throw new BizException("该审核信息不存在"); + } + return metaApply; + } + + /** + * 根据驾驶员id 校验获取审核信息 + * + * @return iTrainingRegistrationReviewService + */ + private TrainingRegistrationReview validateGetTrainingRegistrationReviewByMetaApplyId(Long metaApplyId) { + TrainingRegistrationReview trainingRegistrationReview = iTrainingRegistrationReviewService + .getOne(Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getMetaApplyId, metaApplyId)); + if (Objects.isNull(trainingRegistrationReview)) { + throw new BizException("该培训报名审核信息不存在"); + } + return trainingRegistrationReview; + } + + + /** + * 创建唯一标识用户不可登陆用户账号 并获取用户id + * + * @return + */ + private Long createUniqAccountAndGetUserId(ReqDriverTrainingRegistrationPO request, Long createByUserId) { + NdUserInfo driver = new NdUserInfo(); + driver.setCompanyId(userInfoHelper.getUserCompanyId()); + + String phoneNo = request.getPhoneNo(); + NdUserInfo ndUserInfo = iNdUserInfoService.getOne(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getMobile, phoneNo)); + if (Objects.nonNull(ndUserInfo)) { + log.error("该手机号已有对应驾驶员{}", ndUserInfo.getUsername()); + throw new BizException("该手机号已有对应驾驶员,请更换手机号重新输入!"); + } + driver.setMobile(request.getPhoneNo()); + driver.setNickName(request.getDriverName()); + driver.setUsername(request.getDriverName()); + driver.setCreateOn(LocalDateTime.now()); + driver.setUpdateOn(driver.getCreateOn()); + driver.setCreateBy(createByUserId); + driver.setCanLogin(UserCanLoginEnum.CAN_NOT_LOGIN.getCode()); + iNdUserInfoService.save(driver); + return driver.getId(); + } + + + /** + * 装配驾驶员信息saveRecord + * + * @param request + * @return + */ + private DriverInfo assemblerSaveRecord(ReqDriverTrainingRegistrationPO request) { + DriverInfo saveRecord = new DriverInfo(); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverName(request.getDriverName()); + saveRecord.setGender(request.getGender()); + saveRecord.setIdCard(request.getIdCard()); + saveRecord.setBirth(request.getBirth()); + saveRecord.setNativePlace(request.getNativePlace()); + saveRecord.setPhoneNo(request.getPhoneNo()); + saveRecord.setHealth(request.getHealth()); + saveRecord.setAddress(request.getAddress()); + saveRecord.setDriverLicenseNo(request.getDriverLicenseNo()); + saveRecord.setDriverLicenseType(request.getDriverLicenseType().name()); + saveRecord.setCompanyId(userInfoHelper.getUserCompanyId()); + CompanyDTO company = companiesCacheHelper.getById(userInfoHelper.getUserCompanyId()); + saveRecord.setCompanyName(userInfoHelper.getUserCompanyName()); + if (Objects.nonNull(company)) { + saveRecord.setRegionId(company.getRegionId()); + } + saveRecord.setNativePlaceRegionCode(request.getNativePlaceRegionCode()); + saveRecord.setInitialLicenseTime(request.getInitialLicenseTime()); + if (CollectionUtil.isNotEmpty(request.getMotorcycleTypeList())) { + saveRecord.setMotorcycleTypeList(JSONObject.toJSONString(request.getMotorcycleTypeList())); + } + FileBasicInfo avatarFile = request.getAvatarFile(); + if (Objects.nonNull(avatarFile)) { + saveRecord.setAvatarFile(JSONObject.toJSONString(avatarFile)); + } + saveRecord.setIllegalAndIllegalInfo(request.getIllegalAndIllegalInfo()); + CodeUtil.searchCompanyName(saveRecord); + return saveRecord; + } + + + @Transactional(rollbackFor = Exception.class) + public void driverTrainingPreliminaryTrial(ReqDriverTrainingPreliminaryTrialPO request) { + // 获取当前账号信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + // 获取入参信息 + Long driverId = request.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + Long metaApplyId = request.getMetaApplyId(); + List appendixList = request.getAppendixList(); + Boolean result = request.getResult(); + // 获取审核表信息 培训审核表信息 + TrainingRegistrationReview trainingRegistrationReview = iTrainingRegistrationReviewService.getOne(Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getMetaApplyId, metaApplyId)); + VUtils.isTrue(Objects.isNull(trainingRegistrationReview)).throwMessage("审核信息不存在!"); + MetaApply metaApply = iMetaApplyService.getOne(Wrappers.lambdaQuery(MetaApply.class) + .eq(MetaApply::getId, metaApplyId)); + VUtils.isTrue(Objects.isNull(metaApply)).throwMessage("审核记录不存在!"); + String applyStatus; + if (result) { + applyStatus = MetaApplyStatusEnum.FIRST_TRIAL_APPROVED.name(); + } else { + applyStatus = MetaApplyStatusEnum.FIRST_TRIAL_APPROVAL_REJECTION.name(); + } + // 初审核结果处理 + metaApply.setApplyStatus(applyStatus); + metaApply.setApproverUserId(loginUser.getUserId()); + metaApply.setApprover(loginUser.getNickName()); + metaApply.setAuditOpinion(request.getOpinion()); + metaApply.setReviewTime(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + iMetaApplyService.saveOrUpdate(metaApply); + + // 更新 培训审核表信息 + trainingRegistrationReview.setApprovalStatus(applyStatus); + if (CollectionUtil.isNotEmpty(appendixList)) { + trainingRegistrationReview.setAuditAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.saveOrUpdate(trainingRegistrationReview); + + // 根据初审结果创建 复核审核 + if (result) { + // 创建复审信息 + MetaApply inReviewMetaApply = new MetaApply(); + inReviewMetaApply.setCreateOn(LocalDateTime.now()); + inReviewMetaApply.setUpdateOn(LocalDateTime.now()); + inReviewMetaApply.setUserId(driverInfo.getUserId()); + inReviewMetaApply.setApplyType(MetaApplyTypeEnum.IN_REVIEW.name()); + inReviewMetaApply.setApplyStatus(MetaApplyStatusEnum.REEXAMINATION_UNDER_REVIEW.name()); + inReviewMetaApply.setApplyTime(LocalDateTime.now()); + inReviewMetaApply.setApplicantId(loginUser.getUserId()); + inReviewMetaApply.setApplicant(loginUser.getNickName()); + inReviewMetaApply.setRegionId(loginUser.getRegionId()); + inReviewMetaApply.setCompanyId(loginUser.getCompanyId()); + JSONObject inReviewExtraMaterial = new JSONObject(); + inReviewExtraMaterial.put("driverInfoId", driverId); + inReviewMetaApply.setExtraMaterial(NdJsonUtil.toJson(inReviewExtraMaterial)); + inReviewMetaApply.setDisplayEnable(BooleanDisplayEnum.Y.name()); + if (ApplicantTypeEnum.MATERIAL_APPLICANT.getCode().equals(metaApply.getApplicantType())) { + inReviewMetaApply.setApplicantType(ApplicantTypeEnum.MATERIAL_APPLICANT.getCode()); + }else if (ApplicantTypeEnum.JOB_CHANGE_APPLICANT.getCode().equals(metaApply.getApplicantType())){ + inReviewMetaApply.setApplicantType(ApplicantTypeEnum.JOB_CHANGE_APPLICANT.getCode()); + inReviewMetaApply.setJobChangeCompanyId(metaApply.getJobChangeCompanyId()); + } + + iMetaApplyService.save(inReviewMetaApply); + + // 创建复审 + // 补充驾驶员报名审核表信息 + + Long jobChangeCompanyId = metaApply.getJobChangeCompanyId(); + String jobChangeCompanyName = null; + Long jobChangeCompanyRegionId = null; + if (Objects.nonNull(jobChangeCompanyId)) { + CompanyDTO jobChangeCompany = companiesCacheHelper.getById(jobChangeCompanyId); + jobChangeCompanyName = jobChangeCompany.getName(); + jobChangeCompanyRegionId = jobChangeCompany.getRegionId(); + } + Integer applicantType = metaApply.getApplicantType(); + + Long companyId = driverInfo.getCompanyId(); + CompanyDTO company = companiesCacheHelper.getById(companyId); + + TrainingRegistrationReview trainingRegistrationReviewSaveRecord = new TrainingRegistrationReview(); + trainingRegistrationReviewSaveRecord.setMetaApplyId(inReviewMetaApply.getId()); + trainingRegistrationReviewSaveRecord.setPreliminaryReviewAssociatedId(trainingRegistrationReview.getId()); + trainingRegistrationReviewSaveRecord.setMetaApplyType(MetaApplyTypeEnum.IN_REVIEW.name()); + trainingRegistrationReviewSaveRecord.setApprovalStatus(MetaApplyStatusEnum.REEXAMINATION_UNDER_REVIEW.name()); + + // 如果是正常的驾驶员材料审核,培训审核表企业填写驾驶员所属企业 + if (ApplicantTypeEnum.MATERIAL_APPLICANT.getCode().equals(applicantType)) { + trainingRegistrationReviewSaveRecord.setCompanyId(companyId); + trainingRegistrationReviewSaveRecord.setCompanyName(company.getName()); + trainingRegistrationReviewSaveRecord.setRegionId(company.getRegionId()); + } + // 如果是跳槽审核申请,培训审核表企业填写驾驶员意向跳槽企业 + else if (ApplicantTypeEnum.JOB_CHANGE_APPLICANT.getCode().equals(applicantType)) { + trainingRegistrationReviewSaveRecord.setCompanyId(jobChangeCompanyId); + trainingRegistrationReviewSaveRecord.setCompanyName(jobChangeCompanyName); + trainingRegistrationReviewSaveRecord.setRegionId(jobChangeCompanyRegionId); + } + + trainingRegistrationReviewSaveRecord.setDriverUserId(driverInfo.getUserId()); + trainingRegistrationReviewSaveRecord.setDriverId(driverId); + trainingRegistrationReviewSaveRecord.setDriverIdCard(driverInfo.getIdCard()); + trainingRegistrationReviewSaveRecord.setDriverName(driverInfo.getDriverName()); + trainingRegistrationReviewSaveRecord.setDriverPhoneNo(driverInfo.getPhoneNo()); + trainingRegistrationReviewSaveRecord.setCreateBy(loginUser.getUserId()); + trainingRegistrationReviewSaveRecord.setCreateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setUpdateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord.setRegistrationType(request.getTrainingRegistrationType().name()); + trainingRegistrationReviewSaveRecord.setAppendixListJson(trainingRegistrationReview.getAppendixListJson()); + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord); + } + } + + public void driverTrainingInReview(ReqDriverInReviewingPO request) { + // 获取当前账号信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + + // 获取入参信息 + Long driverId = request.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + Long metaApplyId = request.getMetaApplyId(); + List appendixList = request.getAppendixList(); + Boolean result = request.getResult(); + + // 获取审核表信息 培训审核表信息 + TrainingRegistrationReview trainingRegistrationReview = iTrainingRegistrationReviewService.getOne(Wrappers.lambdaQuery(TrainingRegistrationReview.class) + .eq(TrainingRegistrationReview::getMetaApplyId, metaApplyId)); + VUtils.isTrue(Objects.isNull(trainingRegistrationReview)).throwMessage("审核信息不存在!"); + MetaApply metaApply = iMetaApplyService.getOne(Wrappers.lambdaQuery(MetaApply.class) + .eq(MetaApply::getId, metaApplyId)); + VUtils.isTrue(Objects.isNull(metaApply)).throwMessage("审核记录不存在!"); + String applyStatus; + if (result) { + applyStatus = MetaApplyStatusEnum.REEXAMINATION_APPROVED.name(); + } else { + applyStatus = MetaApplyStatusEnum.REEXAMINATION_APPROVAL_REJECTION.name(); + } + + // 初复核结果处理 + metaApply.setApplyStatus(applyStatus); + metaApply.setApproverUserId(loginUser.getUserId()); + metaApply.setApprover(loginUser.getNickName()); + metaApply.setAuditOpinion(request.getOpinion()); + metaApply.setReviewTime(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + iMetaApplyService.saveOrUpdate(metaApply); + + // 更新 培训审核表信息 + trainingRegistrationReview.setApprovalStatus(applyStatus); + if (CollectionUtil.isNotEmpty(appendixList)) { + trainingRegistrationReview.setAuditAppendixListJson(JSONObject.toJSONString(appendixList)); + } + iTrainingRegistrationReviewService.saveOrUpdate(trainingRegistrationReview); + + + // 如果是材料审核 + if (ApplicantTypeEnum.MATERIAL_APPLICANT.getCode().equals(metaApply.getApplicantType())) { + // 根据复核结果 创建驾驶员账号 更新驾驶员信息 + if (result) { + Long userId = driverInfo.getUserId(); + String phoneNo = driverInfo.getPhoneNo(); + String driverName = driverInfo.getDriverName(); + NdUserAuth userAuth = iNdUserAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class).eq(NdUserAuth::getUserId, userId)); + NdUserAuth ndUserAuth = new NdUserAuth(); + if (Objects.nonNull(userAuth)) { + ndUserAuth.setId(userAuth.getId()); + } + ndUserAuth.setCreateOn(LocalDateTime.now()); + ndUserAuth.setUpdateOn(LocalDateTime.now()); + ndUserAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.name()); + ndUserAuth.setIdentifier(phoneNo); + //ndUserAuth.setCredential(generateCredential(phoneNo, driverName)); + ndUserAuth.setCredential(passwordEncoder.encode(UserLoginConstant.LOGIN_PASSWORD)); + ndUserAuth.setUserId(userId); + iNdUserAuthService.saveOrUpdate(ndUserAuth); + + //将角色和驾驶员账号关联 + UserRole userRole = new UserRole(); + UserRole role = userRoleService.getOne(Wrappers.lambdaQuery(UserRole.class) + .eq(UserRole::getUserId, userId)); + if (Objects.nonNull(role)) { + userRole.setId(role.getId()); + } + userRole.setUserId(userId); + userRole.setRoleId(UserRoleTypeEnum.DRIVER_ROLE_ID.getId()); + userRoleService.saveOrUpdate(userRole); + + // 更新驾驶员信息 + if (TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name().equals(request.getTrainingRegistrationType().name())) { + driverInfo.setDriverRegistrationStatus(DriverRegistrationStatusEnum.exam_training_stage.name()); + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (TrainingRegistrationTypeEnum.CONTINUING_EDUCATION.name().equals(request.getTrainingRegistrationType().name())) { + driverInfo.setContinuingEducationStatus(DriverRegistrationStatusEnum.exam_training_stage.name()); + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (TrainingRegistrationTypeEnum.REPLACEMENT_REGISTRATION.name().equals(request.getTrainingRegistrationType().name())) { + driverInfo.setReplacementRegistrationStatus(DriverRegistrationStatusEnum.exam_training_stage.name()); + driverInfo.setReplacementRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } + iDriverInfoService.saveOrUpdate(driverInfo); + + // 更新用户信息为可登录状态 + NdUserInfo userInfo = iNdUserInfoService.getById(userId); + userInfo.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode()); + userInfo.setUpdateOn(LocalDateTime.now()); + iNdUserInfoService.updateById(userInfo); + } + } else if (ApplicantTypeEnum.JOB_CHANGE_APPLICANT.getCode().equals(metaApply.getApplicantType())) { + // 根据复核结果 更新驾驶员所属企业、所属区域、用户信息所属企业 + if (result){ + Long jobChangeCompanyId = metaApply.getJobChangeCompanyId(); + driverInfo.setCompanyId(jobChangeCompanyId); + CompanyDTO companyDto = companiesCacheHelper.getById(jobChangeCompanyId); + driverInfo.setCompanyName(companyDto.getName()); + driverInfo.setJobChangeStatus(DriverJobChangeStatusEnum.available.name()); + driverInfo.setRegionId(companyDto.getRegionId()); + driverInfoService.updateById(driverInfo); + + Long userId = driverInfo.getUserId(); + NdUserInfo userInfo = iNdUserInfoService.getById(userId); + userInfo.setCompanyId(jobChangeCompanyId); + iNdUserInfoService.updateById(userInfo); + } + } + + } + + + public ResArchivalInfoDetailVO getDriverArchivalInfoByIdCard(String idCard) { + // 查询驾驶员信息 + DriverInfo driverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getIdCard, idCard)); + if (Objects.isNull(driverInfo)) { + throw new BizException("该驾驶员信息不存在"); + } + return getDriverArchivalInfo(driverInfo.getId()); + } + + + public List getViolation(Long driverId, Integer violationType) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleViolation.class); + wrapper.eq(NdVehicleViolation::getDriverId, driverId); + wrapper.eq(NdVehicleViolation::getViolationType, violationType); + List list = vehicleViolationService.list(wrapper); + + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + + return list.stream().map(w -> { + NdVehicleViolationVO vo = BeanUtil.copyProperties(w, NdVehicleViolationVO.class); + if (Objects.nonNull(vo.getViolationType())) { + vo.setViolationTypeName(ViolationTypeEnum.getDescByCode(vo.getViolationType())); + } + if (Objects.nonNull(vo.getMissingCertificateType())) { + vo.setMissingCertificateTypeName(MissCertEnum.getDescByCode(vo.getMissingCertificateType())); + } + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }).collect(Collectors.toList()); + } + + public List getAccidentVehicle(Long driverId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class); + DriverArchivesManage context = (DriverArchivesManage) AopContext.currentProxy(); + context.buildGetOnQuery(wrapper, driverId); + NdVehicleGetOn getOn = vehicleGetOnService.getOne(wrapper); + if (Objects.isNull(getOn)) { + return Collections.emptyList(); + } + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(getOn.getCarPlate()); + PageVo page = vehicleAccidentManage.queryVehicleAccident(param); + if (0L == page.getTotal()) { + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildGetOnQuery(LambdaQueryWrapper wrapper, Long driverId) { + wrapper.eq(NdVehicleGetOn::getDriverId, driverId) + .orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleGetOn::getUpdateOn) + .last(" limit 1"); + } + + public List getAccidentVehicleOpen(Long driverId) { + NdVehicleGetOn getOn = vehicleGetOnService.getOne(Wrappers.lambdaQuery(NdVehicleGetOn.class) + .eq(NdVehicleGetOn::getDriverId, driverId) + .orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleGetOn::getUpdateOn) + .last(" limit 1")); + if (Objects.isNull(getOn)) { + return Collections.emptyList(); + } + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(getOn.getCarPlate()); + PageVo page = vehicleAccidentManage.queryVehicleAccidentOpen(param); + if (0L == page.getTotal()) { + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List getAccidentDead(Long driverId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class); + DriverArchivesManage context = (DriverArchivesManage) AopContext.currentProxy(); + context.buildGetOnQuery(wrapper, driverId); + NdVehicleGetOn getOn = vehicleGetOnService.getOne(wrapper); + if (Objects.isNull(getOn)) { + return Collections.emptyList(); + } + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(getOn.getCarPlate()); + PageVo page = vehicleAccidentManage.queryDead(param); + if (0L == page.getTotal()) { + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentDeadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List getAccidentDeadOpen(Long driverId) { + NdVehicleGetOn getOn = vehicleGetOnService.getOne(Wrappers.lambdaQuery(NdVehicleGetOn.class) + .eq(NdVehicleGetOn::getDriverId, driverId) + .orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleGetOn::getUpdateOn) + .last(" limit 1")); + if (Objects.isNull(getOn)) { + return Collections.emptyList(); + } + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(getOn.getCarPlate()); + PageVo page = vehicleAccidentManage.queryDeadOpen(param); + if (0L == page.getTotal()) { + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentDeadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List getAccidentAnalysis(Long driverId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class); + DriverArchivesManage context = (DriverArchivesManage) AopContext.currentProxy(); + context.buildGetOnQuery(wrapper, driverId); + NdVehicleGetOn getOn = vehicleGetOnService.getOne(wrapper); + if (Objects.isNull(getOn)) { + return Collections.emptyList(); + } + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(getOn.getCarPlate()); + PageVo page = vehicleAccidentManage.queryAccidentAnalysis(param); + if (0L == page.getTotal()) { + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentAnalysisVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + public List getAccidentAnalysisOpen(Long driverId) { + NdVehicleGetOn getOn = vehicleGetOnService.getOne(Wrappers.lambdaQuery(NdVehicleGetOn.class) + .eq(NdVehicleGetOn::getDriverId, driverId) + .orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleGetOn::getUpdateOn) + .last(" limit 1")); + if (Objects.isNull(getOn)) { + return Collections.emptyList(); + } + AccidentPageQuery param = new AccidentPageQuery(); + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + param.setCarPlate(getOn.getCarPlate()); + PageVo page = vehicleAccidentManage.queryAccidentAnalysisOpen(param); + if (0L == page.getTotal()) { + return Collections.emptyList(); + } + return CollUtils.convert(page.getRecords(), w -> { + NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentAnalysisVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + } + + @Transactional(rollbackFor = Exception.class) + public String importDriverArchivesData(ImportTemplateEnum template, MultipartFile file, HttpServletResponse response) { + try (InputStream inputStream = file.getInputStream(); + ExcelReader reader = ExcelUtil.getReader(inputStream)) { + Map alias; + List title = ImportTemplateConstant.getTemplateTitle(template); + alias = new HashMap<>(title.size()); + alias.put(title.get(0), "driverName"); + alias.put(title.get(1), "gender"); + alias.put(title.get(2), "idCard"); + alias.put(title.get(3), "birth"); + alias.put(title.get(4), "nativePlace"); + alias.put(title.get(5), "phoneNo"); + alias.put(title.get(6), "health"); + alias.put(title.get(7), "address"); + alias.put(title.get(8), "driverLicenseNo"); + alias.put(title.get(9), "driverLicenseType"); + alias.put(title.get(10), "initialLicenseTime"); + alias.put(title.get(11), "motorcycleTypeList"); + alias.put(title.get(12), "illegalAndIllegalInfo"); + reader.setHeaderAlias(alias); + return importAndUpdateDriverArchivesData(response, reader.readAll(DriverArchivesDataImportDTO.class)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String importAndUpdateDriverArchivesData(HttpServletResponse response, List importDataList) { + AtomicBoolean flag = new AtomicBoolean(true); + StringBuffer stringBuffer = new StringBuffer(); + if (CollectionUtils.isEmpty(importDataList)) { + return "导入数据为空,请重新导入!"; + } + List driverArchivesDataList = new ArrayList<>(); + List idCards = CollUtils.fieldList(importDataList, DriverArchivesDataImportDTO::getIdCard); + Assert.isTrue(idCards.size() == importDataList.size(), "身份证号不可重复"); + Map driverInfoMap = iDriverInfoService.listByIdCard(idCards); + Assert.isTrue(idCards.size() == driverInfoMap.size(), "请确保所有身份证号存在"); + LocalDateTime now = LocalDateTime.now(); + importDataList.forEach(w -> { + String idCard = w.getIdCard(); + if (idCard == null) { + throw new BizException("身份证号未填写,请填写后重新导入!"); + } + DriverInfo driverInfo = driverInfoMap.get(w.getIdCard()); + + if (driverInfo.getDriverRegistrationStatus().equals(DriverRegistrationStatusEnum.available.name()) || + driverInfo.getReplacementRegistrationStatus().equals(DriverRegistrationStatusEnum.available.name()) || + driverInfo.getContinuingEducationStatus().equals(DriverRegistrationStatusEnum.available.name())) { + driverInfo.setDriverStatus(DriverStatusEnum.induction.name()); + //将导入驾驶员中完成培训的驾驶员导入结果标记为成功 + stringBuffer.append(driverInfo.getDriverName()).append("-").append(driverInfo.getIdCard()).append("-").append("导入成功").append("\n"); + } else { + //将标志位设置为false提醒导入驾驶员中有未完成培训的驾驶员,并将导入结果标记为失败 + stringBuffer.append(driverInfo.getDriverName()).append("-").append(driverInfo.getIdCard()).append("-").append("导入失败!").append("\n"); + flag.set(false); + return; + } + driverInfo.setCreateOn(now); + driverInfo.setUpdateOn(now); + driverInfo.setDriverName(w.getDriverName()); + + driverInfo.setGender(GenderEnum.getByValue(w.getGender()).getCode()); + driverInfo.setIdCard(w.getIdCard()); + driverInfo.setBirth(w.getBirth()); + driverInfo.setNativePlace(w.getNativePlace()); + driverInfo.setPhoneNo(w.getPhoneNo()); + driverInfo.setHealth(w.getHealth()); + driverInfo.setAddress(w.getAddress()); + driverInfo.setDriverLicenseNo(w.getDriverLicenseNo()); + driverInfo.setDriverLicenseType(w.getDriverLicenseType()); + driverInfo.setIllegalAndIllegalInfo(w.getIllegalAndIllegalInfo()); + driverInfo.setInitialLicenseTime(w.getInitialLicenseTime()); + driverInfo.setMotorcycleTypeList(w.getMotorcycleTypeList()); + + DriverInfo driverArchivesinfo = driverInfoMap.get(w.getIdCard()); + driverInfo.setId(driverArchivesinfo.getId()); + // 将现有驾驶员数据更新到导入企业下 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + driverInfo.setCompanyId(loginUser.getCompanyId()); + driverInfo.setCompanyName(loginUser.getCompanyName()); + driverInfo.setRegionId(loginUser.getRegionId()); + driverArchivesDataList.add(driverInfo); + }); + iDriverInfoService.updateBatchById(driverArchivesDataList); + + //将导入结果字符串写入流中,供前端下载 + String importResult = stringBuffer.toString(); + byte[] bytes = importResult.getBytes(); + if (bytes.length > 0) { + try { + response.setContentType("application/octet-stream"); + response.setHeader("Content-disposition", "attachment;filename=导入结果.txt"); + response.setHeader("Content-Length", String.valueOf(bytes.length)); + response.getOutputStream().write(bytes); + response.flushBuffer(); + } catch (IOException e) { + log.error("流错误!"); + } + } + + if (flag.get()) { + return "全部导入成功!"; + } else { + return "部分导入失败,详情请查看导入结果!"; + } + } + + public void exportDriverArchives(HttpServletResponse response, ReqArchivalInfoSearchPO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo pageVo = archivalInfoSearch(param); + List collect = pageVo.getRecords().stream().map(c -> { + DriverArchivesExportDTO exportDTO = new DriverArchivesExportDTO(); + BeanUtils.copyProperties(c, exportDTO); + String createTimeStr = NdDateUtils.format(c.getCreateTime(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + exportDTO.setCreateTime(createTimeStr); + if (DriverStatusEnum.induction.name().equals(exportDTO.getDriverStatus())) { + exportDTO.setDriverStatus("正常"); + } else if (DriverStatusEnum.quit.name().equals(exportDTO.getDriverStatus())) { + exportDTO.setDriverStatus("离职"); + } + return exportDTO; + }).collect(Collectors.toList()); + + String fileName = "驾驶员档案信息列表"; + ExcelDownUtil.setFileName(fileName, response); + //数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), DriverArchivesExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 各市散办通过系统直接录入驾驶员相关信息 + * + * @param param + */ + public Boolean addDriverArchives(ReqAddDriverArchivesPO param) { + //获取登录用户 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + + // 校验驾驶员 手机号/身份证号是否可用 + String idCard = param.getIdCard(); + String phoneNo = param.getPhoneNo(); + validateDriverInfoIdCardAvailable(null, idCard); + validateDriverInfoPhoneNoAvailable(null, phoneNo); + // 校验 获取公司信息是否存在 + Long companyId = userInfoHelper.getUserCompanyId(); + // 创建唯一标识用户不可登陆用户账号 并获取用户id + Long driverUserId = newCreateUniqAccountAndGetUserId(param, loginUser.getUserId()); + // 创建驾驶员可登录账号 + String driverName = param.getDriverName(); + NdUserAuth ndUserAuth = new NdUserAuth(); + ndUserAuth.setCreateOn(LocalDateTime.now()); + ndUserAuth.setUpdateOn(LocalDateTime.now()); + ndUserAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.name()); + ndUserAuth.setIdentifier(phoneNo); + //ndUserAuth.setCredential(generateCredential(phoneNo, driverName)); + ndUserAuth.setCredential(passwordEncoder.encode(UserLoginConstant.LOGIN_PASSWORD)); + ndUserAuth.setUserId(driverUserId); + iNdUserAuthService.save(ndUserAuth); + + //将角色和驾驶员账号关联 + UserRole userRole = new UserRole(); + userRole.setUserId(driverUserId); + userRole.setRoleId(UserRoleTypeEnum.DRIVER_ROLE_ID.getId()); + userRoleService.save(userRole); + + // 装配驾驶员信息 保存驾驶员信息 + DriverInfo saveDriverInfoRecord = newAssemblerSaveRecord(param, companyId); + if (param.getTrainingRegistrationType().name().equals(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name())) { + saveDriverInfoRecord.setDriverRegistrationStatus(DriverRegistrationStatusEnum.available.name()); + } + if (param.getTrainingRegistrationType().name().equals(TrainingRegistrationTypeEnum.REPLACEMENT_REGISTRATION.name())) { + saveDriverInfoRecord.setDriverRegistrationStatus(DriverRegistrationStatusEnum.available.name()); + saveDriverInfoRecord.setReplacementRegistrationStatus(DriverRegistrationStatusEnum.available.name()); + } + if (param.getTrainingRegistrationType().name().equals(TrainingRegistrationTypeEnum.CONTINUING_EDUCATION.name())) { + saveDriverInfoRecord.setDriverRegistrationStatus(DriverRegistrationStatusEnum.available.name()); + saveDriverInfoRecord.setContinuingEducationStatus(DriverRegistrationStatusEnum.available.name()); + } + saveDriverInfoRecord.setCreateOn(LocalDateTime.now()); + saveDriverInfoRecord.setUserId(driverUserId); + saveDriverInfoRecord.setDriverStatus(DriverStatusEnum.induction.name()); + iDriverInfoService.save(saveDriverInfoRecord); + + Long driverId = saveDriverInfoRecord.getId(); + //生成合格证信息 + Certificate certificate = new Certificate(); + + certificate.setDriverId(driverId); + certificate.setUserId(driverUserId); + certificate.setDriverName(driverName); + certificate.setBirth(param.getBirth()); + certificate.setGender(param.getGender()); + certificate.setNativePlace(param.getNativePlace()); + certificate.setHealth(param.getHealth()); + certificate.setPhoneNo(param.getPhoneNo()); + certificate.setAddress(param.getAddress()); + certificate.setDriverLicenseType(param.getDriverLicenseType().name()); + certificate.setDriverLicenseNo(param.getDriverLicenseNo()); + certificate.setCertificateNo(param.getCertificateNo()); + certificate.setIssuedBy(param.getIssueBy()); + certificate.setIssueDate(param.getIssueDate()); + certificate.setExpiryDate(param.getExpiryDate()); + certificate.setRemark(param.getCertificateRemark()); + certificate.setRegionId(loginUser.getRegionId()); + certificate.setRegionName(loginUser.getRegionName()); + certificate.setCompanyId(loginUser.getCompanyId()); + certificate.setCompanyName(loginUser.getCompanyName()); + certificate.setCreateOn(LocalDateTime.now()); + certificate.setUpdateOn(LocalDateTime.now()); + certificate.setCreateBy(loginUser.getUserId()); + certificateService.save(certificate); + //生成上车分数信息 + DriverScoreInfo driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + driverScoreInfo.setCreateBy(loginUser.getUserId()); + driverScoreInfo.setUserId(driverUserId); + driverScoreInfo.setDriverId(driverId); + driverScoreInfo.setDriverScore(60); + iDriverScoreInfoService.save(driverScoreInfo); + return Boolean.TRUE; + } + + /** + * 装配驾驶员信息saveRecord + * + * @param request + * @param request companyRegionId + * @return newAssemblerSaveRecord + */ + private DriverInfo newAssemblerSaveRecord(ReqAddDriverArchivesPO request, Long companyRegionId) { + DriverInfo saveRecord = new DriverInfo(); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverName(request.getDriverName()); + saveRecord.setGender(request.getGender()); + saveRecord.setIdCard(request.getIdCard()); + saveRecord.setBirth(request.getBirth()); + saveRecord.setNativePlace(request.getNativePlace()); + saveRecord.setPhoneNo(request.getPhoneNo()); + saveRecord.setHealth(request.getHealth()); + saveRecord.setAddress(request.getAddress()); + saveRecord.setDriverLicenseNo(request.getDriverLicenseNo()); + saveRecord.setDriverLicenseType(request.getDriverLicenseType().name()); + saveRecord.setCompanyId(userInfoHelper.getUserCompanyId()); + saveRecord.setCompanyName(userInfoHelper.getUserCompanyName()); + saveRecord.setRegionId(companyRegionId); + saveRecord.setNativePlaceRegionCode(request.getNativePlaceRegionCode()); + saveRecord.setInitialLicenseTime(request.getInitialLicenseTime()); + if (CollectionUtil.isNotEmpty(request.getMotorcycleTypeList())) { + saveRecord.setMotorcycleTypeList(JSONObject.toJSONString(request.getMotorcycleTypeList())); + } + FileBasicInfo avatarFile = request.getAvatarFile(); + if (Objects.nonNull(avatarFile)) { + saveRecord.setAvatarFile(JSONObject.toJSONString(avatarFile)); + } + saveRecord.setIllegalAndIllegalInfo(request.getIllegalAndIllegalInfo()); + return saveRecord; + } + + /** + * 创建唯一标识用户不可登陆用户账号 并获取用户id + * + * @return newCreateUniqAccountAndGetUserId + */ + private Long newCreateUniqAccountAndGetUserId(ReqAddDriverArchivesPO request, Long createByUserId) { + NdUserInfo driverUserInfo = new NdUserInfo(); + driverUserInfo.setCompanyId(userInfoHelper.getUserCompanyId()); + driverUserInfo.setMobile(request.getPhoneNo()); + driverUserInfo.setNickName(request.getDriverName()); + driverUserInfo.setUsername(request.getDriverName()); + driverUserInfo.setCreateOn(LocalDateTime.now()); + driverUserInfo.setUpdateOn(LocalDateTime.now()); + driverUserInfo.setCreateBy(createByUserId); + iNdUserInfoService.save(driverUserInfo); + return driverUserInfo.getId(); + } + + public ResArchivalInfoDetailVO modifyDriverBasicInfo(DriverBasicInfoDTO data) { + + Long driverId = data.getDriverId(); + // 获取驾驶员信息 + DriverInfo driverInfo = validateGetDriverInfoBySerializableId(driverId); + + // 装配返回信息,更新编辑信息 + ResArchivalInfoDetailVO resVo = new ResArchivalInfoDetailVO(); + + // 更新编辑信息 + driverInfo.setDriverName(data.getDriverName()); + driverInfo.setGender(data.getGender()); + driverInfo.setBirth(data.getBirth()); + String idCard = data.getIdCard(); + // 身份证号经过编辑 + if (!idCard.contains(StrPool.ASTERISK)){ + // 校验身份证号 + boolean isValid = IdcardUtil.isValidCard(idCard); + if (isValid) { + driverInfo.setIdCard(idCard); + }else { + throw new BizException("身份证号输入错误,请重新输入!"); + } + } + driverInfo.setIdCard(data.getIdCard()); + driverInfo.setNativePlace(data.getNativePlace()); + driverInfo.setNativePlaceRegionCode(data.getNativePlaceRegionCode()); + FileBasicInfo file = data.getAvatarFile(); + if (Objects.nonNull(file)) { + resVo.setAvatarFile(file); + driverInfo.setAvatarFile(JSONObject.toJSONString(file)); + } + driverInfo.setHealth(data.getHealth()); + driverInfo.setDriverLicenseNo(data.getDriverLicenseNo()); + driverInfo.setPhoneNo(data.getDriverPhoneNo()); + + // 更新用户信息表中的驾驶员手机号 + Long userId = driverInfo.getUserId(); + if (Objects.nonNull(userId)) { + NdUserInfo userInfo = iNdUserInfoService.getById(userId); + String driverPhoneNo = data.getDriverPhoneNo(); + if (!driverPhoneNo.contains(StrPool.ASTERISK)) { + // 校验手机号 + boolean isValid = Validator.isMobile(driverPhoneNo); + if (isValid) { + userInfo.setMobile(driverPhoneNo); + iNdUserInfoService.updateById(userInfo); + }else { + throw new BizException("手机号输入错误,请重新输入!"); + } + } + } + driverInfo.setAddress(data.getDriverAddress()); + driverInfo.setDriverLicenseNo(data.getDriverLicenseNo()); + if (StringUtils.isNotBlank(data.getDriverLicenseType().name())) { + resVo.setDriverLicenseType(data.getDriverLicenseType()); + driverInfo.setDriverLicenseType(data.getDriverLicenseType().name()); + } + driverInfo.setInitialLicenseTime(data.getInitialLicenseTime()); + if (CollUtil.isNotEmpty(data.getMotorcycleTypeList())) { + resVo.setMotorcycleTypeList(data.getMotorcycleTypeList()); + driverInfo.setMotorcycleTypeList(JSONObject.toJSONString(data.getMotorcycleTypeList())); + } + driverInfo.setIllegalAndIllegalInfo(data.getIllegalAndIllegalInfo()); + if (Objects.nonNull(data.getCompanyId())){ + CompanyDTO companyDto = companiesCacheHelper.getById(data.getCompanyId()); + if (Objects.isNull(companyDto)){ + throw new BizException("所属企业不存在!"); + } + driverInfo.setCompanyId(companyDto.getId()); + driverInfo.setCompanyName(companyDto.getName()); + driverInfo.setRegionId(companyDto.getRegionId()); + } + driverInfoService.updateById(driverInfo); + + return getResArchivalInfoDetailVO(data, driverId, resVo); + } + + private ResArchivalInfoDetailVO getResArchivalInfoDetailVO(DriverBasicInfoDTO data, Long driverId, ResArchivalInfoDetailVO resVo) { + resVo.setDriverId(driverId); + resVo.setDriverName(data.getDriverName()); + + resVo.setDriverAddress(data.getDriverAddress()); + + // 对手机号和身份证号进行脱敏处理 + String phoneNo = data.getDriverPhoneNo(); + String idCard = data.getIdCard(); + String companyContactPhone = data.getCompanyContactPhone(); + String encryptPhone = DesensitizedUtil.mobilePhone(phoneNo); + String encryptCompanyContactPhone = DesensitizedUtil.mobilePhone(companyContactPhone); + String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END); + resVo.setDriverPhoneNo(encryptPhone); + resVo.setIdCard(encryptIdCard); + resVo.setCompanyContactPhone(encryptCompanyContactPhone); + + resVo.setDriverLicenseNo(data.getDriverLicenseNo()); + resVo.setBirth(data.getBirth()); + resVo.setNativePlace(data.getNativePlace()); + resVo.setDriverAddress(data.getDriverAddress()); + resVo.setIllegalAndIllegalInfo(data.getIllegalAndIllegalInfo()); + resVo.setInitialLicenseTime(data.getInitialLicenseTime()); + resVo.setDriverPhoneNo(data.getDriverPhoneNo()); + resVo.setHealth(data.getHealth()); + resVo.setNativePlaceRegionCode(data.getNativePlaceRegionCode()); + resVo.setGender(data.getGender()); + resVo.setCompanyId(data.getCompanyId()); + if (Objects.nonNull(data.getCompanyId())) { + CompanyDTO dto = companiesCacheHelper.getById(data.getCompanyId()); + if (Objects.nonNull(dto)) { + resVo.setCompanyName(dto.getName()); + } + } + resVo.setCompanyAddress(data.getCompanyAddress()); + resVo.setCompanyContactPerson(data.getCompanyContactPerson()); + // 取证报名的信息作为驾驶员档案基本信息 + resVo.setTrainingRegistrationType(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION); + return resVo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverBlackListManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverBlackListManage.java new file mode 100644 index 0000000..2301cee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverBlackListManage.java @@ -0,0 +1,169 @@ +package com.ningdatech.carapi.driver.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.driver.entity.DriverBlackList; +import com.ningdatech.carapi.driver.model.po.ReqDriverBlackListSearchPO; +import com.ningdatech.carapi.driver.model.vo.ResDriverBlackListVO; +import com.ningdatech.carapi.driver.service.IDriverBlackListService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author liuxinxin + * @date 2022/10/9 下午1:57 + */ +@Component +@RequiredArgsConstructor +public class DriverBlackListManage { + + private final IDriverBlackListService iDriverBlackListService; + + public PageVo driverBlackListSearch(ReqDriverBlackListSearchPO po) { + PageVo pageVo = new PageVo<>(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverBlackList.class); + DriverBlackListManage context = (DriverBlackListManage) AopContext.currentProxy(); + context.buildDriverBlackListQuery(wrapper,po); + Page page = iDriverBlackListService.page(po.page(), wrapper); + long total = page.getTotal(); + pageVo.setTotal(total); + if (total == 0){ + return pageVo; + } + pageVo.setRecords(page.getRecords().stream().map(r -> { + ResDriverBlackListVO resVo = BeanUtil.copyProperties(r,ResDriverBlackListVO.class); + CodeUtil.searchCompanyNameAndRegionName(resVo); + return resVo; + }).collect(Collectors.toList())); + return pageVo; + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildDriverBlackListQuery(LambdaQueryWrapper wrapper, ReqDriverBlackListSearchPO request) { + wrapper.eq(StringUtils.isNotBlank(request.getYear()),DriverBlackList::getYear,request.getYear()) + .like(StringUtils.isNotBlank(request.getCompanyName()),DriverBlackList::getCompanyName,request.getCompanyName()) + .like(StringUtils.isNotBlank(request.getDriverName()),DriverBlackList::getDriverName,request.getDriverName()); + } +// String driverName = reqDriverBlackListSearchPO.getDriverName(); +// RegionInfo regionInfo = reqDriverBlackListSearchPO.getRegionInfo(); +// String year = reqDriverBlackListSearchPO.getYear(); +// +// List companyList = new ArrayList<>(); +// if (StringUtils.isNotBlank(driverName) || +// (Objects.nonNull(regionInfo) && StringUtils.isNotBlank(regionInfo.getRegionCode()))) { +// LambdaQueryWrapper companyLambdaQueryWrapper = Wrappers.lambdaQuery(Company.class); +// DriverBlackListManage context = (DriverBlackListManage) AopContext.currentProxy(); +// context.build(companyLambdaQueryWrapper, reqDriverBlackListSearchPO); +// if (Objects.nonNull(regionInfo) +// && StringUtils.isNotBlank(regionInfo.getRegionCode()) +// && Objects.nonNull(regionInfo.getRegionLevel())) { +// RegionContainsBO containsRegionBo = regionSearchWrapperAssemblerHelper.getContainsRegionBo( +// regionInfo.getRegionLevel(), regionInfo.getRegionCode()); +// regionSearchWrapperAssemblerHelper.expertMetaApplyRegionContainsWrapperAssembler(companyLambdaQueryWrapper, CollUtil.toList(containsRegionBo)); +// } +// companyList = companyService.list(companyLambdaQueryWrapper); +// if (CollectionUtils.isEmpty(companyList)) { +// pageVo.setTotal(0L); +// pageVo.setRecords(new ArrayList<>()); +// return pageVo; +// } +// } +// List companyIdList = companyList.stream().map(Company::getId).collect(Collectors.toList()); +// +// // 获取符合条件的driverId List +// List driverIdList = new ArrayList<>(); +// if (StringUtils.isNotBlank(driverName) && CollectionUtils.isNotEmpty(companyIdList)) { +// LambdaQueryWrapper driverInfoLambdaQueryWrapper = Wrappers.lambdaQuery(DriverInfo.class); +// DriverBlackListManage context2 = (DriverBlackListManage) AopContext.currentProxy(); +// context2.build2(driverInfoLambdaQueryWrapper, driverName, companyIdList); +// List driverInfoList = iDriverInfoService.list(driverInfoLambdaQueryWrapper); +// driverIdList = driverInfoList.stream().map(DriverInfo::getId).collect(Collectors.toList()); +// } +// LambdaQueryWrapper driverBlackListLambdaQueryWrapper = Wrappers.lambdaQuery(DriverBlackList.class); +// DriverBlackListManage context3 = (DriverBlackListManage) AopContext.currentProxy(); +// context3.build3(driverBlackListLambdaQueryWrapper, year, driverIdList); +// Page page = iDriverBlackListService.page(new Page<>(pageNumber, pageSize),driverBlackListLambdaQueryWrapper); +// +// long total = page.getTotal(); +// pageVo.setTotal(total); +// if (total == 0) { +// return pageVo; +// } +// List records = page.getRecords(); +// +// // 黑名单驾驶员信息列表 +// List driverBlackDriverIdList = records.stream().map(DriverBlackList::getDriverId).distinct().collect(Collectors.toList()); +// LambdaQueryWrapper driverInfoLambdaQueryWrapper = Wrappers.lambdaQuery(DriverInfo.class); +// driverInfoLambdaQueryWrapper.in(CollectionUtils.isNotEmpty(driverBlackDriverIdList), DriverInfo::getId, driverBlackDriverIdList); +// List driverInfoList = iDriverInfoService.list(driverInfoLambdaQueryWrapper); +// Map driverIdNameMap = driverInfoList.stream().collect(Collectors.toMap(DriverInfo::getId, DriverInfo::getDriverName)); +// +// // 黑名单驾驶员公司信息列表 +// List blackListDriverCompanyIdList = driverInfoList.stream() +// .filter(r -> Objects.nonNull(r.getCompanyId())) +// .map(DriverInfo::getCompanyId) +// .collect(Collectors.toList()); +// LambdaQueryWrapper companyLambdaQueryWrapper = Wrappers.lambdaQuery(Company.class); +// companyLambdaQueryWrapper.eq(Company::getId, blackListDriverCompanyIdList); +// companyList = companyService.list(companyLambdaQueryWrapper); +// Map companyIdInfoMap = companyList.stream() +// .collect(Collectors.toMap(Company::getId, Function.identity())); +// +// // 装配黑名单列表展示VO +// List resDriverBlackListVOList = records.stream().map(r -> { +// ResDriverBlackListVO resDriverBlackListVO = new ResDriverBlackListVO(); +// Long driverId = r.getDriverId(); +// resDriverBlackListVO.setYear(r.getYear()); +// resDriverBlackListVO.setDriverId(r.getDriverId()); +// // 装配公司信息 驾驶员信息 +// resDriverBlackListVO.setDriverName(driverIdNameMap.get(driverId)); +// Company company = companyIdInfoMap.get(driverId); +// if (Objects.nonNull(company)) { +// RegionInfo companyRegionInfo = new RegionInfo(); +//// companyRegionInfo.setRegionCode(company.getRegionCode()); +//// companyRegionInfo.setRegionLevel(company.getRegionLevel()); +// resDriverBlackListVO.setRegionInfo(companyRegionInfo); +// resDriverBlackListVO.setCompanyName(company.getName()); +// } +// +// resDriverBlackListVO.setAccumulatedAccidentsCnt(r.getAccumulatedAccidentsCnt()); +// resDriverBlackListVO.setAccumulatedOverspeedCnt(r.getAccumulatedOverspeedCnt()); +// resDriverBlackListVO.setAccumulatedViolationsCnt(r.getAccumulatedViolationsCnt()); +// return resDriverBlackListVO; +// }).collect(Collectors.toList()); +// +// pageVo.setRecords(resDriverBlackListVOList); +// return pageVo; +// } + + //@LambdaDataScope + //public void build3(LambdaQueryWrapper driverBlackListLambdaQueryWrapper, String year, List driverIdList) { + // driverBlackListLambdaQueryWrapper.eq(DriverBlackList::getYear, year) + // .in(CollUtil.isNotEmpty(driverIdList), DriverBlackList::getDriverId, driverIdList); + //} + // + //@LambdaDataScope + //public void build2(LambdaQueryWrapper driverInfoLambdaQueryWrapper, String driverName, List companyIdList) { + // driverInfoLambdaQueryWrapper.in(CollectionUtils.isNotEmpty(companyIdList), DriverInfo::getCompanyId, companyIdList) + // .like(StringUtils.isNotBlank(driverName), DriverInfo::getDriverName, driverName); + //} + // + //@LambdaDataScope + //public void build(LambdaQueryWrapper companyLambdaQueryWrapper, ReqDriverBlackListSearchPO reqDriverBlackListSearchPO) { + // String companyName = reqDriverBlackListSearchPO.getCompanyName(); + // companyLambdaQueryWrapper.like(StringUtils.isNotBlank(companyName), Company::getName, companyName); + //} +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverManageDataViewManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverManageDataViewManage.java new file mode 100644 index 0000000..c5a7768 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverManageDataViewManage.java @@ -0,0 +1,126 @@ +package com.ningdatech.carapi.driver.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.model.DataChartVo; +import com.ningdatech.carapi.common.model.MapDataVO; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import com.ningdatech.carapi.driver.constant.DriverAgeRangeEnum; +import com.ningdatech.carapi.driver.constant.DrivingExperienceRangeEnum; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * DriverManageDataViewManage + *

+ * + * @author WendyYang + * @since 15:31 2022/10/26 + */ +@Component +@AllArgsConstructor +public class DriverManageDataViewManage { + + private final RegionsCacheHelper regionsCacheHelper; + + private final IDriverInfoService driverInfoService; + + public List driverStatisticsByRegion(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + List mapDatas = driverInfoService.diverCountByRegion(param); + if(CollUtil.isEmpty(mapDatas)){ + return Collections.emptyList(); + } + int sum = mapDatas.stream().mapToInt(MapDataPO::getValue).sum(); + return mapDatas.stream().map(mapData -> { + MapDataVO vo = BeanUtil.copyProperties(mapData, MapDataVO.class); + String percent = BigDecimal.valueOf(mapData.getValue() * 100) + .divide(BigDecimal.valueOf(sum), BigDecimal.ROUND_CEILING, RoundingMode.HALF_UP) + .stripTrailingZeros().toPlainString(); + vo.setPercent(percent); + return vo; + }).collect(Collectors.toList()); + } + + public List driverAgeStatisticsByRegion(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + String caseSql = Arrays.stream(DriverAgeRangeEnum.values()).map(w -> { + StringBuilder builder = new StringBuilder(" when @age "); + if (w.getStart() == DriverAgeRangeEnum.UNDEFINED) { + builder.append(" <= ").append(w.getEnd()); + } else if (w.getEnd() == DriverAgeRangeEnum.UNDEFINED) { + builder.append(" >= ").append(w.getStart()); + } else { + builder.append(" >= ").append(w.getStart()).append(" and @age <= ").append(w.getEnd()); + } + return builder.append(" then ").append(w.getKey()); + }).collect(Collectors.joining()) + .concat(" else " + DriverAgeRangeEnum.UNDEFINED); + Map ageMap = driverInfoService.driverAgeStatistics(caseSql, DriverAgeRangeEnum.UNDEFINED, param); + return Arrays.stream(DriverAgeRangeEnum.values()) + .sorted(Comparator.comparing(DriverAgeRangeEnum::getKey).reversed()) + .map(w -> { + DataChartVo vo = new DataChartVo(); + vo.setLabel(w.getLabel()); + vo.setValue(ageMap.getOrDefault(w.getKey(), 0)); + return vo; + }).collect(Collectors.toList()); + } + + public List drivingExperienceStatisticsByRegion(Long regionId) { + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + String caseSql = Arrays.stream(DrivingExperienceRangeEnum.values()).map(w -> { + StringBuilder builder = new StringBuilder(" when @age "); + if (w.getStart() == DrivingExperienceRangeEnum.UNDEFINED) { + builder.append(" <= ").append(w.getEnd()); + } else if (w.getEnd() == DriverAgeRangeEnum.UNDEFINED) { + builder.append(" >= ").append(w.getStart()); + } else { + builder.append(" >= ").append(w.getStart()).append(" and @age <= ").append(w.getEnd()); + } + return builder.append(" then ").append(w.getKey()); + }).collect(Collectors.joining()) + .concat(" else " + DrivingExperienceRangeEnum.UNDEFINED); + Map ageMap = driverInfoService.drivingExperienceStatistics(caseSql, DrivingExperienceRangeEnum.UNDEFINED, param); + return Arrays.stream(DrivingExperienceRangeEnum.values()) + .sorted(Comparator.comparing(DrivingExperienceRangeEnum::getKey).reversed()) + .map(w -> { + DataChartVo vo = new DataChartVo(); + vo.setLabel(w.getLabel()); + vo.setValue(ageMap.getOrDefault(w.getKey(), 0)); + return vo; + }).collect(Collectors.toList()); + } + + public List driverNativePlaceStatisticsByRegion(Long regionId) { + List result = new ArrayList<>(); + DataScreenParam param = new DataScreenParam(); + param.setRegionId(regionId); + List> maps = driverInfoService.nativePlaceStatisticsByRegion(param); + Map>> groupByProvince = maps.stream() + .collect(Collectors.groupingBy(w -> String.valueOf(w.get("nativePlace")))); + groupByProvince.forEach((k, v) -> { + MapDataVO mapData = MapDataVO.builder() + .regionCode(MapUtil.getStr(v.get(0), "nativePlaceRegionCode")) + .regionName(k) + .value(CollUtils.sum(v, w -> MapUtil.getInt(w, "count"))) + .build(); + result.add(mapData); + }); + return result; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverScoreRecordManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverScoreRecordManage.java new file mode 100644 index 0000000..0ceb7e9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverScoreRecordManage.java @@ -0,0 +1,161 @@ +package com.ningdatech.carapi.driver.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.constant.ScoreOperateType; +import com.ningdatech.carapi.driver.constant.TrainingStatusEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import com.ningdatech.carapi.driver.entity.*; +import com.ningdatech.carapi.driver.helper.DriverBehaviorScoreHelper; +import com.ningdatech.carapi.driver.model.bo.CodingRuleBO; +import com.ningdatech.carapi.driver.model.po.ReqScoreBonusPO; +import com.ningdatech.carapi.driver.model.po.ReqScoreListPO; +import com.ningdatech.carapi.driver.model.vo.ResDriverScoreRecordListVO; +import com.ningdatech.carapi.driver.service.*; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author liuxinxin + * @date 2022/11/3 下午4:56 + */ +@Component +@RequiredArgsConstructor +public class DriverScoreRecordManage { + + private final IDriverScoreRecordService iDriverScoreRecordService; + private final IDriverScoreInfoService iDriverScoreInfoService; + private final ITrainingBonusRecordService iTrainingBonusRecordService; + private final IDriverInfoService iDriverInfoService; + private final ITrainingOrganizationTrainerService iTrainingOrganizationTrainerService; + private final ITrainingOrganizationService iTrainingOrganizationService; + private final DriverBehaviorScoreHelper driverBehaviorScoreHelper; + + public List list() { + Long userId = LoginUserUtil.getUserId(); + List driverScoreRecordList = iDriverScoreRecordService.list(Wrappers + .lambdaQuery(DriverScoreRecord.class).eq(DriverScoreRecord::getUserId, userId).orderByDesc(DriverScoreRecord::getCreateOn)); + return driverScoreRecordList.stream().map(r -> { + ResDriverScoreRecordListVO resVO = new ResDriverScoreRecordListVO(); + BeanUtil.copyProperties(r, resVO); + return resVO; + }).collect(Collectors.toList()); + } + + + public PageVo pageList(ReqScoreListPO request) { + @NotBlank Long driverId = request.getDriverId(); + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + + Page page = iDriverScoreRecordService.page(new Page<>(pageNumber, pageSize), Wrappers + .lambdaQuery(DriverScoreRecord.class) + .eq(DriverScoreRecord::getDriverId, driverId) + .orderByDesc(DriverScoreRecord::getCreateOn)); + + PageVo pageVo = new PageVo<>(); + long total = page.getTotal(); + if (total > 0) { + List resVOList = page.getRecords().stream().map(r -> { + ResDriverScoreRecordListVO resVO = new ResDriverScoreRecordListVO(); + BeanUtil.copyProperties(r, resVO); + return resVO; + }).collect(Collectors.toList()); + pageVo.setRecords(resVOList); + } + return pageVo; + } + + public Integer getScore(Long driverId) { + DriverScoreInfo driverScoreInfo = iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class) + .eq(DriverScoreInfo::getDriverId, driverId)); + + if (Objects.nonNull(driverScoreInfo)) { + return driverScoreInfo.getDriverScore(); + } + return 0; + } + + @Transactional(rollbackFor = Exception.class) + public void bonus(ReqScoreBonusPO request) { + Long driverId = request.getDriverId(); + String materialType = request.getMaterialType(); + String behaviorType = request.getBehaviorType(); + Long trainingOrganizationId = request.getTrainingOrganizationId(); + Long trainingMaterialId = request.getTrainingMaterialId(); + + DriverInfo driverInfo = iDriverInfoService.getById(driverId); + if (Objects.isNull(driverInfo)) { + throw new BizException("该驾驶员信息不存在"); + } + + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getOne(Wrappers.lambdaQuery(TrainingOrganization.class) + .eq(TrainingOrganization::getId, trainingOrganizationId) + .eq(TrainingOrganization::getTrainingType, TrainingTypeEnum.transcoding_training.name()) + .eq(TrainingOrganization::getTrainingStatus, TrainingStatusEnum.enable.name()) + ); + if (Objects.isNull(trainingOrganization)) { + return; + } + TrainingBonusRecord one = iTrainingBonusRecordService.getOne(Wrappers.lambdaQuery(TrainingBonusRecord.class) + .eq(TrainingBonusRecord::getDriverId, driverId) + .eq(TrainingBonusRecord::getMaterialType, materialType) + .eq(TrainingBonusRecord::getTrainingMaterialId, trainingMaterialId) + .eq(TrainingBonusRecord::getTrainingOrganizationId, trainingOrganizationId) + .eq(TrainingBonusRecord::getBehaviorType, behaviorType)); + + if (Objects.isNull(one)) { + // 获取行为分数 + CodingRuleBO codingRuleBehaviorScore = driverBehaviorScoreHelper.getCodingRuleBehaviorScore(CodingRuleBehaviorTypeEnum.valueOf(behaviorType),null); + int score = codingRuleBehaviorScore.getOperationScore(); + + DriverScoreInfo driverScoreInfo = iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class).eq(DriverScoreInfo::getDriverId, driverInfo.getId())); + if (driverScoreInfo == null) { + driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + driverScoreInfo.setDriverScore(score); + } else { + driverScoreInfo.setDriverScore(driverScoreInfo.getDriverScore() + score); + } + driverScoreInfo.setUpdateOn(LocalDateTime.now()); + iDriverScoreInfoService.saveOrUpdate(driverScoreInfo); + + DriverScoreRecord saveRecord = new DriverScoreRecord(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverId(driverInfo.getId()); + saveRecord.setOperateReason("参加转码培训并查看了材料"); + saveRecord.setOperateScore(score); + saveRecord.setOperateType(ScoreOperateType.add.name()); + saveRecord.setUserId(driverInfo.getUserId()); + iDriverScoreRecordService.save(saveRecord); + + TrainingBonusRecord record = new TrainingBonusRecord(); + record.setUserId(driverInfo.getUserId()); + record.setCreateOn(LocalDateTime.now()); + record.setUpdateOn(LocalDateTime.now()); + record.setBehaviorType(behaviorType); + record.setDriverId(driverId); + record.setMaterialType(materialType); + record.setTrainingMaterialId(trainingMaterialId); + record.setTrainingOrganizationId(trainingOrganizationId); + record.setCompanyId(driverInfo.getCompanyId()); + record.setRegionId(driverInfo.getRegionId()); + iTrainingBonusRecordService.save(record); + } + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverStarManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverStarManage.java new file mode 100644 index 0000000..fb455f3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/DriverStarManage.java @@ -0,0 +1,269 @@ +package com.ningdatech.carapi.driver.manage; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.StarManageDisplayTypeEnum; +import com.ningdatech.carapi.driver.entity.RegionStarDTO; +import com.ningdatech.carapi.driver.entity.StarManage; +import com.ningdatech.carapi.driver.model.StarManageDisplayInfo; +import com.ningdatech.carapi.driver.model.po.ReqCompanyStarPO; +import com.ningdatech.carapi.driver.model.po.ReqDriverStarListPO; +import com.ningdatech.carapi.driver.model.po.ReqRegionStarPO; +import com.ningdatech.carapi.driver.model.vo.ResCompanyStarListVO; +import com.ningdatech.carapi.driver.model.vo.ResDriverStarListVO; +import com.ningdatech.carapi.driver.model.vo.ResRegionStarVO; +import com.ningdatech.carapi.driver.model.vo.StarManageDisplay; +import com.ningdatech.carapi.driver.service.IStarManageService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/11/15 上午9:45 + */ +@Component +@RequiredArgsConstructor +public class DriverStarManage { + + private final IStarManageService iStarManageService; + private final RegionsCacheHelper regionsCacheHelper; + private final IStarManageService starManageService; + private final CompanyService companyService; + + public PageVo driverStarList(ReqDriverStarListPO request) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(StarManage.class); + DriverStarManage context = (DriverStarManage) AopContext.currentProxy(); + List containsRegionIdList = regionsCacheHelper.listChildRegionId(request.getRegionId()); + request.setChildRegionIds(containsRegionIdList); + context.buildDriverStarQuery(wrapper, request); + Page page = iStarManageService.page(request.page(),wrapper); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List records = page.getRecords(); + List resVOList = records.stream().map(r -> { + ResDriverStarListVO resVO = new ResDriverStarListVO(); + BeanUtils.copyProperties(r,resVO); + CodeUtil.searchCompanyNameAndRegionName(resVO); + return resVO; + }).collect(Collectors.toList()); + return PageVo.of(resVOList,page.getTotal()); + } + + @LambdaDataScope + public void buildDriverStarQuery(LambdaQueryWrapper wrapper, ReqDriverStarListPO request) { + wrapper.like(StringUtils.isNotBlank(request.getCompanyName()), StarManage::getCompanyName, request.getCompanyName()) + .like(StringUtils.isNotBlank(request.getDriverName()), StarManage::getDriverName, request.getDriverName()) + .in(Objects.nonNull(request.getChildRegionIds()),StarManage::getRegionId,request.getChildRegionIds()); + } + + public PageVo regionStarList(ReqRegionStarPO request) { + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + Long regionId = request.getRegionId(); + List regionList = regionsCacheHelper.listChild(regionId); + List regionStars = new ArrayList<>(); + long total = 0; + // 如果为空最后一级统计公司 + if (CollectionUtil.isEmpty(regionList)) { + List regionIdList = CollectionUtil.toList(regionId); + RegionStarDTO regionStarDTO = new RegionStarDTO(); + regionStarDTO.setRegionIdList(regionIdList); + Double avgStars = starManageService.getAvgStar(regionStarDTO); + avgStars = avgStars == null ? 0 : avgStars; + BigDecimal avgStarTemp = BigDecimal.valueOf(avgStars); + double avgStar = avgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); + Double totalStar = starManageService.countTotalStar(regionStarDTO); + + LambdaQueryWrapper query = Wrappers.lambdaQuery(Company.class); + DriverStarManage context2 = (DriverStarManage) AopContext.currentProxy(); + context2.buildCompanyQuery(query, request); + + Page page = companyService.page(request.page(),query); + + if (page.getTotal() == 0){ + return PageVo.empty(); + } + List companyRecords = page.getRecords(); + + for (Company company : companyRecords) { + ResRegionStarVO resVO = new ResRegionStarVO(); + resVO.setTotalAvgStar(avgStar); + resVO.setTotalStar(totalStar); + StarManageDisplayInfo starManageDisplayInfo = new StarManageDisplayInfo(); + + StarManageDisplay firstDisplayInfo = new StarManageDisplay(); + firstDisplayInfo.setId(regionId); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + if (Objects.nonNull(regionDTO)) { + firstDisplayInfo.setDisplayName(regionDTO.getRegionName()); + } + firstDisplayInfo.setType(StarManageDisplayTypeEnum.region_id); + + StarManageDisplay secondDisplayInfo = new StarManageDisplay(); + secondDisplayInfo.setId(company.getId()); + secondDisplayInfo.setDisplayName(company.getName()); + secondDisplayInfo.setType(StarManageDisplayTypeEnum.company_id); + + starManageDisplayInfo.setFirstDisplayInfo(firstDisplayInfo); + starManageDisplayInfo.setSecondDisplayInfo(secondDisplayInfo); + RegionStarDTO regionStarDto2 = new RegionStarDTO(); + regionStarDto2.setCompanyId(company.getId()); + Double companyAvgStars = starManageService.getCompanyAvgStar(regionStarDto2); + companyAvgStars = companyAvgStars == null ? 0 : companyAvgStars; + BigDecimal companyAvgStarTemp = BigDecimal.valueOf(companyAvgStars); + double companyAvgStar = companyAvgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); + starManageDisplayInfo.setAvgStar(companyAvgStar); + resVO.setRecord(starManageDisplayInfo); + regionStars.add(resVO); + } + total = page.getTotal(); + } else { + // 如果不为空下一级则为地区 + List containsRegionIdList = regionsCacheHelper.listChildRegionId(regionId); + RegionStarDTO regionStarDTO = new RegionStarDTO(); + regionStarDTO.setRegionIdList(containsRegionIdList); + Double avgStars = starManageService.getAvgStar(regionStarDTO); + avgStars = avgStars == null ? 0 : avgStars; + BigDecimal avgStarTemp = BigDecimal.valueOf(avgStars); + double avgStar = avgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); + Double totalStar = starManageService.countTotalStar(regionStarDTO); + + if (CollUtil.isEmpty(regionList)){ + return PageVo.empty(); + } + + int currIdx = (pageNumber > 1 ? (pageNumber - 1) * pageSize : 0); + int endIdx = Math.min(regionList.size(),currIdx + pageSize); + List regionSubList; + regionSubList = regionList.subList(currIdx, endIdx); + + for (Long childrenRegionId : regionSubList) { + ResRegionStarVO resVO = new ResRegionStarVO(); + resVO.setTotalAvgStar(avgStar); + resVO.setTotalStar(totalStar); + List listChildRegionIdList = regionsCacheHelper.listChildRegionId(childrenRegionId); + + StarManageDisplayInfo starManageDisplayInfo = new StarManageDisplayInfo(); + StarManageDisplay firstDisplayInfo = new StarManageDisplay(); + firstDisplayInfo.setId(regionId); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + if (Objects.nonNull(regionDTO)) { + firstDisplayInfo.setDisplayName(regionDTO.getRegionName()); + } + firstDisplayInfo.setType(StarManageDisplayTypeEnum.region_id); + + StarManageDisplay secondDisplayInfo = new StarManageDisplay(); + secondDisplayInfo.setId(childrenRegionId); + RegionDTO childrenRegionDTO = regionsCacheHelper.getByRegionId(childrenRegionId); + if (Objects.nonNull(childrenRegionDTO)) { + secondDisplayInfo.setDisplayName(childrenRegionDTO.getRegionName()); + } + secondDisplayInfo.setType(StarManageDisplayTypeEnum.region_id); + + starManageDisplayInfo.setFirstDisplayInfo(firstDisplayInfo); + starManageDisplayInfo.setSecondDisplayInfo(secondDisplayInfo); + RegionStarDTO regionStarDto2 = new RegionStarDTO(); + regionStarDto2.setRegionIdList(listChildRegionIdList); + Double listAvgStars = starManageService.getAvgStar(regionStarDto2); + listAvgStars = listAvgStars == null ? 0 : listAvgStars; + BigDecimal listAvgStarTemp = BigDecimal.valueOf(listAvgStars); + double listAvgStar = listAvgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); + starManageDisplayInfo.setAvgStar(listAvgStar); + resVO.setRecord(starManageDisplayInfo); + regionStars.add(resVO); + } + total = regionList.size(); + } + return PageVo.of(regionStars,total); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.COMPANY_TABLE) + public void buildCompanyQuery(LambdaQueryWrapper query, ReqRegionStarPO request) { + query.eq(Company::getRegionId, request.getRegionId()) + .orderByDesc(Company::getId); + } + + public PageVo companyStarList(ReqCompanyStarPO request) { + List companyStarLists = new ArrayList<>(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(StarManage.class); + Long regionId = request.getRegionId(); + DriverStarManage context = (DriverStarManage) AopContext.currentProxy(); + context.buildCompanyStarQuery(wrapper, request); + Page page = iStarManageService.page(request.page(),wrapper); + + long total = page.getTotal(); + if (0L == total){ + return PageVo.empty(); + } + List records = page.getRecords(); + + List containsRegionIdList = regionsCacheHelper.listChildRegionId(regionId); + RegionStarDTO regionStarDTO = new RegionStarDTO(); + regionStarDTO.setRegionIdList(containsRegionIdList); + Double avgStars = starManageService.getAvgStar(regionStarDTO); + avgStars = avgStars == null ? 0 : avgStars; + BigDecimal avgStarTemp = BigDecimal.valueOf(avgStars); + double avgStar = avgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); + Double totalStar = starManageService.countTotalStar(regionStarDTO); + + + for (StarManage starManage : records) { + ResCompanyStarListVO resCompanyStarListVO = new ResCompanyStarListVO(); + StarManageDisplayInfo starManageDisplayInfo = new StarManageDisplayInfo(); + StarManageDisplay firstDisplayInfo = new StarManageDisplay(); + firstDisplayInfo.setId(starManage.getCompanyId()); + firstDisplayInfo.setDisplayName(starManage.getCompanyName()); + firstDisplayInfo.setType(StarManageDisplayTypeEnum.company_id); + + StarManageDisplay secondDisplayInfo = new StarManageDisplay(); + secondDisplayInfo.setId(starManage.getDriverId()); + secondDisplayInfo.setDisplayName(starManage.getDriverName()); + secondDisplayInfo.setType(StarManageDisplayTypeEnum.driver_id); + + starManageDisplayInfo.setFirstDisplayInfo(firstDisplayInfo); + starManageDisplayInfo.setSecondDisplayInfo(secondDisplayInfo); + + if (Objects.nonNull(starManage.getCurrentStar())) { + starManageDisplayInfo.setAvgStar(Double.parseDouble(starManage.getCurrentStar() + "")); + } + resCompanyStarListVO.setTotalAvgStar(avgStar); + resCompanyStarListVO.setTotalStar(totalStar); + resCompanyStarListVO.setRecord(starManageDisplayInfo); + companyStarLists.add(resCompanyStarListVO); + } + return PageVo.of(companyStarLists,page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildCompanyStarQuery(LambdaQueryWrapper wrapper, ReqCompanyStarPO request) { + wrapper.like(StringUtils.isNotBlank(request.getCompanyName()), StarManage::getCompanyName, request.getCompanyName()) + .like(StringUtils.isNotBlank(request.getDriverName()), StarManage::getDriverName, request.getDriverName()); + //.eq(Objects.nonNull(request.getRegionId()), StarManage::getRegionId, request.getRegionId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ExamRecordManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ExamRecordManage.java new file mode 100644 index 0000000..9cc21f1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/ExamRecordManage.java @@ -0,0 +1,101 @@ +package com.ningdatech.carapi.driver.manage; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.driver.constant.ExamQualifiedEnum; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.entity.ExamRecordDetail; +import com.ningdatech.carapi.driver.model.po.ReqListExamRecordPO; +import com.ningdatech.carapi.driver.model.vo.ResListExamRecordVO; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.ningdatech.carapi.driver.service.IExamRecordDetailService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:13 + */ +@Component +@RequiredArgsConstructor +public class ExamRecordManage { + + private final IExamRecordDetailService iExamRecordDetailService; + private final ICertificateService iCertificateService; + + + public PageVo listExamRecord(ReqListExamRecordPO request) { + + // 按照登录用户,如果是驾驶员登录,只展示该驾驶员信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ExamRecordDetail.class); + ExamRecordManage context = (ExamRecordManage) AopContext.currentProxy(); + context.buildExamRecordQuery(wrapper, request); + + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)) { + Long userId = userDetail.getUserId(); + wrapper.eq(ExamRecordDetail::getDriverUserId,userId); + } + Page page = iExamRecordDetailService.page(new Page<>(pageNumber, pageSize),wrapper); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List records = page.getRecords(); + List driverUserIdList = records.stream().map(ExamRecordDetail::getDriverUserId).collect(Collectors.toList()); + List certificateList = iCertificateService.list(Wrappers.lambdaQuery(Certificate.class) + .in(Certificate::getUserId, driverUserIdList)); + Map userIdCertificateNoMap = certificateList.stream().collect(Collectors.toMap(Certificate::getDriverId, Certificate::getCertificateNo)); + + List resVoList = records.stream().map(r -> { + ResListExamRecordVO resVO = BeanUtil.copyProperties(r,ResListExamRecordVO.class); + resVO.setIsQualified(ExamQualifiedEnum.valueOf(r.getExamResult())); + resVO.setCertificateNo(userIdCertificateNoMap.get(r.getDriverId())); + resVO.setExamType(r.getExamType()); + CodeUtil.searchCompanyNameAndRegionName(resVO); + return resVO; + }).collect(Collectors.toList()); + return PageVo.of(resVoList,page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildExamRecordQuery(LambdaQueryWrapper wrapper, ReqListExamRecordPO request) { + String companyName = request.getCompanyName(); + String driverName = request.getDriverName(); + ExamQualifiedEnum isQualified = request.getIsQualified(); + LocalDateTime startTime = request.getStartTime(); + LocalDateTime endTime = request.getEndTime(); + String isQualifiedStr = Objects.nonNull(isQualified) ? isQualified.name() : null; + + wrapper .like(StringUtils.isNotBlank(companyName), ExamRecordDetail::getCompanyName, companyName) + .like(StringUtils.isNotBlank(driverName), ExamRecordDetail::getDriverName, driverName) + .eq(StringUtils.isNotBlank(isQualifiedStr), ExamRecordDetail::getExamResult, isQualifiedStr) + .gt(Objects.nonNull(startTime), ExamRecordDetail::getExamTime, startTime) + .lt(Objects.nonNull(endTime), ExamRecordDetail::getExamTime, endTime) + .orderByDesc(ExamRecordDetail::getExamTime); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingBonusRecordManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingBonusRecordManage.java new file mode 100644 index 0000000..da8eae1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingBonusRecordManage.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.manage; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * @author liuxinxin + * @date 2022/10/31 上午10:25 + */ +@Component +@RequiredArgsConstructor +public class TrainingBonusRecordManage { + + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingMaterialManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingMaterialManage.java new file mode 100644 index 0000000..06e1222 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingMaterialManage.java @@ -0,0 +1,241 @@ +package com.ningdatech.carapi.driver.manage; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.MaterialStatusEnum; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; +import com.ningdatech.carapi.driver.constants.DriverConstant; +import com.ningdatech.carapi.driver.entity.TrainingMaterial; +import com.ningdatech.carapi.driver.entity.TrainingOrganizationMaterial; +import com.ningdatech.carapi.driver.model.po.ReqSaveTrainingMaterialPO; +import com.ningdatech.carapi.driver.model.po.ReqTrainingMaterialListPO; +import com.ningdatech.carapi.driver.model.vo.ResSaveTrainingMaterialVO; +import com.ningdatech.carapi.driver.model.vo.ResTrainingMaterialListVO; +import com.ningdatech.carapi.driver.model.vo.ResTrainingMaterialVO; +import com.ningdatech.carapi.driver.service.ITrainingMaterialService; +import com.ningdatech.carapi.driver.service.ITrainingOrganizationMaterialService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/9 下午3:32 + */ +@Component +@RequiredArgsConstructor +public class TrainingMaterialManage { + + private final ITrainingMaterialService iTrainingMaterialService; + private final RegionsCacheHelper regionsCacheHelper; + private final ITrainingOrganizationMaterialService iTrainingOrganizationMaterialService; + + public PageVo trainingMaterialsList(ReqTrainingMaterialListPO request) { + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(TrainingMaterial.class); + + buildTrainingMaterialsQuery(wrapper, request); + Page page = iTrainingMaterialService.page(new Page<>(pageNumber, pageSize),wrapper); + + PageVo pageVo = new PageVo<>(); + long total = page.getTotal(); + pageVo.setTotal(total); + if (total == 0) { + return pageVo; + } + // 装配培训材料列表VO 下载文件通过文件id 下载 + List records = page.getRecords(); + List resVOList = records.stream().map(r -> { + ResTrainingMaterialListVO resVO = new ResTrainingMaterialListVO(); + resVO.setTrainingMaterialId(r.getId()); + resVO.setTitle(r.getTitle()); + resVO.setMaterialType(MaterialTypeEnum.valueOf(r.getMaterialType())); + if (Objects.nonNull(r.getRegionId())) { + resVO.setRegionId(r.getRegionId()); + resVO.setRegionName(regionsCacheHelper.getDisplayName(r.getRegionId())); + }else { + resVO.setRegionId(DefValConstants.ZJREGION_ID); + resVO.setRegionName(regionsCacheHelper.getDisplayName(DefValConstants.ZJREGION_ID)); + } + resVO.setMaterialStatus(MaterialStatusEnum.valueOf(r.getMaterialStatus())); + resVO.setCreateTime(r.getCreateOn()); + resVO.setContent(r.getContent()); + List appendixList = Lists.newArrayList(); + String appendix = r.getAppendixListJson(); + if (StringUtils.isNotBlank(appendix)) { + List array = JSON.parseArray(appendix, String.class); + if (CollUtil.isNotEmpty(array)) { + for (String fileInfo : array) { + JSONObject jsonObject = JSON.parseObject(fileInfo, JSONObject.class); + FileBasicInfo basicInfo = new FileBasicInfo(); + Long fileId = jsonObject.getLong(DriverConstant.FILE_ID); + String fileName = jsonObject.getString(DriverConstant.FILE_NAME); + basicInfo.setFileId(fileId); + basicInfo.setFileName(fileName); + appendixList.add(basicInfo); + } + resVO.setAppendixList(appendixList); + } + } + return resVO; + }).collect(Collectors.toList()); + pageVo.setRecords(resVOList); + return pageVo; + } + + //@LambdaDataScope + private void buildTrainingMaterialsQuery(LambdaQueryWrapper wrapper, ReqTrainingMaterialListPO request) { + // 获取入参 + String title = request.getTitle(); + MaterialTypeEnum materialType = request.getMaterialType(); + Long regionId = request.getRegionId(); + // 入参转换查询参数 + List regionIdList = new ArrayList<>(); + if (Objects.nonNull(regionId)) { + regionIdList = regionsCacheHelper.listChildRegionId(regionId); + } + String materialTypeStr = null; + if (Objects.nonNull(materialType)) { + materialTypeStr = materialType.name(); + } + wrapper.like(StringUtils.isNotBlank(title), TrainingMaterial::getTitle, title) + .in(CollectionUtil.isNotEmpty(regionIdList), TrainingMaterial::getRegionId, regionId) + .eq(StringUtils.isNotBlank(materialTypeStr), TrainingMaterial::getMaterialType, materialTypeStr) + .orderByDesc(TrainingMaterial::getUpdateOn); + } + + public ResSaveTrainingMaterialVO createTrainingMaterial(ReqSaveTrainingMaterialPO request) { + // 获取入参 + List appendixList = request.getAppendixList(); + String title = request.getTitle(); + MaterialStatusEnum materialStatus = request.getMaterialStatus(); + MaterialTypeEnum materialType = request.getMaterialType(); + String content = request.getContent(); + + // 获取登陆者信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + + // 装配培训材料 + TrainingMaterial saveRecord = new TrainingMaterial(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setCreateBy(loginUser.getUserId()); + saveRecord.setTitle(title); + saveRecord.setContent(content); + saveRecord.setMaterialType(materialType.name()); + saveRecord.setMaterialStatus(materialStatus.name()); + saveRecord.setAppendixListJson(JSONObject.toJSONString(appendixList)); + saveRecord.setRegionId(loginUser.getRegionId()); + saveRecord.setCompanyId(loginUser.getCompanyId()); + iTrainingMaterialService.save(saveRecord); + + ResSaveTrainingMaterialVO resSaveTrainingMaterialVO = new ResSaveTrainingMaterialVO(); + resSaveTrainingMaterialVO.setTrainingMaterialId(saveRecord.getId()); + return resSaveTrainingMaterialVO; + } + + public ResSaveTrainingMaterialVO saveTrainingMaterial(ReqSaveTrainingMaterialPO request) { + // 获取入参 + List appendixList = request.getAppendixList(); + String title = request.getTitle(); + MaterialStatusEnum materialStatus = request.getMaterialStatus(); + MaterialTypeEnum materialType = request.getMaterialType(); + String content = request.getContent(); + Long trainingMaterialId = request.getId(); + + if (Objects.isNull(trainingMaterialId)) { + // 获取登陆者信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + + // 装配培训材料 + TrainingMaterial saveRecord = new TrainingMaterial(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setCreateBy(loginUser.getUserId()); + saveRecord.setTitle(title); + saveRecord.setContent(content); + saveRecord.setMaterialType(materialType.name()); + saveRecord.setMaterialStatus(materialStatus.name()); + saveRecord.setAppendixListJson(JSONObject.toJSONString(appendixList)); + saveRecord.setRegionId(loginUser.getRegionId()); + saveRecord.setCompanyId(loginUser.getCompanyId()); + iTrainingMaterialService.save(saveRecord); + + trainingMaterialId = saveRecord.getId(); + } else { + TrainingMaterial trainingMaterial = iTrainingMaterialService.getById(trainingMaterialId); + if (Objects.isNull(trainingMaterial)) { + throw new BizException("培训材料不存在"); + } + + trainingMaterial.setUpdateOn(LocalDateTime.now()); + trainingMaterial.setTitle(title); + trainingMaterial.setContent(content); + trainingMaterial.setMaterialType(materialType.name()); + trainingMaterial.setMaterialStatus(materialStatus.name()); + trainingMaterial.setAppendixListJson(JSONObject.toJSONString(appendixList)); + iTrainingMaterialService.saveOrUpdate(trainingMaterial); + } + + ResSaveTrainingMaterialVO resSaveTrainingMaterialVO = new ResSaveTrainingMaterialVO(); + resSaveTrainingMaterialVO.setTrainingMaterialId(trainingMaterialId); + return resSaveTrainingMaterialVO; + } + + public ResTrainingMaterialVO getTrainingMaterialDetail(Long trainingMaterialId) { + TrainingMaterial trainingMaterial = iTrainingMaterialService.getById(trainingMaterialId); + if (Objects.isNull(trainingMaterial)) { + throw new BizException("培训材料不存在"); + } + + ResTrainingMaterialVO resTrainingMaterialVO = new ResTrainingMaterialVO(); + resTrainingMaterialVO.setId(trainingMaterial.getId()); + resTrainingMaterialVO.setTitle(trainingMaterial.getTitle()); + resTrainingMaterialVO.setContent(trainingMaterial.getContent()); + if (StringUtils.isNotBlank(trainingMaterial.getMaterialStatus())) { + resTrainingMaterialVO.setMaterialStatus(MaterialStatusEnum.valueOf(trainingMaterial.getMaterialStatus())); + } + if (StringUtils.isNotBlank(trainingMaterial.getMaterialType())) { + resTrainingMaterialVO.setMaterialType(MaterialTypeEnum.valueOf(trainingMaterial.getMaterialType())); + } + if (StringUtils.isNotBlank(trainingMaterial.getAppendixListJson())) { + resTrainingMaterialVO.setAppendixList(JSONObject.parseArray(trainingMaterial.getAppendixListJson(), FileBasicInfo.class)); + } + return resTrainingMaterialVO; + } + + @Transactional(rollbackFor = Exception.class) + public void removeTrainingMaterial(Long trainingMaterialId) { + List trainingOrganizationMaterialList = iTrainingOrganizationMaterialService.list( + Wrappers.lambdaQuery(TrainingOrganizationMaterial.class) + .eq(TrainingOrganizationMaterial::getTrainingMaterialId, trainingMaterialId)); + if (CollectionUtil.isEmpty(trainingOrganizationMaterialList)) { + iTrainingMaterialService.removeById(trainingMaterialId); + } else { + throw new BizException("当前材料有培训组织正在使用,无法删除"); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingOrganizationManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingOrganizationManage.java new file mode 100644 index 0000000..885b510 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/manage/TrainingOrganizationManage.java @@ -0,0 +1,1582 @@ +package com.ningdatech.carapi.driver.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.Month; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.archives.entity.ExamPaper; +import com.ningdatech.carapi.archives.entity.ExamPaperQuestion; +import com.ningdatech.carapi.archives.entity.PaperQuestion; +import com.ningdatech.carapi.archives.enums.DriverRelationConstant; +import com.ningdatech.carapi.archives.enums.ExamPaperQualifiedScoreConstant; +import com.ningdatech.carapi.archives.enums.IsRandomEnum; +import com.ningdatech.carapi.archives.enums.PaperQuestionStatusEnum; +import com.ningdatech.carapi.archives.manage.ExaminationPaperManage; +import com.ningdatech.carapi.archives.model.ExamRuleInfo; +import com.ningdatech.carapi.archives.model.po.ReqExamRulePO; +import com.ningdatech.carapi.archives.model.po.ReqSaveExamPaperPO; +import com.ningdatech.carapi.archives.model.vo.ResExamRuleVO; +import com.ningdatech.carapi.archives.service.IExamPaperQuestionService; +import com.ningdatech.carapi.archives.service.IExamPaperService; +import com.ningdatech.carapi.archives.service.IPaperQuestionService; +import com.ningdatech.carapi.common.constant.GenderEnum; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.assembler.TrainingAssembler; +import com.ningdatech.carapi.driver.constant.*; +import com.ningdatech.carapi.driver.constants.DriverConstant; +import com.ningdatech.carapi.driver.entity.*; +import com.ningdatech.carapi.driver.helper.DriverBehaviorScoreHelper; +import com.ningdatech.carapi.driver.helper.DriverInfoHelper; +import com.ningdatech.carapi.driver.model.*; +import com.ningdatech.carapi.driver.model.bo.CodingRuleBO; +import com.ningdatech.carapi.driver.model.dto.TrainerInfoExportDTO; +import com.ningdatech.carapi.driver.model.po.*; +import com.ningdatech.carapi.driver.model.query.TrainingOrgTrainersQuery; +import com.ningdatech.carapi.driver.model.vo.*; +import com.ningdatech.carapi.driver.service.*; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.RandomUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/10 上午10:00 + */ +@Component +@RequiredArgsConstructor +public class TrainingOrganizationManage { + private final ITrainingOrganizationService iTrainingOrganizationService; + private final RegionsCacheHelper regionsCacheHelper; + private final ITrainingOrganizationMaterialService iTrainingOrganizationMaterialService; + private final ITrainingOrganizationTrainerService iTrainingOrganizationTrainerService; + private final CompanyService companyService; + private final IDriverInfoService driverInfoService; + private final UserInfoHelper userInfoHelper; + private final ITrainingMaterialService iTrainingMaterialService; + private final IExamRecordService iExamRecordService; + private final IExamRecordDetailService iExamRecordDetailService; + private final IDriverScoreInfoService iDriverScoreInfoService; + private final IDriverScoreRecordService iDriverScoreRecordService; + private final DriverBehaviorScoreHelper driverBehaviorScoreHelper; + private final DriverInfoHelper driverInfoHelper; + private final IStarManageService starManageService; + private final ITrainingOrganizationTrainerService trainingOrganizationTrainerService; + private final IDriverInfoService iDriverInfoService; + private final ExaminationPaperManage examinationPaperManage; + private final IPaperQuestionService iPaperQuestionService; + private final IExamPaperQuestionService iExamPaperQuestionService; + private final IExamPaperService iExamPaperService; + private final ICertificateService certificateService; + + + public PageVo trainingOrganizationList(ReqTrainingOrganizationListPO request) { + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(TrainingOrganization.class); + TrainingOrganizationManage context = (TrainingOrganizationManage) AopContext.currentProxy(); + context.buildQuery(wrapper, request); + Page page = iTrainingOrganizationService.page(new Page<>(pageNumber, pageSize), wrapper); + + PageVo pageVo = new PageVo<>(); + long total = page.getTotal(); + pageVo.setTotal(total); + if (total == 0) { + return pageVo; + } + List records = page.getRecords(); + // 获取培训组织关联的试卷信息 + List examPaperIds = records.stream().map(TrainingOrganization::getExamPaperId).collect(Collectors.toList()); + Map examPaperMap = iExamPaperService.list(Wrappers.lambdaQuery(ExamPaper.class) + .in(ExamPaper::getId, examPaperIds)).stream() + .collect(Collectors.toMap(ExamPaper::getId, e -> e)); + + List resVoList = records.stream().map(r -> { + ResTrainingOrganizationListVO resVO = new ResTrainingOrganizationListVO(); + Long trainingOrganizationId = r.getId(); + resVO.setTrainingOrganizationId(trainingOrganizationId); + resVO.setTrainingTopic(r.getTrainingTopic()); + resVO.setAddress(r.getAddress()); + resVO.setTrainingStartTime(r.getTrainingStartTime()); + resVO.setTrainingEndTime(r.getTrainingEndTime()); + Long trainingOrganizationRegionId = r.getRegionId(); + if (Objects.nonNull(trainingOrganizationRegionId)) { + resVO.setRegionId(trainingOrganizationRegionId); + resVO.setRegionName(regionsCacheHelper.getDisplayName(trainingOrganizationRegionId)); + } + resVO.setCreateTime(r.getCreateOn()); + if (Objects.nonNull(r.getTrainingMode())) { + resVO.setTrainingMode(TrainingModeEnum.valueOf(r.getTrainingMode())); + } + if (Objects.nonNull(r.getTrainingStatus())) { + resVO.setTrainingStatus(TrainingStatusEnum.valueOf(r.getTrainingStatus())); + } + List examPaperIdList = Lists.newArrayList(); + List examPaperNameList = Lists.newArrayList(); + // 判断培训组织关联的试卷信息是否是随机试卷 + if (DefValConstants.RANDOM_EXAM_PAPER_ID.equals(r.getExamPaperId()) && + StringUtils.isNotBlank(r.getRandomExamPaperId())){ + // 是随机试卷,返回随机试卷信息 + List idList = Arrays.stream(r.getRandomExamPaperId().split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + examPaperIdList.addAll(idList); + List nameList = Arrays.stream(r.getExamPaperName().split(StrPool.COMMA)).collect(Collectors.toList()); + examPaperNameList.addAll(nameList); + }else { + examPaperIdList.add(r.getExamPaperId()); + examPaperNameList.add(r.getExamPaperName()); + } + resVO.setExamPaperId(examPaperIdList); + resVO.setExamPaperName(examPaperNameList); + // 是线上考试且考试未开始要可以设置考试时间 + String trainingMode = r.getTrainingMode(); + if (TrainingModeEnum.online.name().equals(trainingMode)){ + LocalDateTime examStartTime = r.getExamStartTime(); + if (Objects.isNull(examStartTime) || LocalDateTime.now().compareTo(examStartTime) < 0){ + resVO.setCanSetExamTime(Boolean.TRUE); + } + } + resVO.setExamStartTime(r.getExamStartTime()); + resVO.setExamEndTime(r.getExamEndTime()); + return resVO; + }).collect(Collectors.toList()); + pageVo.setRecords(resVoList); + return pageVo; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildQuery(LambdaQueryWrapper wrapper, ReqTrainingOrganizationListPO request) { + // 获取入参 + String address = request.getAddress(); + String trainingTopic = request.getTrainingTopic(); + Long regionId = request.getRegionId(); + TrainingModeEnum trainingMode = request.getTrainingMode(); + // 转换参数 + String trainingModeStr = Objects.nonNull(trainingMode) ? trainingMode.name() : null; + List regionIdList = new ArrayList<>(); + if (Objects.nonNull(regionId)) { + regionIdList = regionsCacheHelper.listChildRegionId(regionId); + } + List trainingTypeList = request.getTrainingTypeList(); + wrapper.in(CollectionUtil.isNotEmpty(regionIdList), TrainingOrganization::getRegionId, regionIdList) + .eq(StringUtils.isNotBlank(trainingModeStr), TrainingOrganization::getTrainingMode, trainingModeStr) + .like(StringUtils.isNotBlank(address), TrainingOrganization::getAddress, address) + .eq(StringUtils.isNotBlank(trainingTopic), TrainingOrganization::getTrainingTopic, trainingTopic) + .in(CollectionUtil.isNotEmpty(trainingTypeList), TrainingOrganization::getTrainingType, trainingTypeList) + .orderByDesc(TrainingOrganization::getCreateOn); + } + + public ResTrainingOrganizationDetailVO trainingOrganizationDetail(Long organizationId) { + + UserBasicInfoVO userFullInfo = userInfoHelper.getUserFullInfo(); + Long roleId = userFullInfo.getRoleId(); + Long userId = userFullInfo.getUserId(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(TrainingOrganization.class); + TrainingOrganizationManage context = (TrainingOrganizationManage) AopContext.currentProxy(); + context.buildTrainingOrganizationQuery(wrapper, organizationId); + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getOne(wrapper); + //TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(organizationId); + if (Objects.isNull(trainingOrganization)) { + throw new BizException("培训组织不存在"); + } + // 装配培训基本信息 + TrainingBasicInfo trainingBasicInfo = TrainingAssembler.buildTrainingBasicInfo(trainingOrganization); + + // 装配培训资料 + List trainingOrganizationMaterialList = iTrainingOrganizationMaterialService + .list(Wrappers.lambdaQuery(TrainingOrganizationMaterial.class) + .eq(TrainingOrganizationMaterial::getTrainingOrganizationId, organizationId)); + List materialIdList = trainingOrganizationMaterialList.stream() + .map(TrainingOrganizationMaterial::getTrainingMaterialId).collect(Collectors.toList()); + List materialList = iTrainingMaterialService.list(Wrappers.lambdaQuery(TrainingMaterial.class) + .in(TrainingMaterial::getId, materialIdList)); + TrainingMaterialOverviewInfo trainingMaterialOverviewInfo = TrainingAssembler.buildTrainingMaterialOverviewInfo(materialList); + + // 装配试卷 + TrainingExamPaperInfo trainingExamPaperInfo = new TrainingExamPaperInfo(); + Long examPaperId = trainingOrganization.getExamPaperId(); + trainingExamPaperInfo.setExamPaperId(examPaperId); + // 如果是随机试卷且登录用户是驾驶员 + if (DefValConstants.RANDOM_EXAM_PAPER_ID.equals(examPaperId)){ + // 随机试卷 + trainingExamPaperInfo.setExamPaperName(DefValConstants.RANDOM_PAPER); + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)){ + ExamPaper examPaper = iExamPaperService.getOne(Wrappers.lambdaQuery(ExamPaper.class) + .eq(ExamPaper::getTrainingOrganizationId, organizationId) + .eq(ExamPaper::getDriverUserId, userId)); + if (Objects.isNull(examPaper)){ + throw new BizException("未获取到随机试卷!"); + } + trainingExamPaperInfo.setExamPaperName(examPaper.getExamPaperName()); + trainingExamPaperInfo.setExamPaperId(examPaper.getId()); + } + } else { + trainingExamPaperInfo.setExamPaperName(trainingOrganization.getExamPaperName()); + } + + // 装配培训人员信息 + List trainerList = iTrainingOrganizationTrainerService + .list(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, organizationId)); + + List trainersInfoList = trainerList.stream() + .map(TrainingAssembler::buildOrganizationTrainingTrainersInfo).collect(Collectors.toList()); + + ResTrainingOrganizationDetailVO resVO = new ResTrainingOrganizationDetailVO(); + resVO.setTrainingBasicInfo(trainingBasicInfo); + resVO.setTrainingExamPaperInfo(trainingExamPaperInfo); + resVO.setTrainingMaterialOverviewInfo(trainingMaterialOverviewInfo); + resVO.setTrainingTrainersInfoList(trainersInfoList); + return resVO; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildTrainingOrganizationQuery(LambdaQueryWrapper wrapper, Long organizationId) { + wrapper.eq(TrainingOrganization::getId,organizationId); + } + + /** + * 新建培训组织(新接口) + * + * @param request + * @return + */ + @Transactional(rollbackFor = Exception.class) + public ResCreateTrainingOrgVO createTrainingOrganization(ReqCreateTrainingOrgPO request) { + // 获取入参信息 + TrainingBasicInfo trainingBasicInfo = request.getTrainingBasicInfo(); + String trainingType = trainingBasicInfo.getTrainingType().name(); + TrainingExamPaperInfo trainingExamPaperInfo = request.getTrainingExamPaperInfo(); + List trainingTrainersInfoList = request.getTrainingTrainersInfoList(); + TrainingMaterialOverviewInfo trainingMaterialOverviewInfo = request.getTrainingMaterialOverviewInfo(); + + // 获取登陆账号信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + Long loginUserId = loginUser.getUserId(); + // 获取登陆者的 regionId + Long regionId = userInfoHelper.getUserRegionId(); + + // 保存培训基础信息 考试试卷 + TrainingOrganization saveRecord = assemblerTrainingOrganization(trainingBasicInfo, trainingExamPaperInfo, trainingTrainersInfoList, null); + saveRecord.setCreateBy(loginUserId); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setRegionId(regionId); + iTrainingOrganizationService.save(saveRecord); + ResCreateTrainingOrgVO resCreateTrainingOrgVO = new ResCreateTrainingOrgVO(); + resCreateTrainingOrgVO.setTrainingOrganizationId(saveRecord.getId()); + + // 如果是随机试卷 保存生成的随机试卷与培训组织的关联 + if (DefValConstants.RANDOM_EXAM_PAPER_ID.equals(saveRecord.getExamPaperId()) && + StringUtils.isNotBlank(saveRecord.getRandomExamPaperId())){ + List idList = Arrays.stream(saveRecord.getRandomExamPaperId().split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + List examPapers = iExamPaperService.list(Wrappers.lambdaQuery(ExamPaper.class).in(ExamPaper::getId, idList)); + List examPaperList = examPapers.stream().peek(e -> e.setTrainingOrganizationId(saveRecord.getId())).collect(Collectors.toList()); + iExamPaperService.updateBatchById(examPaperList); + } + + // 保存培训资料 + // TODO 校验材料列表 + List allList = trainingMaterialOverviewInfo.getAllList(); + List materialSaveRecordList = new ArrayList<>(); + for (TrainingMaterialInfo trainingMaterialInfo : allList) { + TrainingOrganizationMaterial materialSaveRecord = new TrainingOrganizationMaterial(); + materialSaveRecord.setCreateBy(loginUserId); + materialSaveRecord.setCreateOn(LocalDateTime.now()); + materialSaveRecord.setUpdateOn(LocalDateTime.now()); + materialSaveRecord.setMaterialType(trainingMaterialInfo.getMaterialType().name()); + materialSaveRecord.setTrainingMaterialId(trainingMaterialInfo.getTrainingMaterialId()); + materialSaveRecord.setTrainingOrganizationId(saveRecord.getId()); + materialSaveRecordList.add(materialSaveRecord); + } + iTrainingOrganizationMaterialService.saveBatch(materialSaveRecordList); + + if (CollectionUtil.isNotEmpty(trainingTrainersInfoList)) { + + // 根据培训类型,将选择的培训人员设置为不能参加该类型的培训,直至上传合格证培训完成,再次更新 + List driverIds = trainingTrainersInfoList.stream().map(TrainingTrainersInfo::getDriverId).collect(Collectors.toList()); + List driverInfos = driverInfoService.listByIds(driverIds); + for (DriverInfo driverInfo : driverInfos) { + if (TrainingTypeEnum.forensic_registration_training.name().equals(trainingType)){ + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_NOT_TAKE.getCode()); + } else if (TrainingTypeEnum.continuing_education_training.name().equals(trainingType)) { + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_NOT_TAKE.getCode()); + } else if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingType)) { + driverInfo.setReplacementRegistrationFlag(TrainingRegistrationFlagEnum.CAN_NOT_TAKE.getCode()); + } + // 更新驾驶员是否可以参见培训报名标志 + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + List distinctTrainingTrainersInfoList = new ArrayList<>(); + HashSet driverIdSet = new HashSet<>(); + for (TrainingTrainersInfo trainingTrainersInfo : trainingTrainersInfoList) { + if (driverIdSet.add(trainingTrainersInfo.getDriverId())) { + distinctTrainingTrainersInfoList.add(trainingTrainersInfo); + } + } + + // 保存培训人员 + List companyIdList = distinctTrainingTrainersInfoList.stream().map(TrainingTrainersInfo::getCompanyId).collect(Collectors.toList()); + List driverIdList = distinctTrainingTrainersInfoList.stream().map(TrainingTrainersInfo::getDriverId).collect(Collectors.toList()); + + Map companyMap = companyService.listCompanyByIds(companyIdList); + Map driverInfoMap = driverInfoService.listDriverInfoByIds(driverIdList); + List trainerSaveRecordList = + assemblerTrainingOrganizationTrainerList(distinctTrainingTrainersInfoList, driverInfoMap, companyMap, saveRecord.getId() + , trainingExamPaperInfo.getExamPaperId(), trainingExamPaperInfo.getExamPaperName(),trainingBasicInfo,saveRecord); + iTrainingOrganizationTrainerService.saveBatch(trainerSaveRecordList); + } + + // 新建考试记录 + ExamRecord examRecordSaveRecord = assemblerSaveExamRecord(LoginUserUtil.getUserId() + , request.getTrainingExamPaperInfo().getExamPaperId(), saveRecord.getId() + , trainingBasicInfo.getTrainingType().name()); + iExamRecordService.save(examRecordSaveRecord); + return resCreateTrainingOrgVO; + } + + /** + * 装配考试记录列表 + * + * @return + */ + private ExamRecord assemblerSaveExamRecord(Long createBy, Long examPaperId + , Long trainingOrganizationId, String examType) { + ExamRecord saveRecord = new ExamRecord(); + saveRecord.setCreateBy(createBy); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setExamPaperId(examPaperId); + saveRecord.setTrainingOrganizationId(trainingOrganizationId); + saveRecord.setExamType(examType); + return saveRecord; + } + + + /** + * 装配新的培训组织驾驶员列表 SaveRecordList + */ + private List assemblerTrainingOrganizationTrainerList(List trainingTrainersInfoList + , Map driverInfoMap, Map companyMap + , Long trainingOrganizationId, Long examPaperId, String examPaperName, TrainingBasicInfo trainingBasicInfo, TrainingOrganization saveRecord) { + List trainerSaveRecordList = new ArrayList<>(); + Map examPaperMap = iExamPaperService.list(Wrappers.lambdaQuery(ExamPaper.class) + .eq(ExamPaper::getTrainingOrganizationId,saveRecord.getId()) + .select(ExamPaper::getId, ExamPaper::getExamPaperName)) + .stream().collect(Collectors.toMap(ExamPaper::getExamPaperName, e -> e)); + for (TrainingTrainersInfo trainersInfo : trainingTrainersInfoList) { + DriverInfo driverInfo = driverInfoMap.get(trainersInfo.getDriverId()); + Company company = companyMap.get(driverInfo.getCompanyId()); + + TrainingOrganizationTrainer trainerSaveRecord = new TrainingOrganizationTrainer(); + trainerSaveRecord.setCreateOn(LocalDateTime.now()); + trainerSaveRecord.setUpdateOn(LocalDateTime.now()); + trainerSaveRecord.setTrainingOrganizationId(trainingOrganizationId); + trainerSaveRecord.setDriverName(driverInfo.getDriverName()); + trainerSaveRecord.setDriverUserId(driverInfo.getUserId()); + trainerSaveRecord.setDriverId(driverInfo.getId()); + // 如果是随机试卷 + String trainingTopic = trainingBasicInfo.getTrainingTopic(); + if (DefValConstants.RANDOM_PAPER.equals(examPaperName)){ + String randomExamPaperName = trainingTopic + StrPool.DASH + trainersInfo.getDriverName() + + StrPool.DASH + DefValConstants.RANDOM_PAPER; + trainerSaveRecord.setExamPaperName(randomExamPaperName); + ExamPaper examPaper = examPaperMap.get(randomExamPaperName); + if (Objects.nonNull(examPaper)) { + trainerSaveRecord.setExamPaperId(examPaper.getId()); + } + }else { + trainerSaveRecord.setExamPaperId(examPaperId); + trainerSaveRecord.setExamPaperName(examPaperName); + } + trainerSaveRecord.setExamRegistrationNo(generateExamRegistrationNo()); + trainerSaveRecord.setExaminationStatus(ExaminationStatusEnum.waiting_examination.name()); + trainerSaveRecord.setCompanyId(company.getId()); + trainerSaveRecord.setCompanyName(company.getName()); + trainerSaveRecordList.add(trainerSaveRecord); + } + return trainerSaveRecordList; + } + + /** + * 保存培训组织(新接口) + * + * @param request + * @return + */ + @Transactional(rollbackFor = Exception.class) + public ResCreateTrainingOrgVO saveTrainingOrganization(ReqCreateTrainingOrgPO request) { + Long organizationId = request.getOrganizationId(); + TrainingExamPaperInfo trainingExamPaperInfo = request.getTrainingExamPaperInfo(); + if (Objects.isNull( trainingExamPaperInfo.getExamPaperName())){ + throw new BizException("请选择考试试卷!"); + } + + if (Objects.isNull(organizationId)) { + return createTrainingOrganization(request); + } else { + return updateTrainingOrganization(request); + } + } + + @Transactional(rollbackFor = Exception.class) + public ResCreateTrainingOrgVO updateTrainingOrganization(ReqCreateTrainingOrgPO request) { + // 获取入参信息 + Long organizationId = request.getOrganizationId(); + TrainingBasicInfo trainingBasicInfo = request.getTrainingBasicInfo(); + String trainingType = trainingBasicInfo.getTrainingType().name(); + TrainingExamPaperInfo trainingExamPaperInfo = request.getTrainingExamPaperInfo(); + List trainingTrainersInfoList = request.getTrainingTrainersInfoList(); + TrainingMaterialOverviewInfo trainingMaterialOverviewInfo = request.getTrainingMaterialOverviewInfo(); + + // 获取登陆账号信息 + Long loginUserId = LoginUserUtil.getUserId(); + // 获取登陆者的 regionId + Long regionId = userInfoHelper.getUserRegionId(); + + TrainingOrganization currentTrainingOrganization = iTrainingOrganizationService.getById(organizationId); + if (Objects.isNull(currentTrainingOrganization)) { + throw new BizException("培训组织不存在"); + } + + // 保存培训基础信息 考试试卷 + TrainingOrganization updateRecord = assemblerTrainingOrganization(trainingBasicInfo, trainingExamPaperInfo, trainingTrainersInfoList,organizationId); + updateRecord.setId(organizationId); + iTrainingOrganizationService.updateById(updateRecord); + ResCreateTrainingOrgVO resCreateTrainingOrgVO = new ResCreateTrainingOrgVO(); + resCreateTrainingOrgVO.setTrainingOrganizationId(updateRecord.getId()); + + // 如果是随机试卷 保存生成的随机试卷与培训组织的关联 + if (DefValConstants.RANDOM_EXAM_PAPER_ID.equals(updateRecord.getExamPaperId()) && + StringUtils.isNotBlank(updateRecord.getRandomExamPaperId())){ + List idList = Arrays.stream(updateRecord.getRandomExamPaperId().split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + List examPapers = iExamPaperService.list(Wrappers.lambdaQuery(ExamPaper.class).in(ExamPaper::getId, idList)); + List examPaperList = examPapers.stream().peek(e -> e.setTrainingOrganizationId(updateRecord.getId())).collect(Collectors.toList()); + iExamPaperService.updateBatchById(examPaperList); + } + + // 保存培训资料 先删除后新增 + // TODO 校验材料列表 + iTrainingOrganizationMaterialService.remove(Wrappers.lambdaQuery(TrainingOrganizationMaterial.class) + .eq(TrainingOrganizationMaterial::getTrainingOrganizationId, organizationId)); + List allList = trainingMaterialOverviewInfo.getAllList(); + List materialSaveRecordList = new ArrayList<>(); + for (TrainingMaterialInfo trainingMaterialInfo : allList) { + TrainingOrganizationMaterial materialSaveRecord = new TrainingOrganizationMaterial(); + materialSaveRecord.setCreateBy(loginUserId); + materialSaveRecord.setCreateOn(LocalDateTime.now()); + materialSaveRecord.setUpdateOn(LocalDateTime.now()); + materialSaveRecord.setMaterialType(trainingMaterialInfo.getMaterialType().name()); + materialSaveRecord.setTrainingMaterialId(trainingMaterialInfo.getTrainingMaterialId()); + materialSaveRecord.setTrainingOrganizationId(organizationId); + materialSaveRecordList.add(materialSaveRecord); + } + iTrainingOrganizationMaterialService.saveBatch(materialSaveRecordList); + + + // 获取原来培训组织选择的驾驶员 + List currentTrainingOrganizationTrainerList = iTrainingOrganizationTrainerService + .list(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, organizationId)); + List currentDriverIdList = currentTrainingOrganizationTrainerList.stream() + .map(TrainingOrganizationTrainer::getDriverId) + .collect(Collectors.toList()); + + + if (CollectionUtil.isNotEmpty(trainingTrainersInfoList)) { + List distinctTrainingTrainersInfoList = new ArrayList<>(); + HashSet driverIdSet = new HashSet<>(); + for (TrainingTrainersInfo trainingTrainersInfo : trainingTrainersInfoList) { + if (driverIdSet.add(trainingTrainersInfo.getDriverId())) { + distinctTrainingTrainersInfoList.add(trainingTrainersInfo); + } + } + // 保存培训人员 先删除再新增 + List companyIdList = distinctTrainingTrainersInfoList.stream() + .map(TrainingTrainersInfo::getCompanyId) + .collect(Collectors.toList()); + List driverIdList = distinctTrainingTrainersInfoList.stream() + .map(TrainingTrainersInfo::getDriverId) + .collect(Collectors.toList()); + + List addList = new ArrayList<>(); + List removeList = new ArrayList<>(); + + // 新增列表 + for (Long driverId : driverIdList) { + if (!currentDriverIdList.contains(driverId)) { + addList.add(driverId); + } + } + + // 删除列表 + for (Long driverId : currentDriverIdList) { + if (!driverIdList.contains(driverId)) { + removeList.add(driverId); + } + } + + // 删除培训人员,并将其培训标志更新为可参加对应的培训报名 + if (CollectionUtil.isNotEmpty(removeList)) { + // 移除掉该培训组织删除掉的培训人员 + iTrainingOrganizationTrainerService.remove(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId,organizationId) + .in(TrainingOrganizationTrainer::getDriverId, removeList)); + List removeDriverInfos = driverInfoService.listByIds(removeList); + for (DriverInfo driverInfo : removeDriverInfos) { + if (TrainingTypeEnum.forensic_registration_training.name().equals(trainingType)){ + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (TrainingTypeEnum.continuing_education_training.name().equals(trainingType)) { + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingType)) { + driverInfo.setReplacementRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } + // 更新驾驶员是否可以参见培训报名标志 + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + } + + // 新增培训人员 + if (CollectionUtil.isNotEmpty(addList)) { + // 根据培训类型,将新选择的培训人员设置为不能参加该类型的培训,直至上传合格证培训完成,再次更新 + List driverInfos = driverInfoService.listByIds(addList); + for (DriverInfo driverInfo : driverInfos) { + if (TrainingTypeEnum.forensic_registration_training.name().equals(trainingType)){ + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_NOT_TAKE.getCode()); + } else if (TrainingTypeEnum.continuing_education_training.name().equals(trainingType)) { + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_NOT_TAKE.getCode()); + } else if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingType)) { + driverInfo.setReplacementRegistrationFlag(TrainingRegistrationFlagEnum.CAN_NOT_TAKE.getCode()); + } + // 更新驾驶员是否可以参见培训报名标志 + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + + distinctTrainingTrainersInfoList = distinctTrainingTrainersInfoList.stream().filter(r -> addList.contains(r.getDriverId())).collect(Collectors.toList()); + Map idCompanyMap = companyService.listCompanyByIds(companyIdList); + Map idDriverInfoMap = driverInfoService.listDriverInfoByIds(driverIdList); + + List trainerSaveRecordList = new ArrayList<>(); + Long examPaperId = trainingExamPaperInfo.getExamPaperId(); + String examPaperName = trainingExamPaperInfo.getExamPaperName(); + Map examPaperMap = iExamPaperService.list(Wrappers.lambdaQuery(ExamPaper.class) + .eq(ExamPaper::getTrainingOrganizationId,organizationId) + .select(ExamPaper::getId, ExamPaper::getExamPaperName)) + .stream().collect(Collectors.toMap(ExamPaper::getExamPaperName, e -> e)); + for (TrainingTrainersInfo trainersInfo : distinctTrainingTrainersInfoList) { + DriverInfo driverInfo = idDriverInfoMap.get(trainersInfo.getDriverId()); + if (Objects.nonNull(driverInfo)) { + Company company = idCompanyMap.get(driverInfo.getCompanyId()); + TrainingOrganizationTrainer trainerSaveRecord = new TrainingOrganizationTrainer(); + trainerSaveRecord.setCreateOn(LocalDateTime.now()); + trainerSaveRecord.setUpdateOn(LocalDateTime.now()); + trainerSaveRecord.setTrainingOrganizationId(organizationId); + trainerSaveRecord.setDriverName(driverInfo.getDriverName()); + trainerSaveRecord.setDriverUserId(driverInfo.getUserId()); + trainerSaveRecord.setDriverId(driverInfo.getId()); + + // 如果是随机试卷 + String trainingTopic = trainingBasicInfo.getTrainingTopic(); + if (DefValConstants.RANDOM_PAPER.equals(examPaperName)){ + String randomExamPaperName = trainingTopic + StrPool.DASH + trainersInfo.getDriverName() + + StrPool.DASH + DefValConstants.RANDOM_PAPER; + trainerSaveRecord.setExamPaperName(randomExamPaperName); + ExamPaper examPaper = examPaperMap.get(randomExamPaperName); + if (Objects.nonNull(examPaper)) { + trainerSaveRecord.setExamPaperId(examPaper.getId()); + } + }else { + trainerSaveRecord.setExamPaperId(examPaperId); + trainerSaveRecord.setExamPaperName(examPaperName); + } + trainerSaveRecord.setExamRegistrationNo(generateExamRegistrationNo()); + trainerSaveRecord.setExaminationStatus(ExaminationStatusEnum.waiting_examination.name()); + trainerSaveRecord.setCompanyId(company.getId()); + trainerSaveRecord.setCompanyName(company.getName()); + trainerSaveRecordList.add(trainerSaveRecord); + } + } + if (CollectionUtil.isNotEmpty(trainerSaveRecordList)) { + iTrainingOrganizationTrainerService.saveBatch(trainerSaveRecordList); + } + } + // TODO 向所有驾驶员发送短信通知: + // {驾驶员姓名}您好:{散办名称}组织了关于{培训主题}的{培训模式}培训, + // 培训时间为{培训开始 至 结束时间},培训地点为{培训地点:线下培训时显示}, + // 培训链接{生成培训链接,点击后跳转培训页面},请准时参加培训。 + // 联系人:{联系人},联系电话:{联系电话},考证号:{准考证号}。 + for (TrainingTrainersInfo trainingTrainersInfo : trainingTrainersInfoList) { + // 若是线下培训 + String offlineMessage = String.format(DefValConstants.OFFLINE_MESSAGE_TEMPLATE,trainingTrainersInfo.getDriverName() ,"散办名称", "培训主题","培训模式","培训开始时间","培训结束时间","培训地点","培训链接","联系人","联系电话","准考证号"); + // 若是线上培训 + String onlineMessage = String.format(DefValConstants.ONLINE_MESSAGE_TEMPLATE,trainingTrainersInfo.getDriverName() ,"散办名称", "培训主题","培训模式","培训开始时间","培训结束时间","培训链接","联系人","联系电话","准考证号"); + // TODO 调用发短信接口发送短信 + } + } + return resCreateTrainingOrgVO; + } + + + private TrainingOrganization assemblerTrainingOrganization(TrainingBasicInfo trainingBasicInfo, TrainingExamPaperInfo trainingExamPaperInfo, List trainingTrainersInfoList, Long organizationId) { + TrainingOrganization saveRecord = new TrainingOrganization(); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setTrainingTopic(trainingBasicInfo.getTrainingTopic()); + saveRecord.setTrainingStartTime(trainingBasicInfo.getTrainingStartTime()); + saveRecord.setTrainingEndTime(trainingBasicInfo.getTrainingEndTime()); + saveRecord.setAddress(trainingBasicInfo.getAddress()); + if (Objects.nonNull(trainingBasicInfo.getTrainingMode())) { + saveRecord.setTrainingMode(trainingBasicInfo.getTrainingMode().name()); + } + saveRecord.setTrainingType(trainingBasicInfo.getTrainingType().name()); + saveRecord.setContacts(trainingBasicInfo.getContacts()); + saveRecord.setContactNumber(trainingBasicInfo.getContactNumber()); + + String trainingStatus = Objects.nonNull(trainingBasicInfo.getTrainingStatus()) ? trainingBasicInfo.getTrainingStatus().name() : TrainingStatusEnum.enable.name(); + saveRecord.setTrainingStatus(trainingStatus); + saveRecord.setRemark(trainingBasicInfo.getRemark()); + Long examPaperId = trainingExamPaperInfo.getExamPaperId(); + String examPaperName = trainingExamPaperInfo.getExamPaperName(); + // 判断是否为随机试卷 + if (Objects.isNull(examPaperId) && DefValConstants.RANDOM_PAPER.equals(examPaperName)){ + List randomExamPaperList = createRandomPaper(trainingBasicInfo.getTrainingTopic(),trainingTrainersInfoList,organizationId); + String idStr = randomExamPaperList.stream().map(r -> String.valueOf(r.getId())).collect(Collectors.joining(StrPool.COMMA)); + saveRecord.setRandomExamPaperId(idStr); + saveRecord.setExamPaperId(DefValConstants.RANDOM_EXAM_PAPER_ID); + String examNameList = randomExamPaperList.stream().map(ExamPaper::getExamPaperName).collect(Collectors.joining(StrPool.COMMA)); + saveRecord.setExamPaperName(examNameList); + }else { + saveRecord.setExamPaperId(examPaperId); + saveRecord.setExamPaperName(examPaperName); + } + return saveRecord; + } + private List createRandomPaper(String trainTopic, List trainingTrainersInfoList, Long organizationId) { + // 获取当前登录用户所在区域的考试试卷规则 + UserBasicInfoVO userFullInfo = userInfoHelper.getUserFullInfo(); + Long regionId = userFullInfo.getRegionId(); + ReqExamRulePO request = new ReqExamRulePO(); + request.setRegionId(regionId); + ResExamRuleVO examRule = examinationPaperManage.getExamRule(request); + + // 对在当前培训组织内的每个培训人员 + // 根据试卷规则从题库中抽取对应的题目,组成一套试卷 + List resList = Lists.newArrayList(); + List driverUserIdList = trainingTrainersInfoList.stream().map(TrainingTrainersInfo::getDriverUserId).collect(Collectors.toList()); + // 如果培训组织ID不为null 说明为编辑,先删除选择的培训人员所在培训组织已经生成的随机的试卷 + if (Objects.nonNull(organizationId) && CollUtil.isNotEmpty(driverUserIdList)){ + iExamPaperService.remove(Wrappers.lambdaQuery(ExamPaper.class) + .eq(ExamPaper::getTrainingOrganizationId, organizationId) + .eq(ExamPaper::getIsRandom, IsRandomEnum.RANDOM_PAPER.getCode()) + .in(ExamPaper::getDriverUserId, driverUserIdList)); + } + + for (TrainingTrainersInfo trainingTrainersInfo : trainingTrainersInfoList) { + ExamRuleInfo singleChoiceQuestionRule = examRule.getSingleChoiceQuestionRule(); + ExamRuleInfo multipleChoiceQuestionRule = examRule.getMultipleChoiceQuestionRule(); + ExamRuleInfo judgmentalQuestionRule = examRule.getJudgmentalQuestionRule(); + // 单选题 + Integer singleChoiceQuestionCnt = singleChoiceQuestionRule.getQuestionCnt(); + // 从题库中获取所有在使用的单选题 + List singleList = iPaperQuestionService.list(Wrappers.lambdaQuery(PaperQuestion.class) + .eq(PaperQuestion::getQuestionStatus, PaperQuestionStatusEnum.IN_USE.name()) + .eq(PaperQuestion::getQuestionType, QuestionTypeEnum.SINGLE_CHOICE.name())); + // 使用 Collections.synchronizedList() 方法确保多线程安全 + List singleSynchronizedList = Collections.synchronizedList(singleList); + // 从列表中随机抽取指定数量的单选题 + List singleElements = getRandomElements(singleSynchronizedList, singleChoiceQuestionCnt); + + // 多选题 + Integer multipleChoiceQuestionCnt = multipleChoiceQuestionRule.getQuestionCnt(); + // 从题库中获取所有在使用的多选题 + List multipleList = iPaperQuestionService.list(Wrappers.lambdaQuery(PaperQuestion.class) + .eq(PaperQuestion::getQuestionStatus, PaperQuestionStatusEnum.IN_USE.name()) + .eq(PaperQuestion::getQuestionType, QuestionTypeEnum.MULTIPLE_CHOICE.name())); + // 使用 Collections.synchronizedList() 方法确保多线程安全 + List multipleSynchronizedList = Collections.synchronizedList(multipleList); + // 从列表中随机抽取指定数量的多选题 + List multipleElements = getRandomElements(multipleSynchronizedList, multipleChoiceQuestionCnt); + + // 判断题 + Integer judgmentalQuestionCnt = judgmentalQuestionRule.getQuestionCnt(); + // 从题库中获取所有在使用的判断题 + List judgmentalList = iPaperQuestionService.list(Wrappers.lambdaQuery(PaperQuestion.class) + .eq(PaperQuestion::getQuestionStatus, PaperQuestionStatusEnum.IN_USE.name()) + .eq(PaperQuestion::getQuestionType, QuestionTypeEnum.JUDGMENTAL.name())); + // 使用 Collections.synchronizedList() 方法确保多线程安全 + List judgementalSynchronizedList = Collections.synchronizedList(judgmentalList); + // 从列表中随机抽取指定数量的单选题 + List judgmentalElements = getRandomElements(judgementalSynchronizedList, judgmentalQuestionCnt); + + + List examPaperQuestionIdList = new ArrayList<>(); + examPaperQuestionIdList.addAll(singleElements); + examPaperQuestionIdList.addAll(multipleElements); + examPaperQuestionIdList.addAll(judgmentalElements); + + List questionIdList = examPaperQuestionIdList.stream() + .map(ReqSaveExamPaperPO.ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList()); + + List paperQuestionList = iPaperQuestionService + .list(Wrappers.lambdaQuery(PaperQuestion.class).in(PaperQuestion::getId, questionIdList)); + Map paperQuestionIdTypeMap = paperQuestionList.stream().collect(Collectors.toMap(PaperQuestion::getId, PaperQuestion::getQuestionType)); + // 保存随机试卷基本信息 + ExamPaper examPaper = new ExamPaper(); + examPaper.setCreateOn(LocalDateTime.now()); + examPaper.setUpdateOn(LocalDateTime.now()); + examPaper.setExamPaperName(trainTopic + StrPool.DASH + trainingTrainersInfo.getDriverName() + + StrPool.DASH + DefValConstants.RANDOM_PAPER); + examPaper.setFullScore(ExamPaperQualifiedScoreConstant.EXAM_PAPER_FULL_SCORE); + examPaper.setQualifiedScore(ExamPaperQualifiedScoreConstant.EXAM_PAPER_QUALIFIED_SCORE); + examPaper.setRegionId(regionId); + examPaper.setExamRuleJson(JSONObject.toJSONString(examRule)); + examPaper.setIsRandom(IsRandomEnum.RANDOM_PAPER.getCode()); + examPaper.setDriverUserId(trainingTrainersInfo.getDriverUserId()); + iExamPaperService.save(examPaper); + + // 保存试卷题目关联关系 + List saveRecordList = new ArrayList<>(); + for (ReqSaveExamPaperPO.ExamPaperQuestionIdPO idPo : examPaperQuestionIdList) { + ExamPaperQuestion examPaperQuestion = new ExamPaperQuestion(); + examPaperQuestion.setExamPaperId(examPaper.getId()); + examPaperQuestion.setPaperQuestionId(idPo.getPaperQuestionId()); + examPaperQuestion.setCreateOn(LocalDateTime.now()); + examPaperQuestion.setUpdateOn(LocalDateTime.now()); + examPaperQuestion.setSortValue(idPo.getSortValue()); + examPaperQuestion.setQuestionType(paperQuestionIdTypeMap.get(idPo.getPaperQuestionId())); + examPaperQuestion.setIsRandom(IsRandomEnum.RANDOM_PAPER.getCode()); + saveRecordList.add(examPaperQuestion); + } + iExamPaperQuestionService.saveBatch(saveRecordList); + + List questionUsageCntUpdateList = examPaperQuestionIdList.stream().map(ReqSaveExamPaperPO.ExamPaperQuestionIdPO::getPaperQuestionId).collect(Collectors.toList()); + for (Long questionId : questionUsageCntUpdateList) { + questionUsageCntUpdate(questionId); + } + resList.add(examPaper); + } + return resList; + } + + public void questionUsageCntUpdate(Long questionId) { + PaperQuestion paperQuestion = iPaperQuestionService.getById(questionId); + if (Objects.isNull(paperQuestion)) { + return; + } else { + long usage = iExamPaperQuestionService.count(Wrappers.lambdaQuery(ExamPaperQuestion.class) + .eq(ExamPaperQuestion::getPaperQuestionId, questionId)); + paperQuestion.setUsageCnt(usage); + iPaperQuestionService.updateById(paperQuestion); + } + } + + private List getRandomElements(List list, Integer count) { + // 使用 Random 对象生成随机索引 + Random random = new Random(); + List randomList = Lists.newArrayList(); + for (int i = 0; i < count; i++) { + int index = random.nextInt(list.size()); + randomList.add(list.get(index)); + } + AtomicLong i = new AtomicLong(1L); + return randomList.stream().map(r -> { + ReqSaveExamPaperPO.ExamPaperQuestionIdPO po = new ReqSaveExamPaperPO.ExamPaperQuestionIdPO(); + po.setPaperQuestionId(r.getId()); + po.setSortValue(i.longValue()); + i.incrementAndGet(); + return po; + }).collect(Collectors.toList()); + } + + private String generateExamRegistrationNo() { + String examRegistrationNo = RandomUtil.randomString(16); + return examRegistrationNo; + } + + @Transactional(rollbackFor = Exception.class) + public void uploadExamResult(ReqUploadExamResultPO request) { + // 获取入参参数 + Long driverId = request.getDriverId(); + Long trainingOrganizationId = request.getTrainingOrganizationId(); + Integer score = request.getScore(); + + // 获取驾驶员详情 + DriverInfo driverInfo = driverInfoService.getById(driverId); + // 获取培训组织详情 + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(trainingOrganizationId); + + String isQualified = score >= ExamPaperQualifiedScoreConstant.EXAM_PAPER_QUALIFIED_SCORE ? ExamQualifiedEnum.qualified.name() : ExamQualifiedEnum.unqualified.name(); + if (!TrainingTypeEnum.transcoding_training.name().equals(trainingOrganization.getTrainingType())) { + // 获取培训驾驶员信息 更新驾驶员培训人员信息 + TrainingOrganizationTrainer trainingOrganizationTrainer = iTrainingOrganizationTrainerService.getOne(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getDriverId, driverId) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, trainingOrganizationId)); + trainingOrganizationTrainer.setScore(score); + trainingOrganizationTrainer.setIsQualified(isQualified); + trainingOrganizationTrainer.setExaminationStatus(ExaminationStatusEnum.examined.name()); + iTrainingOrganizationTrainerService.saveOrUpdate(trainingOrganizationTrainer); + } + + ExamRecord examRecord = iExamRecordService.getOne(Wrappers.lambdaQuery(ExamRecord.class) + .eq(ExamRecord::getTrainingOrganizationId, trainingOrganizationId)); + // 新建考试记录 + ExamRecordDetail examRecordDetailSaveRecord = new ExamRecordDetail(); + examRecordDetailSaveRecord.setExamRecordId(examRecord.getId()); + examRecordDetailSaveRecord.setCompanyId(driverInfo.getCompanyId()); + examRecordDetailSaveRecord.setCompanyName(driverInfo.getCompanyName()); + examRecordDetailSaveRecord.setCreateBy(LoginUserUtil.getUserId()); + examRecordDetailSaveRecord.setCreateOn(LocalDateTime.now()); + examRecordDetailSaveRecord.setUpdateOn(LocalDateTime.now()); + examRecordDetailSaveRecord.setDriverId(driverInfo.getId()); + examRecordDetailSaveRecord.setDriverUserId(driverInfo.getUserId()); + examRecordDetailSaveRecord.setDriverName(driverInfo.getDriverName()); + examRecordDetailSaveRecord.setExamResult(isQualified); + examRecordDetailSaveRecord.setExamTime(LocalDateTime.now()); + examRecordDetailSaveRecord.setExamType(examRecord.getExamType()); + examRecordDetailSaveRecord.setScore(score); + examRecordDetailSaveRecord.setRegionId(driverInfo.getRegionId()); + iExamRecordDetailService.save(examRecordDetailSaveRecord); + + // 如果为培训报名考试 并且考试成绩合格 进入下一阶段 + if (TrainingTypeEnum.forensic_registration_training.name().equals(trainingOrganization.getTrainingType()) + && ExamQualifiedEnum.qualified.name().equals(isQualified)) { + driverInfo.setDriverRegistrationStatus(DriverRegistrationStatusEnum.upload_training_certificate_stage.name()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + // 更新驾驶员分数为 100分 + DriverScoreInfo driverScoreInfo = iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class).eq(DriverScoreInfo::getDriverId, driverInfo.getId())); + if (driverScoreInfo == null) { + driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + } + driverScoreInfo.setDriverScore(DriverRelationConstant.DRIVER_FULL_SCORE); + driverScoreInfo.setUpdateOn(LocalDateTime.now()); + iDriverScoreInfoService.saveOrUpdate(driverScoreInfo); + + DriverScoreRecord saveRecord = new DriverScoreRecord(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverId(driverInfo.getId()); + saveRecord.setOperateReason("通过驾驶员报名培训并完成了考试"); + saveRecord.setOperateScore(DriverRelationConstant.DRIVER_FULL_SCORE); + saveRecord.setOperateType(ScoreOperateType.add.name()); + saveRecord.setUserId(driverInfo.getUserId()); + iDriverScoreRecordService.save(saveRecord); + + //初始化驾驶员星级及分数 + StarManage starManage = new StarManage(); + starManage.setCurrentScore(DriverRelationConstant.DRIVER_FULL_SCORE); + starManage.setCurrentStar(TaskContant.Star.FIVE_STAR); + starManage.setRegionId(driverInfo.getRegionId()); + starManage.setCompanyId(driverInfo.getCompanyId()); + starManage.setCompanyName(driverInfo.getCompanyName()); + starManage.setDriverName(driverInfo.getDriverName()); + starManage.setDriverId(driverId); + starManage.setCreateOn(LocalDateTime.now()); + starManage.setUpdateOn(LocalDateTime.now()); + starManageService.save(starManage); + + } + // 如果为继续教育考试 并且考试成绩合格 更新阶段和可参加继续教育培训报名标志 加分 + if (TrainingTypeEnum.continuing_education_training.name().equals(trainingOrganization.getTrainingType()) + && ExamQualifiedEnum.qualified.name().equals(isQualified)) { + driverInfo.setContinuingEducationStatus(DriverReplacementRegistrationStatusEnum.available.name()); + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + // 如果为换证培训 并且考试成绩合格 加分 + if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingOrganization.getTrainingType()) + && ExamQualifiedEnum.qualified.name().equals(isQualified)) { + driverInfo.setReplacementRegistrationStatus(DriverReplacementRegistrationStatusEnum.upload_training_certificate_stage.name()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + // 如果为转码培训 并且考试成绩合格 加40分 + if (TrainingTypeEnum.transcoding_training.name().equals(trainingOrganization.getTrainingType()) + && ExamQualifiedEnum.qualified.name().equals(isQualified)) { + DriverScoreInfo driverScoreInfo = iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class).eq(DriverScoreInfo::getDriverId, driverInfo.getId())); + CodingRuleBO codingRuleBehaviorScore = driverBehaviorScoreHelper.getCodingRuleBehaviorScore(CodingRuleBehaviorTypeEnum.complete_the_exam,null); + Integer operationScore = codingRuleBehaviorScore.getOperationScore(); + if (driverScoreInfo == null) { + driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + driverScoreInfo.setDriverScore(operationScore); + } else { + driverScoreInfo.setDriverScore(driverScoreInfo.getDriverScore() + operationScore); + } + driverScoreInfo.setUpdateOn(LocalDateTime.now()); + iDriverScoreInfoService.saveOrUpdate(driverScoreInfo); + + DriverScoreRecord saveRecord = new DriverScoreRecord(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverId(driverInfo.getId()); + saveRecord.setOperateReason("驾驶员参加转码培训并完成了考试"); + saveRecord.setOperateScore(operationScore); + saveRecord.setOperateType(ScoreOperateType.add.name()); + saveRecord.setUserId(driverInfo.getUserId()); + iDriverScoreRecordService.save(saveRecord); + } + } + + public void deleteTrainingOrganization(Long organizationId) { + // TODO 补充校验逻辑 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(TrainingOrganization.class); + TrainingOrganizationManage context = (TrainingOrganizationManage) AopContext.currentProxy(); + context.buildTrainingOrganizationQuery(wrapper, organizationId); + TrainingOrganization organization = iTrainingOrganizationService.getOne(wrapper); + if (Objects.isNull(organization)) { + throw new BizException("培训组织不存在"); + } + //TrainingOrganization organization = iTrainingOrganizationService.getById(organizationId); + + String trainingType = organization.getTrainingType(); + + if(iTrainingOrganizationService.removeById(organizationId)) { + // 删除培训组织中的培训人员 + // 移除掉该培训组织删除掉的培训人员 + List removeList = iTrainingOrganizationTrainerService.list(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, organizationId)); + iTrainingOrganizationTrainerService.removeBatchByIds(removeList); + List driverIds = removeList.stream().map(TrainingOrganizationTrainer::getDriverId).collect(Collectors.toList()); + List removeDriverInfos = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class).in(DriverInfo::getId, driverIds)); + for (DriverInfo driverInfo : removeDriverInfos) { + if (TrainingTypeEnum.forensic_registration_training.name().equals(trainingType)) { + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (TrainingTypeEnum.continuing_education_training.name().equals(trainingType)) { + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingType)) { + driverInfo.setReplacementRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } + // 更新驾驶员是否可以参见培训报名标志 + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + } + } + + @Transactional(rollbackFor = Exception.class) + public void trainingOrganizationStatusModify(ReqTrainingOrganizationStatusModifyPO request) { + Long organizationId = request.getOrganizationId(); + TrainingStatusEnum trainingStatus = request.getTrainingStatus(); + + + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(organizationId); + if (Objects.isNull(trainingOrganization)) { + throw new BizException("该培训组织不存在"); + } + + trainingOrganization.setTrainingStatus(trainingStatus.name()); + trainingOrganization.setUpdateOn(LocalDateTime.now()); + iTrainingOrganizationService.updateById(trainingOrganization); + + // 转码培训只能有一个是生效状态 + if (TrainingStatusEnum.enable.equals(trainingStatus) + && TrainingTypeEnum.transcoding_training.name().equals(trainingOrganization.getTrainingType())) { + iTrainingOrganizationService.update(Wrappers.lambdaUpdate(TrainingOrganization.class) + .eq(TrainingOrganization::getTrainingType, TrainingTypeEnum.transcoding_training.name()) + .ne(TrainingOrganization::getId, organizationId) + .set(TrainingOrganization::getTrainingStatus, TrainingStatusEnum.disable.name())); + } + + } + + public ResCurrentUserOrganizationVO getCurrentUserOrganization(ReqCurrentUserOrganizationPO request) { + Long userId = LoginUserUtil.getUserId(); + TrainingTypeEnum trainingType = request.getTrainingType(); + + List trainingOrganizationList = iTrainingOrganizationService.list(Wrappers.lambdaQuery(TrainingOrganization.class) + .eq(TrainingOrganization::getTrainingType, trainingType)); + + ResCurrentUserOrganizationVO resVO = new ResCurrentUserOrganizationVO(); + resVO.setStatus(CurrentUserOrganizationEnum.uncommitted); + + if (TrainingTypeEnum.transcoding_training.equals(trainingType)) { + if (driverInfoHelper.hasDriverAvailableCertificate(userId)) { + trainingOrganizationList = trainingOrganizationList.stream() + .filter(r -> TrainingStatusEnum.enable.name().equals(r.getTrainingStatus())).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(trainingOrganizationList)) { + resVO.setTrainingOrganizationId(trainingOrganizationList.get(0).getId()); + resVO.setStatus(CurrentUserOrganizationEnum.incomplete); + return resVO; + } + } else { + return resVO; + } + } + List trainingOrganizationIdList = trainingOrganizationList.stream().map(TrainingOrganization::getId).collect(Collectors.toList()); + + if (CollectionUtil.isNotEmpty(trainingOrganizationIdList)) { + List trainingOrganizationTrainers = iTrainingOrganizationTrainerService.list(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getDriverUserId, userId) + .in(TrainingOrganizationTrainer::getTrainingOrganizationId, trainingOrganizationIdList) + .orderByDesc(TrainingOrganizationTrainer::getCreateOn) + .last("limit 1")); + + if (CollectionUtil.isNotEmpty(trainingOrganizationTrainers)) { + TrainingOrganizationTrainer trainingOrganizationTrainer = trainingOrganizationTrainers.get(0); + resVO.setTrainingOrganizationId(trainingOrganizationTrainer.getTrainingOrganizationId()); + if (ExaminationStatusEnum.examined.name().equals(trainingOrganizationTrainer.getExaminationStatus())) { + resVO.setStatus(CurrentUserOrganizationEnum.completed); + } else { + resVO.setStatus(CurrentUserOrganizationEnum.incomplete); + } + } + } + return resVO; + } + + public void organizationSign(Long organizationId) { + Long userId = LoginUserUtil.getUserId(); + + DriverInfo driverInfo = driverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class).eq(DriverInfo::getUserId, userId)); + if (Objects.isNull(driverInfo)){ + throw new BizException("您未参加该培训!"); + } + TrainingOrganizationTrainer one = iTrainingOrganizationTrainerService.getOne(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, organizationId) + .eq(TrainingOrganizationTrainer::getDriverUserId, userId) + .eq(TrainingOrganizationTrainer::getDriverId,driverInfo.getId())); + if (Objects.isNull(one)){ + throw new BizException("您未参加该培训!"); + } + one.setSignTime(LocalDateTime.now()); + iTrainingOrganizationTrainerService.updateById(one); + } + + public Boolean organizationSignCheck(Long organizationId) { + Long userId = LoginUserUtil.getUserId(); + TrainingOrganizationTrainer one = iTrainingOrganizationTrainerService.getOne(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, organizationId) + .eq(TrainingOrganizationTrainer::getDriverUserId, userId)); + + if (Objects.isNull(one)) { + return false; + } + return Objects.nonNull(one.getSignTime()); + } + + public PageVo driverTrainingList(ReqDriverTrainingListPO request) { + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + Long driverId = request.getDriverId(); + + Page page = iTrainingOrganizationTrainerService.page(new Page<>(pageNumber, pageSize) + , Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getDriverId, driverId)); + + PageVo pageVo = new PageVo<>(); + Long total = page.getTotal(); + if (total > 0) { + List records = page.getRecords(); + List trainingOrganizationIdList = records.stream().map(TrainingOrganizationTrainer::getTrainingOrganizationId).distinct().collect(Collectors.toList()); + // 过滤掉培训组织不存在的数据 + List traIds = iTrainingOrganizationService.list(Wrappers.lambdaQuery(TrainingOrganization.class).select(TrainingOrganization::getId)).stream() + .map(TrainingOrganization::getId).collect(Collectors.toList()); + List ids = trainingOrganizationIdList.stream().filter(traIds::contains).collect(Collectors.toList()); + List results = records.stream().filter(r -> ids.contains(r.getTrainingOrganizationId())).collect(Collectors.toList()); + List trainingOrganizationList = iTrainingOrganizationService.list(Wrappers.lambdaQuery(TrainingOrganization.class) + .in(TrainingOrganization::getId, ids)); + + Map trainingOrganizationMap = trainingOrganizationList.stream().collect(Collectors.toMap(TrainingOrganization::getId, Function.identity())); + + List resVOList = results.stream().map(r -> { + String isQualified = r.getIsQualified(); + Long trainingOrganizationId = r.getTrainingOrganizationId(); + TrainingOrganization trainingOrganization = trainingOrganizationMap.get(trainingOrganizationId); + if (Objects.nonNull(trainingOrganization)) { + ResDriverTrainingListVO resVO = new ResDriverTrainingListVO(); + resVO.setOrganizationId(trainingOrganization.getId()); + resVO.setTrainingTopic(trainingOrganization.getTrainingTopic()); + resVO.setTrainingType(TrainingTypeEnum.valueOf(trainingOrganization.getTrainingType())); + resVO.setTrainingMode(TrainingModeEnum.valueOf(trainingOrganization.getTrainingMode())); + resVO.setTrainingStartTime(trainingOrganization.getTrainingStartTime()); + resVO.setTrainingEndTime(trainingOrganization.getTrainingEndTime()); + resVO.setAddress(trainingOrganization.getAddress()); + resVO.setIsQualified(isQualified); + return resVO; + }else { + return null; + } + }).collect(Collectors.toList()); + pageVo.setRecords(resVOList); + pageVo.setTotal((long) resVOList.size()); + } + return pageVo; + } + + /** + * 补考 + * + * @param request + */ + public void makeUpExam(ReqMakeUpExamPO request) { + // 获取入参参数 + Long driverId = request.getDriverId(); + Long trainingOrganizationId = request.getTrainingOrganizationId(); + + // 获取驾驶员详情 + DriverInfo driverInfo = driverInfoService.getById(driverId); + // 获取培训组织详情 + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(trainingOrganizationId); + + if (!TrainingTypeEnum.transcoding_training.name().equals(trainingOrganization.getTrainingType())) { + // 获取培训驾驶员信息 更新驾驶员培训人员信息 + TrainingOrganizationTrainer trainingOrganizationTrainer = iTrainingOrganizationTrainerService.getOne(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getDriverId, driverId) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, trainingOrganizationId)); + trainingOrganizationTrainer.setScore(null); + trainingOrganizationTrainer.setIsQualified(""); + trainingOrganizationTrainer.setExaminationStatus(ExaminationStatusEnum.waiting_examination.name()); + iTrainingOrganizationTrainerService.saveOrUpdate(trainingOrganizationTrainer); + } + + } + + /** + * 获取培训组织关联的培训人员信息 + * @param request + * @return + */ + public PageVo trainerList(TrainingOrgTrainersQuery request) { + + List organizationTrainers; + List resVos = Lists.newArrayList(); + // 如果培训组织ID不为空说明是编辑培训组织,要查询出相关联的培训人员 + if (Objects.nonNull(request.getTrainingOrganizationId())) { + organizationTrainers = trainingOrganizationTrainerService.list(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, request.getTrainingOrganizationId())); + List driverIds = organizationTrainers.stream() + .map(TrainingOrganizationTrainer::getDriverId) + .collect(Collectors.toList()); + Map driverInfoMap = iDriverInfoService.listByIds(driverIds).stream() + .collect(Collectors.toMap(DriverInfo::getId, v -> v)); + for (TrainingOrganizationTrainer trainer : organizationTrainers) { + ResTrainingOrgTrainerVO vo = new ResTrainingOrgTrainerVO(); + BeanUtils.copyProperties(trainer, vo); + DriverInfo driverInfo = driverInfoMap.get(trainer.getDriverId()); + LocalDateTime now = LocalDateTime.now(); + int compare = now.compareTo(driverInfo.getInitialLicenseTime()); + // 当前时间大于驾驶证初次申领时间 -> 驾驶证过期 + if (compare > 0 || compare == 0) { + vo.setCertificateExpireFlag(false); + } else { + vo.setCertificateExpireFlag(true); + } + resVos.add(vo); + } + } + + ReqArchivalInfoSearchPO po = new ReqArchivalInfoSearchPO(); + BeanUtils.copyProperties(request, po); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverInfo.class); + wrapper.like(StringUtils.isNotBlank(request.getCompanyName()), DriverInfo::getCompanyName, request.getCompanyName()) + .like(StringUtils.isNotBlank(request.getDriverName()), DriverInfo::getDriverName, request.getDriverName()) + .orderByDesc(DriverInfo::getCreateOn); + if (request.getTrainingRegistrationType().equals(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name())) { + wrapper.eq(DriverInfo::getDriverRegistrationStatus,DriverRegistrationStatusEnum.exam_training_stage.name()); + wrapper.eq(DriverInfo::getDriverRegistrationFlag,TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (request.getTrainingRegistrationType().equals(TrainingRegistrationTypeEnum.CONTINUING_EDUCATION.name())) { + wrapper.eq(DriverInfo::getContinuingEducationStatus,DriverRegistrationStatusEnum.exam_training_stage.name()); + wrapper.eq(DriverInfo::getContinuingEducationFlag,TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } else if (request.getTrainingRegistrationType().equals(TrainingRegistrationTypeEnum.REPLACEMENT_REGISTRATION.name())) { + wrapper.eq(DriverInfo::getReplacementRegistrationStatus,DriverRegistrationStatusEnum.exam_training_stage.name()); + wrapper.eq(DriverInfo::getReplacementRegistrationFlag,TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + } + List driverInfos = iDriverInfoService.list(wrapper); + + for (DriverInfo driverInfo : driverInfos) { + ResTrainingOrgTrainerVO vo = new ResTrainingOrgTrainerVO(); + BeanUtils.copyProperties(driverInfo,vo); + vo.setDriverUserId(driverInfo.getUserId()); + vo.setDriverId(driverInfo.getId()); + LocalDateTime now = LocalDateTime.now(); + int compare = now.compareTo(driverInfo.getInitialLicenseTime()); + // 当前时间大于驾驶证初次申领时间 -> 驾驶证到期 + if (compare > 0 || compare == 0 ){ + vo.setCertificateExpireFlag(false); + } else { + vo.setCertificateExpireFlag(true); + } + resVos.add(vo); + } + + // 获取传入的分页参数 + Integer pageNumber = request.getPageNumber(); + Integer pageSize = request.getPageSize(); + List records = resVos.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + + return PageVo.of(records,resVos.size()); + } + + public String setExamTime(ReqSetExamTimePO request) { + Long trainingOrganizationId = request.getTrainingOrganizationId(); + List randomExamPaperIdList = request.getRandomExamPaperId(); + LocalDateTime examStartTime = request.getExamStartTime(); + LocalDateTime examEndTime = request.getExamEndTime(); + if (CollUtil.isNotEmpty(randomExamPaperIdList)) { + Map examPaperMap = iExamPaperService.list(Wrappers.lambdaQuery(ExamPaper.class).in(ExamPaper::getId, randomExamPaperIdList)) + .stream().collect(Collectors.toMap(ExamPaper::getId, e -> e)); + List examPapers = Lists.newArrayList(); + for (Long id : randomExamPaperIdList) { + ExamPaper examPaper = examPaperMap.get(id); + examPaper.setExamStartTime(examStartTime); + examPaper.setExamEndTime(examEndTime); + examPaper.setUpdateOn(LocalDateTime.now()); + examPapers.add(examPaper); + } + if(iExamPaperService.updateBatchById(examPapers)) { + // 保存考试时间到培训组织ID + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(trainingOrganizationId); + trainingOrganization.setExamStartTime(examStartTime); + trainingOrganization.setExamEndTime(examEndTime); + trainingOrganization.setUpdateOn(LocalDateTime.now()); + iTrainingOrganizationService.updateById(trainingOrganization); + return "设置成功!"; + }else { + return "设置失败!"; + } + }else { + throw new BizException("请传入随机试卷ID!"); + } + } + + public void exportTrainer(HttpServletResponse response, ReqTrainerExportPO req) { + Long trainingOrganizationId = req.getTrainingOrganizationId(); + // 获取培训人员信息 + List trainerList = iTrainingOrganizationTrainerService + .list(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, trainingOrganizationId)); + List driverIdList = trainerList.stream().map(TrainingOrganizationTrainer::getDriverId).collect(Collectors.toList()); + Map driverInfoMap = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class).in(DriverInfo::getId, driverIdList)) + .stream().collect(Collectors.toMap(DriverInfo::getId, d -> d)); + + List collect = trainerList.stream().map(r -> { + TrainerInfoExportDTO exportDTO = new TrainerInfoExportDTO(); + Long driverId = r.getDriverId(); + DriverInfo driverInfo = driverInfoMap.get(driverId); + if (Objects.nonNull(driverInfo)){ + exportDTO.setAddress(driverInfo.getAddress()); + exportDTO.setBirth(NdDateUtils.format(driverInfo.getBirth(),NdDateUtils.DEFAULT_DATE_FORMAT)); + exportDTO.setDriverName(driverInfo.getDriverName()); + exportDTO.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + exportDTO.setDriverLicenseType(driverInfo.getDriverLicenseType()); + Integer gender = driverInfo.getGender(); + if (Objects.nonNull(gender)) { + exportDTO.setGender(GenderEnum.getDescByCode(gender)); + } + exportDTO.setHealth(driverInfo.getHealth()); + exportDTO.setIdCard(driverInfo.getIdCard()); + exportDTO.setPhoneNo(driverInfo.getPhoneNo()); + exportDTO.setIllegalAndIllegalInfo(driverInfo.getIllegalAndIllegalInfo()); + exportDTO.setNativePlace(driverInfo.getNativePlace()); + exportDTO.setNativePlaceRegionCode(driverInfo.getNativePlaceRegionCode()); + String motorcycleTypeList = driverInfo.getMotorcycleTypeList(); + String substring = motorcycleTypeList.substring(1, motorcycleTypeList.length() - 1); + String motorcycleTypeListStr = Arrays.stream(substring.split(StrPool.COMMA)).map(VehicleTypeEnum::getDescByEnum).collect(Collectors.joining(StrPool.COMMA)); + exportDTO.setMotorcycleTypeList(motorcycleTypeListStr); + exportDTO.setInitialLicenseTime(NdDateUtils.format(driverInfo.getInitialLicenseTime(),NdDateUtils.DEFAULT_DATE_FORMAT)); + // 获取培训组织信息 + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(trainingOrganizationId); + exportDTO.setTrainingTopic(trainingOrganization.getTrainingTopic()); + String trainingType = trainingOrganization.getTrainingType(); + if (StringUtils.isNotBlank(trainingType)) { + if (TrainingTypeEnum.forensic_registration_training.name().equals(trainingType)){ + exportDTO.setTrainingType(DefValConstants.FORENSIC_REGISTRATION_TRAINING); + } else if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingType)) { + exportDTO.setTrainingType(DefValConstants.REPLACEMENT_REGISTRATION_TRAINING); + } else if (TrainingTypeEnum.continuing_education_training.name().equals(trainingType)) { + exportDTO.setTrainingType(DefValConstants.CONTINUING_EDUCATION_TRAINING); + }else if (TrainingTypeEnum.transcoding_training.name().equals(trainingType)){ + exportDTO.setTrainingType(DefValConstants.TRANSCODING_TRAINING); + } + } + exportDTO.setTrainAddress(trainingOrganization.getAddress()); + String trainingMode = trainingOrganization.getTrainingMode(); + if (StringUtils.isNotBlank(trainingMode) && TrainingModeEnum.online.name().equals(trainingMode)){ + exportDTO.setTrainingMode(DefValConstants.ONLINE); + } else if (StringUtils.isNotBlank(trainingMode) && TrainingModeEnum.offline.name().equals(trainingMode)) { + exportDTO.setTrainingMode(DefValConstants.OFFLINE); + } + exportDTO.setTrainingStartTime(NdDateUtils.format(trainingOrganization.getTrainingStartTime(),NdDateUtils.DEFAULT_DATE_FORMAT)); + exportDTO.setTrainingEndTime(NdDateUtils.format(trainingOrganization.getTrainingEndTime(),NdDateUtils.DEFAULT_DATE_FORMAT)); + exportDTO.setRemark(trainingOrganization.getRemark()); + exportDTO.setExamStartTime(NdDateUtils.format(trainingOrganization.getExamStartTime(),NdDateUtils.DEFAULT_DATE_FORMAT)); + exportDTO.setExamEndTime(NdDateUtils.format(trainingOrganization.getExamEndTime(),NdDateUtils.DEFAULT_DATE_FORMAT)); + // 获取培训合格证信息 + Certificate certificate = certificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getDriverId, r.getDriverId()) + .last(DefValConstants.LIMIT_1)); + if (Objects.nonNull(certificate)) { + exportDTO.setCertificateNo(certificate.getCertificateNo()); + exportDTO.setIssuedBy(certificate.getIssuedBy()); + exportDTO.setIssueDate(NdDateUtils.format(certificate.getIssueDate(), NdDateUtils.DEFAULT_DATE_FORMAT)); + exportDTO.setExpiryDate(NdDateUtils.format(certificate.getExpiryDate(), NdDateUtils.DEFAULT_DATE_FORMAT)); + } + } + return exportDTO; + }).collect(Collectors.toList()); + String fileName = "培训人员信息列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), TrainerInfoExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void uploadExamResultAndGenerateCertificate(ReqUploadExamResultPO request) { + + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + // 获取登录用户所在区域编码 + Long regionId = user.getRegionId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + // 获取入参参数 + Long driverId = request.getDriverId(); + Long trainingOrganizationId = request.getTrainingOrganizationId(); + Integer score = request.getScore(); + + // 获取驾驶员详情 + DriverInfo driverInfo = driverInfoService.getById(driverId); + // 获取培训组织详情 + TrainingOrganization trainingOrganization = iTrainingOrganizationService.getById(trainingOrganizationId); + + String isQualified = score >= ExamPaperQualifiedScoreConstant.EXAM_PAPER_QUALIFIED_SCORE ? ExamQualifiedEnum.qualified.name() : ExamQualifiedEnum.unqualified.name(); + if (!TrainingTypeEnum.transcoding_training.name().equals(trainingOrganization.getTrainingType())) { + // 获取培训驾驶员信息 更新驾驶员培训人员信息 + TrainingOrganizationTrainer trainingOrganizationTrainer = iTrainingOrganizationTrainerService.getOne(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(TrainingOrganizationTrainer::getDriverId, driverId) + .eq(TrainingOrganizationTrainer::getTrainingOrganizationId, trainingOrganizationId)); + trainingOrganizationTrainer.setScore(score); + trainingOrganizationTrainer.setIsQualified(isQualified); + trainingOrganizationTrainer.setExaminationStatus(ExaminationStatusEnum.examined.name()); + iTrainingOrganizationTrainerService.saveOrUpdate(trainingOrganizationTrainer); + } + + ExamRecord examRecord = iExamRecordService.getOne(Wrappers.lambdaQuery(ExamRecord.class) + .eq(ExamRecord::getTrainingOrganizationId, trainingOrganizationId)); + // 新建考试记录 + ExamRecordDetail examRecordDetailSaveRecord = new ExamRecordDetail(); + examRecordDetailSaveRecord.setExamRecordId(examRecord.getId()); + examRecordDetailSaveRecord.setCompanyId(driverInfo.getCompanyId()); + examRecordDetailSaveRecord.setCompanyName(driverInfo.getCompanyName()); + examRecordDetailSaveRecord.setCreateBy(LoginUserUtil.getUserId()); + examRecordDetailSaveRecord.setCreateOn(LocalDateTime.now()); + examRecordDetailSaveRecord.setUpdateOn(LocalDateTime.now()); + examRecordDetailSaveRecord.setDriverId(driverInfo.getId()); + examRecordDetailSaveRecord.setDriverUserId(driverInfo.getUserId()); + examRecordDetailSaveRecord.setDriverName(driverInfo.getDriverName()); + examRecordDetailSaveRecord.setExamResult(isQualified); + examRecordDetailSaveRecord.setExamTime(LocalDateTime.now()); + examRecordDetailSaveRecord.setExamType(examRecord.getExamType()); + examRecordDetailSaveRecord.setScore(score); + examRecordDetailSaveRecord.setRegionId(driverInfo.getRegionId()); + iExamRecordDetailService.save(examRecordDetailSaveRecord); + + String examType = trainingOrganization.getTrainingType(); + // 获取已经存在的所有合格证信息 + Long max; + OptionalLong maxId = certificateService.list().stream().mapToLong(Certificate::getId).max(); + if (maxId.isPresent()){ + max = maxId.getAsLong(); + }else { + max = 0L; + } + // 如果考试成绩合格,生成证书信息 + if (ExamQualifiedEnum.qualified.name().equals(isQualified)) { + // 保存合格证信息 + Certificate saveRecord = new Certificate(); + // 生成证书编号 + String certificateNo = generateCertificateNo(regionDto,max); + saveRecord.setCertificateNo(certificateNo); + saveRecord.setDriverId(driverId); + saveRecord.setDriverName(driverInfo.getDriverName()); + // 发证日期为当前时间、有效期加3年 + saveRecord.setIssueDate(LocalDateTime.now()); + saveRecord.setExpiryDate(LocalDateTime.now().plusYears(DriverConstant.YEAR_3)); + // 发证单位为所属区域散装中心 + String regionName = regionDto.getRegionName(); + saveRecord.setIssuedBy(regionName + DriverConstant.MANAGE_UNIT); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setCreateBy(user.getUserId()); + saveRecord.setUserId(driverInfo.getUserId()); + saveRecord.setBirth(driverInfo.getBirth()); + saveRecord.setGender(driverInfo.getGender()); + saveRecord.setNativePlace(driverInfo.getNativePlace()); + saveRecord.setHealth(driverInfo.getHealth()); + saveRecord.setPhoneNo(driverInfo.getPhoneNo()); + saveRecord.setAddress(driverInfo.getAddress()); + saveRecord.setDriverLicenseType(driverInfo.getDriverLicenseType()); + saveRecord.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + saveRecord.setRegionId(user.getRegionId()); + saveRecord.setRegionName(user.getRegionName()); + saveRecord.setCompanyId(user.getCompanyId()); + saveRecord.setCompanyName(user.getCompanyName()); + // 如果是换证培训,替换原来过期的取证培训合格证信息 + if (TrainingTypeEnum.replacement_registration_training.name().equals(examType)) { + Certificate certificate = certificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, driverInfo.getUserId()).last(DefValConstants.LIMIT_1)); + saveRecord.setId(certificate.getId()); + } + certificateService.saveOrUpdate(saveRecord); + // 生成电子合格证图片,并上传到OSS上 + + + }else { + throw new BizException("考试成绩不满60分!"); + } + + // 如果为培训报名考试 并且考试成绩合格 更新阶段和可参加取证培训报名标志 + if (TrainingTypeEnum.forensic_registration_training.name().equals(examType)) { + driverInfo.setDriverRegistrationStatus(DriverRegistrationStatusEnum.available.name()); + driverInfo.setDriverRegistrationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + // 更新驾驶员分数为 100分 + DriverScoreInfo driverScoreInfo = iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class).eq(DriverScoreInfo::getDriverId, driverInfo.getId())); + if (driverScoreInfo == null) { + driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + } + driverScoreInfo.setDriverScore(DriverRelationConstant.DRIVER_FULL_SCORE); + driverScoreInfo.setUpdateOn(LocalDateTime.now()); + iDriverScoreInfoService.saveOrUpdate(driverScoreInfo); + + DriverScoreRecord saveRecord = new DriverScoreRecord(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverId(driverInfo.getId()); + saveRecord.setOperateReason("通过驾驶员报名培训并完成了考试"); + saveRecord.setOperateScore(DriverRelationConstant.DRIVER_FULL_SCORE); + saveRecord.setOperateType(ScoreOperateType.add.name()); + saveRecord.setUserId(driverInfo.getUserId()); + iDriverScoreRecordService.save(saveRecord); + + //初始化驾驶员星级及分数 + StarManage starManage = new StarManage(); + starManage.setCurrentScore(DriverRelationConstant.DRIVER_FULL_SCORE); + starManage.setCurrentStar(TaskContant.Star.FIVE_STAR); + starManage.setRegionId(driverInfo.getRegionId()); + starManage.setCompanyId(driverInfo.getCompanyId()); + starManage.setCompanyName(driverInfo.getCompanyName()); + starManage.setDriverName(driverInfo.getDriverName()); + starManage.setDriverId(driverId); + starManage.setCreateOn(LocalDateTime.now()); + starManage.setUpdateOn(LocalDateTime.now()); + starManageService.save(starManage); + + } + // 如果为继续教育考试 并且考试成绩合格 更新阶段和可参加继续教育培训报名标志 加分 + if (TrainingTypeEnum.continuing_education_training.name().equals(trainingOrganization.getTrainingType())) { + driverInfo.setContinuingEducationStatus(DriverReplacementRegistrationStatusEnum.available.name()); + driverInfo.setContinuingEducationFlag(TrainingRegistrationFlagEnum.CAN_TAKE.getCode()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + // 如果为换证培训 并且考试成绩合格 加分 + if (TrainingTypeEnum.replacement_registration_training.name().equals(trainingOrganization.getTrainingType())) { + driverInfo.setReplacementRegistrationStatus(DriverReplacementRegistrationStatusEnum.upload_training_certificate_stage.name()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.updateById(driverInfo); + } + // 如果为转码培训 并且考试成绩合格 加40分 + if (TrainingTypeEnum.transcoding_training.name().equals(trainingOrganization.getTrainingType())) { + DriverScoreInfo driverScoreInfo = iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class).eq(DriverScoreInfo::getDriverId, driverInfo.getId())); + CodingRuleBO codingRuleBehaviorScore = driverBehaviorScoreHelper.getCodingRuleBehaviorScore(CodingRuleBehaviorTypeEnum.complete_the_exam,null); + Integer operationScore = codingRuleBehaviorScore.getOperationScore(); + if (driverScoreInfo == null) { + driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + driverScoreInfo.setDriverScore(operationScore); + } else { + driverScoreInfo.setDriverScore(driverScoreInfo.getDriverScore() + operationScore); + } + driverScoreInfo.setUpdateOn(LocalDateTime.now()); + iDriverScoreInfoService.saveOrUpdate(driverScoreInfo); + + DriverScoreRecord saveRecord = new DriverScoreRecord(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverId(driverInfo.getId()); + saveRecord.setOperateReason("驾驶员参加转码培训并完成了考试"); + saveRecord.setOperateScore(operationScore); + saveRecord.setOperateType(ScoreOperateType.add.name()); + saveRecord.setUserId(driverInfo.getUserId()); + iDriverScoreRecordService.save(saveRecord); + } + } + + private String generateCertificateNo(RegionDTO regionDto, Long max) { + String regionCode = regionDto.getRegionCode(); + // 获取当前时间所在年份 + LocalDateTime now = LocalDateTime.now(); + int year = now.getYear(); + // 获取当前时间所在月份 + Month month = now.getMonth(); + // 获取当前时间所在天数 + int day = now.getDayOfMonth(); + // 证书序号加一 + Long maxCurrent = max + 1; + String serialNumber = String.format(DriverConstant.NO_5,maxCurrent); + return regionCode + year + month + day + serialNumber; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.java new file mode 100644 index 0000000..4e270c6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.ArticleInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface ArticleInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.xml new file mode 100644 index 0000000..9182ba8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ArticleInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.java new file mode 100644 index 0000000..615b916 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.java @@ -0,0 +1,7 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.driver.entity.BehaviorAnalysisProcessingMode; + +public interface BehaviorAnalysisProcessingModeMapper extends BaseMapper { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.xml new file mode 100644 index 0000000..c5f22ae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviorAnalysisProcessingModeMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.java new file mode 100644 index 0000000..ae5cbf6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysis; +import com.ningdatech.carapi.driver.model.po.AlarmWarnFilePO; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface BehaviourAnalysisMapper extends BaseMapper { + + String QUERY_SQL = "SELECT " + + " (case when p.alarm_id is not null then p.alarm_id else v.alarm_id end) alarm_id, " + + " (case when p.plate_no is not null then p.plate_no else v.plate_no end) car_plate, " + + " c.name company_name,c.region_id,b.vehicle_type, " + + " (case when p.alarm_type is not null then p.alarm_type else v.alarm_type end) alarm_type, " + + " (case when p.capture_time is not null then p.capture_time else v.alarm_time end) alarm_time," + + " (case when p.region_name is not null then p.region_name else v.region_name end) alarm_address, " + + " p.url picture_url,v.url video_url,g.driver_id,g.driver_name " + + " from nd_vehicle_base_info b " + + " left join nd_company_info c on b.company_id = c.id " + + " right join nd_alarm_data_picture p on b.car_plate = p.plate_no " + + " right join nd_alarm_data_video v on p.alarm_id = v.alarm_id " + + " left join nd_vehicle_get_on g on p.plate_no = g.car_plate or v.plate_no = g.car_plate " + + " group by " + + " (case when p.alarm_id is not null then p.alarm_id else v.alarm_id end), " + + " (case when p.plate_no is not null then p.plate_no else v.plate_no end), " + + " c.name,c.region_id,b.vehicle_type, " + + " (case when p.alarm_type is not null then p.alarm_type else v.alarm_type end), " + + " (case when p.capture_time is not null then p.capture_time else v.alarm_time end), " + + " (case when p.region_name is not null then p.region_name else v.region_name end),p.url,v.url,g.driver_id,g.driver_name "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageBehiviour(Page page, @Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + DriverAbnormalBehaviorAnalysis getOneBehiviour(@Param("ew") LambdaQueryWrapper wrapper); + + List selectDriverAbnormalBehaviorAnalysisByCarPlate(@Param("index") long index); + + List selectDriverAbnormalBehaviorAnalysisAppendixData(@Param("alarmMsgSnList") List alarmMsgSnList); + + Long selectOneByAlarmMsgSn(@Param("alarmMsgSn") Integer alarmMsgSn); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.xml new file mode 100644 index 0000000..b68919c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/BehaviourAnalysisMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.java new file mode 100644 index 0000000..4d6332a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.Certificate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-24 + */ +public interface CertificateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.xml new file mode 100644 index 0000000..18bfc7e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/CertificateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.java new file mode 100644 index 0000000..41ca7f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.DriverBlackList; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface DriverBlackListMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.xml new file mode 100644 index 0000000..cac4933 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverBlackListMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.java new file mode 100644 index 0000000..285152f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.model.KeyValueDTO; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface DriverInfoMapper extends BaseMapper { + + /** + * 驾驶员年龄分布计算 + * + * @param caseSql 年龄区间计算SQL + * @param undefinedAge 不参与统计的年龄 + * @param param + * @return key 年龄、value 驾驶员数量 + * @author WendyYang + **/ + List> driverAgeStatistics(@Param("caseSql") String caseSql, + @Param("undefinedAge") int undefinedAge, + @Param("param") DataScreenParam param); + + /** + * 驾驶员驾龄分布计算 + * + * @param caseSql 驾龄区间计算SQL + * @param undefinedAge 不参与统计的驾龄 + * @param param + * @return key 驾龄、value 驾驶员数量 + * @author WendyYang + **/ + List> drivingExperienceStatistics(@Param("caseSql") String caseSql, + @Param("undefinedAge") int undefinedAge, + @Param("param") DataScreenParam param); + + List diverCountByRegion(@Param("param") DataScreenParam param); + + List> nativePlaceStatisticsByRegion(@Param("param") DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.xml new file mode 100644 index 0000000..e57c690 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverInfoMapper.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.java new file mode 100644 index 0000000..5b3a1e9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.DriverScoreInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +public interface DriverScoreInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.xml new file mode 100644 index 0000000..c2d5df0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.java new file mode 100644 index 0000000..3cc5b04 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.DriverScoreRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +public interface DriverScoreRecordMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.xml new file mode 100644 index 0000000..d3f684f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverScoreRecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverWorkRecordInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverWorkRecordInfoMapper.java new file mode 100644 index 0000000..947fa88 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/DriverWorkRecordInfoMapper.java @@ -0,0 +1,7 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.driver.entity.DriverWorkRecordInfo; + +public interface DriverWorkRecordInfoMapper extends BaseMapper { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.java new file mode 100644 index 0000000..6e8a412 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.ExamRecordDetail; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +public interface ExamRecordDetailMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.xml new file mode 100644 index 0000000..d622631 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordDetailMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.java new file mode 100644 index 0000000..e3bb3f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.ExamRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +public interface ExamRecordMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.xml new file mode 100644 index 0000000..6970c5b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/ExamRecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.java new file mode 100644 index 0000000..431da52 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.TrainingOrganization; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-10 + */ +public interface NdTrainingOrganizationMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.xml new file mode 100644 index 0000000..c421243 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/NdTrainingOrganizationMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.java new file mode 100644 index 0000000..d3babba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.driver.entity.RegionStarDTO; +import com.ningdatech.carapi.driver.entity.StarManage; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-11-15 + */ +public interface StarManageMapper extends BaseMapper { + + Double getAvgStar(@Param("param") RegionStarDTO param); + + Double getCompanyAvgStar(@Param("param") RegionStarDTO param); + + Double countTotalStar(@Param("param") RegionStarDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.xml new file mode 100644 index 0000000..bd7a998 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/StarManageMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.java new file mode 100644 index 0000000..7e0890a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.TrainingBonusRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-31 + */ +public interface TrainingBonusRecordMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.xml new file mode 100644 index 0000000..bd752ff --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingBonusRecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.java new file mode 100644 index 0000000..bc793c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.TrainingMaterial; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-21 + */ +public interface TrainingMaterialMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.xml new file mode 100644 index 0000000..e7eb5b3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingMaterialMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.java new file mode 100644 index 0000000..b35796c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.TrainingOrganizationMaterial; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +public interface TrainingOrganizationMaterialMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.xml new file mode 100644 index 0000000..82929d5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationMaterialMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.java new file mode 100644 index 0000000..c4dff3b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.ningdatech.carapi.driver.entity.TrainingOrganizationTrainer; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +public interface TrainingOrganizationTrainerMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.xml new file mode 100644 index 0000000..38719c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingOrganizationTrainerMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.java new file mode 100644 index 0000000..3861cce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.driver.entity.TrainingRegistrationReview; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +public interface TrainingRegistrationReviewMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.xml new file mode 100644 index 0000000..bbbfa91 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/mapper/TrainingRegistrationReviewMapper.xml @@ -0,0 +1,4 @@ + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/DriverArchivesExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/DriverArchivesExportDTO.java new file mode 100644 index 0000000..b77e7bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/DriverArchivesExportDTO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.driver.model; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 驾驶员档案导出实体 + * + * @author CMM + * @since 2023/05/15 14:06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DriverArchivesExportDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ExcelProperty("姓名") + private String driverName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("身份证号") + private String idCard; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("手机号码") + private String phoneNo; + + @ExcelProperty("创建时间") + private String createTime; + + @ExcelProperty("状态") + private String driverStatus; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/JudgmentalQuestionInfoTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/JudgmentalQuestionInfoTextContent.java new file mode 100644 index 0000000..d19c7ad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/JudgmentalQuestionInfoTextContent.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.driver.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/11 下午3:58 + */ +@Data +@ApiModel("判断题题目") +public class JudgmentalQuestionInfoTextContent { + + @ApiModelProperty("题干") + private String stem; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/MultipleChoiceQuestionInfoTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/MultipleChoiceQuestionInfoTextContent.java new file mode 100644 index 0000000..d5128f1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/MultipleChoiceQuestionInfoTextContent.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.driver.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/11 下午3:58 + */ +@Data +@ApiModel("多选题题目") +public class MultipleChoiceQuestionInfoTextContent { + + @ApiModelProperty("题干") + private String stem; + + @ApiModelProperty("选项") + private List options; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/SingleChoiceQuestionInfoTextContent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/SingleChoiceQuestionInfoTextContent.java new file mode 100644 index 0000000..9c27333 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/SingleChoiceQuestionInfoTextContent.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.driver.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/11 下午3:58 + */ +@Data +@ApiModel("单选题题目") +public class SingleChoiceQuestionInfoTextContent { + + @ApiModelProperty("题干") + private String stem; + + @ApiModelProperty("选项") + private List options; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/StarManageDisplayInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/StarManageDisplayInfo.java new file mode 100644 index 0000000..f5001e7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/StarManageDisplayInfo.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.driver.model; + +import com.ningdatech.carapi.driver.model.vo.StarManageDisplay; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/11/15 下午3:39 + */ + +@Data +@ApiModel("星级管理列表展示列表字段") +public class StarManageDisplayInfo { + + @ApiModelProperty("第一列展示信息") + private StarManageDisplay firstDisplayInfo; + + @ApiModelProperty("第二列展示信息") + private StarManageDisplay secondDisplayInfo; + + @ApiModelProperty("平均分数") + private Double avgStar; +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingBasicInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingBasicInfo.java new file mode 100644 index 0000000..0e999ef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingBasicInfo.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.driver.model; + +import com.ningdatech.carapi.driver.constant.TrainingModeEnum; +import com.ningdatech.carapi.driver.constant.TrainingStatusEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/21 下午3:05 + */ +@Data +@ApiModel("培训基础信息") +public class TrainingBasicInfo { + + @NotBlank(message = "培训主题不能为空") + @ApiModelProperty("培训主题") + private String trainingTopic; + + @ApiModelProperty("培训开始时间") + private LocalDateTime trainingStartTime; + + @ApiModelProperty("培训结束时间") + private LocalDateTime trainingEndTime; + + @ApiModelProperty("培训地点") + private String address; + + /** + * 培训模式 线上/线下 + * {@link TrainingModeEnum} + */ + @NotNull(message = "培训模式不能为空") + @ApiModelProperty(value = "培训模式 线上/线下", allowableValues = "online,offline") + private TrainingModeEnum trainingMode; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @NotNull(message = "培训类型不能为空") + @ApiModelProperty(value = "培训类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private TrainingTypeEnum trainingType; + + @NotBlank(message = "联系人不能为空") + @ApiModelProperty("联系人") + private String contacts; + + /** + * 联系电话 + */ + @NotBlank(message = "联系电话不能为空") + @ApiModelProperty("联系电话") + private String contactNumber; + + /** + * 培训状态 启用/禁用 + * {@link TrainingStatusEnum} + */ + @NotNull(message = "培训状态不能为空") + @ApiModelProperty(value = "培训状态", allowableValues = "enable 启用,disable 禁用") + private TrainingStatusEnum trainingStatus; + + /** + * 备注 + */ + @NotBlank(message = "备注不能为空") + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingExamPaperInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingExamPaperInfo.java new file mode 100644 index 0000000..3af643c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingExamPaperInfo.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.driver.model; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/21 下午3:07 + */ + +@Data +@ApiModel("培训考试试卷") +public class TrainingExamPaperInfo { + /** + * 考试试卷名称id + */ + @ApiModelProperty("考试试卷名称id") + private Long examPaperId; + + /** + * 考试试卷名称 + */ + @NotBlank(message = "考试试卷名称不能为空") + @ApiModelProperty("考试试卷名称") + private String examPaperName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialInfo.java new file mode 100644 index 0000000..0598cc2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialInfo.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.driver.model; + +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/22 上午9:29 + */ +@Data +@ApiModel("培训材料信息") +public class TrainingMaterialInfo { + + @NotNull(message = "培训材料id 不能为空") + @ApiModelProperty("培训材料id") + private Long trainingMaterialId; + + @NotBlank(message = "标题不能为空") + @ApiModelProperty("标题") + private String title; + + @NotNull(message = "培训材料附件 不能为空") + @ApiModelProperty("培训材料附件") + private List appendixList; + + @NotNull(message = "材料类型 不能为空") + @ApiModelProperty("材料类型") + private MaterialTypeEnum materialType; + + @NotBlank(message = "内容 不能为空") + @ApiModelProperty("内容") + private String content; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialOverviewInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialOverviewInfo.java new file mode 100644 index 0000000..f51ae47 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingMaterialOverviewInfo.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.driver.model; + +import cn.hutool.core.collection.CollectionUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/22 上午9:34 + */ + +@ApiModel("培训材料总揽列表") +@Data +public class TrainingMaterialOverviewInfo { + + @Size(min = 1, max = 6) + @ApiModelProperty("规则制度材料列表") + private List ruleSystemMaterialList; + + @Size(min = 1, max = 6) + @ApiModelProperty("政策文件材料列表") + private List policyDocumentsMaterialInfoList; + + @Size(min = 1, max = 6) + @ApiModelProperty("安全知识材料列表") + private List safetyKnowledgeMaterialInfoList; + + @Size(min = 1, max = 6) + @ApiModelProperty("事故案例材料列表") + private List accidentCaseMaterialInfoList; + + @Size(min = 1, max = 6) + @ApiModelProperty("培训视频材料列表") + private List trainingVideoMaterialInfoList; + + @Size(min = 1, max = 6) + @ApiModelProperty("其他材料列表") + private List otherMaterialInfoList; + + + public List getAllList() { + List trainingMaterialInfoList = new ArrayList<>(); + if (CollectionUtil.isNotEmpty(this.ruleSystemMaterialList)) { + trainingMaterialInfoList.addAll(this.ruleSystemMaterialList); + } + if (CollectionUtil.isNotEmpty(this.policyDocumentsMaterialInfoList)) { + trainingMaterialInfoList.addAll(this.policyDocumentsMaterialInfoList); + } + if (CollectionUtil.isNotEmpty(this.safetyKnowledgeMaterialInfoList)) { + trainingMaterialInfoList.addAll(this.safetyKnowledgeMaterialInfoList); + } + if (CollectionUtil.isNotEmpty(this.accidentCaseMaterialInfoList)) { + trainingMaterialInfoList.addAll(this.accidentCaseMaterialInfoList); + } + if (CollectionUtil.isNotEmpty(this.trainingVideoMaterialInfoList)) { + trainingMaterialInfoList.addAll(this.trainingVideoMaterialInfoList); + } + if (CollectionUtil.isNotEmpty(this.otherMaterialInfoList)) { + trainingMaterialInfoList.addAll(this.otherMaterialInfoList); + } + return trainingMaterialInfoList; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingTrainersInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingTrainersInfo.java new file mode 100644 index 0000000..ef73214 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/TrainingTrainersInfo.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.driver.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/21 下午4:08 + */ +@Data +@ApiModel("培训人员信息") +public class TrainingTrainersInfo { + + @NotNull(message = "驾驶员id 不能为空") + @ApiModelProperty("驾驶员id") + private Long driverId; + + @NotNull(message = "驾驶员用户id 不能为空") + @ApiModelProperty("驾驶员用户id") + private Long driverUserId; + + @NotBlank(message = "驾驶员姓名 不能为空") + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @NotBlank(message = "驾驶员所属企业id 不能为空") + @ApiModelProperty("驾驶员所属企业id") + private Long companyId; + + @NotBlank(message = "驾驶员所属企业 不能为空") + @ApiModelProperty("驾驶员所属企业") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/bo/CodingRuleBO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/bo/CodingRuleBO.java new file mode 100644 index 0000000..ed77acf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/bo/CodingRuleBO.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.driver.model.bo; + +import com.ningdatech.carapi.sys.entity.enumeration.RuleOperationTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/11/14 上午11:33 + */ +@Data +public class CodingRuleBO { + + @ApiModelProperty("加分减分") + private RuleOperationTypeEnum ruleOperationType; + + @ApiModelProperty("操作分数") + private Integer operationScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/DriverBasicInfoDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/DriverBasicInfoDTO.java new file mode 100644 index 0000000..5376414 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/DriverBasicInfoDTO.java @@ -0,0 +1,114 @@ +package com.ningdatech.carapi.driver.model.dto; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.ningdatech.carapi.common.constant.DriverLicenseTypeEnum; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 驾驶员基本信息实体类 + * + * @author CMM + * @since 2023/06/08 10:13 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DriverBasicInfoDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("驾驶员id") + @NotNull(message = "驾驶员ID不能为空") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + @NotBlank(message = "驾驶员姓名不能为空") + private String driverName; + + @ApiModelProperty("性别 0:女 ,1:男 ") + @NotNull(message = "性别不能为空") + private Integer gender; + + @ApiModelProperty("身份证号") + @NotBlank(message = "身份证号不能为空") + private String idCard; + + @ApiModelProperty("出生年月") + @NotNull(message = "出生年月不能为空") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯不能为空") + private String nativePlace; + + @ApiModelProperty(value = "免冠照图片文件") + private FileBasicInfo avatarFile; + + @ApiModelProperty(value = "健康状况") + private String health; + + @ApiModelProperty("手机号码") + @NotBlank(message = "手机号码不能为空") + private String driverPhoneNo; + + @ApiModelProperty("住址") + @NotBlank(message = "住址不能为空") + private String driverAddress; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty("驾驶证类型/准驾车型") + private DriverLicenseTypeEnum driverLicenseType; + + @ApiModelProperty("所属服务企业唯一标识id") + @NotNull(message = "公司id不能为空") + private Long companyId; + + @ApiModelProperty(value = "企业名称") + private String companyName; + + @ApiModelProperty(value = "企业地址") + private String companyAddress; + + @ApiModelProperty(value = "企业联系人") + private String companyContactPerson; + + @ApiModelProperty(value = "企业电话") + private String companyContactPhone; + + @ApiModelProperty("附件") + private List appendixList; + + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + @NotNull(message = "培训报名类型不能为空") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + + @ApiModelProperty("初次领证时间") + @NotNull(message = "初次领证时间不能为空") + private LocalDateTime initialLicenseTime; + + @ApiModelProperty("违规违法信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯编码") + private String nativePlaceRegionCode; + + @ApiModelProperty(value = "驾驶员拟驾车型列表", allowableValues = "MIXER 搅拌车,PUMP_TRUCK 泵车,BULK_CEMENT_TRUCK 散装水泥车" + + ",MORTAR_TRUCK 砂浆车,OTHER 其他") + private List motorcycleTypeList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/TrainerInfoExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/TrainerInfoExportDTO.java new file mode 100644 index 0000000..6b9cb87 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/dto/TrainerInfoExportDTO.java @@ -0,0 +1,132 @@ +package com.ningdatech.carapi.driver.model.dto; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 培训驾驶员信息实体类 + * + * @author CMM + * @since 2023/06/08 10:13 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TrainerInfoExportDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("身份证号") + @ExcelProperty("身份证号") + private String idCard; + + @ApiModelProperty("出生年月") + @ExcelProperty("出生年月") + private String birth; + + @ApiModelProperty("驾驶员姓名") + @ExcelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("性别 0:女 ,1:男 ") + @ExcelProperty("性别") + private String gender; + + @ApiModelProperty("籍贯") + @ExcelProperty("籍贯") + private String nativePlace; + + @ApiModelProperty("邮政编码") + @ExcelProperty("邮政编码") + private String nativePlaceRegionCode; + + @ApiModelProperty(value = "健康状况") + @ExcelProperty("健康状况") + private String health; + + @ApiModelProperty("手机号码") + @ExcelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("住址") + @ExcelProperty("住址") + private String address; + + @ApiModelProperty("驾驶员证档案编号") + @ExcelProperty("驾驶员证档案编号") + private String driverLicenseNo; + + @ApiModelProperty("准驾车型") + @ExcelProperty("准驾车型") + private String driverLicenseType; + + @ApiModelProperty("驾驶证初次申领时间") + @ExcelProperty("驾驶证初次申领时间") + private String initialLicenseTime; + + @ApiModelProperty("拟驾车型") + @ExcelProperty("拟驾车型") + private String motorcycleTypeList; + + @ApiModelProperty("违规违法信息") + @ExcelProperty("违规违法信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty("培训主题") + @ExcelProperty("培训主题") + private String trainingTopic; + + @ApiModelProperty("培训开始时间") + @ExcelProperty("培训开始时间") + private String trainingStartTime; + + @ApiModelProperty("培训结束时间") + @ExcelProperty("培训结束时间") + private String trainingEndTime; + + @ApiModelProperty("培训地点") + @ExcelProperty("培训地点") + private String trainAddress; + + @ApiModelProperty("培训模式") + @ExcelProperty("培训模式") + private String trainingMode; + + @ApiModelProperty(value = "培训类型") + @ExcelProperty("培训类型") + private String trainingType; + + @ApiModelProperty("备注") + @ExcelProperty("备注") + private String remark; + + @ApiModelProperty("考试开始时间") + @ExcelProperty("考试开始时间") + private String examStartTime; + + @ApiModelProperty("考试结束时间") + @ExcelProperty("考试结束时间") + private String examEndTime; + + @ApiModelProperty("证书编号") + @ExcelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证单位") + @ExcelProperty("发证单位") + private String issuedBy; + + @ApiModelProperty("发证日期") + @ExcelProperty("发证日期") + private String issueDate; + + @ApiModelProperty("有效期") + @ExcelProperty("有效期") + private String expiryDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AlarmWarnFilePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AlarmWarnFilePO.java new file mode 100644 index 0000000..89185dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AlarmWarnFilePO.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.driver.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @description + * @since 2022/12/07 14:49 + */ +@Data +@ApiModel("驾驶员异常行为分析附件") +public class AlarmWarnFilePO { + @ApiModelProperty("供应商告警唯一序号") + private Integer alarmMsgSn; + + @ApiModelProperty(value = "告警附件类型",allowableValues = "0 图片,1 视频") + private Integer fileType; + + @ApiModelProperty(value = "告警附件格式",allowableValues = "0 jpg,1 mp4") + private Integer fileFormat; + + @ApiModelProperty("告警附件路径") + private String filePath; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AuditInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AuditInfo.java new file mode 100644 index 0000000..6e2521e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/AuditInfo.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/15 上午10:42 + */ +@Data +@ApiModel(description = "审核信息") +public class AuditInfo { + + @ApiModelProperty("审核员Id") + private Long auditorId; + + @ApiModelProperty("审核员姓名") + private String auditorName; + + @ApiModelProperty("审核意见") + private String reviewComments; + + @ApiModelProperty("审核时间") + private LocalDateTime auditTime; + + @ApiModelProperty("附件") + private List appendixList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqAddDriverArchivesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqAddDriverArchivesPO.java new file mode 100644 index 0000000..a68d500 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqAddDriverArchivesPO.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.common.constant.DriverLicenseTypeEnum; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + + +@Data +@ApiModel(description = "录入特殊驾驶员") +public class ReqAddDriverArchivesPO { + + @ApiModelProperty("驾驶员id 驾驶员培训报名首次信息填入无需传入") + private Long driverId; + + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + @NotNull(message = "培训报名类型不能为空") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + @ApiModelProperty("驾驶员姓名") + @NotBlank(message = "驾驶员姓名不能为空") + private String driverName; + + @ApiModelProperty("性别 0:女 ,1:男 ") + @NotNull(message = "性别不能为空") + private Integer gender; + + @ApiModelProperty("身份证号") + @NotBlank(message = "身份证号不能为空") + private String idCard; + + @ApiModelProperty("出生年月") + @NotNull(message = "出生年月不能为空") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯不能为空") + private String nativePlace; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯编码") + private String nativePlaceRegionCode; + + @ApiModelProperty(value = "免冠照图片文件") + private FileBasicInfo avatarFile; + + @ApiModelProperty(value = "健康状况") + private String health; + + @ApiModelProperty("手机号码") + @NotBlank(message = "手机号码不能为空") + private String phoneNo; + + @ApiModelProperty("住址") + @NotBlank(message = "住址不能为空") + private String address; + + @ApiModelProperty("驾驶证号") + private String driverLicenseNo; + + @ApiModelProperty(value = "驾驶证类型/准驾车型", allowableValues = "A1, A2, B1, B2, C1, OTHER") + private DriverLicenseTypeEnum driverLicenseType; + + @ApiModelProperty("初次领证时间") + @NotNull(message = "初次领证时间不能为空") + private LocalDateTime initialLicenseTime; + + @ApiModelProperty("附件") + private List appendixList; + + @ApiModelProperty("违规违法信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty(value = "驾驶员拟驾车型列表", allowableValues = "MIXER 搅拌车,PUMP_TRUCK 泵车,BULK_CEMENT_TRUCK 散装水泥车" + + ",MORTAR_TRUCK 砂浆车,OTHER 其他") + private List motorcycleTypeList; + + @ApiModelProperty("合格证编号") + @NotBlank(message = "合格证编号不能为空") + private String certificateNo; + + @ApiModelProperty("发证单位") + @NotBlank(message = "发证单位不能为空") + private String issueBy; + + @ApiModelProperty("发证日期") + @NotNull(message = "发证日期不能为空") + private LocalDateTime issueDate; + + @ApiModelProperty("合格证有效期至") + @NotNull(message = "合格证有效期不能为空") + private LocalDateTime expiryDate; + + @ApiModelProperty("合格证备注") + private String certificateRemark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArchivalInfoSearchPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArchivalInfoSearchPO.java new file mode 100644 index 0000000..e3b0c46 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArchivalInfoSearchPO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.DriverStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/9 上午10:43 + */ +@Data +@ApiModel(description = "驾驶员信息档案查询请求") +public class ReqArchivalInfoSearchPO extends PagePo { + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("企业") + private String companyName; + + @ApiModelProperty("区域信息id") + private Long regionId; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("驾驶员状态:入职/离职") + private DriverStatusEnum driverStatus; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("创建开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("创建结束时间") + private LocalDateTime endTime; + + @ApiModelProperty("培训类型") + private String trainingRegistrationType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArticleInfoListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArticleInfoListPO.java new file mode 100644 index 0000000..645000e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqArticleInfoListPO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.ArticleTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/9 下午4:54 + */ +@Data +@ApiModel(description = "文章列表查询") +public class ReqArticleInfoListPO extends PagePo { + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("截止时间") + private LocalDateTime endTime; + + @ApiModelProperty("文章类型") + private ArticleTypeEnum articleType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqChangedJobPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqChangedJobPO.java new file mode 100644 index 0000000..76f3528 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqChangedJobPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.driver.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/11/3 下午2:32 + */ +@Data +@ApiModel("驾驶员跳槽申请PO") +public class ReqChangedJobPO { + + @NotNull + @ApiModelProperty("跳槽目标公司id") + private Long newCompanyId; + + @NotNull + @ApiModelProperty("驾驶员id") + private Long driverId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCompanyStarPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCompanyStarPO.java new file mode 100644 index 0000000..ced0d88 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCompanyStarPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("公司星级筛选列表") +@Data +public class ReqCompanyStarPO extends PagePo { + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("所属区域id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCreateTrainingOrgPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCreateTrainingOrgPO.java new file mode 100644 index 0000000..75b0a79 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCreateTrainingOrgPO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.driver.model.TrainingBasicInfo; +import com.ningdatech.carapi.driver.model.TrainingExamPaperInfo; +import com.ningdatech.carapi.driver.model.TrainingMaterialOverviewInfo; +import com.ningdatech.carapi.driver.model.TrainingTrainersInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/21 下午2:52 + */ +@Data +@ApiModel("创建培训组织请求PO") +public class ReqCreateTrainingOrgPO { + + @ApiModelProperty("培训组织id") + private Long organizationId; + + @ApiModelProperty("培训基础信息") + @NotNull + private TrainingBasicInfo trainingBasicInfo; + + @ApiModelProperty("培训资料") + @NotNull + private TrainingMaterialOverviewInfo trainingMaterialOverviewInfo; + + @ApiModelProperty("培训人员") + @Size(min = 1) + private List trainingTrainersInfoList; + + @ApiModelProperty("培训考试试卷") + @NotNull + private TrainingExamPaperInfo trainingExamPaperInfo; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCurrentUserOrganizationPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCurrentUserOrganizationPO.java new file mode 100644 index 0000000..8c4f19a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqCurrentUserOrganizationPO.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/11/3 下午3:11 + */ +@Data +@ApiModel(value = "获取当前培训组织PO") +public class ReqCurrentUserOrganizationPO { + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @NotNull(message = "培训类型不能为空") + @ApiModelProperty(value = "培训类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private TrainingTypeEnum trainingType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverBlackListSearchPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverBlackListSearchPO.java new file mode 100644 index 0000000..5361fcf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverBlackListSearchPO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author liuxinxin + * @date 2022/10/9 下午1:53 + */ +@Data +@ApiModel(description = "黑名单查询请求") +public class ReqDriverBlackListSearchPO extends PagePo { + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业") + private String companyName; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("年度") + @NotBlank(message = "年度不能为空") + private String year; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInReviewingPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInReviewingPO.java new file mode 100644 index 0000000..ac949cc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInReviewingPO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/15 上午9:28 + */ +@Data +@ApiModel("驾驶员复审结果") +public class ReqDriverInReviewingPO { + + @NotNull(message = "审核id 不能为空") + @ApiModelProperty("审核id") + private Long metaApplyId; + + @NotNull(message = "驾驶员id 不能为空") + @ApiModelProperty("驾驶员id") + private Long driverId; + + @NotNull(message = "培训类型 不能为空") + @ApiModelProperty("培训类型") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + @NotNull(message = "审核结果不能为空") + @ApiModelProperty("审核结果") + private Boolean result; + + @NotBlank(message = "审核意见不能为空") + @ApiModelProperty("审核意见") + private String opinion; + + @ApiModelProperty("附件") + private List appendixList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInductionPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInductionPO.java new file mode 100644 index 0000000..1f30d26 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverInductionPO.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.driver.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/9 下午5:50 + */ +@Data +@ApiModel("驾驶员入职请求入参") +public class ReqDriverInductionPO { + + @ApiModelProperty("驾驶员ID") + @NotNull(message = "驾驶员ID不能为空") + private Long driverId; + + @ApiModelProperty("要入职的新公司的ID") + @NotNull + private Long newCompanyId; + + //@ApiModelProperty("驾驶员姓名") + //@NotBlank(message = "驾驶员姓名不能为空") + //private String driverName; + // + //@ApiModelProperty("性别") + //@NotNull(message = "性别不能为空") + //private Integer gender; + // + //@ApiModelProperty("身份证号") + //@NotBlank(message = "身份证号不能为空") + //private String idCard; + // + //@ApiModelProperty("出生年月") + //@NotNull(message = "出生年月不能为空") + //private LocalDateTime birth; + // + //@ApiModelProperty("籍贯") + //@NotBlank(message = "籍贯不能为空") + //private String nativePlace; + // + //@ApiModelProperty("手机号码") + //@NotBlank(message = "手机号码不能为空") + //private String phoneNo; + // + //@ApiModelProperty("文化程度") + //@NotBlank(message = "文化程度不能为空") + //private String edu; + // + //@ApiModelProperty("违章次数") + //private Integer violationsCount; + // + //@ApiModelProperty("驾驶员证号") + //private String driverLicenseNo; + // + //@ApiModelProperty("驾驶证类型") + //private String driverLicenseType; + // + //@ApiModelProperty("驾驶证号生效日期") + //private LocalDateTime driverLicenseEffectiveDate; + // + //@ApiModelProperty("驾驶证号失效日期") + //private LocalDateTime driverLicenseExpiryDate; + // + //@ApiModelProperty("从业资格证号") + //private String qualificationCertificateNo; + // + //@ApiModelProperty("从业资格证生效日期") + //private LocalDateTime qualificationCertificateNoEffectiveDate; + // + //@ApiModelProperty("从业资格证失效日期") + //private LocalDateTime qualificationCertificateNoExpiryDate; + // + //@ApiModelProperty("服务企业唯一标识id") + //private Long companyId; + // + //@ApiModelProperty("企业名称") + //private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverStarListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverStarListPO.java new file mode 100644 index 0000000..f4dbb2a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverStarListPO.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("驾驶员星级筛选列表") +@Data +public class ReqDriverStarListPO extends PagePo { + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("所属区域id") + private Long regionId; + + @ApiModelProperty("子区域id列表") + private List childRegionIds; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingListPO.java new file mode 100644 index 0000000..abf378e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingListPO.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/11/9 上午9:09 + */ +@Data +@ApiModel("驾驶员培训记录列表PO") +public class ReqDriverTrainingListPO extends PagePo { + + @ApiModelProperty("驾驶员id") + private Long driverId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingPreliminaryTrialPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingPreliminaryTrialPO.java new file mode 100644 index 0000000..3022562 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingPreliminaryTrialPO.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.driver.model.po; + +import java.util.List; + +import javax.validation.constraints.NotNull; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/15 上午9:11 + */ +@ApiModel(description = "驾驶员培训初审结果请求PO") +@Data +public class ReqDriverTrainingPreliminaryTrialPO { + + @NotNull(message = "审核id 不能为空") + @ApiModelProperty("审核id") + private Long metaApplyId; + + @NotNull(message = "驾驶员id 不能为空") + @ApiModelProperty("驾驶员id") + private Long driverId; + + @NotNull(message = "培训类型 不能为空") + @ApiModelProperty("培训类型") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + @NotNull(message = "审核结果不能为空") + @ApiModelProperty("审核结果") + private Boolean result; + + @ApiModelProperty("审核意见") + private String opinion; + + @ApiModelProperty("附件") + private List appendixList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationListPO.java new file mode 100644 index 0000000..ee921f8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationListPO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import com.ningdatech.carapi.sys.entity.enumeration.MetaApplyTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/12 下午5:19 + */ + +@ApiModel(description = "驾驶员培训列表请求") +@Data +public class ReqDriverTrainingRegistrationListPO extends PagePo { + + @ApiModelProperty("驾驶员名称") + private String driverName; + + @ApiModelProperty("公司姓名") + private String companyName; + + @ApiModelProperty(value = "审核类型", allowableValues = "PRELIMINARY_REVIEW 初审,IN_REVIEW 复核") + private MetaApplyTypeEnum metaApplyType; + + @ApiModelProperty(value = "meta审核状态", + allowableValues = "FIRST_TRIAL_UNDER_REVIEW 材料初审中," + + "REEXAMINATION_UNDER_REVIEW 材料复核中," + + "FIRST_TRIAL_APPROVED 材料初审通过," + + "REEXAMINATION_APPROVED 材料复核通过," + + "FIRST_TRIAL_APPROVAL_REJECTION 材料初审驳回," + + "REEXAMINATION_APPROVAL_REJECTION 材料复核驳回") + private List metaApplyStatusList; + + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,JOB_APPLICATION 跳槽申请,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + @ApiModelProperty("区域信息 regionId") + private Long regionId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationPO.java new file mode 100644 index 0000000..703c582 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqDriverTrainingRegistrationPO.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.common.constant.DriverLicenseTypeEnum; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/9 下午5:50 + */ +@Data +@ApiModel(description = "驾驶员培训报名") +public class ReqDriverTrainingRegistrationPO { + + @ApiModelProperty("驾驶员id 驾驶员培训报名首次信息填入无需传入") + private Long driverId; + + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,JOB_APPLICATION 申请跳槽,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + @NotNull(message = "培训报名类型不能为空") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + @ApiModelProperty("驾驶员姓名") + @NotBlank(message = "驾驶员姓名不能为空") + private String driverName; + + @ApiModelProperty("性别 0:女 ,1:男 ") + @NotNull(message = "性别不能为空") + private Integer gender; + + @ApiModelProperty("身份证号") + @NotBlank(message = "身份证号不能为空") + private String idCard; + + @ApiModelProperty("出生年月") + @NotNull(message = "出生年月不能为空") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯不能为空") + private String nativePlace; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯编码") + private String nativePlaceRegionCode; + + @ApiModelProperty(value = "免冠照图片文件") + private FileBasicInfo avatarFile; + + @ApiModelProperty(value = "健康状况") + private String health; + + @ApiModelProperty("手机号码") + @NotBlank(message = "手机号码不能为空") + private String phoneNo; + + @ApiModelProperty("住址") + @NotBlank(message = "住址不能为空") + private String address; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty(value = "驾驶证类型/准驾车型", allowableValues = "A1, A2, B1, B2, C1, OTHER") + private DriverLicenseTypeEnum driverLicenseType; + + @ApiModelProperty("初次领证时间") + @NotNull(message = "初次领证时间不能为空") + private LocalDateTime initialLicenseTime; + + @ApiModelProperty("附件") + private List appendixList; + + @ApiModelProperty("违规违法信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty(value = "驾驶员拟驾车型列表", allowableValues = "MIXER 搅拌车,PUMP_TRUCK 泵车,BULK_CEMENT_TRUCK 散装水泥车" + + ",MORTAR_TRUCK 砂浆车,OTHER 其他") + private List motorcycleTypeList; + + @ApiModelProperty("培训报名id") + private Long trainingRegistrationReviewId; + + @ApiModelProperty("驾驶员用户ID") + private Long driverUserId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqGetArchivalInfoReviewDetailPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqGetArchivalInfoReviewDetailPO.java new file mode 100644 index 0000000..502be97 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqGetArchivalInfoReviewDetailPO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.driver.model.po; + +import javax.validation.constraints.NotNull; + +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/20 下午5:52 + */ + +@Data +@ApiModel(description = "获取驾驶员档案审核详情PO") +public class ReqGetArchivalInfoReviewDetailPO { + + @ApiModelProperty("驾驶员id") + @NotNull(message = "驾驶员id不能为空") + private Long driverId; + + @NotNull(message = "培训报名类型不能为空") + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,JOB_APPLICATION 跳槽申请,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + @ApiModelProperty("培训报名id") + private Long trainingRegistrationReviewId; + + @ApiModelProperty("审核ID") + private Long metaApplyId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqListExamRecordPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqListExamRecordPO.java new file mode 100644 index 0000000..2929644 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqListExamRecordPO.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.ExamQualifiedEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("培训考试记录筛选") +@Data +public class ReqListExamRecordPO extends PagePo { + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("所属企业") + private String companyName; + + @ApiModelProperty("考试结果") + private ExamQualifiedEnum isQualified; + + @ApiModelProperty("考试开始时间") + private LocalDateTime startTime; + + @ApiModelProperty("考试结束时间") + private LocalDateTime endTime; + + @ApiModelProperty("所属区域id") + private Long regionId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqMakeUpExamPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqMakeUpExamPO.java new file mode 100644 index 0000000..df7172b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqMakeUpExamPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.driver.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/24 上午11:01 + */ +@ApiModel("补考") +@Data +public class ReqMakeUpExamPO { + + @NotNull(message = "培训组织id 不能为空") + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @NotNull(message = "驾驶员id 不能为空") + @ApiModelProperty("驾驶员id") + private Long driverId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqRegionStarPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqRegionStarPO.java new file mode 100644 index 0000000..ce7376f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqRegionStarPO.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("省/市/区级星级筛选列表") +@Data +public class ReqRegionStarPO extends PagePo { + @ApiModelProperty("所属区域id") + private Long regionId; + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSaveTrainingMaterialPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSaveTrainingMaterialPO.java new file mode 100644 index 0000000..31225f5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSaveTrainingMaterialPO.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.MaterialStatusEnum; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/21 下午5:01 + */ +@Data +@ApiModel(description = "创建培训材料入参PO") +public class ReqSaveTrainingMaterialPO { + + @ApiModelProperty("材料id 更新材料时传入") + private Long id; + + @NotBlank(message = "标题不能为空") + @ApiModelProperty("标题") + private String title; + + @NotNull(message = "材料类型 不能为空") + @ApiModelProperty("材料类型") + private MaterialTypeEnum materialType; + + @NotNull(message = "材料状态 不能为空") + @ApiModelProperty(value = "材料状态", allowableValues = "enable 启用,disable 禁用") + private MaterialStatusEnum materialStatus; + + @NotBlank(message = "内容 不能为空") + @ApiModelProperty("内容") + private String content; + + @ApiModelProperty("附件") + private List appendixList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreBonusPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreBonusPO.java new file mode 100644 index 0000000..daa14d3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreBonusPO.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.driver.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/11/4 上午9:49 + */ +@Data +@ApiModel("驾驶员奖励分数") +public class ReqScoreBonusPO { + + @NotNull + @ApiModelProperty("驾驶员id") + private Long driverId; + + @NotBlank + @ApiModelProperty("材料类型") + private String materialType; + + @NotNull + @ApiModelProperty("培训材料id") + private Long trainingMaterialId; + + @NotNull + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @NotBlank + @ApiModelProperty(value = "行为类型", allowableValues = "watch_video 观看视频,watch_profile 观看材料") + private String behaviorType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreListPO.java new file mode 100644 index 0000000..733f7f2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqScoreListPO.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/11/9 上午9:28 + */ +@Data +@ApiModel("驾驶员分数列表请求PO") +public class ReqScoreListPO extends PagePo { + + @NotNull + @ApiModelProperty("驾驶员id") + private Long driverId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSetExamTimePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSetExamTimePO.java new file mode 100644 index 0000000..dca61af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqSetExamTimePO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.driver.model.po; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午4:22 + */ +@Data +@ApiModel("设置考试时间") +public class ReqSetExamTimePO implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @ApiModelProperty("培训组织ID") + private Long trainingOrganizationId; + + @NotNull + @ApiModelProperty("随机试卷ID集合") + private List randomExamPaperId; + + @NotNull + @ApiModelProperty("考试开始日期") + private LocalDateTime examStartTime; + + @NotNull + @ApiModelProperty("考试结束时间") + private LocalDateTime examEndTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainerExportPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainerExportPO.java new file mode 100644 index 0000000..5e11cfe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainerExportPO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.driver.model.po; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午4:22 + */ +@Data +@ApiModel("导出培训人员信息") +public class ReqTrainerExportPO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("培训组织ID") + private Long trainingOrganizationId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingMaterialListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingMaterialListPO.java new file mode 100644 index 0000000..6c85bb9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingMaterialListPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/9 下午3:36 + */ +@Data +@ApiModel(description = "驾驶员培训材料分页查询入参") +public class ReqTrainingMaterialListPO extends PagePo { + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("材料类型") + private MaterialTypeEnum materialType; + + @ApiModelProperty("所属区域") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationListPO.java new file mode 100644 index 0000000..3889337 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationListPO.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.carapi.driver.constant.TrainingModeEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/11 上午10:25 + */ +@Data +@ApiModel(description = "培训组织列表查询PO") +public class ReqTrainingOrganizationListPO extends PagePo { + + @ApiModelProperty("培训主题") + private String trainingTopic; + + @ApiModelProperty("培训地点") + private String address; + + /** + * 培训模式 线上/线下 + * {@link TrainingModeEnum} + */ + @ApiModelProperty(value = "培训模式 线上/线下", allowableValues = "online,offline") + private TrainingModeEnum trainingMode; + + @ApiModelProperty("培训区域id") + private Long regionId; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @ApiModelProperty(value = "培训类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private List trainingTypeList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationStatusModifyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationStatusModifyPO.java new file mode 100644 index 0000000..83a9db6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqTrainingOrganizationStatusModifyPO.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.driver.constant.TrainingStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/31 下午2:44 + */ +@Data +@ApiModel("培训组织") +public class ReqTrainingOrganizationStatusModifyPO { + /** + * 培训状态 启用/禁用 + * {@link TrainingStatusEnum} + */ + @NotNull(message = "培训状态不能为空") + @ApiModelProperty(value = "培训状态", allowableValues = "enable 启用,disable 禁用") + private TrainingStatusEnum trainingStatus; + + @NotNull(message = "培训状态不能为空") + @ApiModelProperty(value = "培训组织id") + private Long organizationId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadCertificatePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadCertificatePO.java new file mode 100644 index 0000000..e358123 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadCertificatePO.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.driver.model.po; + +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/26 下午4:22 + */ +@Data +@ApiModel("上传合格证") +public class ReqUploadCertificatePO { + + private static final long serialVersionUID = 1L; + + @NotNull + @ApiModelProperty("驾驶员id") + private Long driverId; + + @NotBlank + @ApiModelProperty("合格证编号") + private String certificateNo; + + @NotBlank + @ApiModelProperty("发证单位") + private String issuedBy; + + @NotNull + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @NotNull + @ApiModelProperty("有效期至") + private LocalDateTime expiryDate; + + @ApiModelProperty("备注") + private String remark; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @NotNull(message = "培训类型不能为空") + @ApiModelProperty(value = "考试类型 取证培训/继续教育/换证培训/转码培训", + allowableValues = "forensic_registration_training 取证报名," + + "replacement_registration_training 换证报名 ," + + "continuing_education_training 继续教育," + + "transcoding_training 转码培训") + private String examType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadExamResultPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadExamResultPO.java new file mode 100644 index 0000000..1038156 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/po/ReqUploadExamResultPO.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.driver.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/24 上午11:01 + */ +@ApiModel("上传考试结果PO") +@Data +public class ReqUploadExamResultPO { + + @NotNull(message = "培训组织id 不能为空") + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @NotNull(message = "驾驶员id 不能为空") + @ApiModelProperty("驾驶员id") + private Long driverId; + + @NotNull(message = "考试分数 不能为空") + @ApiModelProperty("考试分数") + private Integer score; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/ArchivalInfoListQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/ArchivalInfoListQuery.java new file mode 100644 index 0000000..74a2d38 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/ArchivalInfoListQuery.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.driver.model.query; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/9 上午11:14 + */ +@Data +public class ArchivalInfoListQuery { + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/TrainingOrgTrainersQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/TrainingOrgTrainersQuery.java new file mode 100644 index 0000000..897a0b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/query/TrainingOrgTrainersQuery.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.driver.model.query; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 培训组织培训人员查询参数 + * + * @author CMM + * @since 2023/02/21 17:17 + */ +@Data +public class TrainingOrgTrainersQuery extends PagePo { + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("培训类型") + @NotNull(message = "请选择培训类型!") + private String trainingRegistrationType; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("企业") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/BehaviourAnalysisVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/BehaviourAnalysisVO.java new file mode 100644 index 0000000..24ad921 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/BehaviourAnalysisVO.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.constant.BgTypeEnum; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author CMM + * @Classname SecurityMonitorJoin + * @Description + * @Date 2022/11/6 20:59 + */ +@Data +public class BehaviourAnalysisVO implements Serializable { + + private static final long serialVersionUID = 4403907708033803066L; + + @ApiModelProperty("告警事件id") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + /** + * {@link BgTypeEnum} + */ + @ApiModelProperty("告警类型") + private Integer alarmType; + + @ApiModelProperty("告警类型名称") + private String alarmTypeName; + + @ApiModelProperty(value = "告警级别",allowableValues = "1 预警,2 报警") + private Integer alarmLevel; + + @ApiModelProperty("告警级别名称") + private String alarmLevelName; + + @ApiModelProperty("车辆速度") + private BigDecimal speed; + + @ApiModelProperty("告警时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime alarmTime; + + @ApiModelProperty("告警地址") + private String alarmAddress; + + @ApiModelProperty("告警图片|视频附件") + private List alarmAppendix; + + @ApiModelProperty(value = "处理状态",allowableValues = "0 待处理,1 已处理") + private Integer processingStatus; + + @ApiModelProperty(value = "督办状态",allowableValues = "0 待督办,1 已督办") + private Integer overseeStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverAbnormalBehaviorAnalysisDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverAbnormalBehaviorAnalysisDetailVO.java new file mode 100644 index 0000000..6656e60 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverAbnormalBehaviorAnalysisDetailVO.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.driver.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author CMM + * @description + * @since 2022/12/07 10:58 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DriverAbnormalBehaviorAnalysisDetailVO { + + @ApiModelProperty("异常行为数据ID") + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("告警类型名称") + private String alarmTypeName; + + @ApiModelProperty("告警类型") + private Integer alarmType; + + @ApiModelProperty("告警级别") + private String alarmLevel; + + @ApiModelProperty("车速") + private Integer speed; + + @ApiModelProperty("告警时间") + private LocalDateTime alarmTime; + + @ApiModelProperty("告警地址") + private String alarmAddress; + + @ApiModelProperty("告警图片附件") + private String alarmPictureAppendix; + + @ApiModelProperty("告警视频附件") + private String alarmVideoAppendix; + + @ApiModelProperty("驾驶员当日告警事件列表") + private List alarmEventList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverDailyAlarmEvent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverDailyAlarmEvent.java new file mode 100644 index 0000000..a494573 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/DriverDailyAlarmEvent.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author CMM + * @description + * @since 2022/12/07 11:09 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DriverDailyAlarmEvent { + + @ApiModelProperty("告警ID") + private Integer id; + + @ApiModelProperty("告警类型") + private Integer alarmType; + + @ApiModelProperty("告警类型名称") + private String alarmTypeName; + + @ApiModelProperty("告警时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime alarmTime; + + @ApiModelProperty("告警附件") + private List alarmAppendix; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/OrganizationTrainingTrainersInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/OrganizationTrainingTrainersInfo.java new file mode 100644 index 0000000..a0c0d00 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/OrganizationTrainingTrainersInfo.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.ExaminationStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/22 下午4:22 + */ +@Data +@ApiModel("培训人员 包含培训记录") +public class OrganizationTrainingTrainersInfo { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员用户id") + private Long driverUserId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("分数") + private Integer score; + + @ApiModelProperty("是否合格") + private String isQualified; + + @ApiModelProperty("试卷id") + private Long examPaperId; + + @ApiModelProperty("试卷名称") + private String examPaperName; + + @ApiModelProperty("准考证号") + private String examRegistrationNo; + + /** + * {@link ExaminationStatusEnum} + */ + @ApiModelProperty("考试状态") + private ExaminationStatusEnum examinationStatus; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名称") + private String companyName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoDetailVO.java new file mode 100644 index 0000000..3e24e31 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoDetailVO.java @@ -0,0 +1,126 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.constant.DriverLicenseTypeEnum; +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import com.ningdatech.carapi.driver.model.po.AuditInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/9 上午10:51 + */ +@Data +@ApiModel("驾驶员信息档案查询详情VO") +public class ResArchivalInfoDetailVO { + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + @NotBlank(message = "驾驶员姓名不能为空") + private String driverName; + + @ApiModelProperty("性别 0:女 ,1:男 ") + @NotNull(message = "性别不能为空") + private Integer gender; + + @ApiModelProperty("身份证号") + @NotBlank(message = "身份证号不能为空") + private String idCard; + + @ApiModelProperty("出生年月") + @NotNull(message = "出生年月不能为空") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime birth; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯不能为空") + private String nativePlace; + + @ApiModelProperty(value = "免冠照图片文件") + private FileBasicInfo avatarFile; + + @ApiModelProperty(value = "健康状况") + private String health; + + @ApiModelProperty("手机号码") + @NotBlank(message = "手机号码不能为空") + private String driverPhoneNo; + + @ApiModelProperty("住址") + @NotBlank(message = "住址不能为空") + private String driverAddress; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty("驾驶证类型/准驾车型") + private DriverLicenseTypeEnum driverLicenseType; + + @NotBlank(message = "公司id不能为空") + @ApiModelProperty("所属服务企业唯一标识id") + private Long companyId; + + @ApiModelProperty(value = "企业名称") + private String companyName; + + @ApiModelProperty(value = "企业地址") + private String companyAddress; + + @ApiModelProperty(value = "企业联系人") + private String companyContactPerson; + + @ApiModelProperty(value = "企业电话") + private String companyContactPhone; + + @ApiModelProperty("附件") + private List appendixList; + + @ApiModelProperty(value = "初审信息") + private AuditInfo preliminaryReviewInfo; + + @ApiModelProperty(value = "复审信息") + private AuditInfo reviewInfo; + + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + @NotNull(message = "培训报名类型不能为空") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + + @ApiModelProperty("初次领证时间") + @NotNull(message = "初次领证时间不能为空") + private LocalDateTime initialLicenseTime; + + @ApiModelProperty("违规违法信息") + private String illegalAndIllegalInfo; + + @ApiModelProperty("籍贯") + @NotBlank(message = "籍贯编码") + private String nativePlaceRegionCode; + + @ApiModelProperty(value = "驾驶员拟驾车型列表", allowableValues = "MIXER 搅拌车,PUMP_TRUCK 泵车,BULK_CEMENT_TRUCK 散装水泥车" + + ",MORTAR_TRUCK 砂浆车,OTHER 其他") + private List motorcycleTypeList; + + @ApiModelProperty("意向跳槽企业ID") + private Long jobChangeCompanyId; + + @ApiModelProperty("意向跳槽企业名称") + private String jobChangeCompanyName; + + @ApiModelProperty("培训合格证编号") + private String certificateNo; + + @ApiModelProperty("驾驶员用户ID") + private Long driverUserId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoSearchListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoSearchListVO.java new file mode 100644 index 0000000..c4122f7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArchivalInfoSearchListVO.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.driver.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/9 上午10:51 + */ +@Data +@ApiModel("驾驶员信息档案查询返回列表VO") +public class ResArchivalInfoSearchListVO implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("服务企业唯一标识id") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + @ApiModelProperty(value = "驾驶员状态", + allowableValues = " induction 入职,quit 离职") + private String driverStatus; + + @ApiModelProperty("系统用户ID") + private Long driverUserId; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("离职时间") + private LocalDateTime quitTime; + + @ApiModelProperty("入职时间") + private LocalDateTime inductionTime; + + @ApiModelProperty("驾驶员合格证") + private String certificateNo; + + @ApiModelProperty("驾驶证号") + private String driverLicenseNo; + + @ApiModelProperty("驾驶证类型") + private String driverLicenseType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArticleInfoListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArticleInfoListVO.java new file mode 100644 index 0000000..13831b2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResArticleInfoListVO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.ArticleTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/9 下午4:54 + */ +@Data +@ApiModel(description = "文章列表查询") +public class ResArticleInfoListVO { + + @ApiModelProperty("文章id") + private Long articleId; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("文章类型") + private ArticleTypeEnum articleType; + + @ApiModelProperty("制定时间") + private LocalDateTime formulationTime; + + @ApiModelProperty("文章状态") + private String articleStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCertificateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCertificateVO.java new file mode 100644 index 0000000..d6f89f2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCertificateVO.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.driver.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/11/3 上午11:38 + */ +@Data +@ApiModel("合格证详情VO") +public class ResCertificateVO { + + @ApiModelProperty("驾驶员合格证表id") + private Long id; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员用户id") + private Long userId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("出生年月") + private LocalDateTime birth; + + @ApiModelProperty("性别") + private Integer gender; + + @ApiModelProperty("籍贯") + private String nativePlace; + + @ApiModelProperty("健康状况") + private String health; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("住址") + private String address; + + @ApiModelProperty("驾驶证类型") + private String driverLicenseType; + + @ApiModelProperty("驾驶证号") + private String driverLicenseNo; + + @ApiModelProperty("合格证编号") + private String certificateNo; + + @ApiModelProperty("发证单位") + private String issuedBy; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("有效期至") + private LocalDateTime expiryDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCompanyStarListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCompanyStarListVO.java new file mode 100644 index 0000000..7b8a903 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCompanyStarListVO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.model.StarManageDisplayInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("公司星级筛选VO") +@Data +public class ResCompanyStarListVO { + + @ApiModelProperty("平均分数") + private Double totalAvgStar; + + @ApiModelProperty("总分数") + private Double totalStar; + + @ApiModelProperty("展示行列表") + private StarManageDisplayInfo record; + + //@ApiModelProperty("总数") + //private Long total; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCreateTrainingOrgVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCreateTrainingOrgVO.java new file mode 100644 index 0000000..da1bcc5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCreateTrainingOrgVO.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.model.TrainingBasicInfo; +import com.ningdatech.carapi.driver.model.TrainingExamPaperInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/21 下午2:52 + */ +@Data +@ApiModel("创建培训组织请求返回VO") +public class ResCreateTrainingOrgVO { + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCurrentUserOrganizationVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCurrentUserOrganizationVO.java new file mode 100644 index 0000000..a2f4a59 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResCurrentUserOrganizationVO.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.CurrentUserOrganizationEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/11/3 下午6:25 + */ +@Data +@ApiModel +public class ResCurrentUserOrganizationVO { + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("参与状态") + private CurrentUserOrganizationEnum status; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverBlackListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverBlackListVO.java new file mode 100644 index 0000000..6cfce76 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverBlackListVO.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.driver.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/9 下午1:59 + */ + +@Data +@ApiModel(description = "驾驶员黑名单列表展示VO") +public class ResDriverBlackListVO { + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("所属企业id") + private Long companyId; + + @ApiModelProperty("所属企业") + private String companyName; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("年度") + private String year; + + @ApiModelProperty("超速累计次数") + private Long accumulatedOverspeedCnt; + + @ApiModelProperty("出险累计次数") + private Long accumulatedAccidentsCnt; + + @ApiModelProperty("违章累计次数") + private Long accumulatedViolationsCnt; + + @ApiModelProperty("累计伤人次数") + private Long accumulatedHurtCnt; + + @ApiModelProperty("累计亡人次数") + private Long accumulatedDeathCnt; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverScoreRecordListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverScoreRecordListVO.java new file mode 100644 index 0000000..30358e4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverScoreRecordListVO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/11/3 下午4:53 + */ +@Data +@ApiModel("驾驶员分数记录") +public class ResDriverScoreRecordListVO { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("操作分数") + private Integer operateScore; + + @ApiModelProperty("操作类型 加分减分") + private String operateType; + + @ApiModelProperty("加分减分原因") + private String operateReason; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverStarListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverStarListVO.java new file mode 100644 index 0000000..d6e0489 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverStarListVO.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.driver.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("驾驶员星级列表VO") +@Data +public class ResDriverStarListVO { + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域") + private String regionName; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("受伤人数") + private Integer injuredCnt; + + @ApiModelProperty("事故次数") + private Integer accidentsCnt; + + @ApiModelProperty("出险次数") + private Integer insuranceCnt; + + @ApiModelProperty("死亡人数") + private Integer deathCnt; + + @ApiModelProperty("当前星级") + private Double currentStar; + + @ApiModelProperty("扣除星级") + private Double deductStar; + + @ApiModelProperty("当前分值") + private Integer currentScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingListVO.java new file mode 100644 index 0000000..123f4aa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingListVO.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.TrainingModeEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/11/9 上午9:09 + */ +@Data +@ApiModel("驾驶员培训记录列表VO") +public class ResDriverTrainingListVO { + + @ApiModelProperty("培训组织id") + private Long organizationId; + + @ApiModelProperty("培训主题") + private String trainingTopic; + + @ApiModelProperty("培训开始时间") + private LocalDateTime trainingStartTime; + + @ApiModelProperty("培训结束时间") + private LocalDateTime trainingEndTime; + + @ApiModelProperty("培训地点") + private String address; + + /** + * 培训模式 线上/线下 + * {@link TrainingModeEnum} + */ + @ApiModelProperty(value = "培训模式 线上/线下", allowableValues = "online,offline") + private TrainingModeEnum trainingMode; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @ApiModelProperty(value = "培训类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private TrainingTypeEnum trainingType; + + @ApiModelProperty("是否合格") + private String isQualified; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingRegistrationListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingRegistrationListVO.java new file mode 100644 index 0000000..b21d163 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResDriverTrainingRegistrationListVO.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/12 下午5:19 + */ + +@Data +@ApiModel(description = "培训报名列表筛选") +public class ResDriverTrainingRegistrationListVO { + + @ApiModelProperty("培训报名id") + private Long trainingRegistrationReviewId; + + @ApiModelProperty("初审复审关联id") + private Long preliminaryReviewAssociatedId; + + @ApiModelProperty("meta审核id") + private Long metaApplyId; + + @ApiModelProperty(value = "meta审核状态", + allowableValues = "FIRST_TRIAL_UNDER_REVIEW 材料初审中," + + "REEXAMINATION_UNDER_REVIEW 材料复核中," + + "FIRST_TRIAL_APPROVED 材料初审通过," + + "REEXAMINATION_APPROVED 材料复核通过," + + "FIRST_TRIAL_APPROVAL_REJECTION 材料初审驳回," + + "REEXAMINATION_APPROVAL_REJECTION 材料复核驳回") + private String metaApplyStatus; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("所属企业id") + private Long companyId; + + @ApiModelProperty("所属企业名称") + private String companyName; + + @ApiModelProperty("所属区域id") + private Long regionId; + + @ApiModelProperty("所属区域展示名称") + private String regionName; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + @ApiModelProperty(value = "培训报名类型", allowableValues = "FORENSIC_REGISTRATION 取证报名,REPLACEMENT_REGISTRATION 换证报名,CONTINUING_EDUCATION 继续教育") + @NotNull(message = "培训报名类型不能为空") + private TrainingRegistrationTypeEnum trainingRegistrationType; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResListExamRecordVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResListExamRecordVO.java new file mode 100644 index 0000000..fe586ca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResListExamRecordVO.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.ExamQualifiedEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("培训考试记录筛选VO") +@Data +public class ResListExamRecordVO { + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员用户id") + private String driverUserId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("所属企业id") + private Long companyId; + + @ApiModelProperty("所属企业") + private String companyName; + + @ApiModelProperty("考试结果") + private ExamQualifiedEnum isQualified; + + @ApiModelProperty("考试分") + private Integer score; + + @ApiModelProperty("考试时间") + private LocalDateTime examTime; + + @ApiModelProperty("所属区域id") + private Long regionId; + + @ApiModelProperty("所属区域") + private String regionName; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @NotNull(message = "培训类型不能为空") + @ApiModelProperty(value = "考试类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private String examType; + + @ApiModelProperty("驾驶员合格证编号") + private String certificateNo; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResRegionStarVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResRegionStarVO.java new file mode 100644 index 0000000..efaab0a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResRegionStarVO.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.model.StarManageDisplayInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/26 下午5:20 + */ +@ApiModel("驾驶员星级筛选列表") +@Data +public class ResRegionStarVO { + + @ApiModelProperty("平均分数") + private Double totalAvgStar; + + @ApiModelProperty("总分数") + private Double totalStar; + + @ApiModelProperty("展示记录") + private StarManageDisplayInfo record; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResSaveTrainingMaterialVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResSaveTrainingMaterialVO.java new file mode 100644 index 0000000..6f66e87 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResSaveTrainingMaterialVO.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.driver.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/21 下午5:01 + */ +@Data +@ApiModel(description = "创建培训材料返回参数VO") +public class ResSaveTrainingMaterialVO { + + @ApiModelProperty("培训材料id") + private Long trainingMaterialId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialListVO.java new file mode 100644 index 0000000..230b3f7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialListVO.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.MaterialStatusEnum; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/9 下午3:47 + */ + +@Data +@ApiModel(description = "驾驶员培训材料分页查询列表VO") +public class ResTrainingMaterialListVO { + + @ApiModelProperty("培训材料id") + private Long trainingMaterialId; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("材料类型") + private MaterialTypeEnum materialType; + + @ApiModelProperty(value = "材料状态", allowableValues = "enable 启用,disable 禁用") + private MaterialStatusEnum materialStatus; + + @ApiModelProperty(value = "所属区域") + private String regionName; + + @ApiModelProperty(value = "regionId") + private Long regionId; + + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + @NotBlank(message = "内容 不能为空") + @ApiModelProperty("内容") + private String content; + + @ApiModelProperty("附件") + private List appendixList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialVO.java new file mode 100644 index 0000000..42ccf2b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingMaterialVO.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.common.model.FileBasicInfo; +import com.ningdatech.carapi.driver.constant.MaterialStatusEnum; +import com.ningdatech.carapi.driver.constant.MaterialTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/21 下午5:01 + */ +@Data +@ApiModel(description = "培训材料详情VO") +public class ResTrainingMaterialVO { + + @ApiModelProperty("id") + private Long id; + + @NotBlank(message = "标题不能为空") + @ApiModelProperty("标题") + private String title; + + @NotNull(message = "材料类型 不能为空") + @ApiModelProperty("材料类型") + private MaterialTypeEnum materialType; + + @NotNull(message = "材料状态 不能为空") + @ApiModelProperty(value = "材料状态", allowableValues = "enable 启用,disable 禁用") + private MaterialStatusEnum materialStatus; + + @NotBlank(message = "内容 不能为空") + @ApiModelProperty("内容") + private String content; + + @ApiModelProperty("附件") + private List appendixList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrgTrainerVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrgTrainerVO.java new file mode 100644 index 0000000..ddd7ea5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrgTrainerVO.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.driver.model.vo; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 培训组织培训人员实体类 + * + * @author CMM + * @since 2023/02/21 16:46 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ResTrainingOrgTrainerVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("驾驶员id") + private Long driverId; + + @ApiModelProperty("驾驶员姓名") + private String driverName; + + @ApiModelProperty("驾驶员用户id") + private Long driverUserId; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("证件是否到期") + private Boolean certificateExpireFlag; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationDetailVO.java new file mode 100644 index 0000000..a82e976 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationDetailVO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.model.TrainingBasicInfo; +import com.ningdatech.carapi.driver.model.TrainingExamPaperInfo; +import com.ningdatech.carapi.driver.model.TrainingMaterialOverviewInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/11 上午10:53 + */ + +@Data +@ApiModel(description = "培训组织详情VO") +public class ResTrainingOrganizationDetailVO { + @ApiModelProperty("培训基础信息") + private TrainingBasicInfo trainingBasicInfo; + + @ApiModelProperty("培训资料") + private TrainingMaterialOverviewInfo trainingMaterialOverviewInfo; + + @ApiModelProperty("培训考试试卷") + private TrainingExamPaperInfo trainingExamPaperInfo; + + @ApiModelProperty("培训人员") + private List trainingTrainersInfoList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationListVO.java new file mode 100644 index 0000000..df7a9cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/ResTrainingOrganizationListVO.java @@ -0,0 +1,91 @@ +package com.ningdatech.carapi.driver.model.vo; + +import java.time.LocalDateTime; +import java.util.List; + +import javax.validation.constraints.NotNull; + +import com.ningdatech.carapi.driver.constant.TrainingModeEnum; +import com.ningdatech.carapi.driver.constant.TrainingStatusEnum; +import com.ningdatech.carapi.driver.constant.TrainingTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/11 上午10:25 + */ +@Data +@ApiModel(description = "培训组织列表查询展示VO") +public class ResTrainingOrganizationListVO { + + @ApiModelProperty("培训组织id") + private Long trainingOrganizationId; + + @ApiModelProperty("培训主题") + private String trainingTopic; + + @ApiModelProperty("培训地点") + private String address; + + @ApiModelProperty("培训开始时间") + private LocalDateTime trainingStartTime; + + @ApiModelProperty("培训结束时间") + private LocalDateTime trainingEndTime; + + @ApiModelProperty("区域id") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + /** + * 培训模式 线上/线下 + * {@link TrainingModeEnum} + */ + @ApiModelProperty(value = "培训模式 线上/线下", allowableValues = "online,offline") + private TrainingModeEnum trainingMode; + + /** + * 培训类型 取证培训/继续教育/换证培训/转码培训 + * {@link TrainingTypeEnum} + */ + @ApiModelProperty(value = "培训类型 取证培训/继续教育/换证培训/转码培训", allowableValues = "forensic_registration_training 取证报名,replacement_registration_training 换证报名 ,continuing_education_training 继续教育,transcoding_training 转码培训") + private TrainingTypeEnum trainingType; + + /** + * 培训状态 启用/禁用 + * {@link TrainingStatusEnum} + */ + @NotNull(message = "培训状态不能为空") + @ApiModelProperty(value = "培训状态", allowableValues = "enable 启用,disable 禁用") + private TrainingStatusEnum trainingStatus; + + /** + * 是否可以设置考试时间 + */ + private Boolean canSetExamTime = Boolean.FALSE; + + /** + * 考试试卷ID + */ + private List examPaperId; + + /** + * 考试试卷名称 + */ + private List examPaperName; + + @ApiModelProperty("考试开始时间") + private LocalDateTime examStartTime; + + @ApiModelProperty("考试结束时间") + private LocalDateTime examEndTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/StarManageDisplay.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/StarManageDisplay.java new file mode 100644 index 0000000..3da06df --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/model/vo/StarManageDisplay.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.driver.model.vo; + +import com.ningdatech.carapi.driver.constant.StarManageDisplayTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/11/15 下午2:18 + */ + +@Data +@ApiModel("星级管理展示类") +public class StarManageDisplay { + + @ApiModelProperty("展示名称") + private String displayName; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("展示字段类型") + private StarManageDisplayTypeEnum type; +} + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IArticleInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IArticleInfoService.java new file mode 100644 index 0000000..296db54 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IArticleInfoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.ArticleInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface IArticleInfoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviorAnalysisProcessingModeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviorAnalysisProcessingModeService.java new file mode 100644 index 0000000..9387014 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviorAnalysisProcessingModeService.java @@ -0,0 +1,11 @@ +package com.ningdatech.carapi.driver.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.driver.entity.BehaviorAnalysisProcessingMode; + +/** + * @author CMM + * @since 2022/12/14 17:56 + */ +public interface IBehaviorAnalysisProcessingModeService extends IService { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviourAnalysisService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviourAnalysisService.java new file mode 100644 index 0000000..7f571f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IBehaviourAnalysisService.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.driver.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysis; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisOverseeDTO; +import com.ningdatech.carapi.driver.model.po.AlarmWarnFilePO; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface IBehaviourAnalysisService extends IService { + + Page pageBehaviour(Page page, LambdaQueryWrapper wrapper); + + DriverAbnormalBehaviorAnalysis getOneBehaviour(LambdaQueryWrapper wrapper); + + List selectDriverAbnormalBehaviorAnalysisData(long index); + + Boolean oversee(DriverAbnormalBehaviorAnalysisOverseeDTO param, Long userId); + + List selectDriverAbnormalBehaviorAnalysisAppendixData(List alarmMsgSnList); + + Long selectOneByAlarmMsgSn(Integer alarmMsgSn); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ICertificateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ICertificateService.java new file mode 100644 index 0000000..dc479e1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ICertificateService.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.driver.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-24 + */ +public interface ICertificateService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverBlackListService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverBlackListService.java new file mode 100644 index 0000000..bc3c937 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverBlackListService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.DriverBlackList; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface IDriverBlackListService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverInfoService.java new file mode 100644 index 0000000..302789c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverInfoService.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.driver.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import com.ningdatech.carapi.driver.entity.DriverInfo; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +public interface IDriverInfoService extends IService { + + Map listDriverInfoByIds(Collection ids); + + /** + * 驾驶员年龄分布计算 + * + * @param caseSql 年龄区间计算SQL + * @param undefinedAge 不参与统计的年龄 + * @param param + * @return key 年龄、value 驾驶员数量 + * @author WendyYang + **/ + Map driverAgeStatistics(String caseSql, Integer undefinedAge, DataScreenParam param); + + /** + * 驾驶员驾龄分布计算 + * + * @param caseSql 驾龄区间计算SQL + * @param undefinedAge 不参与统计的驾龄 + * @param param + * @return key 驾龄、value 驾驶员数量 + * @author WendyYang + **/ + Map drivingExperienceStatistics(String caseSql, Integer undefinedAge,DataScreenParam param); + + Long selectUserIdById(Long driverId); + + Map listByIdCard(List idCards); + + List diverCountByRegion(DataScreenParam param); + + List> nativePlaceStatisticsByRegion(DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreInfoService.java new file mode 100644 index 0000000..e47a283 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreInfoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.DriverScoreInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +public interface IDriverScoreInfoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreRecordService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreRecordService.java new file mode 100644 index 0000000..2c7c452 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverScoreRecordService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.DriverScoreRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +public interface IDriverScoreRecordService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverWorkRecordService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverWorkRecordService.java new file mode 100644 index 0000000..4d56e80 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IDriverWorkRecordService.java @@ -0,0 +1,8 @@ +package com.ningdatech.carapi.driver.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.driver.entity.DriverWorkRecordInfo; + +public interface IDriverWorkRecordService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordDetailService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordDetailService.java new file mode 100644 index 0000000..90fa749 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordDetailService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.ExamRecordDetail; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +public interface IExamRecordDetailService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordService.java new file mode 100644 index 0000000..b1dc671 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IExamRecordService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.ExamRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +public interface IExamRecordService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IStarManageService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IStarManageService.java new file mode 100644 index 0000000..3fd7f5a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/IStarManageService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.RegionStarDTO; +import com.ningdatech.carapi.driver.entity.StarManage; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-11-15 + */ +public interface IStarManageService extends IService { + + Double getAvgStar(RegionStarDTO param); + + Double countTotalStar(RegionStarDTO param); + + Double getCompanyAvgStar(RegionStarDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingBonusRecordService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingBonusRecordService.java new file mode 100644 index 0000000..0269ff0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingBonusRecordService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.TrainingBonusRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-31 + */ +public interface ITrainingBonusRecordService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingMaterialService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingMaterialService.java new file mode 100644 index 0000000..0a425be --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingMaterialService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.TrainingMaterial; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-21 + */ +public interface ITrainingMaterialService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationMaterialService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationMaterialService.java new file mode 100644 index 0000000..ccf30e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationMaterialService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.TrainingOrganizationMaterial; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +public interface ITrainingOrganizationMaterialService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationService.java new file mode 100644 index 0000000..6cdcf1c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.TrainingOrganization; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-10 + */ +public interface ITrainingOrganizationService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationTrainerService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationTrainerService.java new file mode 100644 index 0000000..21de7c7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingOrganizationTrainerService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.ningdatech.carapi.driver.entity.TrainingOrganizationTrainer; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +public interface ITrainingOrganizationTrainerService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingRegistrationReviewService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingRegistrationReviewService.java new file mode 100644 index 0000000..caa8b71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/ITrainingRegistrationReviewService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.driver.entity.TrainingRegistrationReview; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +public interface ITrainingRegistrationReviewService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ArticleInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ArticleInfoServiceImpl.java new file mode 100644 index 0000000..785fb5e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ArticleInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.ArticleInfo; +import com.ningdatech.carapi.driver.mapper.ArticleInfoMapper; +import com.ningdatech.carapi.driver.service.IArticleInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@Service +public class ArticleInfoServiceImpl extends ServiceImpl implements IArticleInfoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviorAnalysisProcessingModeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviorAnalysisProcessingModeServiceImpl.java new file mode 100644 index 0000000..431a417 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviorAnalysisProcessingModeServiceImpl.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.driver.service.impl; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.driver.entity.BehaviorAnalysisProcessingMode; +import com.ningdatech.carapi.driver.mapper.BehaviorAnalysisProcessingModeMapper; +import com.ningdatech.carapi.driver.service.IBehaviorAnalysisProcessingModeService; + +/** + * @author CMM + * @description + * @since 2022/12/14 17:51 + */ +@Service +public class BehaviorAnalysisProcessingModeServiceImpl extends ServiceImpl implements IBehaviorAnalysisProcessingModeService { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviourAnalysisServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviourAnalysisServiceImpl.java new file mode 100644 index 0000000..83baa54 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/BehaviourAnalysisServiceImpl.java @@ -0,0 +1,112 @@ +package com.ningdatech.carapi.driver.service.impl; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.driver.call.RestTemplateToInterface; +import com.ningdatech.carapi.driver.constant.DriverAbnormalBehaviorOverseeEnum; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysis; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisOverseeDTO; +import com.ningdatech.carapi.driver.entity.OverseeInterfaceCallDTO; +import com.ningdatech.carapi.driver.mapper.BehaviourAnalysisMapper; +import com.ningdatech.carapi.driver.model.po.AlarmWarnFilePO; +import com.ningdatech.carapi.driver.service.IBehaviourAnalysisService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Service +@RequiredArgsConstructor +public class BehaviourAnalysisServiceImpl extends ServiceImpl + implements IBehaviourAnalysisService { + + private final BehaviourAnalysisMapper behaviourAnalysisMapper; + private final RestTemplateToInterface restTemplateToInterface; + + @Value("${send-urge-warn.url}") + private String sendUrgeWarnUrl; + + @Override + public Page pageBehaviour(Page page, LambdaQueryWrapper wrapper) { + return behaviourAnalysisMapper.pageBehiviour(page, wrapper); + } + + @Override + public DriverAbnormalBehaviorAnalysis getOneBehaviour(LambdaQueryWrapper wrapper) { + return behaviourAnalysisMapper.getOneBehiviour(wrapper); + } + + @Override + public List selectDriverAbnormalBehaviorAnalysisData(long index) { + return behaviourAnalysisMapper.selectDriverAbnormalBehaviorAnalysisByCarPlate(index); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean oversee(DriverAbnormalBehaviorAnalysisOverseeDTO param, Long userId) { + //校验传入的审核码 + if (!DriverAbnormalBehaviorOverseeEnum.OVERSEE.getCode().equals(param.getOverseeStatus())) { + throw new BizException("请检查传入的督办code!"); + } + DriverAbnormalBehaviorAnalysis driverAbnormalBehaviorAnalysis = behaviourAnalysisMapper.selectById(param.getId()); + if (Objects.isNull(driverAbnormalBehaviorAnalysis)) { + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "驾驶员异常行为 {}为空", param.getId()); + } + if (driverAbnormalBehaviorAnalysis.getOverseeStatus().equals(DriverAbnormalBehaviorOverseeEnum.OVERSEE.getCode())) { + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "只能督办待督办的驾驶员异常行为 {}", param.getId()); + } + //调用外部接口下发督办请求 + //装配请求参数 + OverseeInterfaceCallDTO req = new OverseeInterfaceCallDTO(); + req.setGnssCenterId(driverAbnormalBehaviorAnalysis.getGnssCenterId()); + req.setMSgSn(driverAbnormalBehaviorAnalysis.getAlarmMsgSn()); + req.setSupervisor(LoginUserUtil.getUsername()); + String resultJson = restTemplateToInterface.doPostWith2(sendUrgeWarnUrl, req); + //保存督办处理结果 + driverAbnormalBehaviorAnalysis.setOverseeResult(resultJson); + JSONObject result = JSON.parseObject(resultJson); + String status = result.getString(CommonConstant.CALL_STATUS); + if (CommonConstant.CALL_STATUS_OK_VALUE.equals(status)) { + //设置告警异常行为状态为已督办 + driverAbnormalBehaviorAnalysis.setOverseeStatus(param.getOverseeStatus()); + driverAbnormalBehaviorAnalysis.setOverseeTime(LocalDateTime.now()); + driverAbnormalBehaviorAnalysis.setUpdateBy(userId); + driverAbnormalBehaviorAnalysis.setUpdateOn(LocalDateTime.now()); + behaviourAnalysisMapper.updateById(driverAbnormalBehaviorAnalysis); + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + @Override + public List selectDriverAbnormalBehaviorAnalysisAppendixData(List alarmMsgSnList) { + return behaviourAnalysisMapper.selectDriverAbnormalBehaviorAnalysisAppendixData(alarmMsgSnList); + } + + @Override + public Long selectOneByAlarmMsgSn(Integer alarmMsgSn) { + return behaviourAnalysisMapper.selectOneByAlarmMsgSn(alarmMsgSn); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/CertificateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/CertificateServiceImpl.java new file mode 100644 index 0000000..2a65750 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/CertificateServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.mapper.CertificateMapper; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-24 + */ +@Service +public class CertificateServiceImpl extends ServiceImpl implements ICertificateService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverBlackListServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverBlackListServiceImpl.java new file mode 100644 index 0000000..3ea962a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverBlackListServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.DriverBlackList; +import com.ningdatech.carapi.driver.mapper.DriverBlackListMapper; +import com.ningdatech.carapi.driver.service.IDriverBlackListService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@Service +public class DriverBlackListServiceImpl extends ServiceImpl implements IDriverBlackListService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverInfoServiceImpl.java new file mode 100644 index 0000000..9b110f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverInfoServiceImpl.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.model.KeyValueDTO; +import com.ningdatech.carapi.common.model.po.MapDataPO; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.mapper.DriverInfoMapper; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-09 + */ +@Service +@RequiredArgsConstructor +public class DriverInfoServiceImpl extends ServiceImpl implements IDriverInfoService { + + @Override + public Map listDriverInfoByIds(Collection ids) { + if (CollectionUtils.isEmpty(ids)) { + return Collections.emptyMap(); + } + List driverInfoList = list(Wrappers.lambdaQuery(DriverInfo.class) + .in(DriverInfo::getId, ids)); + return CollUtils.listToMap(driverInfoList, DriverInfo::getId); + } + + @Override + @XmlDataScope(entityIndex = 2) + @BuildChildrenRegionEntity(entityIndex = 2) + public Map driverAgeStatistics(String caseSql, Integer undefinedAge, DataScreenParam param) { + List> countList = baseMapper.driverAgeStatistics(caseSql, undefinedAge, param); + return CollUtils.listToMap(countList, KeyValueDTO::getKey, w -> w.getValue().intValue()); + } + + @Override + @XmlDataScope(entityIndex = 2) + @BuildChildrenRegionEntity(entityIndex = 2) + public Map drivingExperienceStatistics(String caseSql, Integer undefinedAge, DataScreenParam param) { + List> countList = baseMapper.drivingExperienceStatistics(caseSql, undefinedAge, param); + return CollUtils.listToMap(countList, KeyValueDTO::getKey, w -> w.getValue().intValue()); + } + + @Override + public Long selectUserIdById(Long driverId) { + DriverInfo driverInfo = baseMapper.selectById(driverId); + return driverInfo.getUserId(); + } + + @Override + public Map listByIdCard(List idCards) { + if (CollectionUtils.isEmpty(idCards)) { + return Collections.emptyMap(); + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverInfo.class); + wrapper.in(DriverInfo::getIdCard, idCards); + return CollUtils.listToMap(this.list(wrapper), DriverInfo::getIdCard); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List diverCountByRegion(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return baseMapper.diverCountByRegion(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List> nativePlaceStatisticsByRegion(DataScreenParam param) { + return baseMapper.nativePlaceStatisticsByRegion(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreInfoServiceImpl.java new file mode 100644 index 0000000..9d6d64a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.DriverScoreInfo; +import com.ningdatech.carapi.driver.mapper.DriverScoreInfoMapper; +import com.ningdatech.carapi.driver.service.IDriverScoreInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +@Service +public class DriverScoreInfoServiceImpl extends ServiceImpl implements IDriverScoreInfoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreRecordServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreRecordServiceImpl.java new file mode 100644 index 0000000..a6aca90 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverScoreRecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.DriverScoreRecord; +import com.ningdatech.carapi.driver.mapper.DriverScoreRecordMapper; +import com.ningdatech.carapi.driver.service.IDriverScoreRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-27 + */ +@Service +public class DriverScoreRecordServiceImpl extends ServiceImpl implements IDriverScoreRecordService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverWorkRecordServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverWorkRecordServiceImpl.java new file mode 100644 index 0000000..92cf891 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/DriverWorkRecordServiceImpl.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.driver.entity.DriverWorkRecordInfo; +import com.ningdatech.carapi.driver.mapper.DriverWorkRecordInfoMapper; +import com.ningdatech.carapi.driver.service.IDriverWorkRecordService; +import org.springframework.stereotype.Service; + +/** + * @author CMM + * @description + * @since 2022/11/25 14:44 + */ +@Service +public class DriverWorkRecordServiceImpl extends ServiceImpl implements IDriverWorkRecordService { +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordDetailServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordDetailServiceImpl.java new file mode 100644 index 0000000..369f1a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordDetailServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.ExamRecordDetail; +import com.ningdatech.carapi.driver.mapper.ExamRecordDetailMapper; +import com.ningdatech.carapi.driver.service.IExamRecordDetailService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +@Service +public class ExamRecordDetailServiceImpl extends ServiceImpl implements IExamRecordDetailService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordServiceImpl.java new file mode 100644 index 0000000..b12288f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/ExamRecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.ExamRecord; +import com.ningdatech.carapi.driver.mapper.ExamRecordMapper; +import com.ningdatech.carapi.driver.service.IExamRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-26 + */ +@Service +public class ExamRecordServiceImpl extends ServiceImpl implements IExamRecordService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/StarManageServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/StarManageServiceImpl.java new file mode 100644 index 0000000..6c12f4e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/StarManageServiceImpl.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.driver.service.impl; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.driver.entity.RegionStarDTO; +import com.ningdatech.carapi.driver.entity.StarManage; +import com.ningdatech.carapi.driver.mapper.StarManageMapper; +import com.ningdatech.carapi.driver.service.IStarManageService; + +import lombok.RequiredArgsConstructor; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-11-15 + */ +@Service +@RequiredArgsConstructor +public class StarManageServiceImpl extends ServiceImpl implements IStarManageService { + + private final StarManageMapper starManageMapper; + + @Override + @XmlDataScope + public Double getAvgStar(RegionStarDTO param) { + return starManageMapper.getAvgStar(param); + } + + @Override + @XmlDataScope + public Double countTotalStar(RegionStarDTO param) { + return starManageMapper.countTotalStar(param); + } + + @Override + @XmlDataScope + public Double getCompanyAvgStar(RegionStarDTO param) { + return starManageMapper.getCompanyAvgStar(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingBonusRecordServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingBonusRecordServiceImpl.java new file mode 100644 index 0000000..9d4a8e1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingBonusRecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.TrainingBonusRecord; +import com.ningdatech.carapi.driver.mapper.TrainingBonusRecordMapper; +import com.ningdatech.carapi.driver.service.ITrainingBonusRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-31 + */ +@Service +public class TrainingBonusRecordServiceImpl extends ServiceImpl implements ITrainingBonusRecordService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingMaterialServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingMaterialServiceImpl.java new file mode 100644 index 0000000..0c031cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingMaterialServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.TrainingMaterial; +import com.ningdatech.carapi.driver.mapper.TrainingMaterialMapper; +import com.ningdatech.carapi.driver.service.ITrainingMaterialService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-21 + */ +@Service +public class TrainingMaterialServiceImpl extends ServiceImpl implements ITrainingMaterialService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationMaterialServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationMaterialServiceImpl.java new file mode 100644 index 0000000..d0a1916 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationMaterialServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.TrainingOrganizationMaterial; +import com.ningdatech.carapi.driver.mapper.TrainingOrganizationMaterialMapper; +import com.ningdatech.carapi.driver.service.ITrainingOrganizationMaterialService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +@Service +public class TrainingOrganizationMaterialServiceImpl extends ServiceImpl implements ITrainingOrganizationMaterialService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationServiceImpl.java new file mode 100644 index 0000000..a3f8466 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.TrainingOrganization; +import com.ningdatech.carapi.driver.mapper.NdTrainingOrganizationMapper; +import com.ningdatech.carapi.driver.service.ITrainingOrganizationService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-10 + */ +@Service +public class TrainingOrganizationServiceImpl extends ServiceImpl implements ITrainingOrganizationService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationTrainerServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationTrainerServiceImpl.java new file mode 100644 index 0000000..46515b9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingOrganizationTrainerServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.TrainingOrganizationTrainer; +import com.ningdatech.carapi.driver.mapper.TrainingOrganizationTrainerMapper; +import com.ningdatech.carapi.driver.service.ITrainingOrganizationTrainerService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-22 + */ +@Service +public class TrainingOrganizationTrainerServiceImpl extends ServiceImpl implements ITrainingOrganizationTrainerService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingRegistrationReviewServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingRegistrationReviewServiceImpl.java new file mode 100644 index 0000000..9c1b4d6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/driver/service/impl/TrainingRegistrationReviewServiceImpl.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.driver.service.impl; + +import com.ningdatech.carapi.driver.entity.TrainingRegistrationReview; +import com.ningdatech.carapi.driver.mapper.TrainingRegistrationReviewMapper; +import com.ningdatech.carapi.driver.service.ITrainingRegistrationReviewService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Service +@RequiredArgsConstructor +public class TrainingRegistrationReviewServiceImpl extends ServiceImpl implements ITrainingRegistrationReviewService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/constant/HomepageConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/constant/HomepageConstant.java new file mode 100644 index 0000000..03a7073 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/constant/HomepageConstant.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.homepage.constant; + +/** + * @author CMM + * @description + * @since 2022/11/11 17:17 + */ + +public class HomepageConstant { + private HomepageConstant(){} + //首页选择本年按钮时,携带的标志参数 + public static final String YEAR_FLAG = "1"; + //首页选择本月按钮时,携带的标志参数 + public static final String MONTH_FLAG = "2"; + //首页选择本日按钮时,携带的标志参数 + public static final String DAY_FLAG = "3"; + + public static final String REDIS_ONLINE_INDEX = "online_index"; + public static final Integer TIME_INTERVAL = 5; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/controller/AiWorkbenchController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/controller/AiWorkbenchController.java new file mode 100644 index 0000000..cc64ad4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/controller/AiWorkbenchController.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.homepage.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleAuditPageQuery; +import com.ningdatech.carapi.car.vehicle.manage.VehicleManage; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleBaseVO; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.position.manage.PositionMonitorManage; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.driver.manage.DriverArchivesManage; +import com.ningdatech.carapi.driver.model.po.ReqDriverTrainingRegistrationListPO; +import com.ningdatech.carapi.driver.model.vo.ResDriverTrainingRegistrationListVO; +import com.ningdatech.carapi.homepage.entity.dto.HomepageAbnormalBehaviorPageParamDTO; +import com.ningdatech.carapi.homepage.entity.vo.HomepageDriverAbnormalBehaviorVo; +import com.ningdatech.carapi.homepage.entity.vo.HomepageVo; +import com.ningdatech.carapi.homepage.manage.HomepageManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +/** + * @author CMM + * @description 首页AI工作台 + * @since 2022/11/10 10:05 + */ +@RestController +@Api(tags = "首页AI工作台") +@RequestMapping("/api/homepage/workbench") +@RequiredArgsConstructor +public class AiWorkbenchController { + + private final HomepageManage homepageManage; + private final PositionMonitorManage positionMonitorManage; + private final VehicleManage vehicleManage; + private final DriverArchivesManage driverArchivesManage; + + @ApiOperation("首页数据显示") + @GetMapping + public HomepageVo onlineVehicleStatistics(@Valid @ModelAttribute DataScreenParam param) { + return homepageManage.queryVehicleStatistics(param); + } + + @GetMapping("/monitorVehicleGisList") + @ApiOperation("首页GPS地图车辆分布显示") + public List queryMonitorVehicleGisList(@Valid @ModelAttribute DataScreenParam param) { + return positionMonitorManage.realTimeMonitorVehicleGisList(param); + } + + @GetMapping("/toBeAuditList") + @ApiOperation("首页工作台车辆待审核列表") + public PageVo queryToBeAudit(@Valid @ModelAttribute VehicleAuditPageQuery vehicleAuditPageQuery) { + return vehicleManage.queryToBeAudit(vehicleAuditPageQuery); + } + + @GetMapping("/training/registration/un-deal/list") + @ApiOperation("首页工作台驾驶员待审核列表") + public PageVo queryDriverTrainingRegistrationUnDealList + (@Valid @ModelAttribute ReqDriverTrainingRegistrationListPO po) { + List metaApplyStatusList = new ArrayList<>(); + metaApplyStatusList.add("FIRST_TRIAL_UNDER_REVIEW"); + metaApplyStatusList.add("REEXAMINATION_UNDER_REVIEW"); + po.setMetaApplyStatusList(metaApplyStatusList); + return driverArchivesManage.driverTrainingRegistrationUnDealList(po); + } + + @GetMapping("/abnormalBehavior") + @ApiOperation("首页工作台驾驶员异常行为数据及列表") + public HomepageDriverAbnormalBehaviorVo abnormalBehaviorList(@Valid @ModelAttribute HomepageAbnormalBehaviorPageParamDTO param) { + return homepageManage.abnormalBehaviorList(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageAbnormalBehaviorPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageAbnormalBehaviorPageParamDTO.java new file mode 100644 index 0000000..2a5185a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageAbnormalBehaviorPageParamDTO.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.homepage.entity.dto; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisPageParamDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author CMM + * @description + * @since 2022/11/11 11:48 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("首页驾驶员异常行为分页参数DTO") +public class HomepageAbnormalBehaviorPageParamDTO extends DriverAbnormalBehaviorAnalysisPageParamDTO implements Serializable { + + private static final long serialVersionUID = -7248039494876621922L; + @ApiModelProperty("区域ID") + private Long regionId; + private List regionIds; + + @ApiModelProperty("时间筛选条件") + private String timeFlag; + + @ApiModelProperty("筛选当前数据开始时间") + private LocalDateTime queryStartTime; + + @ApiModelProperty("筛选当前数据结束时间") + private LocalDateTime queryEndTime; + + private String dataScopeSql; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageVehicleAuditPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageVehicleAuditPageQuery.java new file mode 100644 index 0000000..e3ad892 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/dto/HomepageVehicleAuditPageQuery.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.homepage.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author CMM + * @description + * @since 2022/11/11 09:00 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("首页车辆审核") +public class HomepageVehicleAuditPageQuery extends PagePo implements Serializable { + private static final long serialVersionUID = 255142541885848486L; + + @ApiModelProperty(value = "车牌号") + private String carPlate; + + @ApiModelProperty(value = "所属企业名") + private String companyName; + + @ApiModelProperty(value = "所属区域id") + private Long regionId; + + @ApiModelProperty(value = "企业联系人") + private String driverName; + + @ApiModelProperty(value = "企业联系人电话") + private String mobileNum; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/MyCacheHashKey.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/MyCacheHashKey.java new file mode 100644 index 0000000..d26683b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/MyCacheHashKey.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.homepage.entity.model; + +import com.ningdatech.cache.model.cache.CacheHashKey; +import com.ningdatech.cache.model.cache.CacheKeyBuilder; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author CMM + * @since 2023/07/06 10:47 + */ +@Component +@Slf4j +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MyCacheHashKey implements CacheKeyBuilder { + + private String prefix; + + @Override + public String getPrefix() { + return this.prefix; + } + + @Override + public CacheHashKey hashKey(Object... suffix) { + return CacheKeyBuilder.super.hashKey(suffix); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/OnlineNumCnt.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/OnlineNumCnt.java new file mode 100644 index 0000000..48ddd1b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/model/OnlineNumCnt.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.homepage.entity.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author CMM + * @since 2023/07/06 15:42 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class OnlineNumCnt { + private Integer cnt; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/DriverAbnormalBehaviorNumPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/DriverAbnormalBehaviorNumPO.java new file mode 100644 index 0000000..8d63d9a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/DriverAbnormalBehaviorNumPO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.homepage.entity.po; + +import lombok.Data; + +/** + * @author CMM + * @description + * @since 2022/12/09 10:35 + */ +@Data +public class DriverAbnormalBehaviorNumPO { + /** + * 已督办总数 + */ + private Long overSeedCount; + + /** + * 已处理总数 + */ + private Long processedCount; + + /** + * 驾驶员异常行为总数 + */ + private Long total; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/VehicleNumPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/VehicleNumPO.java new file mode 100644 index 0000000..d283486 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/po/VehicleNumPO.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.homepage.entity.po; + +import lombok.Data; + +/** + * @author PoffyZhang + * @Classname VehicleNumPO + * @Description + * @Date 2022/12/6 9:10 + */ +@Data +public class VehicleNumPO { + + private Integer totalNum; + + private Integer totalOnlineNum; + + private Integer totalOfflineNum; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageDriverAbnormalBehaviorVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageDriverAbnormalBehaviorVo.java new file mode 100644 index 0000000..27b89e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageDriverAbnormalBehaviorVo.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.homepage.entity.vo; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.model.vo.BehaviourAnalysisVO; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author CMM + * @description + * @since 2022/11/11 14:48 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HomepageDriverAbnormalBehaviorVo { + + @ApiModelProperty("异常行为列表") + private PageVo of; + + @ApiModelProperty("异常行为总数") + private Long abnormalBehaviorTotalNum; + + @ApiModelProperty("已督办总数") + private Long overSeedTotalNum; + + @ApiModelProperty("已处理总数") + private Long processedTotalNum; + + @ApiModelProperty("同比增长率") + private String growthRate; + + @ApiModelProperty("督办率") + private String overSeedRate; + + @ApiModelProperty("处理率") + private String processedRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageVo.java new file mode 100644 index 0000000..6c693ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/entity/vo/HomepageVo.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.homepage.entity.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @description 首页在线车辆统计Vo + * @since 2022/11/10 15:40 + */ +@Data +public class HomepageVo { + @ApiModelProperty("车辆总数") + private Integer vehicleNum; + + @ApiModelProperty("车辆在线数") + private Integer onlineVehicleNum; + + @ApiModelProperty("车辆离线数") + private Integer offlineVehicleNum; + + @ApiModelProperty("今日累计在线数") + private Integer accumulativeOnlineNumber; + + @ApiModelProperty("车辆上线率") + private String vehicleOnlineRate; + + @ApiModelProperty("车辆离线率") + private String vehicleOfflineRate; + + @ApiModelProperty("车辆累积在线率") + private String accumulativeOnlineRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/manage/HomepageManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/manage/HomepageManage.java new file mode 100644 index 0000000..fec3cf5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/manage/HomepageManage.java @@ -0,0 +1,284 @@ +package com.ningdatech.carapi.homepage.manage; + +import java.text.NumberFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.TemporalAdjusters; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +import org.springframework.aop.framework.AopContext; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.DeletedEnum; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.BizUtils; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysis; +import com.ningdatech.carapi.driver.entity.DriverAbnormalBehaviorAnalysisPageParamDTO; +import com.ningdatech.carapi.driver.manage.BehaviourAnalysisManage; +import com.ningdatech.carapi.driver.model.vo.BehaviourAnalysisVO; +import com.ningdatech.carapi.homepage.constant.HomepageConstant; +import com.ningdatech.carapi.homepage.entity.dto.HomepageAbnormalBehaviorPageParamDTO; +import com.ningdatech.carapi.homepage.entity.model.OnlineNumCnt; +import com.ningdatech.carapi.homepage.entity.po.DriverAbnormalBehaviorNumPO; +import com.ningdatech.carapi.homepage.entity.po.VehicleNumPO; +import com.ningdatech.carapi.homepage.entity.vo.HomepageDriverAbnormalBehaviorVo; +import com.ningdatech.carapi.homepage.entity.vo.HomepageVo; +import com.ningdatech.carapi.homepage.service.IHomepageService; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.StopWatch; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description + * @since 2022/12/08 17:10 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class HomepageManage { + + private final BehaviourAnalysisManage behaviourAnalysisManage; + private final IHomepageService homepageService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final StringRedisTemplate stringRedisTemplate; + /** + * 驾驶员异常行为列表及数据统计 + * @param param + * @return + */ + public HomepageDriverAbnormalBehaviorVo abnormalBehaviorList(HomepageAbnormalBehaviorPageParamDTO param) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverAbnormalBehaviorAnalysis.class); + HomepageManage context = (HomepageManage) AopContext.currentProxy(); + + // 装配今年查询时间 + LocalDate year = LocalDate.now(); + HomepageAbnormalBehaviorPageParamDTO paramDTO = getAbnormalBehaviorQueryTimeParamDTO(year, param); + // 根据传入的筛选时间参数和当前时间,从告警表中查出今年的告警异常行为总数、已督办的总数、已处理的总数 + HomepageDriverAbnormalBehaviorVo currentYearResult = context.search(wrapper, paramDTO); + + // 装配去年查询时间 + LocalDate lastYear = LocalDate.now().minusYears(1); + HomepageAbnormalBehaviorPageParamDTO lastYearParamDTO = getAbnormalBehaviorQueryTimeParamDTO(lastYear, param); + // 根据传入的筛选时间参数和当前时间,从告警表中查出上一年同期的告警异常行为总数 + HomepageDriverAbnormalBehaviorVo lastYearResult = context.search(wrapper, lastYearParamDTO); + Long samePeriodTotalNum = lastYearResult.getAbnormalBehaviorTotalNum(); + + log.info("同期告警事件总数为:" + samePeriodTotalNum); + + Long total = currentYearResult.getAbnormalBehaviorTotalNum(); + Long overSeedCount = currentYearResult.getOverSeedTotalNum(); + Long processedCount = currentYearResult.getProcessedTotalNum(); + log.info("告警事件的总数为:" + total); + log.info("告警事件已督办的总数为:" + overSeedCount); + log.info("告警事件已处理的总数为:" + processedCount); + + // 计算督办率 + String overSeedRate = BizUtils.percent(overSeedCount, total); + log.info("督办率为:" + overSeedRate); + currentYearResult.setOverSeedRate(overSeedRate); + // 计算处理率 + String processedRate = BizUtils.percent(processedCount, total); + log.info("处理率为:" + processedRate); + currentYearResult.setProcessedRate(processedRate); + + // 计算同比增长率 + if (Objects.isNull(total)){ + total = 0L; + } + if (Objects.isNull(samePeriodTotalNum)){ + samePeriodTotalNum = 0L; + } + String growthRate = BizUtils.percent(total - samePeriodTotalNum, total); + log.info("同期增长率为:" + growthRate); + currentYearResult.setGrowthRate(growthRate); + + return currentYearResult; + } + + /** + * 获取去年同期查询时间 + * @param param + * @return + */ + private HomepageAbnormalBehaviorPageParamDTO getAbnormalBehaviorQueryTimeParamDTO(LocalDate year, HomepageAbnormalBehaviorPageParamDTO param) { + HomepageAbnormalBehaviorPageParamDTO paramDTO = new HomepageAbnormalBehaviorPageParamDTO(); + LocalDateTime queryStartTime = null; + LocalDateTime queryEndTime = null; + String time = param.getTimeFlag(); + + if (HomepageConstant.YEAR_FLAG.equals(time)) { + // 获取传入年份的第一天及最后一天 + queryStartTime = + LocalDateTime.of(LocalDate.from(year.with(TemporalAdjusters.firstDayOfYear())), LocalTime.MIN); + queryEndTime = + LocalDateTime.of(LocalDate.from(year.with(TemporalAdjusters.lastDayOfYear())), LocalTime.MAX); + } else if (HomepageConstant.MONTH_FLAG.equals(time)) { + // 获取传入年份当前月第一天及最后一天 + queryStartTime = + LocalDateTime.of(LocalDate.from(year.with(TemporalAdjusters.firstDayOfMonth())), LocalTime.MIN); + queryEndTime = + LocalDateTime.of(LocalDate.from(year.with(TemporalAdjusters.lastDayOfMonth())), LocalTime.MAX); + } else if (HomepageConstant.DAY_FLAG.equals(time)) { + // 获取传入年份当天的起始时间 + queryStartTime = LocalDateTime.of(year, LocalTime.MIN); + queryEndTime = LocalDateTime.of(year, LocalTime.MAX); + } + + paramDTO.setQueryStartTime(queryStartTime); + paramDTO.setQueryEndTime(queryEndTime); + paramDTO.setTimeFlag(param.getTimeFlag()); + return paramDTO; + } + + /** + * 驾驶员异常行为按时间标志查询 + * @param wrapper + * @param param + * @return + */ + @LambdaDataScope + public HomepageDriverAbnormalBehaviorVo search(LambdaQueryWrapper wrapper, HomepageAbnormalBehaviorPageParamDTO param) { + HomepageDriverAbnormalBehaviorVo resVo = new HomepageDriverAbnormalBehaviorVo(); + wrapper.orderByDesc(DriverAbnormalBehaviorAnalysis::getAlarmTime); + + // 获取异常行为列表请求实体 + DriverAbnormalBehaviorAnalysisPageParamDTO paramDTO = new DriverAbnormalBehaviorAnalysisPageParamDTO(); + //获取统计数据请求实体 + HomepageAbnormalBehaviorPageParamDTO po = new HomepageAbnormalBehaviorPageParamDTO(); + // 异常行为列表 + PageVo of = null; + + LocalDateTime queryStartTime = param.getQueryStartTime(); + LocalDateTime queryEndTime = param.getQueryEndTime(); + po.setQueryStartTime(queryStartTime); + po.setQueryEndTime(queryEndTime); + if (Objects.nonNull(param.getTimeFlag())) { + paramDTO.setStartTime(queryStartTime); + paramDTO.setEndTime(queryEndTime); + paramDTO.setRegionId(param.getRegionId()); + } + of = behaviourAnalysisManage.behaviorAnalysisList(paramDTO); + + resVo.setOf(of); + // 根据传入的时间标志查询出告警事件的总数以及已督办、已处理事件的总数. + DriverAbnormalBehaviorNumPO driverAbnormalBehaviorNum = homepageService.driverAbnormalBehaviorNum(po); + if (Objects.nonNull(driverAbnormalBehaviorNum)) { + resVo.setAbnormalBehaviorTotalNum(Objects.isNull(driverAbnormalBehaviorNum.getTotal()) ? 0L : driverAbnormalBehaviorNum.getTotal()); + resVo.setOverSeedTotalNum(Objects.isNull(driverAbnormalBehaviorNum.getOverSeedCount()) ? 0L : driverAbnormalBehaviorNum.getOverSeedCount()); + resVo.setProcessedTotalNum(Objects.isNull(driverAbnormalBehaviorNum.getProcessedCount()) ? 0L : driverAbnormalBehaviorNum.getProcessedCount()); + } + return resVo; + } + + /** + * 根据传入的区域id查询车辆状态信息 + * + * @param param + * @return + */ + public HomepageVo queryVehicleStatistics(DataScreenParam param) { + HomepageVo result = new HomepageVo(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + param.setOperatorId(operatorId); + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + HomepageManage context = (HomepageManage) AopContext.currentProxy(); + context.buildSearchQuery(wrapper, param); + List vehicleBaseInfos = vehicleBaseInfoService.list(wrapper); + + VehicleNumPO vehicleNumPo = homepageService.vehicleNum(param); + Integer vehicleNum = vehicleNumPo.getTotalNum(); + Integer onlineVehicleNum = vehicleNumPo.getTotalOnlineNum(); + Integer offlineVehicleNum = vehicleNumPo.getTotalOfflineNum(); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + AtomicInteger cnt = new AtomicInteger(0); + if (CollUtil.isNotEmpty(vehicleBaseInfos)) { + List cntList = homepageService.getOnlineNumCnt(vehicleBaseInfos); + for (OnlineNumCnt onlineNumCnt : cntList) { + Integer onlineNum = onlineNumCnt.getCnt(); + cnt.addAndGet(onlineNum); + } + } + stopWatch.stop(); + log.info("共耗时 {}s", stopWatch.getTotalTimeSeconds()); + log.info("缓存中车辆在线数为:" + cnt); + onlineVehicleNum = cnt.get(); + offlineVehicleNum = vehicleNum - cnt.get(); + Integer accumulativeOnlineNumber = homepageService.searchAccumulativeOnlineNum(param); + log.info("车辆总数为:" + vehicleNum); + log.info("车辆在线数为:" + onlineVehicleNum); + log.info("车辆离线数为:" + offlineVehicleNum); + log.info("车辆累积在线数为:" + accumulativeOnlineNumber); + + result.setVehicleNum(vehicleNum); + + result.setOnlineVehicleNum(onlineVehicleNum); + result.setOfflineVehicleNum(offlineVehicleNum); + result.setAccumulativeOnlineNumber(accumulativeOnlineNumber); + try { + NumberFormat numberFormat = NumberFormat.getInstance(); + numberFormat.setMaximumFractionDigits(2); + String vehicleOnlineRate = vehicleNum.equals(0) ? "0%" + : numberFormat.format((float)onlineVehicleNum / (float)vehicleNum * 100) + "%"; + log.info("车辆上线率为:" + vehicleOnlineRate); + result.setVehicleOnlineRate(vehicleOnlineRate); + + String vehicleOfflineRate = vehicleNum.equals(0) ? "0%" + : numberFormat.format((float)offlineVehicleNum / (float)vehicleNum * 100) + "%"; + log.info("车辆离线率为:" + vehicleOfflineRate); + result.setVehicleOfflineRate(vehicleOfflineRate); + + String accumulativeOnlineRate = vehicleNum.equals(0) ? "0%" + : numberFormat.format((float)accumulativeOnlineNumber / (float)vehicleNum * 100) + "%"; + log.info("车辆累积在线率为:" + accumulativeOnlineRate); + result.setAccumulativeOnlineRate(accumulativeOnlineRate); + } catch (Exception e) { + log.error("AI工作台异常{}", e.getMessage()); + } + return result; + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildSearchQuery(LambdaQueryWrapper wrapper, DataScreenParam param) { + wrapper.eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .eq(Objects.nonNull(param.getOperatorId()),NdVehicleBaseInfo::getOperatorId,param.getOperatorId()) + .in(Objects.nonNull(param.getCompanyIds()),NdVehicleBaseInfo::getCompanyId,param.getCompanyIds()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.java new file mode 100644 index 0000000..4ae36b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.homepage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.homepage.entity.dto.HomepageAbnormalBehaviorPageParamDTO; +import com.ningdatech.carapi.homepage.entity.po.DriverAbnormalBehaviorNumPO; +import org.apache.ibatis.annotations.Param; + +public interface HomepageMapper extends BaseMapper { + + Integer searchAccumulativeOnlineNumByTable(@Param("tableName") String tableName, @Param("param") DataScreenParam param); + + Integer searchAccumulativeOnlineNum(@Param("param") DataScreenParam param); + DriverAbnormalBehaviorNumPO selectDriverAbnormalBehaviorNum(@Param("param") HomepageAbnormalBehaviorPageParamDTO param); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.xml new file mode 100644 index 0000000..80b17f2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/mapper/HomepageMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/IHomepageService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/IHomepageService.java new file mode 100644 index 0000000..47e31df --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/IHomepageService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.homepage.service; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.homepage.entity.dto.HomepageAbnormalBehaviorPageParamDTO; +import com.ningdatech.carapi.homepage.entity.model.OnlineNumCnt; +import com.ningdatech.carapi.homepage.entity.po.DriverAbnormalBehaviorNumPO; +import com.ningdatech.carapi.homepage.entity.po.VehicleNumPO; + +import java.util.List; + +/** + * @author CMM + * @since 2022/12/08 15:55 + */ +public interface IHomepageService { + + VehicleNumPO vehicleNum(DataScreenParam param); + + Integer searchAccumulativeOnlineNum(DataScreenParam param) ; + + DriverAbnormalBehaviorNumPO driverAbnormalBehaviorNum(HomepageAbnormalBehaviorPageParamDTO param); + + List getOnlineNumCnt(List vehicleBaseInfos); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/impl/HomepageServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/impl/HomepageServiceImpl.java new file mode 100644 index 0000000..5244cfe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/homepage/service/impl/HomepageServiceImpl.java @@ -0,0 +1,146 @@ +package com.ningdatech.carapi.homepage.service.impl; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.homepage.constant.HomepageConstant; +import com.ningdatech.carapi.homepage.entity.dto.HomepageAbnormalBehaviorPageParamDTO; +import com.ningdatech.carapi.homepage.entity.model.OnlineNumCnt; +import com.ningdatech.carapi.homepage.entity.po.DriverAbnormalBehaviorNumPO; +import com.ningdatech.carapi.homepage.entity.po.VehicleNumPO; +import com.ningdatech.carapi.homepage.mapper.HomepageMapper; +import com.ningdatech.carapi.homepage.service.IHomepageService; +import com.ningdatech.carapi.scheduler.mapper.VehicleOnlineStatusDayMapper; + +import cn.hutool.core.collection.ListUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description 首页查询车辆信息 + * @since 2022/11/10 17:10 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class HomepageServiceImpl implements IHomepageService { + private final HomepageMapper homepageMapper; + private final VehicleBaseInfoMapper vehicleBaseInfoMapper; + private final VehicleOnlineStatusDayMapper statusDayMapper; + private final StringRedisTemplate stringRedisTemplate; + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public VehicleNumPO vehicleNum(DataScreenParam param) { + return vehicleBaseInfoMapper.searchVehicleNum(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public Integer searchAccumulativeOnlineNum(DataScreenParam param) { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(statusDayMapper.countTable(tableName) == 0){ + return homepageMapper.searchAccumulativeOnlineNum(param); + } + return homepageMapper.searchAccumulativeOnlineNumByTable(tableName,param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public DriverAbnormalBehaviorNumPO driverAbnormalBehaviorNum(HomepageAbnormalBehaviorPageParamDTO param) { + return homepageMapper.selectDriverAbnormalBehaviorNum(param); + } + + @Override + public List getOnlineNumCnt(List vehicleBaseInfos) { + Map onlineMap = stringRedisTemplate.opsForHash().entries("online_index"); + + // 分批 + List> batchList = new ArrayList<>(ListUtil.partition(new ArrayList<>(vehicleBaseInfos), 5000)); + // 创建线程池 线程数是 分批的数量 + ExecutorService executorService = Executors.newFixedThreadPool(batchList.size()); + // 线程计数器,就是 分批的数 + CountDownLatch countDownLatch = new CountDownLatch(batchList.size()); + List cntList = Lists.newArrayList(); + batchList.forEach(e -> { + // 创建一个变量 + AtomicInteger value = new AtomicInteger(); + //每个分批用一个线程执行 + executorService.execute(()->{ + List resultList = e.stream().filter(v -> { + // 取到每个数据进行业务执行 + String carPlate = v.getCarPlate(); + LocalDateTime startTime = LocalDateTime.now(); + String timeStamp = (String) onlineMap.get(carPlate); + if (Objects.nonNull(timeStamp)) { + // 将时间戳转换为Instant对象 + Instant instant = Instant.ofEpochSecond(Long.parseLong(timeStamp)); + // 将Instant对象转换为LocalDateTime对象 + LocalDateTime endTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + Duration minuteDuration = Duration.between(endTime,startTime); + long minute = minuteDuration.toMinutes(); + // 判断最后一次上传时间距离当前时间是否大于5分钟 + if (minute <= HomepageConstant.TIME_INTERVAL) { + return true; + } + } + return false; + }).collect(Collectors.toList()); + log.info("当前线程单组在线数为{}",resultList.size()); + // 创建一个 Lambda 表达式,使用闭包给变量赋值 + Consumer consumer = (newValue) -> { + value.set(newValue); + log.info("Value updated to " + value); + }; + consumer.accept(resultList.size()); + OnlineNumCnt onlineNumCnt = new OnlineNumCnt(); + onlineNumCnt.setCnt(value.get()); + cntList.add(onlineNumCnt); + }); + countDownLatch.countDown(); + }); + try { + // 等待所有线程执行完成 + countDownLatch.await(); + } catch (InterruptedException e) { + throw new BizException(e.getMessage()); + } + executorService.shutdown(); + try { + executorService.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + throw new BizException(e.getMessage()); + } + if (executorService.isTerminated()) { + log.info("子线程执行完毕"); + log.info("主线程开始"); + } + return cntList; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/contants/CertificateContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/contants/CertificateContant.java new file mode 100644 index 0000000..7bc5c2e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/contants/CertificateContant.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.industry.contants; + +public interface CertificateContant { + + public final static Integer OPERATION_TYPE_APPCATION = 1; + + public final static String OPERATION_TYPE_APPCATION_NAME = "申请"; + + public final static Integer OPERATION_TYPE_REISSUE = 2; + + public final static String OPERATION_TYPE_REISSUE_NAME = "补换"; + + public final static Integer AUDIT_FLAG = 0; + public final static Integer AUDIT_PASS_FLAG = 1; + + + + class ScoringRubric{ + /** + * 上传资质评分细则 + */ + public final static String UPLOAD_QUALIFICATION_SCORING_RUBRIC = "服务商只能上传散装水泥专用车辆,且授权服务的车辆的卫星定位数据,不得违规上传。判定标准: 不满足要求的上传数据为不合格数据"; + /** + * 上传频率数量评分细则 + */ + public final static String UPLOAD_FREQUENCY_QUANTITY_SCORING_RUBRIC = "卫星定位数据上传间隔: 在点火状态下,车辆上传间隔为每15~20秒1条;在熄火状态下,车辆上传间隔为每14~16分钟1条。车辆熄火后终端至少需要传输2小时熄火定位数据。判定标准: 计算不满足要求的程度,超过一定程度,则认为当天数据不合格。若当天上传数据总量少于60条或大于10000条,也认为当天数据不合格。〔缺失的定义: 点火状态下30秒以上未上传,熄火状态下16分钟以上未上传. 冗余的定义: 点火状态下15秒以内上传,熄火状态下14分钟以内上传〕"; + /** + * 字段完整性评分细则 + */ + public final static String FIELD_INTEGRITY_SCORING_RUBRIC = "上传的卫星定位数据中速度、经度、纬度、高度、方向、时间,仪表盘速度、里程计读数,状态码、警报码、营运商编号字段不能为空。判定标准: 存在以上重要字段缺失,则认为该数据不合格"; + /** + * 时效性评分细则 + */ + public final static String TIME_SENSITIVE_SCORING_RUBRIC = "上传的卫星定位数据的观测时间不得晚于监管平台服务端的接收时间,监管平台服务端数据接收时间不能延迟1分钟以上。判定标准: 不满足以上任一要求,则认为该数据不合格"; + /** + * 位置及方向的正确性、一致性评分细则 + */ + public final static String POSITION_DIRECTION_CORRECTNESS_CONSISTENCY_SCORING_RUBRIC = "上传的卫星定位数据的经纬度在中国范围内;位置必须真实有效;不能遗漏必要数据;熄火状态或定位速度为0时,前后距离变化在5公里内;海拔要求在-200米至6000米; 方向要求0度至359度且数值取整。判定标准:不满足以上任一要求,则认为该数据不合格"; + /** + * 速度的正确性、一致性评分细则 + */ + public final static String SPEED_CORRECTNESS_CONSISTENCY_SCORING_RUBRIC = "上传的卫星定位数据的速度、仪表盘速度要求符合0千米/小时至160千米/小时,必须上传真实有效的仪表盘速度。判定标准: 不满足以上任一要求,则认为该数据不合格"; + /** + * 时间一致性评分细则 + */ + public final static String TIME_CONSISTENCY_SCORING_RUBRIC = "定位数据上传时间小于保存时间。判定标准:不满足以上任一要求,将认为该数据不合格。上传的卫星定位数据的观测时间晚于监管平台服务端的接收时间的记录超过5条,则判定车辆当日不合格"; + /** + * 位置一致性评分细则 + */ + public final static String POSITION_CONSISTENCY_SCORING_RUBRIC = "相邻“两点定位”直线距离不能超过25km。判定标准:不满足以上任一要求,将认为该数据不合格。如果两条相邻记录的距离超过25km则判定车辆当日不合格"; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataQualityMonitorController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataQualityMonitorController.java new file mode 100644 index 0000000..c2621e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataQualityMonitorController.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.trips.model.dto.VehicleTripsParamDTO; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.DataQualityMonitorManage; +import com.ningdatech.carapi.industry.model.dto.DataQualityMonitorDynamicsPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.DataQualityMonitorGpsPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.DataQualityMonitorStaticPageParamDTO; +import com.ningdatech.carapi.industry.model.vo.DataQualityMonitorDynamicsVO; +import com.ningdatech.carapi.industry.model.vo.DataQualityMonitorGpsVO; +import com.ningdatech.carapi.industry.model.vo.DataQualityMonitorStaticVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 数据质量监控 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@RequestMapping("/api/industry/data-quality-monitor") +@Slf4j +@Validated +@RestController +@Api(value = "DataQualityMonitor", tags = "行业服务-数据质量监控") +@RequiredArgsConstructor +public class DataQualityMonitorController { + + private final DataQualityMonitorManage dataQualityMonitorManage; + + @ApiOperation(value = "静态数据采集监控", notes = "静态数据采集监控") + @GetMapping("/list-static") + public PageVo staticList(@Valid @ModelAttribute DataQualityMonitorStaticPageParamDTO param) { + return dataQualityMonitorManage.staticList(param); + } + + @ApiOperation(value = "静态数据采集监控详情", notes = "静态数据采集监控详情") + @GetMapping("/details-static/{id}") + public DataQualityMonitorStaticVO staticDeatils(@Valid @PathVariable Long id) { + return dataQualityMonitorManage.staticDetails(id); + } + + @ApiOperation(value = "静态数据采集监控导出", notes = "静态数据采集监控导出") + @GetMapping("/export-static") + public void exportStatic(DataQualityMonitorStaticPageParamDTO param, HttpServletResponse response) { + ExcelDownUtil.downXls(response, param, dataQualityMonitorManage::exportStatic); + } + + @ApiOperation(value = "动态数据采集监控", notes = "动态数据采集监控") + @GetMapping("/list-dynamics") + public PageVo dynamicsList(@Valid @ModelAttribute DataQualityMonitorDynamicsPageParamDTO param) { + return dataQualityMonitorManage.dynamicsList(param); + } + + @ApiOperation(value = "动态数据采集监控详情", notes = "动态数据采集监控详情") + @GetMapping("/details-dynamics/{id}") + public DataQualityMonitorDynamicsVO dynamicsDetails(@Valid @PathVariable Long id) { + return dataQualityMonitorManage.dynamicsDetails(id); + } + + @ApiOperation(value = "动态数据采集监控导出", notes = "动态数据采集监控导出") + @GetMapping("/export-dynamics") + public void exportDynamics(DataQualityMonitorDynamicsPageParamDTO param, HttpServletResponse response) { + ExcelDownUtil.downXls(response, param, dataQualityMonitorManage::exportDynamics); + } + + @ApiOperation(value = "异常GPS数据查询报警", notes = "异常GPS数据查询报警") + @GetMapping("/list-gps") + public PageVo gpsList(@Valid @ModelAttribute DataQualityMonitorGpsPageParamDTO param) { + return dataQualityMonitorManage.gpsList(param); + } + + @ApiOperation(value = "异常GPS数据查询报警详情", notes = "异常GPS数据查询报警详情") + @GetMapping("/details-gps/{id}") + public DataQualityMonitorGpsVO gpsDetails(@Valid @PathVariable Long id) { + return dataQualityMonitorManage.gpsDetails(id); + } + + @ApiOperation(value = "异常GPS数据查询报警导出", notes = "异常GPS数据查询报警导出") + @GetMapping("/export-gps") + public void exportGps(DataQualityMonitorGpsPageParamDTO param, HttpServletResponse response) { + ExcelDownUtil.downXls(response, param, dataQualityMonitorManage::exportGps); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataScreenController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataScreenController.java new file mode 100644 index 0000000..3ae33c6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DataScreenController.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.industry.controller; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.vo.*; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.industry.manage.DataScreenManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.*; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-22 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/industry/data-screen") +@Api(value = "industry", tags = "行业服务-大屏") +@RequiredArgsConstructor +public class DataScreenController { + + private final DataScreenManage dataScreenManage; + + + @ApiOperation(value = "各区域车辆分布", notes = "各区域车辆分布") + @GetMapping("/region") + public List regionDistribution(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return dataScreenManage.regionDistribution(param); + } + + @ApiOperation(value = "全省当前驾驶员合格证数", notes = "全省当前驾驶员合格证数") + @GetMapping("/tain-certificate") + public Map tainCertificate(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return dataScreenManage.tainCertificate(param); + } + + @ApiOperation(value = "实验室从业资格证", notes = "实验室从业资格证") + @GetMapping("/laboratory-qualification-certificate") + public JSONObject laboratoryQualificationCertificate(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return dataScreenManage.laboratoryQualificationCertificate(param); + } + + @ApiOperation(value = "实验室验收合格证", notes = "实验室验收合格证") + @GetMapping("/laboratory-acceptance-certificate") + public JSONObject laboratoryAcceptanceCertificate(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return dataScreenManage.laboratoryAcceptanceCertificate(param); + } + + @ApiOperation(value = "砂浆企业备案证", notes = "砂浆企业备案证") + @GetMapping("/record-certificate-mortar-enterprise") + public JSONObject recordCertificateMortarEnterprise(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return dataScreenManage.recordCertificateMortarEnterprise(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DriverTrainingCertificateController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DriverTrainingCertificateController.java new file mode 100644 index 0000000..29a14c0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/DriverTrainingCertificateController.java @@ -0,0 +1,96 @@ +package com.ningdatech.carapi.industry.controller; + + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.contants.CertificateContant; +import com.ningdatech.carapi.industry.manage.DriverTrainingCertificateManage; +import com.ningdatech.carapi.industry.model.dto.DriverTrainingCertificatePageParamDTO; +import com.ningdatech.carapi.industry.model.dto.DriverTrainingCertificateUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.DriverTrainingCertificateOperVO; +import com.ningdatech.carapi.industry.model.vo.DriverTrainingCertificateVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 驾驶员合格证 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/industry/driver-training-certificate") +@Api(value = "DriverTrainingCertificate", tags = "行业服务-驾驶员培训合格证") +@RequiredArgsConstructor +public class DriverTrainingCertificateController { + + private final DriverTrainingCertificateManage driverTrainingCertificateManage; + + @ApiOperation(value = "合格证信息列表", notes = "合格证信息列表") + @GetMapping("/info-list") + public PageVo infoList(@Valid @ModelAttribute DriverTrainingCertificatePageParamDTO param) { + return driverTrainingCertificateManage.infoList(param); + } + + @ApiOperation(value = "合格证信息详情", notes = "合格证信息详情") + @GetMapping("/info-details/{id}") + public DriverTrainingCertificateVO infoDetails(@Valid @PathVariable Long id) { + return driverTrainingCertificateManage.infoDetails(id); + } + + @ApiOperation(value = "新增", notes = "新增") + @PostMapping("/save") + public Long save(@Valid @RequestBody DriverTrainingCertificateUpdateDTO data) { + return driverTrainingCertificateManage.save(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public DriverTrainingCertificateVO modify(@Valid @RequestBody DriverTrainingCertificateUpdateDTO data) { + return driverTrainingCertificateManage.modify(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "合格证申请列表", notes = "合格证申请列表") + @GetMapping("/application-list") + public PageVo applicationList(@Valid @ModelAttribute DriverTrainingCertificatePageParamDTO param) { + return driverTrainingCertificateManage.operationList(param, CertificateContant.OPERATION_TYPE_APPCATION); + } + + @ApiOperation(value = "合格证补发列表", notes = "合格证补发列表") + @GetMapping("/reissue-list") + public PageVo reissueList(@Valid @ModelAttribute DriverTrainingCertificatePageParamDTO param) { + return driverTrainingCertificateManage.operationList(param, CertificateContant.OPERATION_TYPE_REISSUE); + } + + @ApiOperation(value = "审核", notes = "审核") + @RequestMapping("/approve/{id}") + public DriverTrainingCertificateOperVO approve(@Valid @PathVariable Long id) { + return driverTrainingCertificateManage.approve(id, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "取消审核", notes = "取消审核") + @RequestMapping("/unapprove/{id}") + public DriverTrainingCertificateOperVO unapprove(@Valid @PathVariable Long id) { + return driverTrainingCertificateManage.unapprove(id, LoginUserUtil.getUserId()); + } + + @ApiOperation("驾驶员培训合格证书信息列表导出") + @GetMapping("/infoListExport") + public void infoListExport(DriverTrainingCertificatePageParamDTO param,HttpServletResponse response){ + ExcelDownUtil.downXls(response, param, driverTrainingCertificateManage::infoListExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabAcceptanceCertificateController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabAcceptanceCertificateController.java new file mode 100644 index 0000000..394a036 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabAcceptanceCertificateController.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.LabAcceptanceCertificateManage; +import com.ningdatech.carapi.industry.model.req.LabAcceptanceCertificateListReq; +import com.ningdatech.carapi.industry.model.req.LabAcceptanceCertificateReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.model.vo.LabAcceptanceCertificateChangeListVo; +import com.ningdatech.carapi.industry.model.vo.LabAcceptanceCertificateListVo; +import com.ningdatech.carapi.industry.service.ILabAcceptanceCertificateService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 实验室验收合格证 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +@RestController +@Api(tags = "行业服务-实验室验收合格证") +@AllArgsConstructor +@RequestMapping("/api/v1/industry/lab-acceptance-certificate") +public class LabAcceptanceCertificateController { + + private final LabAcceptanceCertificateManage labAcceptanceCertificateManage; + private final ILabAcceptanceCertificateService labAcceptanceCertificateService; + + @GetMapping("/list") + @ApiOperation("列表查询") + public PageVo list(LabAcceptanceCertificateListReq req) { + return labAcceptanceCertificateManage.labAcceptanceCertificateList(req); + } + + @GetMapping("/changeList") + @ApiOperation("变更列表查询") + public PageVo changeList(LabAcceptanceCertificateListReq req) { + return labAcceptanceCertificateManage.changeList(req); + } + + @GetMapping("/export") + @ApiOperation("导出") + public void export(LabAcceptanceCertificateListReq req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, labAcceptanceCertificateManage::exportLabAcceptanceCertificate); + } + + @DeleteMapping("/del/{id}") + @ApiOperation("删除") + @WebLog(value = "删除") + public void delete(@PathVariable Long id) { + labAcceptanceCertificateManage.delete(id); + } + + @PostMapping("/saveOrUpdate") + @ApiOperation("新增/修改") + @WebLog(value = "新增/修改") + public void saveOrUpdate(@Valid @RequestBody LabAcceptanceCertificateReq req) { + labAcceptanceCertificateManage.saveOrUpdate(req); + } + + @ApiOperation("审核验收合格证换证申请]") + @PostMapping("/audit") + public Boolean audit(@Valid @RequestBody LabWorkerCertificateAuditReq req){ + return labAcceptanceCertificateManage.audit(req, LoginUserUtil.getUserId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabWorkerCertificateController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabWorkerCertificateController.java new file mode 100644 index 0000000..2281fff --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/LabWorkerCertificateController.java @@ -0,0 +1,86 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.enums.LabWorkerCertificateTypeEnum; +import com.ningdatech.carapi.industry.manage.LabWorkerCertificateManage; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateListReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateReq; +import com.ningdatech.carapi.industry.model.vo.LabWorkerCertificateChangeListVo; +import com.ningdatech.carapi.industry.model.vo.LabWorkerCertificateListVo; +import com.ningdatech.carapi.industry.service.ILabWorkerCertificateService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 实验室人员从业资格证 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-04 + */ +@Api(tags = "行业服务-实验室人员从业资格证") +@RestController +@AllArgsConstructor +@RequestMapping("/api/v1/industry/lab-worker-certificate") +public class LabWorkerCertificateController { + + private final LabWorkerCertificateManage labWorkerCertificateManage; + private final ILabWorkerCertificateService labWorkerCertificateService; + + @GetMapping("/list") + @ApiOperation("实验室人员[从业资格证|继续教育合格证]列表") + public PageVo labWorkerCertificateList(@Valid LabWorkerCertificateListReq req) { + return labWorkerCertificateManage.labWorkerCertificateList(req); + } + + @DeleteMapping("/del/{id}/{type}") + @ApiOperation("删除[从业资格证|继续教育合格证]") + @WebLog(value = "删除[从业资格证|继续教育合格证]", modular = "行业服务") + public void delLabWorkerCertificate(@PathVariable Long id, @PathVariable Integer type) { + // 验证类型合法性 + LabWorkerCertificateTypeEnum.getByCode(type); + labWorkerCertificateManage.delete(id); + } + + @GetMapping("/export") + @ApiOperation("导出实验室人员[从业资格证|继续教育合格证]") + public void exportLabWorkerCertificate(@Valid LabWorkerCertificateListReq req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, labWorkerCertificateManage::labWorkerCertificateExport); + } + + @PostMapping("/saveOrUpdate") + @ApiOperation("保存/修改[从业资格证|继续教育合格证]") + @WebLog(value = "保存/修改[从业资格证|继续教育合格证]", modular = "行业服务") + public void saveLabWorkerCertificate(@Valid @RequestBody LabWorkerCertificateReq req) { + labWorkerCertificateManage.saveOrUpdate(req); + } + + @ApiOperation("实验室人员[从业资格证|继续教育合格证]换证列表") + @GetMapping("/changeList") + public PageVo changeList(@Valid LabWorkerCertificateListReq req) { + return labWorkerCertificateManage.changeCertificate(req); + } + + @ApiOperation("审核[从业资格证|继续教育合格证换证申请]") + @PostMapping("/audit") + public Boolean audit(@Valid @RequestBody LabWorkerCertificateAuditReq req){ + return labWorkerCertificateManage.audit(req, LoginUserUtil.getUserId()); + } + + @ApiOperation("从业资格证取消审核") + @PostMapping("/cancelAudit") + public Boolean cancelAudit(@Valid @RequestBody LabWorkerCertificateAuditReq req){ + return labWorkerCertificateManage.cancelAudit(req, LoginUserUtil.getUserId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/MortarEnterpriseFilingCertificateController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/MortarEnterpriseFilingCertificateController.java new file mode 100644 index 0000000..2e8bab0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/MortarEnterpriseFilingCertificateController.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.industry.controller; + + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.MortarEnterpriseFilingCertificateManage; +import com.ningdatech.carapi.industry.model.dto.MortarEnterpriseFilingCertificateDTO; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateListReq; +import com.ningdatech.carapi.industry.model.vo.MortarEnterpriseFilingCertificateChangeVO; +import com.ningdatech.carapi.industry.model.vo.MortarEnterpriseFilingCertificateVO; +import com.ningdatech.carapi.industry.service.IMortarEnterpriseFilingCertificateService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; + +/** + *

+ * 砂浆企业备案证 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +@Api(tags = "行业服务-砂浆企业备案证") +@RestController +@AllArgsConstructor +@RequestMapping("/api/v1/industry/mortar-enterprise-filing-certificate") +public class MortarEnterpriseFilingCertificateController { + + private final MortarEnterpriseFilingCertificateManage mortarEnterpriseFilingCertificateManage; + private final IMortarEnterpriseFilingCertificateService mortarEnterpriseFilingCertificateService; + + @GetMapping("/list") + @ApiOperation("列表") + public PageVo list(LabWorkerCertificateListReq req) { + return mortarEnterpriseFilingCertificateManage.mortarEnterpriseFilingCertificateList(req); + } + + @GetMapping("/export") + @ApiOperation("导出") + public void export(LabWorkerCertificateListReq req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, mortarEnterpriseFilingCertificateManage::mortarEnterpriseFilingCertificateExport); + } + + @GetMapping("/changeList") + @ApiOperation("换证列表") + public PageVo changeList(LabWorkerCertificateListReq req) { + return mortarEnterpriseFilingCertificateManage.changeList(req); + } + + @DeleteMapping("/del/{id}") + @ApiOperation("删除") + @WebLog(value = "删除") + public void delete(@PathVariable Long id) { + mortarEnterpriseFilingCertificateManage.delete(id); + } + + @PostMapping("/saveOrUpdate") + @ApiOperation("保存/修改") + @WebLog(value = "保存/修改") + public void saveOrUpdate(@Valid @RequestBody MortarEnterpriseFilingCertificateDTO mortarEnterprise) { + mortarEnterpriseFilingCertificateManage.saveOrUpdate(mortarEnterprise); + } + + @ApiOperation("审核砂浆企业备案证换证申请]") + @PostMapping("/audit") + public Boolean audit(@Valid @RequestBody LabWorkerCertificateAuditReq req){ + return mortarEnterpriseFilingCertificateManage.audit(req, LoginUserUtil.getUserId()); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/OperatorAssessmentSystemController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/OperatorAssessmentSystemController.java new file mode 100644 index 0000000..64c3463 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/OperatorAssessmentSystemController.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.industry.controller; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.carapi.industry.manage.OperatorAssessmentManage; +import com.ningdatech.carapi.industry.model.dto.OperatorAssessmentDTO; +import com.ningdatech.carapi.industry.model.vo.OperatorScoreDetailVO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 运营商考核系统前端控制器 + * + * @author CMM + * @since 2023/01/05 09:13 + */ +@RequestMapping("/api/industry/operator-assessment-system") +@Slf4j +@Validated +@RestController +@Api(value = "OperatorAssessmentSystem", tags = "行业管理-运营商考核系统") +@RequiredArgsConstructor +public class OperatorAssessmentSystemController { + + private final OperatorAssessmentManage operatorAssessmentManage; + + @ApiOperation(value = "运营商考核详情",notes = "运营商考核详情") + @PostMapping("/detail") + public OperatorScoreDetailVO getOperatorScore(@RequestBody @Valid OperatorAssessmentDTO data){ + return operatorAssessmentManage.getOperatorScore(data); + } + + @GetMapping("/download") + @ApiOperation("下载表格") + public void export(OperatorAssessmentDTO data, HttpServletResponse response) { + operatorAssessmentManage.exportDocx(response,data); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PassportManageController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PassportManageController.java new file mode 100644 index 0000000..bd0f3dc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PassportManageController.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.PassportManage; +import com.ningdatech.carapi.industry.model.dto.PassportPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.PassportSaveDTO; +import com.ningdatech.carapi.industry.model.dto.PassportUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.PassportVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 通行证管理 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/industry/passport") +@Api(value = "PassportManage", tags = "行业服务-通行证管理") +@RequiredArgsConstructor +public class PassportManageController { + + private final PassportManage passportManage; + + @ApiOperation(value = "通行证证书信息", notes = "通行证证书信息") + @GetMapping("/info-list") + public PageVo infoList(@Valid @ModelAttribute PassportPageParamDTO param) { + return passportManage.infoList(param); + } + + @ApiOperation(value = "通行证证书详情", notes = "通行证证书详情") + @GetMapping("/details/{id}") + public PassportVO details(@Valid @PathVariable Long id) { + return passportManage.details(id); + } + + @ApiOperation(value = "通行证申请列表", notes = "通行证申请列表") + @GetMapping("/application-list") + public PageVo applicationList(@Valid @ModelAttribute PassportPageParamDTO param) { + return passportManage.infoList(param); + } + + @ApiOperation(value = "通行证审核列表", notes = "通行证审核列表") + @GetMapping("/approve-list") + public PageVo approveList(@Valid @ModelAttribute PassportPageParamDTO param) { + return passportManage.infoList(param); + } + + @ApiOperation(value = "通行证补发列表", notes = "通行证补发列表") + @GetMapping("/reissue-list") + public PageVo reissueList(@Valid @ModelAttribute PassportPageParamDTO param) { + return passportManage.infoList(param); + } + + @ApiOperation(value = "新增", notes = "新增") + @PostMapping("/save") + public PassportVO save(@Valid @RequestBody PassportSaveDTO passportSave) { + return passportManage.save(passportSave, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public PassportVO modify(@Valid @RequestBody PassportUpdateDTO passportUpdate) { + return passportManage.modify(passportUpdate, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "删除", notes = "删除") + @DeleteMapping("/remove/{id}") + public Boolean remove(@Valid @PathVariable Long id) { + return passportManage.remove(id, LoginUserUtil.getUserId()); + } + + @ApiOperation("通行证证书信息列表导出") + @GetMapping("/infoListExport") + public void infoListExport(PassportPageParamDTO param, HttpServletResponse response){ + ExcelDownUtil.downXls(response, param, passportManage::infoListExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseOilController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseOilController.java new file mode 100644 index 0000000..7716d03 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseOilController.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.industry.manage.PurchaseOilManage; +import com.ningdatech.carapi.industry.model.req.PurchaseOilListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseOilListVo; +import com.ningdatech.carapi.industry.service.IPurchaseOilService; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 油品采购信息表 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Api(tags = "行业服务-采购信息-油品采购信息") +@RestController +@AllArgsConstructor +@RequestMapping("/api/v1/industry/purchase-oil") +public class PurchaseOilController { + + private final IPurchaseOilService purchaseOilService; + private final PurchaseOilManage purchaseOilManage; + + + @GetMapping("/list") + @ApiOperation("列表") + public PageVo list(PurchaseOilListReq req) { + return purchaseOilManage.purchaseOilList(req); + } + + @DeleteMapping("/del/{id}") + @ApiOperation("删除") + @WebLog(value = "删除") + public void delete(@PathVariable Long id) { + purchaseOilService.removeById(id); + } + + @PostMapping("/saveOrUpdate") + @ApiOperation("保存/修改") + @WebLog(value = "保存/修改") + public void saveOrUpdate(@Valid @RequestBody PurchaseOilListVo req) { + purchaseOilManage.saveOrUpdate(req); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseRawMaterialController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseRawMaterialController.java new file mode 100644 index 0000000..daea66e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseRawMaterialController.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.industry.manage.PurchaseRawMaterialManage; +import com.ningdatech.carapi.industry.model.req.PurchaseRawMaterialListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseRawMaterialListVo; +import com.ningdatech.carapi.industry.service.IPurchaseRawMaterialService; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 原材料采购信息表 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Validated +@Api(tags = "行业服务-采购服务-原材料信息") +@RestController +@AllArgsConstructor +@RequestMapping("/api/v1/industry/purchase-raw-material") +public class PurchaseRawMaterialController { + + private final PurchaseRawMaterialManage purchaseRawMaterialManage; + private final IPurchaseRawMaterialService purchaseRawMaterialService; + + @ApiOperation("列表查询") + @GetMapping("/list") + public PageVo list(PurchaseRawMaterialListReq req) { + return purchaseRawMaterialManage.list(req); + } + + @ApiOperation("保存/修改") + @PostMapping("/saveOrUpdate") + @WebLog(value = "保存/修改") + public void saveOrUpdate(@Valid @RequestBody PurchaseRawMaterialListVo req) { + purchaseRawMaterialManage.saveOrUpdate(req); + } + + @ApiOperation("删除") + @DeleteMapping("/del/{id}") + @WebLog(value = "删除") + public void delete(@PathVariable Long id) { + purchaseRawMaterialService.removeById(id); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseVehicleController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseVehicleController.java new file mode 100644 index 0000000..5391c71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseVehicleController.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.industry.manage.PurchaseVehicleManage; +import com.ningdatech.carapi.industry.model.req.PurchaseVehicleListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseVehicleListVo; +import com.ningdatech.carapi.industry.service.IPurchaseVehicleService; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 车辆采购信息表 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@RestController +@Api(tags = "行业服务-采购服务-车辆采购信息") +@AllArgsConstructor +@RequestMapping("/api/v1/industry/purchase-vehicle") +public class PurchaseVehicleController { + + private final IPurchaseVehicleService purchaseVehicleService; + private final PurchaseVehicleManage purchaseVehicleManage; + + @DeleteMapping("/del/{id}") + @ApiOperation("删除") + @WebLog(value = "删除") + public void delete(@PathVariable Long id) { + purchaseVehicleService.removeById(id); + } + + @GetMapping("/list") + @ApiOperation("列表") + public PageVo list(PurchaseVehicleListReq req) { + return purchaseVehicleManage.purchaseWheelList(req); + } + + @PostMapping("/saveOrUpdate") + @ApiOperation("保存/修改") + @WebLog(value = "保存/修改") + public void saveOrUpdate(@Valid @RequestBody PurchaseVehicleListVo req) { + purchaseVehicleManage.saveOrUpdate(req); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseWheelController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseWheelController.java new file mode 100644 index 0000000..ef3cafd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/PurchaseWheelController.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.industry.manage.PurchaseWheelManage; +import com.ningdatech.carapi.industry.model.req.PurchaseOilListReq; +import com.ningdatech.carapi.industry.model.req.PurchaseWheelListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseOilListVo; +import com.ningdatech.carapi.industry.model.vo.PurchaseWheelListVo; +import com.ningdatech.carapi.industry.service.IPurchaseWheelService; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.validation.Valid; + +/** + *

+ * 轮胎采购信息表 前端控制器 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@RestController +@Api(tags = "行业服务-采购服务-轮胎采购信息") +@AllArgsConstructor +@RequestMapping("/api/v1/industry/purchase-wheel") +public class PurchaseWheelController { + + private final IPurchaseWheelService purchaseWheelService; + private final PurchaseWheelManage purchaseWheelManage; + + @DeleteMapping("/del/{id}") + @ApiOperation("删除") + @WebLog(value = "删除") + public void delete(@PathVariable Long id) { + purchaseWheelService.removeById(id); + } + + @GetMapping("/list") + @ApiOperation("列表") + public PageVo list(PurchaseWheelListReq req) { + return purchaseWheelManage.purchaseWheelList(req); + } + + @PostMapping("/saveOrUpdate") + @ApiOperation("保存/修改") + @WebLog(value = "保存/修改") + public void saveOrUpdate(@Valid @RequestBody PurchaseWheelListVo req) { + purchaseWheelManage.saveOrUpdate(req); + } + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/ReadyMixedMortarIndustryManageController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/ReadyMixedMortarIndustryManageController.java new file mode 100644 index 0000000..1e73832 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/ReadyMixedMortarIndustryManageController.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.ReadyMixedMortarManage; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedMortarIndustryManageSaveDTO; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedMortarIndustryManageUpdateDTO; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedPageParamDTO; +import com.ningdatech.carapi.industry.model.vo.ReadyMixedMortarIndustryManageVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 预拌砂浆行业管理 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/industry/ready-mixed-mortar") +@Api(value = "PassportManage", tags = "行业服务-通行证管理") +@RequiredArgsConstructor +public class ReadyMixedMortarIndustryManageController { + + private final ReadyMixedMortarManage readyMixedMortarManage; + + @ApiOperation(value = "列表查询", notes = "列表查询") + @GetMapping("/list") + public PageVo list(@Valid @ModelAttribute ReadyMixedPageParamDTO param) { + return readyMixedMortarManage.list(param); + } + + @ApiOperation(value = "通行证证书详情", notes = "通行证证书详情") + @GetMapping("/details/{id}") + public ReadyMixedMortarIndustryManageVO details(@Valid @PathVariable Long id) { + return readyMixedMortarManage.details(id); + } + + @ApiOperation(value = "新增", notes = "新增") + @PostMapping("/save") + public ReadyMixedMortarIndustryManageVO save(@Valid @RequestBody ReadyMixedMortarIndustryManageSaveDTO data) { + return readyMixedMortarManage.save(data, LoginUserUtil.loginUserDetail()); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public ReadyMixedMortarIndustryManageVO modify(@Valid @RequestBody ReadyMixedMortarIndustryManageUpdateDTO data) { + return readyMixedMortarManage.modify(data, LoginUserUtil.loginUserDetail()); + } + + @ApiOperation(value = "删除", notes = "删除") + @DeleteMapping("/remove/{id}") + public Boolean remove(@Valid @PathVariable Long id) { + return readyMixedMortarManage.remove(id, LoginUserUtil.loginUserDetail()); + } + + @ApiOperation("导出") + @GetMapping("/export") + public void export(ReadyMixedPageParamDTO param, HttpServletResponse response) { + ExcelDownUtil.downXls(response, param, readyMixedMortarManage::export); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/RegistrationRecordController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/RegistrationRecordController.java new file mode 100644 index 0000000..bcd69fd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/RegistrationRecordController.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.industry.manage.RegistrationRecordManage; +import com.ningdatech.carapi.industry.model.dto.*; +import com.ningdatech.carapi.industry.model.vo.RegistrationRecordVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.validation.Valid; + +/** + *

+ * 新车上牌记录 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +@Controller +@RequestMapping("/api/industry/registration-record") +@Slf4j +@Validated +@RestController +@Api(value = "RegistrationRecord", tags = "行业服务-新车上牌记录") +@RequiredArgsConstructor +public class RegistrationRecordController { + private final RegistrationRecordManage registrationRecordManage; + + @ApiOperation(value = "上牌信息列表", notes = "上牌信息列表") + @GetMapping("/info-list") + public PageVo infoList(@Valid @ModelAttribute RegistrationRecordPageParamDTO param) { + return registrationRecordManage.infoList(param); + } + + @ApiOperation(value = "上牌信息详情", notes = "上牌信息详情") + @GetMapping("/details/{id}") + public RegistrationRecordVO details(@Valid @PathVariable Long id) { + return registrationRecordManage.details(id); + } + + @ApiOperation(value = "上牌信息申请列表", notes = "上牌信息申请列表") + @GetMapping("/application-list") + public PageVo applicationList(@Valid @ModelAttribute RegistrationRecordPageParamDTO param) { + return registrationRecordManage.infoList(param); + } + + @ApiOperation(value = "新增", notes = "新增") + @PostMapping("/save") + public RegistrationRecordVO save(@Valid @RequestBody RegistrationRecordSaveDTO data) { + return registrationRecordManage.save(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public RegistrationRecordVO modify(@Valid @RequestBody RegistrationRecordUpdateDTO data) { + return registrationRecordManage.modify(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "删除", notes = "删除") + @DeleteMapping("/remove/{id}") + public Boolean remove(@Valid @PathVariable Long id) { + return registrationRecordManage.remove(id, LoginUserUtil.getUserId()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateController.java new file mode 100644 index 0000000..8f3c951 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateController.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.SafetyEquipmentIntallUserCertificateManage; +import com.ningdatech.carapi.industry.model.dto.UseCertPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertSaveDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.SafetyEquipmentInstallUseCertificateVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 安全设备安装使用证书信息 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Controller +@RequestMapping("/api/industry/safety-equipment-install-use-certificate") +@Slf4j +@Validated +@RestController +@Api(value = "SafetyEquipmentInstallUseCertificate", tags = "行业服务-安全设备安装使用证书") +@RequiredArgsConstructor +public class SafetyEquipmentInstallUseCertificateController { + + private final SafetyEquipmentIntallUserCertificateManage safetyEquipmentIntallUserCertificateManage; + + @ApiOperation(value = "证书信息列表", notes = "证书信息列表") + @GetMapping("/list") + public PageVo list(@Valid @ModelAttribute UseCertPageParamDTO param) { + return safetyEquipmentIntallUserCertificateManage.list(param); + } + + @ApiOperation(value = "证书信息详情", notes = "证书信息详情") + @GetMapping("/details/{id}") + public SafetyEquipmentInstallUseCertificateVO details(@Valid @PathVariable Long id) { + return safetyEquipmentIntallUserCertificateManage.details(id); + } + + @ApiOperation(value = "新增", notes = "新增") + @PostMapping("/save") + public SafetyEquipmentInstallUseCertificateVO save(@Valid @RequestBody UseCertSaveDTO data) { + return safetyEquipmentIntallUserCertificateManage.save(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public SafetyEquipmentInstallUseCertificateVO modify(@Valid @RequestBody UseCertUpdateDTO data) { + return safetyEquipmentIntallUserCertificateManage.modify(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "删除", notes = "删除") + @DeleteMapping("/remove/{id}") + public Boolean remove(@Valid @PathVariable Long id) { + return safetyEquipmentIntallUserCertificateManage.remove(id, LoginUserUtil.getUserId()); + } + + @ApiOperation("信息列表导出") + @GetMapping("/infoListExport") + public void infoListExport(UseCertPageParamDTO param, HttpServletResponse response){ + ExcelDownUtil.downXls(response, param, safetyEquipmentIntallUserCertificateManage::infoListExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateOperationController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateOperationController.java new file mode 100644 index 0000000..23685fb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/SafetyEquipmentInstallUseCertificateOperationController.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.SafetyEquipmentInstallUseCertificateOperationManage; +import com.ningdatech.carapi.industry.model.dto.UseCertOperatePageParamDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertOperateUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.SafetyEquipmentInstallUseCertificateOperationVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 安全设备安装使用证书操作信息 前端控制器 + *

+ * + * @author CMM + * @since 2022-11-26 + */ +@RestController +@RequestMapping("/api/industry/safety-equipment-install-use-certificate-operation") +@Slf4j +@Validated +@Api(value = "SafetyEquipmentInstallUseCertificateOperation",tags = "行业服务-安全设备安装使用证书") +@RequiredArgsConstructor +public class SafetyEquipmentInstallUseCertificateOperationController { + private final SafetyEquipmentInstallUseCertificateOperationManage safetyEquipmentInstallUseCertificateOperationManage; + + @ApiOperation(value = "证书操作信息列表", notes = "证书操作信息列表") + @GetMapping("/list") + public PageVo list(@Valid @ModelAttribute UseCertOperatePageParamDTO param){ + return safetyEquipmentInstallUseCertificateOperationManage.list(param); + } + + @ApiModelProperty("证书操作信息详情") + @GetMapping("/detail/{id}") + public SafetyEquipmentInstallUseCertificateOperationVO details(@Valid @PathVariable Long id){ + return safetyEquipmentInstallUseCertificateOperationManage.details(id); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public SafetyEquipmentInstallUseCertificateOperationVO modify(@Valid @RequestBody UseCertOperateUpdateDTO data) { + return safetyEquipmentInstallUseCertificateOperationManage.modify(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "删除", notes = "删除") + @DeleteMapping("/remove/{id}") + public Boolean remove(@Valid @PathVariable Long id) { + return safetyEquipmentInstallUseCertificateOperationManage.remove(id, LoginUserUtil.getUserId()); + } + + @ApiOperation("安全设备安装使用证书信息列表导出") + @GetMapping("/infoListExport") + public void infoListExport(UseCertOperatePageParamDTO param, HttpServletResponse response){ + ExcelDownUtil.downXls(response, param, safetyEquipmentInstallUseCertificateOperationManage::infoListExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/VehicleAnnualInspectionReviewController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/VehicleAnnualInspectionReviewController.java new file mode 100644 index 0000000..e99109a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/controller/VehicleAnnualInspectionReviewController.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.industry.controller; + + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.industry.manage.AnnualInspectionReviewManage; +import com.ningdatech.carapi.industry.model.dto.InspectionReviewSaveDTO; +import com.ningdatech.carapi.industry.model.dto.InspectionReviewUpdateDTO; +import com.ningdatech.carapi.industry.model.dto.ReviewPageParamDTO; +import com.ningdatech.carapi.industry.model.vo.VehicleAnnualInspectionReviewApplicationVO; +import com.ningdatech.carapi.industry.model.vo.VehicleAnnualInspectionReviewVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

+ * 车辆年检年审 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Controller +@RequestMapping("/api/industry/vehicle-annual-inspection-review") +@Slf4j +@Validated +@RestController +@Api(value = "VehicleAnnualInspectionReview", tags = "行业服务-车辆年检年审") +@RequiredArgsConstructor +public class VehicleAnnualInspectionReviewController { + + private final AnnualInspectionReviewManage annualInspectionReviewManage; + + @ApiOperation(value = "年检年审记录", notes = "年检年审记录") + @GetMapping("/info-list") + public PageVo infoList(@Valid @ModelAttribute ReviewPageParamDTO param) { + return annualInspectionReviewManage.infoList(param); + } + + @ApiOperation(value = "年检年审记录详情", notes = "年检年审记录详情") + @GetMapping("/details/{id}") + public VehicleAnnualInspectionReviewVO details(@Valid @PathVariable Long id) { + return annualInspectionReviewManage.details(id); + } + + @ApiOperation(value = "年检年审记录申请", notes = "年检年审记录申请") + @GetMapping("/application-list") + public PageVo applicationList(@Valid @ModelAttribute ReviewPageParamDTO param) { + return annualInspectionReviewManage.applicationList(param); + } + + @ApiOperation(value = "新增", notes = "新增") + @PostMapping("/save") + public VehicleAnnualInspectionReviewVO save(@Valid @RequestBody InspectionReviewSaveDTO data) { + return annualInspectionReviewManage.save(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "编辑", notes = "编辑") + @PostMapping("/modify") + public VehicleAnnualInspectionReviewVO modify(@Valid @RequestBody InspectionReviewUpdateDTO data) { + return annualInspectionReviewManage.modify(data, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "删除", notes = "删除") + @DeleteMapping("/remove/{id}") + public Boolean remove(@Valid @PathVariable Long id) { + return annualInspectionReviewManage.remove(id, LoginUserUtil.getUserId()); + } + + @ApiOperation("车辆年检年审记录列表导出") + @GetMapping("/infoListExport") + public void infoListExport(ReviewPageParamDTO param, HttpServletResponse response){ + ExcelDownUtil.downXls(response, param, annualInspectionReviewManage::infoListExport); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorDynamics.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorDynamics.java new file mode 100644 index 0000000..51267c9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorDynamics.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 异常GPS数据监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@TableName("nd_data_quality_monitor_dynamics") +@Data +@ApiModel(value = "DataQualityMonitorDynamics对象", description = "动态数据监控") +public class DataQualityMonitorDynamics extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("0正常 1异常") + private Integer state; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("驾驶员名字") + private String driverName; + + @ApiModelProperty("数据时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorGps.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorGps.java new file mode 100644 index 0000000..9f028e7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorGps.java @@ -0,0 +1,106 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * GPS数据质量监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@TableName("nd_data_quality_monitor_gps") +@Data +@ApiModel(value = "DataQualityMonitorGps对象", description = "GPS数据质量监控") +public class DataQualityMonitorGps extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("经度") + private BigDecimal longitude; + + @ApiModelProperty("纬度") + private BigDecimal latitude; + + @ApiModelProperty("速度") + private BigDecimal velocity; + + @ApiModelProperty("方向") + private BigDecimal direction; + + @ApiModelProperty("0离线 1在线") + private Integer state; + + @ApiModelProperty("告警级别") + private Integer alarm; + + @ApiModelProperty("告警级别名称") + private String alarmName; + + @ApiModelProperty("异常原因") + private Integer abnormalCauses; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("数据采集时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorStatic.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorStatic.java new file mode 100644 index 0000000..f20612a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DataQualityMonitorStatic.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 静态数据质量监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@TableName("nd_data_quality_monitor_static") +@Data +@ApiModel(value = "DataQualityMonitorStatic对象", description = "静态数据质量监控") +public class DataQualityMonitorStatic extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("数据类型") + private Integer dataType; + + @ApiModelProperty("数据类型名") + private String dataTypeName; + + @ApiModelProperty("数据异常状态 0正常 1不正常") + private Integer state; + + @ApiModelProperty("批次号") + private String batchNo; + + @ApiModelProperty("数据采集时间") + private LocalDateTime dataTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateJoin.java new file mode 100644 index 0000000..e9646ec --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateJoin.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 驾驶员合格证 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@TableName("nd_certificate") +@Data +@ApiModel(value = "DriverTrainingCertificate Join对象", description = "驾驶员合格证") +public class DriverTrainingCertificateJoin extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("驾驶员名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("培训时间") + private LocalDateTime trainingTime; + + @ApiModelProperty("培训结果 合格") + private String trainingResult; + + @ApiModelProperty("有效时间") + private LocalDateTime effectiveTime; + + @ApiModelProperty("培训项目") + private String trainingProgram; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOper.java new file mode 100644 index 0000000..7076915 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOper.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 驾驶员合格证操作 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +@TableName("nd_driver_training_certificate_oper") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DriverTrainingCertificateOper", description = "驾驶员合格证操作") +public class DriverTrainingCertificateOper extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证单位") + private String issuedBy; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("有效期至") + private LocalDateTime expiryDate; + + @ApiModelProperty("操作类型 1.申请 2.补发") + private Integer operationTypeId; + + @ApiModelProperty("操作类型") + private String operationTypeName; + + @ApiModelProperty("审核状态 0待审核 1已审核") + private Integer auditState; + + @ApiModelProperty("已通过") + private String auditStateName; + + @ApiModelProperty("申请时间") + private LocalDateTime operationTime; + + @ApiModelProperty("申请事项") + private String application; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("证书ID") + private Long certificateId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("公司ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOperJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOperJoin.java new file mode 100644 index 0000000..2fc3ab5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/DriverTrainingCertificateOperJoin.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 驾驶员合格证操作 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +@TableName("nd_driver_training_certificate_oper") +@Data +@ApiModel(value = "DriverTrainingCertificateOperJoin", description = "驾驶员合格证操作") +public class DriverTrainingCertificateOperJoin extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("驾驶员名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("培训时间") + private LocalDateTime trainingTime; + + @ApiModelProperty("培训结果 合格") + private String trainingResult; + + @ApiModelProperty("有效时间") + private LocalDateTime effectiveTime; + + @ApiModelProperty("培训项目") + private String trainingProgram; + + @ApiModelProperty("合格证id") + private Long certificateId; + + @ApiModelProperty("操作类型 1.申请 2.补发") + private Integer operationTypeId; + + @ApiModelProperty("操作类型") + private String operationTypeName; + + @ApiModelProperty("审核状态 0待审核 1已审核") + private Integer auditState; + + @ApiModelProperty("已通过") + private String auditStateName; + + @ApiModelProperty("申请时间") + private LocalDateTime operationTime; + + @ApiModelProperty("申请事项") + private String application; + + @ApiModelProperty("申请原因") + private String applicationReason; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificate.java new file mode 100644 index 0000000..19fc4f1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificate.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 实验室验收合格证 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +@Data +@TableName("nd_lab_acceptance_certificate") +@ApiModel(value = "LabAcceptanceCertificate对象", description = "实验室验收合格证") +public class LabAcceptanceCertificate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("有效时间") + private LocalDate validDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("执行标准") + private String standard; + + @ApiModelProperty("检测项目") + private String testItem; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificateChange.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificateChange.java new file mode 100644 index 0000000..1fd7fbb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabAcceptanceCertificateChange.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 实验室验收合格证换证 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +@TableName("nd_lab_acceptance_certificate_change") +@Data +@ApiModel(value = "LabAcceptanceCertificateChange对象", description = "实验室验收合格证换证") +public class LabAcceptanceCertificateChange implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("有效时间") + private LocalDate validDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("检测项目") + private String testItem; + + @ApiModelProperty("执行标准") + private String standard; + + @ApiModelProperty("换证时间(审核通过)") + private LocalDate replacementTime; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("申请原因") + private String applicationReason; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificate.java new file mode 100644 index 0000000..01b6de7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificate.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.industry.enums.LabWorkerCertificateTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 实验室人员证书 + *

+ * + * @author WendyYang + * @since 2022-11-04 + */ +@Data +@TableName("nd_lab_worker_certificate") +@ApiModel(value = "LabWorkerCertificate对象", description = "实验室人员证书") +public class LabWorkerCertificate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("姓名") + private String userName; + + @ApiModelProperty("性别:1 男、2 女") + private Integer gender; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("有效时间/更换时间") + private LocalDate validDate; + + @ApiModelProperty("备注") + private String remark; + + /** + * @see LabWorkerCertificateTypeEnum + */ + @ApiModelProperty("证书类型") + private Integer certificateType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificateChange.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificateChange.java new file mode 100644 index 0000000..cc67342 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/LabWorkerCertificateChange.java @@ -0,0 +1,90 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 实验室人员从业资格证更换 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +@TableName("nd_lab_worker_certificate_change") +@Data +@ApiModel(value = "LabWorkerCertificateChange对象", description = "实验室人员从业资格证更换") +public class LabWorkerCertificateChange implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("姓名") + private String userName; + + @ApiModelProperty("性别:1 男、2 女") + private Integer gender; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("有效时间") + private LocalDate validDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("证书类型:1 从业资格证、2 继续教育合格证") + private Integer certificateType; + + @ApiModelProperty("换证申请事项") + private String applicationItem; + + @ApiModelProperty("换证申请原因") + private String applicationReason; + + @ApiModelProperty("换证时间(审核通过)") + private LocalDate replacementTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificate.java new file mode 100644 index 0000000..357979f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificate.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 砂浆企业备案证 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +@TableName("nd_mortar_enterprise_filing_certificate") +@ApiModel(value = "MortarEnterpriseFilingCertificate对象", description = "砂浆企业备案证") +@Data +public class MortarEnterpriseFilingCertificate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("生产能力") + private String throughput; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("有效时间") + private LocalDate validDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("执行标准") + private String standards; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificateChange.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificateChange.java new file mode 100644 index 0000000..01c9011 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/MortarEnterpriseFilingCertificateChange.java @@ -0,0 +1,88 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 砂浆企业备案证换证 + *

+ * + * @author CMM + * @since 2022-12-15 + */ +@TableName("nd_mortar_enterprise_filing_certificate_change") +@Data +@ApiModel(value = "MortarEnterpriseFilingCertificateChange对象", description = "砂浆企业备案证换证") +public class MortarEnterpriseFilingCertificateChange implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("企业编码") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("创建人ID") + private Long createBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("修改人ID") + private Long updateBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("生产能力") + private String throughput; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("有效时间") + private LocalDate validDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("执行标准") + private String standards; + + @ApiModelProperty("换证时间") + private LocalDate replacementTime; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("申请原因") + private String applicationReason; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorIndexScoreInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorIndexScoreInfo.java new file mode 100644 index 0000000..b08d0ad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorIndexScoreInfo.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2023-01-04 + */ +@TableName("nd_operator_index_score_info") +@Data +@ApiModel(value = "OperatorIndexScoreInfo对象", description = "") +public class OperatorIndexScoreInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("运营商考核指标") + private Integer operatorScoreIndex; + + @ApiModelProperty("运营商考核指标名称") + private String operatorScoreIndexName; + + @ApiModelProperty("运营商考核指标分数") + private Integer operatorScoreIndexScore; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorScoreInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorScoreInfo.java new file mode 100644 index 0000000..351db6b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/OperatorScoreInfo.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.industry.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2023-01-04 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("nd_operator_score_info") +@ApiModel(value = "运营商考核分数对象", description = "") +public class OperatorScoreInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("运营商id") + private Long operatorId; + + @ApiModelProperty("运营商名称") + private String operatorName; + + @ApiModelProperty("上传资质分数") + private Integer uploadQualification; + + @ApiModelProperty("上传频率、数量分数") + private Integer uploadFrequencyQuantity; + + @ApiModelProperty("字段完整性分数") + private Integer fieldIntegrity; + + @ApiModelProperty("时效性分数") + private Integer timeSensitive; + + @ApiModelProperty("位置及方向的正确性、一致性分数") + private Integer positionDirectionCorrectnessConsistency; + + @ApiModelProperty("速度的正确性、一致性分数") + private Integer speedCorrectnessConsistency; + + @ApiModelProperty("时间一致性分数") + private Integer timeConsistency; + + @ApiModelProperty("位置一致性分数") + private Integer positionConsistency; + + @ApiModelProperty("所属季度") + private Integer quarter; + + @ApiModelProperty("所属年份") + private String year; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PassportInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PassportInfo.java new file mode 100644 index 0000000..976c92e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PassportInfo.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 通行证信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@TableName("nd_passport_info") +@Data +@ApiModel(value = "PassportInfo对象", description = "通行证信息") +public class PassportInfo extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆所有人") + private String vehicleOwner; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("可通行区域") + private String accessibleArea; + + @ApiModelProperty("有效期") + private LocalDateTime expirationDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseOil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseOil.java new file mode 100644 index 0000000..c561faa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseOil.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 油品采购信息表 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@TableName("nd_purchase_oil") +@ApiModel(value = "PurchaseOil对象", description = "油品采购信息表") +public class PurchaseOil implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("油品名称") + private String oilName; + + @ApiModelProperty("质量等级") + private String qualityLevel; + + @ApiModelProperty("数量") + private Integer number; + + @ApiModelProperty("单价") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + private String purchaseOrg; + + @ApiModelProperty("采购企业ID") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + private String approvalDept; + + private Long createBy; + + private LocalDateTime createOn; + + private Long updateBy; + + private LocalDateTime updateOn; + + @ApiModelProperty("公司ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseRawMaterial.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseRawMaterial.java new file mode 100644 index 0000000..7c5d8e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseRawMaterial.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 原材料采购信息表 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@TableName("nd_purchase_raw_material") +@ApiModel(value = "PurchaseRawMaterial对象", description = "原材料采购信息表") +public class PurchaseRawMaterial implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("原材料名称") + private String rawMaterialName; + + @ApiModelProperty("规格型号") + private String model; + + @ApiModelProperty("数量") + private Integer number; + + @ApiModelProperty("计量单位") + private String unit; + + @ApiModelProperty("单价") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + private String purchaseOrg; + + @ApiModelProperty("采购单位ID") + private Long purchaseOrgId; + + private Long createBy; + + private LocalDateTime createOn; + + private Long updateBy; + + private LocalDateTime updateOn; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("批准部门") + private String approvalDept; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseVehicle.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseVehicle.java new file mode 100644 index 0000000..f89f998 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseVehicle.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆采购信息表 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@TableName("nd_purchase_vehicle") +@ApiModel(value = "PurchaseVehicle对象", description = "车辆采购信息表") +public class PurchaseVehicle implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车辆品牌") + private String vehicleBrand; + + @ApiModelProperty("车辆类型") + private String vehicleType; + + @ApiModelProperty("数量") + private Integer number; + + @ApiModelProperty("单价") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + private String purchaseOrg; + + @ApiModelProperty("采购企业ID") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + private String approvalDept; + + private Long createBy; + + private LocalDateTime createOn; + + private Long updateBy; + + private LocalDateTime updateOn; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseWheel.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseWheel.java new file mode 100644 index 0000000..9b9eb6c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/PurchaseWheel.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 轮胎采购信息表 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@TableName("nd_purchase_wheel") +@ApiModel(value = "PurchaseWheel对象", description = "轮胎采购信息表") +public class PurchaseWheel implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("轮胎品牌") + private String wheelBrand; + + @ApiModelProperty("轮胎类型") + private String wheelType; + + @ApiModelProperty("数量") + private Integer number; + + @ApiModelProperty("单价") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + private String purchaseOrg; + + @ApiModelProperty("采购企业ID") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + private String approvalDept; + + private Long createBy; + + private LocalDateTime createOn; + + private Long updateBy; + + private LocalDateTime updateOn; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/ReadyMixedMortarIndustryManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/ReadyMixedMortarIndustryManage.java new file mode 100644 index 0000000..c25c44f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/ReadyMixedMortarIndustryManage.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 预拌砂浆行业管理 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +@TableName("nd_ready_mixed_mortar_industry_manage") +@Data +@ApiModel(value = "ReadyMixedMortarIndustryManage对象", description = "预拌砂浆行业管理") +public class ReadyMixedMortarIndustryManage implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("0启用 1禁用") + private Integer state; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("file id") + private Long fileId; + + @ApiModelProperty("文件名") + private String fileName; + + @ApiModelProperty("下载次数") + private Integer downTimes; + + @ApiModelProperty("内容") + private String content; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/RegistrationRecord.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/RegistrationRecord.java new file mode 100644 index 0000000..fac863c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/RegistrationRecord.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 新车上牌记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +@TableName("nd_registration_record") +@Data +@ApiModel(value = "RegistrationRecord对象", description = "新车上牌记录") +public class RegistrationRecord extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车架号") + private String vin; + + @ApiModelProperty("引擎号") + private String engineNo; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("已上牌 未上牌") + private String registrationRecord; + + @ApiModelProperty("车辆品牌") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + private String vehicleModels; + + @ApiModelProperty("购买价格") + private BigDecimal purchasePrice; + + @ApiModelProperty("购买日期") + private LocalDateTime purchaseDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificate.java new file mode 100644 index 0000000..d4ea838 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificate.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 安全设备安装使用证书信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@TableName("nd_safety_equipment_install_use_certificate") +@Data +@ApiModel(value = "SafetyEquipmentInstallUseCertificate对象", description = "安全设备安装使用证书信息") +public class SafetyEquipmentInstallUseCertificate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificateOperation.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificateOperation.java new file mode 100644 index 0000000..aabd5b4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/SafetyEquipmentInstallUseCertificateOperation.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全设备安装使用证书操作信息 + *

+ * + * @author CMM + * @since 2022-11-26 + */ +@Data +@TableName("nd_safety_equipment_install_use_certificate_operation") +@ApiModel(value = "SafetyEquipmentInstallUseCertificateOperation对象", description = "安全设备安装使用证书操作信息") +public class SafetyEquipmentInstallUseCertificateOperation implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("申请状态") + private String applicationStatus; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("年检状态") + private String yearCheckStatus; + + @ApiModelProperty("补换状态") + private String replacementStatus; + + @ApiModelProperty("视频运营商") + private String videoOperator; + + @ApiModelProperty("证书编号") + private Long certificateNumber; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/VehicleAnnualInspectionReview.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/VehicleAnnualInspectionReview.java new file mode 100644 index 0000000..758145a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/entity/VehicleAnnualInspectionReview.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.industry.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆年检年审 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@TableName("nd_vehicle_annual_inspection_review") +@Data +@ApiModel(value = "VehicleAnnualInspectionReview对象", description = "车辆年检年审") +public class VehicleAnnualInspectionReview extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年检记录") + private String inspectionRecords; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型") + private String vehicleTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AbnormalDataTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AbnormalDataTypeEnum.java new file mode 100644 index 0000000..19200c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AbnormalDataTypeEnum.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.industry.enums; + +import com.ningdatech.carapi.common.constant.GenderEnum; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 异常数据类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AbnormalDataTypeEnum", description = "异常数据类型-枚举") +public enum AbnormalDataTypeEnum { + /** + * 运政 + */ + TRANSPORT_ADMINISTRATION(1, "运政"), + + /** + *运营商 + */ + OPERATOR(2, "运营商"), + + /** + * 电子路单 + */ + ELECTRONIC_WAYBILL(3, "电子路单"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (AbnormalDataTypeEnum t : AbnormalDataTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AddTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AddTypeEnum.java new file mode 100644 index 0000000..7f69209 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/AddTypeEnum.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.industry.enums; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * @return + * @author CMM + * @since 2023/01/04 11:03 + */ + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AddTypeEnum", description = "证书添加类型-枚举") +public enum AddTypeEnum { + /** + * 证书新增类型 + */ + NEW(1,"新增"), + REPLACE(2,"换证"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (AddTypeEnum t : AddTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/DataQualityMonitorGpsEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/DataQualityMonitorGpsEnum.java new file mode 100644 index 0000000..3381d2b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/DataQualityMonitorGpsEnum.java @@ -0,0 +1,107 @@ +package com.ningdatech.carapi.industry.enums; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * @return + * @author CMM + * @since 2023/01/04 14:18 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DataQualityMonitorGpsEnum", description = "数据质量监控Gps异常原因-枚举") +public enum DataQualityMonitorGpsEnum { + /** + * 上传资质异常 + */ + UPLOAD_QUALIFICATION_ANOMALY(1,"上传资质异常"), + + /** + *上传频率异常 + */ + UPLOAD_FREQUENCY_ANOMALY(2,"上传频率异常"), + + /** + *上传数量异常 + */ + UPLOAD_QUANTITY_ANOMALY(4,"上传数量异常"), + + /** + * 字段完整性异常 + */ + FIELD_INTEGRITY_ANOMALY(8,"字段完整性异常"), + + /** + * 时效性异常 + */ + TIME_SENSITIVE_ANOMALY(16,"时效性异常"), + + /** + * 位置及方向的正确性、一致性异常 + */ + POSITION_DIRECTION_CORRECTNESS_CONSISTENCY_ANOMALY(32,"位置及方向的正确性、一致性异常"), + + /** + * 速度的正确性、一致性异常 + */ + SPEED_CORRECTNESS_CONSISTENCY_ANOMALY(64,"速度的正确性、一致性异常"), + + /** + * 时间一致性异常 + */ + TIME_CONSISTENCY_ANOMALY(128,"时间一致性异常"), + + /** + * 位置一致性异常 + */ + POSITION_CONSISTENCY_ANOMALY(256,"位置一致性异常"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public Integer getCode() { + return code; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (DataQualityMonitorGpsEnum t : DataQualityMonitorGpsEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static DataQualityMonitorGpsEnum getEnumByValue(Integer code) { + if(Objects.isNull(code)){ + return null; + } + for (DataQualityMonitorGpsEnum t : DataQualityMonitorGpsEnum.values()) { + if (code.equals(t.getCode())) { + return t; + } + } + return null; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/LabWorkerCertificateTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/LabWorkerCertificateTypeEnum.java new file mode 100644 index 0000000..01ff0ce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/LabWorkerCertificateTypeEnum.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.industry.enums; + +import lombok.Getter; + +import java.util.Arrays; + +/** + *

+ * LabWorkerCertificateTypeEnum + *

+ * + * @author WendyYang + * @since 11:26 2022/11/8 + */ +@Getter +public enum LabWorkerCertificateTypeEnum { + + /** + * 实验室人员从业资格证 + */ + QUALIFICATION(1, "实验室人员从业资格证"), + EDUCATION(2, "实验室从业人员继续教育合格证"); + + private final int code; + + private final String value; + + LabWorkerCertificateTypeEnum(int code, String value) { + this.code = code; + this.value = value; + } + + public static LabWorkerCertificateTypeEnum getByCode(int code) { + return Arrays.stream(values()) + .filter(w -> w.getCode() == code) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("无效的证书类型编码")); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/OperatorAssessmentIndexEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/OperatorAssessmentIndexEnum.java new file mode 100644 index 0000000..aca8c58 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/OperatorAssessmentIndexEnum.java @@ -0,0 +1,100 @@ +package com.ningdatech.carapi.industry.enums; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * 运营商考核指标枚举 + * + * @author CMM + * @since 2023/01/05 09:37 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "OperatorAssessmentIndexEnum", description = "运营商考核指标-枚举") +public enum OperatorAssessmentIndexEnum { + /** + * 上传资质 + */ + UPLOAD_QUALIFICATION(1,"上传资质"), + + /** + *上传频率、数量 + */ + UPLOAD_FREQUENCY_QUANTITY(2,"上传频率、数量"), + + /** + * 字段完整性 + */ + FIELD_INTEGRITY(3,"字段完整性"), + + /** + * 时效性 + */ + TIME_SENSITIVE(4,"时效性"), + + /** + * 位置及方向的正确性、一致性 + */ + POSITION_DIRECTION_CORRECTNESS_CONSISTENCY(5,"位置及方向的正确性、一致性"), + + /** + * 速度的正确性、一致性 + */ + SPEED_CORRECTNESS_CONSISTENCY(6,"速度的正确性、一致性"), + + /** + * 时间一致性 + */ + TIME_CONSISTENCY(7,"时间一致性"), + + /** + * 位置一致性 + */ + POSITION_CONSISTENCY(8,"位置一致性"); + + + private Integer code; + private String desc; + + public String getDesc() { + return desc; + } + + public Integer getCode() { + return code; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (OperatorAssessmentIndexEnum t : OperatorAssessmentIndexEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public static OperatorAssessmentIndexEnum getEnumByValue(Integer code) { + if(Objects.isNull(code)){ + return null; + } + for (OperatorAssessmentIndexEnum t : OperatorAssessmentIndexEnum.values()) { + if (code.equals(t.getCode())) { + return t; + } + } + return null; + } + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/QuarterEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/QuarterEnum.java new file mode 100644 index 0000000..f199f09 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/enums/QuarterEnum.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.industry.enums; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Objects; + +/** + * @return + * @author CMM + * @since 2023/01/04 11:03 + */ + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "QuarterEnum", description = "季度-枚举") +public enum QuarterEnum { + FIRST_QUARTER(1,"第一季度"), + SECOND_QUARTER(2,"第二季度"), + THIRD_QUARTER(3,"第三季度"), + FOURTH_QUARTER(4,"第四季度"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (QuarterEnum t : QuarterEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/AnnualInspectionReviewManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/AnnualInspectionReviewManage.java new file mode 100644 index 0000000..0527996 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/AnnualInspectionReviewManage.java @@ -0,0 +1,240 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.VehicleAnnualInspectionReview; +import com.ningdatech.carapi.industry.model.dto.InspectionReviewSaveDTO; +import com.ningdatech.carapi.industry.model.dto.InspectionReviewUpdateDTO; +import com.ningdatech.carapi.industry.model.dto.ReviewPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.VehicleAnnualInspectionExportDTO; +import com.ningdatech.carapi.industry.model.vo.VehicleAnnualInspectionReviewApplicationVO; +import com.ningdatech.carapi.industry.model.vo.VehicleAnnualInspectionReviewVO; +import com.ningdatech.carapi.industry.service.IVehicleAnnualInspectionReviewService; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname AnnualInspectionReviewManage + * @Description + * @Date 2022/11/3 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class AnnualInspectionReviewManage { + + private final IVehicleAnnualInspectionReviewService vehicleAnnualInspectionReviewService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + public PageVo infoList(ReviewPageParamDTO param) { + Page page = param.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + param.setCarPlateList(carPlateList); + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class); + AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy(); + context.search(page,wrapper,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public VehicleAnnualInspectionReviewVO details(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class); + AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + VehicleAnnualInspectionReview record = vehicleAnnualInspectionReviewService.getOne(wrapper); + if (Objects.isNull(record)){ + return null; + } + + //VehicleAnnualInspectionReview record = vehicleAnnualInspectionReviewService.getById(id); + return convert(record); + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(VehicleAnnualInspectionReview::getId,id); + } + + public PageVo applicationList(ReviewPageParamDTO param) { + Page page = param.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + param.setCarPlateList(carPlateList); + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class); + AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy(); + context.search(page,wrapper,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> convertApplication(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + + /** + * 查询 + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void search(Page page, LambdaQueryWrapper wrapper,ReviewPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), VehicleAnnualInspectionReview::getCompanyName, param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getCarPlate()), VehicleAnnualInspectionReview::getCarPlate, param.getCarPlate()) + .eq(Objects.nonNull(param.getVehicleType()), VehicleAnnualInspectionReview::getVehicleType, param.getVehicleType()) + .eq(StringUtils.isNoneBlank(param.getInspectionRecords()), VehicleAnnualInspectionReview::getInspectionRecords, param.getInspectionRecords()) + .in(CollUtil.isNotEmpty(param.getCarPlateList()),VehicleAnnualInspectionReview::getCarPlate,param.getCarPlateList()) + .orderBy(Boolean.TRUE,Boolean.FALSE, VehicleAnnualInspectionReview::getUpdateOn); + vehicleAnnualInspectionReviewService.page(page, wrapper); + } + + private VehicleAnnualInspectionReviewVO convert(VehicleAnnualInspectionReview review) { + if(Objects.isNull(review)){ + return null; + } + VehicleAnnualInspectionReviewVO vo = BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + private VehicleAnnualInspectionReviewApplicationVO convertApplication(VehicleAnnualInspectionReview review) { + VehicleAnnualInspectionReviewApplicationVO vo = BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewApplicationVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setStatus("首次申请"); + vo.setOperation("无"); + return vo; + } + + + public VehicleAnnualInspectionReviewVO save(InspectionReviewSaveDTO data, Long userId) { + VehicleAnnualInspectionReview review = BeanUtil.copyProperties(data, VehicleAnnualInspectionReview.class); + review.setRegionId(LoginUserUtil.loginUserDetail().getRegionId()); + CodeUtil.searchCompanyNameAndRegionName(review); + if(Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(vehicleTypeName -> + review.setVehicleTypeName(vehicleTypeName)); + } + review.setCreateBy(userId); + review.setUpdateBy(userId); + vehicleAnnualInspectionReviewService.save(review); + return BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewVO.class); + } + + public VehicleAnnualInspectionReviewVO modify(InspectionReviewUpdateDTO data, Long userId) { + VehicleAnnualInspectionReview review = BeanUtil.copyProperties(data, VehicleAnnualInspectionReview.class); + CodeUtil.searchCompanyNameAndRegionName(review); + if(Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(vehicleTypeName -> + review.setVehicleTypeName(vehicleTypeName)); + } + review.setUpdateBy(userId); + vehicleAnnualInspectionReviewService.updateById(review); + return BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewVO.class); + } + + public Boolean remove(Long id, Long userId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class); + AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + VehicleAnnualInspectionReview record = vehicleAnnualInspectionReviewService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法撤销!"); + } + + vehicleAnnualInspectionReviewService.removeById(id); + return Boolean.TRUE; + } + + public void infoListExport(HttpServletResponse response, ReviewPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = infoList(param); + List collect = page.getRecords().stream().map(r -> { + VehicleAnnualInspectionExportDTO exportDTO = new VehicleAnnualInspectionExportDTO(); + BeanUtils.copyProperties(r, exportDTO); + return exportDTO; + }).collect(Collectors.toList()); + String fileName = "车辆年检年审记录列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), VehicleAnnualInspectionExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataQualityMonitorManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataQualityMonitorManage.java new file mode 100644 index 0000000..fa9f2dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataQualityMonitorManage.java @@ -0,0 +1,304 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleStatusEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.industry.entity.DataQualityMonitorDynamics; +import com.ningdatech.carapi.industry.entity.DataQualityMonitorGps; +import com.ningdatech.carapi.industry.entity.DataQualityMonitorStatic; +import com.ningdatech.carapi.industry.enums.DataQualityMonitorGpsEnum; +import com.ningdatech.carapi.industry.model.dto.*; +import com.ningdatech.carapi.industry.model.vo.DataQualityMonitorDynamicsVO; +import com.ningdatech.carapi.industry.model.vo.DataQualityMonitorGpsVO; +import com.ningdatech.carapi.industry.model.vo.DataQualityMonitorStaticVO; +import com.ningdatech.carapi.industry.service.IDataQualityMonitorDynamicsService; +import com.ningdatech.carapi.industry.service.IDataQualityMonitorGpsService; +import com.ningdatech.carapi.industry.service.IDataQualityMonitorStaticService; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname DataQualityMonitorManage + * @Description + * @Date 2022/11/07 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class DataQualityMonitorManage { + + private final IDataQualityMonitorStaticService dataQualityMonitorStaticService; + private final IDataQualityMonitorDynamicsService dataQualityMonitorDynamicsService; + private final IDataQualityMonitorGpsService dataQualityMonitorGpsService; + + private final RegionsCacheHelper regionsCacheHelper; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + public PageVo staticList(DataQualityMonitorStaticPageParamDTO param) { + Page page = param.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆所在的所有企业 + List companyIds = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)) + .stream().map(NdVehicleBaseInfo::getCompanyId).collect(Collectors.toList()); + HashSet set = new HashSet<>(); + List companyIdList = companyIds.stream().filter(c -> set.add(c)).collect(Collectors.toList()); + // 过滤掉不在这些企业下的数据 + param.setCompanyIds(companyIdList); + } + + searchStatic(page,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> convertStatic(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public DataQualityMonitorStaticVO staticDetails(Long id) { + DataQualityMonitorStatic record = dataQualityMonitorStaticService.getById(id); + + return convertStatic(record); + } + + public PageVo dynamicsList(DataQualityMonitorDynamicsPageParamDTO param) { + Page page = param.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆所在的所有企业 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream() + .map(NdVehicleBaseInfo::getCarPlate) + .collect(Collectors.toList()); + // 过滤掉不在这些企业下的数据 + param.setCarPlateList(carPlateList); + } + + searchDynamics(page,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> convertDynamics(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public DataQualityMonitorDynamicsVO dynamicsDetails(Long id) { + DataQualityMonitorDynamics record = dataQualityMonitorDynamicsService.getById(id); + + return convertDynamics(record); + } + + public PageVo gpsList(DataQualityMonitorGpsPageParamDTO param) { + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DataQualityMonitorGps.class); + searchGps(page, param,wrapper); + + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + wrapper.eq(DataQualityMonitorGps::getOperatorId,operatorId); + } + + dataQualityMonitorGpsService.page(page, wrapper); + if (CollUtil.isEmpty(page.getRecords())) { + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(this::convertGps).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + + } + + public DataQualityMonitorGpsVO gpsDetails(Long id) { + DataQualityMonitorGps record = dataQualityMonitorGpsService.getById(id); + + return convertGps(record); + } + + /** + * 查询 + * @param page + * @param param + */ + private void searchStatic(Page page, DataQualityMonitorStaticPageParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DataQualityMonitorStatic.class); + wrapper.like(StringUtils.isNotBlank(param.getBatchNo()), DataQualityMonitorStatic::getBatchNo, param.getBatchNo()) + .like(Objects.nonNull(param.getState()), DataQualityMonitorStatic::getState, param.getState()) + .ge(Objects.nonNull(param.getStartTime()), DataQualityMonitorStatic::getDataTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), DataQualityMonitorStatic::getDataTime, param.getEndTime()) + .in(CollUtil.isNotEmpty(param.getCompanyIds()),DataQualityMonitorStatic::getCompanyId,param.getCompanyIds()) + .orderBy(Boolean.TRUE,Boolean.FALSE, DataQualityMonitorStatic::getDataTime); + dataQualityMonitorStaticService.page(page, wrapper); + } + + private void searchDynamics(Page page, DataQualityMonitorDynamicsPageParamDTO param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DataQualityMonitorDynamics.class); + wrapper.like(StringUtils.isNotBlank(param.getCarPlate()), DataQualityMonitorDynamics::getCarPlate, param.getCarPlate()) + .like(Objects.nonNull(param.getState()), DataQualityMonitorDynamics::getState, param.getState()) + .ge(Objects.nonNull(param.getStartTime()), DataQualityMonitorDynamics::getDataTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), DataQualityMonitorDynamics::getDataTime, param.getEndTime()) + .in(CollUtil.isNotEmpty(param.getCarPlateList()),DataQualityMonitorDynamics::getCarPlate,param.getCarPlateList()) + .orderBy(Boolean.TRUE,Boolean.FALSE, DataQualityMonitorDynamics::getDataTime); + dataQualityMonitorDynamicsService.page(page, wrapper); + } + + private void searchGps(Page page, DataQualityMonitorGpsPageParamDTO param, LambdaQueryWrapper wrapper) { + if(Objects.nonNull(param.getRegionId())){ + List regionIds = regionsCacheHelper.listChildRegionId(param.getRegionId()); + wrapper.in(CollUtil.isNotEmpty(regionIds), DataQualityMonitorGps::getRegionId,regionIds); + } + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), DataQualityMonitorGps::getCompanyName, param.getCompanyName()) + .like(Objects.nonNull(param.getVehicleType()), DataQualityMonitorGps::getVehicleType, param.getVehicleType()) + .like(StringUtils.isNotBlank(param.getCarPlate()), DataQualityMonitorGps::getCarPlate, param.getCarPlate()) + .like(StringUtils.isNotBlank(param.getPlateColor()), DataQualityMonitorGps::getPlateColor, param.getPlateColor()) + .like(StringUtils.isNotBlank(param.getOperatorName()), DataQualityMonitorGps::getOperatorName, param.getOperatorName()) + .ge(Objects.nonNull(param.getStartTime()), DataQualityMonitorGps::getDataTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), DataQualityMonitorGps::getDataTime, param.getEndTime()) + .orderBy(Boolean.TRUE,Boolean.FALSE, DataQualityMonitorGps::getDataTime); + } + + private DataQualityMonitorStaticVO convertStatic(DataQualityMonitorStatic data) { + return BeanUtil.copyProperties(data, DataQualityMonitorStaticVO.class); + } + + private DataQualityMonitorDynamicsVO convertDynamics(DataQualityMonitorDynamics data) { + if(Objects.isNull(data)){ + return null; + } + DataQualityMonitorDynamicsVO vo = BeanUtil.copyProperties(data, DataQualityMonitorDynamicsVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + private DataQualityMonitorGpsVO convertGps(DataQualityMonitorGps data) { + if(Objects.isNull(data)){ + return null; + } + DataQualityMonitorGpsVO vo = BeanUtil.copyProperties(data, DataQualityMonitorGpsVO.class); + vo.setAbnormalCausesName(DataQualityMonitorGpsEnum.getDescByCode(vo.getAbnormalCauses())); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + public void exportStatic(HttpServletResponse response, DataQualityMonitorStaticPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = staticList(param); + List collect = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, DataQualityMonitorStaticVO.class)).collect(Collectors.toList()); + String fileName = "静态监控采集列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), DataQualityMonitorStaticExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void exportDynamics(HttpServletResponse response, DataQualityMonitorDynamicsPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = dynamicsList(param); + List collect = page.getRecords().stream().map(w -> + BeanUtil.copyProperties(w, DataQualityMonitorDynamicsVO.class)).collect(Collectors.toList()); + String fileName = "动态监控采集列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), DataQualityMonitorDynamicsExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void exportGps(HttpServletResponse response, DataQualityMonitorGpsPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = gpsList(param); + List collect = page.getRecords().stream().map(w -> { + DataQualityMonitorGpsExportDTO gpsExportDTO = new DataQualityMonitorGpsExportDTO(); + BeanUtils.copyProperties(w,gpsExportDTO); + String timeStr = NdDateUtils.format(w.getDataTime(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + gpsExportDTO.setDataTime(timeStr); + gpsExportDTO.setState(VehicleStatusEnum.getDescByCode(w.getState())); + return gpsExportDTO; + }).collect(Collectors.toList()); + String fileName = "GPS监控采集列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), DataQualityMonitorGpsExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataScreenManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataScreenManage.java new file mode 100644 index 0000000..ecf4a6c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DataScreenManage.java @@ -0,0 +1,98 @@ +package com.ningdatech.carapi.industry.manage; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.vo.RegionDistributionStatisticsVO; +import com.ningdatech.carapi.car.datascreen.service.VehicleStatisticsService; +import com.ningdatech.carapi.industry.model.po.CeriticatePO; +import com.ningdatech.carapi.industry.service.DataScreenService; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * @author PoffyZhang + * @Classname DataScreenManage + * @Description + * @Date 2022/12/15 19:06 + */ +@Component +@RequiredArgsConstructor +public class DataScreenManage { + + private final VehicleStatisticsService vehicleStatisticsService; + + private final DataScreenService dataScreenService; + + private final RegionsCacheHelper regionsCacheHelper; + + public List regionDistribution(DataScreenParam param) { + return vehicleStatisticsService.getRegionDistribution(param); + } + + public Map tainCertificate(DataScreenParam param) { + Map res = new LinkedHashMap<>(); + List list = dataScreenService.tainCertificate(param); + complementaryRegion(list, param.getRegionId()); + for (CeriticatePO ceriticate : list) { + res.put(ceriticate.getRegionName(), ceriticate.getCount()); + } + + return res; + } + + public JSONObject laboratoryQualificationCertificate(DataScreenParam param) { + JSONObject res = new JSONObject(true); + List list = dataScreenService.laboratoryQualificationCertificate(param); + complementaryRegion(list, param.getRegionId()); + for (CeriticatePO ceriticate : list) { + res.put(ceriticate.getRegionName(), ceriticate.getCount()); + } + return res; + } + + public JSONObject laboratoryAcceptanceCertificate(DataScreenParam param) { + JSONObject res = new JSONObject(true); + List list = dataScreenService.laboratoryAcceptanceCertificate(param); + complementaryRegion(list, param.getRegionId()); + for (CeriticatePO ceriticate : list) { + res.put(ceriticate.getRegionName(), ceriticate.getCount()); + } + return res; + } + + public JSONObject recordCertificateMortarEnterprise(DataScreenParam param) { + JSONObject res = new JSONObject(true); + List list = dataScreenService.recordCertificateMortarEnterprise(param); + complementaryRegion(list, param.getRegionId()); + for (CeriticatePO ceriticate : list) { + res.put(ceriticate.getRegionName(), ceriticate.getCount()); + } + return res; + } + + private void complementaryRegion(List list, Long regionId) { + List regions = regionsCacheHelper.listChildOnly(regionId, true); + Map regionMap = CollUtils.listToMap(list, CeriticatePO::getRegionName); + List tmpList = new ArrayList<>(); + regions.forEach(w -> { + CeriticatePO ceriticate = regionMap.get(w.getRegionName()); + if (ceriticate == null) { + ceriticate = new CeriticatePO(); + ceriticate.setRegionId(w.getId()); + ceriticate.setRegionName(w.getRegionName()); + ceriticate.setCount(0); + } + tmpList.add(ceriticate); + }); + list.clear(); + list.addAll(tmpList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DriverTrainingCertificateManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DriverTrainingCertificateManage.java new file mode 100644 index 0000000..7f04cc2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/DriverTrainingCertificateManage.java @@ -0,0 +1,359 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.archives.enums.ApproveStateEnum; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.industry.contants.CertificateContant; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateJoin; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOper; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOperJoin; +import com.ningdatech.carapi.industry.model.dto.DriverTrainingCertificateExportDTO; +import com.ningdatech.carapi.industry.model.dto.DriverTrainingCertificatePageParamDTO; +import com.ningdatech.carapi.industry.model.dto.DriverTrainingCertificateUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.DriverTrainingCertificateOperVO; +import com.ningdatech.carapi.industry.model.vo.DriverTrainingCertificateVO; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateJoinService; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateOperJoinService; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateOperService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname DriverTrainingCertificateManage + * @Description + * @Date 2022/11/3 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@AllArgsConstructor +public class DriverTrainingCertificateManage { + + private final IDriverTrainingCertificateJoinService driverTrainingCertificateJoinService; + private final IDriverTrainingCertificateOperService driverTrainingCertificateOperService; + private final IDriverTrainingCertificateOperJoinService driverTrainingCertificateOperJoinService; + + private final ICertificateService certificateService; + private final IDriverInfoService driverInfoService; + private final RegionsCacheHelper regionCacheHelper; + + /** + * 合格证信息列表 + */ + public PageVo infoList(DriverTrainingCertificatePageParamDTO param) { + Page page = param.page(); + LambdaQueryWrapper query + = Wrappers.lambdaQuery(DriverTrainingCertificateJoin.class); + DriverTrainingCertificateManage context = (DriverTrainingCertificateManage) AopContext.currentProxy(); + context.search(page,query,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public DriverTrainingCertificateVO infoDetails(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Certificate.class); + DriverTrainingCertificateManage context = (DriverTrainingCertificateManage) AopContext.currentProxy(); + context.buildCertificateQuery(wrapper, id); + Certificate certificate = certificateService.getOne(wrapper); + if (Objects.isNull(certificate)){ + return null; + } + //Certificate certificate = certificateService.getById(id); + DriverTrainingCertificateOper oper = driverTrainingCertificateOperService + .getOne(Wrappers.lambdaQuery(DriverTrainingCertificateOper.class) + .eq(DriverTrainingCertificateOper::getCertificateId, id) + .last("limit 1")); + + DriverInfo driverInfo = driverInfoService.getById(certificate.getDriverId()); + + DriverTrainingCertificateVO vo = new DriverTrainingCertificateVO(); + vo.setId(id); + vo.setDriverId(certificate.getDriverId()); + vo.setDriverName(certificate.getDriverName()); + vo.setIdCard(driverInfo.getIdCard()); + vo.setCertificateNo(certificate.getCertificateNo()); + if(Objects.nonNull(oper)){ + vo.setCertificateType(oper.getOperationTypeId()); + vo.setCertificateTypeName(oper.getOperationTypeName()); + } + + vo.setIssuedBy(certificate.getIssuedBy()); + vo.setIssueDate(certificate.getIssueDate()); + vo.setDriverLicenseNo(certificate.getDriverLicenseNo()); + vo.setExpiryDate(certificate.getExpiryDate()); + vo.setCompanyId(certificate.getCompanyId()); + vo.setCompanyName(certificate.getCompanyName()); + vo.setRemark(certificate.getRemark()); + return vo; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildCertificateQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(Certificate::getId,id); + } + + /** + * 合格证申请列表 + */ + public PageVo operationList(DriverTrainingCertificatePageParamDTO param, Integer operationTypeAppcation) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverTrainingCertificateOperJoin.class); + DriverTrainingCertificateManage context = (DriverTrainingCertificateManage) AopContext.currentProxy(); + context.searchJoin(page,wrapper,param,operationTypeAppcation); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> convertOper(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public DriverTrainingCertificateOperVO approve(Long id, Long userId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverTrainingCertificateOper.class); + DriverTrainingCertificateManage context = (DriverTrainingCertificateManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + DriverTrainingCertificateOper oper = driverTrainingCertificateOperService.getOne(wrapper); + if(Objects.isNull(oper)){ + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "此id证书操作不存在"); + } + oper.setUpdateBy(userId); + oper.setAuditState(ApproveStateEnum.AUDIT_SUCESS.getCode()); + oper.setAuditStateName(ApproveStateEnum.AUDIT_SUCESS.getDesc()); + driverTrainingCertificateOperService.updateById(oper); + // 将审核通过的证书信息保存到证书表中 + // 如果是新增证书,审核后先判断合格证列表中是否已经存在该驾驶员的合格证信息 + Long driverId = oper.getDriverId(); + if (oper.getOperationTypeId().equals(CertificateContant.OPERATION_TYPE_APPCATION)){ + List certificateList = certificateService.list(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getDriverId, driverId) + .gt(Certificate::getExpiryDate, LocalDateTime.now())); + if (CollectionUtil.isNotEmpty(certificateList)) { + throw new BizException("该驾驶员证书已上传"); + } + } + DriverInfo driverInfo = driverInfoService.getById(driverId); + Certificate certificate = new Certificate(); + BeanUtils.copyProperties(oper,certificate); + certificate.setUserId(driverInfo.getUserId()); + certificate.setBirth(driverInfo.getBirth()); + certificate.setGender(driverInfo.getGender()); + certificate.setNativePlace(driverInfo.getNativePlace()); + certificate.setHealth(driverInfo.getHealth()); + certificate.setPhoneNo(driverInfo.getPhoneNo()); + certificate.setAddress(driverInfo.getAddress()); + certificate.setDriverLicenseType(driverInfo.getDriverLicenseType()); + certificate.setRegionId(driverInfo.getRegionId()); + certificate.setRegionName(regionCacheHelper.getDisplayName(driverInfo.getRegionId())); + certificate.setCompanyId(driverInfo.getCompanyId()); + certificate.setCompanyName(driverInfo.getCompanyName()); + // 如果是补换证书,更新原来存在的证书信息 + if (oper.getOperationTypeId().equals(CertificateContant.OPERATION_TYPE_REISSUE)){ + certificate.setId(oper.getCertificateId()); + } + certificateService.saveOrUpdate(certificate); + return BeanUtil.copyProperties(oper,DriverTrainingCertificateOperVO.class); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(DriverTrainingCertificateOper::getId,id); + } + + public DriverTrainingCertificateOperVO unapprove(Long id, Long userId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(DriverTrainingCertificateOper.class); + DriverTrainingCertificateManage context = (DriverTrainingCertificateManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + DriverTrainingCertificateOper oper = driverTrainingCertificateOperService.getOne(wrapper); + if(Objects.isNull(oper)){ + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "此id证书操作不存在"); + } + oper.setUpdateBy(userId); + oper.setAuditState(ApproveStateEnum.AUDIT.getCode()); + oper.setAuditStateName(ApproveStateEnum.AUDIT.getDesc()); + driverTrainingCertificateOperService.updateById(oper); + return BeanUtil.copyProperties(oper,DriverTrainingCertificateOperVO.class); + } + + /** + * 查询 + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void search(Page page,LambdaQueryWrapper wrapper,DriverTrainingCertificatePageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), DriverTrainingCertificateJoin::getCompanyName, param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getIdCard()), DriverTrainingCertificateJoin::getIdCard, param.getIdCard()) + .like(StringUtils.isNotBlank(param.getDriverName()), DriverTrainingCertificateJoin::getDriverName, param.getDriverName()) + .eq(StringUtils.isNotBlank(param.getTrainingResult()), DriverTrainingCertificateJoin::getTrainingResult, param.getTrainingResult()) + .ge(Objects.nonNull(param.getStartTime()), DriverTrainingCertificateJoin::getTrainingTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), DriverTrainingCertificateJoin::getTrainingTime, param.getEndTime()) + .orderByDesc(DriverTrainingCertificateJoin::getUpdateOn); + driverTrainingCertificateJoinService.pageJoin(page, wrapper); + } + + /** + * 查询 + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchJoin(Page page,LambdaQueryWrapper wrapper,DriverTrainingCertificatePageParamDTO param,Integer operationTypeAppcation) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()),DriverTrainingCertificateOperJoin::getCompanyName, param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getIdCard()),DriverTrainingCertificateOperJoin::getIdCard, param.getIdCard()) + .like(StringUtils.isNotBlank(param.getDriverName()),DriverTrainingCertificateOperJoin::getDriverName, param.getDriverName()) + .eq(StringUtils.isNotBlank(param.getTrainingResult()),DriverTrainingCertificateOperJoin::getTrainingResult, param.getTrainingResult()) + .ge(Objects.nonNull(param.getStartTime()),DriverTrainingCertificateOperJoin::getTrainingTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()),DriverTrainingCertificateOperJoin::getTrainingTime, param.getEndTime()) + .eq(DriverTrainingCertificateOperJoin::getOperationTypeId,operationTypeAppcation) + .orderByDesc(DriverTrainingCertificateOperJoin::getUpdateOn); + driverTrainingCertificateOperJoinService.pageJoin(page, wrapper); + } + + private DriverTrainingCertificateVO convert(DriverTrainingCertificateJoin driver) { + if(Objects.isNull(driver)){ + return null; + } + DriverTrainingCertificateVO vo = BeanUtil.copyProperties(driver, DriverTrainingCertificateVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + private DriverTrainingCertificateOperVO convertOper(DriverTrainingCertificateOperJoin driver) { + DriverTrainingCertificateOperVO vo = BeanUtil.copyProperties(driver, DriverTrainingCertificateOperVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + public void infoListExport(HttpServletResponse response, DriverTrainingCertificatePageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = infoList(param); + + List collect = page.getRecords().stream().map(r -> { + DriverTrainingCertificateExportDTO exportDTO = new DriverTrainingCertificateExportDTO(); + BeanUtils.copyProperties(r, exportDTO); + String trainingTimeStr = NdDateUtils.format(r.getTrainingTime(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + exportDTO.setTrainingTime(trainingTimeStr); + String effectiveTimeStr = NdDateUtils.format(r.getTrainingTime(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + exportDTO.setEffectiveTime(effectiveTimeStr); + return exportDTO; + }).collect(Collectors.toList()); + String fileName = "驾驶员培训合格证书信息列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), DriverTrainingCertificateExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public DriverTrainingCertificateVO modify(DriverTrainingCertificateUpdateDTO data, Long userId) { + DriverTrainingCertificateVO certificateVO = new DriverTrainingCertificateVO(); + BeanUtils.copyProperties(data,certificateVO); + Long certificateId = data.getId(); + Certificate certificate = certificateService.getById(certificateId); + BeanUtils.copyProperties(data,certificate); + certificate.setUpdateOn(LocalDateTime.now()); + certificateService.updateById(certificate); + return certificateVO; + } + + public Long save(DriverTrainingCertificateUpdateDTO data, Long userId) { + + Long driverId = data.getDriverId(); + String certificateNo = data.getCertificateNo(); + + // 校验合格证号是否可用 + Certificate check = certificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getCertificateNo, certificateNo) + .ne(Certificate::getId,data.getId())); + + if (Objects.nonNull(check)) { + throw new BizException("证书编号重复!"); + } + + Certificate oldCertificate = certificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getCertificateNo, certificateNo)); + + DriverTrainingCertificateOper certificateOper = new DriverTrainingCertificateOper(); + BeanUtils.copyProperties(data,certificateOper); + Integer certificateType = data.getCertificateType(); + if (certificateType.equals(CertificateContant.OPERATION_TYPE_APPCATION)){ + certificateOper.setOperationTypeId(CertificateContant.OPERATION_TYPE_APPCATION); + certificateOper.setOperationTypeName(CertificateContant.OPERATION_TYPE_APPCATION_NAME); + } else if (certificateType.equals(CertificateContant.OPERATION_TYPE_REISSUE)){ + certificateOper.setOperationTypeId(CertificateContant.OPERATION_TYPE_REISSUE); + // 从证书列表中查出要补换的证书ID + DriverInfo driverInfo = driverInfoService.getById(driverId); + Certificate certificate = certificateService.getOne(Wrappers.lambdaQuery(Certificate.class) + .eq(Certificate::getUserId, driverInfo.getUserId())); + if (Objects.nonNull(certificate)){ + certificateOper.setCertificateId(certificate.getId()); + } + certificateOper.setOperationTypeName(CertificateContant.OPERATION_TYPE_REISSUE_NAME); + } + certificateOper.setOperationTime(LocalDateTime.now()); + certificateOper.setApplication(data.getApplication()); + certificateOper.setApplicationReason(data.getApplicationReason()); + if(Objects.isNull(data.getId())){ + certificateOper.setAuditState(ApproveStateEnum.AUDIT.getCode()); + certificateOper.setAuditStateName(ApproveStateEnum.AUDIT.getDesc()); + certificateOper.setCreateOn(LocalDateTime.now()); + certificateOper.setCreateBy(userId); + } + driverTrainingCertificateOperService.saveOrUpdate(certificateOper); + + if (Objects.nonNull(oldCertificate)) { + oldCertificate.setDriverLicenseNo(data.getDriverLicenseNo()); + oldCertificate.setRemark(data.getRemark()); + certificateService.updateById(oldCertificate); + } + + return certificateOper.getId(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabAcceptanceCertificateManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabAcceptanceCertificateManage.java new file mode 100644 index 0000000..e5f959d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabAcceptanceCertificateManage.java @@ -0,0 +1,298 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.ValidUtil; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificate; +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificateChange; +import com.ningdatech.carapi.industry.enums.AddTypeEnum; +import com.ningdatech.carapi.industry.model.dto.LabAcceptanceCertificateExportDto; +import com.ningdatech.carapi.industry.model.dto.LabAcceptanceCertificateImportDto; +import com.ningdatech.carapi.industry.model.req.LabAcceptanceCertificateListReq; +import com.ningdatech.carapi.industry.model.req.LabAcceptanceCertificateReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.model.vo.LabAcceptanceCertificateChangeListVo; +import com.ningdatech.carapi.industry.model.vo.LabAcceptanceCertificateListVo; +import com.ningdatech.carapi.industry.service.ILabAcceptanceCertificateChangeService; +import com.ningdatech.carapi.industry.service.ILabAcceptanceCertificateService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.event.ImportDataEvent; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * LabAcceptanceCertificateManage + *

+ * + * @author WendyYang + * @since 14:35 2022/11/8 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class LabAcceptanceCertificateManage { + + private final ILabAcceptanceCertificateService labAcceptanceCertificateService; + + private final ILabAcceptanceCertificateChangeService labAcceptanceCertificateChangeService; + private final RegionsCacheHelper regionsCacheHelper; + private final CompanyService companyService; + private final UserInfoHelper userInfoHelper; + + public PageVo labAcceptanceCertificateList(LabAcceptanceCertificateListReq req) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(LabAcceptanceCertificate.class); + LabAcceptanceCertificateManage context = (LabAcceptanceCertificateManage) AopContext.currentProxy(); + context.build(wrapper,req); + Page page = labAcceptanceCertificateService.page(req.page(),wrapper); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List result = page.getRecords().stream().map(w -> { + LabAcceptanceCertificateListVo vo = BeanUtil.copyProperties(w, LabAcceptanceCertificateListVo.class); + vo.setRegionName(regionsCacheHelper.getDisplayName(w.getRegionId())); + vo.setValidDate(w.getValidDate()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(result, page.getTotal()); + } + @LambdaDataScope + @BuildChildrenRegionWrapper + public void build(LambdaQueryWrapper wrapper,LabAcceptanceCertificateListReq req) { + wrapper.ge(Objects.nonNull(req.getStartDate()),LabAcceptanceCertificate::getConferDate,req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()),LabAcceptanceCertificate::getConferDate,req.getEndDate()) + .like(StringUtils.isNotBlank(req.getCompanyName()),LabAcceptanceCertificate::getCompanyName,req.getCompanyName()) + .orderByDesc(LabAcceptanceCertificate::getConferDate); + } + + //=======================================================导出======================================================== + + @EventListener(condition = "event.getTemplate() == T(com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum).LAB_ACCEPTANCE_CERTIFICATE") + public void importDataListener(ImportDataEvent event) throws IOException { + MultipartFile file = (MultipartFile) event.getSource(); + EasyExcel.read(file.getInputStream(), LabAcceptanceCertificateImportDto.class, + new ReadListener() { + + final List insert = new ArrayList<>(); + + @Override + public void invoke(LabAcceptanceCertificateImportDto data, AnalysisContext context) { + String s = ValidUtil.validFast(data); + Assert.isTrue(StrUtil.isBlank(s), s); + insert.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + log.info("所有数据读取完成:{}", insert.size()); + importDataSave(insert); + } + }).sheet(0).doRead(); + } + + private void importDataSave(List records) { + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + List companyNames = CollUtils.fieldList(records, LabAcceptanceCertificateImportDto::getCompanyName); + List companies = companyService.listCompanyByCompanyNames(companyNames); + Map companyMap = CollUtils.listToMap(companies, Company::getName); + List list = new ArrayList<>(); + records.forEach(w -> { + Company company = companyMap.get(w.getCompanyName()); + if (company == null) { + return; + } + LabAcceptanceCertificate certificate = new LabAcceptanceCertificate(); + certificate.setCertificateNo(w.getCertificateNo()); + certificate.setRemark(w.getRemark()); + certificate.setRegionId(company.getRegionId()); + certificate.setValidDate(NdDateUtils.date2LocalDate(w.getValidDate())); + certificate.setConferDate(NdDateUtils.date2LocalDate(w.getConferDate())); + certificate.setConferOrg(w.getConferOrg()); + certificate.setCompanyName(company.getName()); + certificate.setCompanyId(company.getId()); + certificate.setCreateBy(userId); + certificate.setCreateOn(now); + certificate.setUpdateBy(userId); + certificate.setUpdateOn(now); + list.add(certificate); + }); + labAcceptanceCertificateService.saveBatch(list); + } + + //================================================================================================================== + + public void exportLabAcceptanceCertificate(HttpServletResponse response, LabAcceptanceCertificateListReq req) { + req.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = labAcceptanceCertificateList(req); + List collect = page.getRecords().stream().map(w -> { + LabAcceptanceCertificateExportDto dto = BeanUtil.copyProperties(w, LabAcceptanceCertificateExportDto.class); + dto.setStandard(w.getStandard()); + dto.setTestItem(w.getTestItem()); + String conferDateStr = NdDateUtils.format(w.getConferDate(), NdDateUtils.DEFAULT_DATE_FORMAT); + dto.setConferDate(conferDateStr); + String validDateStr= NdDateUtils.format(w.getValidDate(), NdDateUtils.DEFAULT_DATE_FORMAT); + dto.setValidDate(validDateStr); + return dto; + }).collect(Collectors.toList()); + String fileName = "实验室验收合格证"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), LabAcceptanceCertificateExportDto.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void saveOrUpdate(LabAcceptanceCertificateReq req) { + Long userId = LoginUserUtil.getUserId(); + Integer addType = req.getAddType(); + // 说明是新增证书 + if (AddTypeEnum.NEW.getCode().equals(addType)) { + LabAcceptanceCertificate labAcceptanceCertificate = new LabAcceptanceCertificate(); + if (Objects.nonNull(req.getId())){ + // 说明为编辑 + labAcceptanceCertificate.setId(req.getId()); + } + labAcceptanceCertificate.setRegionId(req.getRegionId()); + labAcceptanceCertificate.setCompanyId(req.getCompanyId()); + labAcceptanceCertificate.setCompanyName(req.getCompanyName()); + labAcceptanceCertificate.setRecordItem(req.getRecordItem()); + labAcceptanceCertificate.setCertificateNo(req.getCertificateNo()); + labAcceptanceCertificate.setConferDate(req.getConferDate()); + labAcceptanceCertificate.setStandard(req.getStandard()); + labAcceptanceCertificate.setTestItem(req.getTestItem()); + labAcceptanceCertificate.setRemark(req.getRemark()); + labAcceptanceCertificate.setConferOrg(req.getConferOrg()); + + labAcceptanceCertificate.setCreateOn(LocalDateTime.now()); + labAcceptanceCertificate.setCreateBy(userId); + labAcceptanceCertificate.setUpdateOn(LocalDateTime.now()); + labAcceptanceCertificate.setUpdateBy(userId); + + labAcceptanceCertificateService.saveOrUpdate(labAcceptanceCertificate); + } else if (AddTypeEnum.REPLACE.getCode().equals(req.getAddType())) { + // 说明为换证 + LabAcceptanceCertificateChange labAcceptanceCertificateChange = new LabAcceptanceCertificateChange(); + if (Objects.nonNull(req.getId())){ + // 说明为编辑 + labAcceptanceCertificateChange.setId(req.getId()); + } + String applicationItem = req.getApplicationItem(); + String applicationReason = req.getApplicationReason(); + if (Objects.isNull(applicationItem) || Objects.isNull(applicationReason)){ + throw new BizException("申请事项和申请原因不能为空!"); + } + labAcceptanceCertificateChange.setCompanyName(req.getCompanyName()); + labAcceptanceCertificateChange.setRegionId(req.getRegionId()); + labAcceptanceCertificateChange.setCompanyId(req.getCompanyId()); + labAcceptanceCertificateChange.setCertificateNo(req.getCertificateNo()); + labAcceptanceCertificateChange.setRecordItem(req.getRecordItem()); + labAcceptanceCertificateChange.setReplacementTime(req.getReplaceDate()); + labAcceptanceCertificateChange.setConferOrg(req.getConferOrg()); + labAcceptanceCertificateChange.setRemark(req.getRemark()); + labAcceptanceCertificateChange.setApplicationItem(req.getApplicationItem()); + labAcceptanceCertificateChange.setApplicationReason(req.getApplicationReason()); + labAcceptanceCertificateChange.setTestItem(req.getTestItem()); + labAcceptanceCertificateChange.setValidDate(req.getValidDate()); + labAcceptanceCertificateChange.setStandard(req.getStandard()); + + labAcceptanceCertificateChange.setCreateOn(LocalDateTime.now()); + labAcceptanceCertificateChange.setCreateBy(userId); + labAcceptanceCertificateChange.setUpdateOn(LocalDateTime.now()); + labAcceptanceCertificateChange.setUpdateBy(userId); + labAcceptanceCertificateChangeService.saveOrUpdate(labAcceptanceCertificateChange); + } + } + + public PageVo changeList(LabAcceptanceCertificateListReq req) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(LabAcceptanceCertificateChange.class); + LabAcceptanceCertificateManage context = (LabAcceptanceCertificateManage) AopContext.currentProxy(); + context.buildChangeListQuery(wrapper,req); + Page page = labAcceptanceCertificateChangeService.page(req.page(), wrapper); + if (CollUtil.isEmpty(page.getRecords())){ + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), w -> { + LabAcceptanceCertificateChangeListVo resVo = BeanUtil.copyProperties(w, LabAcceptanceCertificateChangeListVo.class); + resVo.setRegionName(regionsCacheHelper.getDisplayName(w.getRegionId())); + resVo.setReplaceDate(w.getReplacementTime()); + return resVo; + }); + + return PageVo.of(data,page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildChangeListQuery(LambdaQueryWrapper wrapper, LabAcceptanceCertificateListReq req) { + wrapper.like(StrUtil.isNotBlank(req.getCompanyName()), LabAcceptanceCertificateChange::getCompanyName, req.getCompanyName()) + .ge(Objects.nonNull(req.getStartDate()),LabAcceptanceCertificateChange::getReplacementTime,req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()),LabAcceptanceCertificateChange::getReplacementTime,req.getEndDate()) + .orderByDesc(LabAcceptanceCertificateChange::getUpdateOn); + } + + public Boolean audit(LabWorkerCertificateAuditReq req, Long userId) { + return labAcceptanceCertificateService.audit(req,userId); + } + + public void delete(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(LabAcceptanceCertificate.class); + LabAcceptanceCertificateManage context = (LabAcceptanceCertificateManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + LabAcceptanceCertificate record = labAcceptanceCertificateService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法删除!"); + } + labAcceptanceCertificateService.removeById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(LabAcceptanceCertificate::getId,id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabWorkerCertificateManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabWorkerCertificateManage.java new file mode 100644 index 0000000..2e0b196 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/LabWorkerCertificateManage.java @@ -0,0 +1,309 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.aop.framework.AopContext; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.ValidUtil; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.GenderEnum; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.LabWorkerCertificate; +import com.ningdatech.carapi.industry.entity.LabWorkerCertificateChange; +import com.ningdatech.carapi.industry.enums.AddTypeEnum; +import com.ningdatech.carapi.industry.enums.LabWorkerCertificateTypeEnum; +import com.ningdatech.carapi.industry.model.dto.LabWorkerCertificateExportDto; +import com.ningdatech.carapi.industry.model.dto.LabWorkerCertificateImportDto; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateListReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateReq; +import com.ningdatech.carapi.industry.model.vo.LabWorkerCertificateChangeListVo; +import com.ningdatech.carapi.industry.model.vo.LabWorkerCertificateListVo; +import com.ningdatech.carapi.industry.service.ILabWorkerCertificateChangeService; +import com.ningdatech.carapi.industry.service.ILabWorkerCertificateService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.event.ImportDataEvent; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * LabWorkerCertificateManage + *

+ * + * @author WendyYang + * @since 14:57 2022/11/4 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class LabWorkerCertificateManage { + + private final CompaniesCacheHelper companiesCacheHelper; + private final CompanyService companyService; + private final RegionsCacheHelper regionsCacheHelper; + private final ILabWorkerCertificateService labWorkerCertificateService; + + private final ILabWorkerCertificateChangeService labWorkerCertificateChangeService; + + public PageVo labWorkerCertificateList(LabWorkerCertificateListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(LabWorkerCertificate.class); + LabWorkerCertificateManage context = (LabWorkerCertificateManage) AopContext.currentProxy(); + context.buildLabWorkerCertificateQuery(query, req); + Page page = labWorkerCertificateService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), w -> { + LabWorkerCertificateListVo vo = BeanUtil.copyProperties(w, LabWorkerCertificateListVo.class); + vo.setRegionName(regionsCacheHelper.getDisplayName(w.getRegionId())); + vo.setGenderName(GenderEnum.getDescByCode(w.getGender())); + vo.setUserName(w.getUserName()); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildLabWorkerCertificateQuery(LambdaQueryWrapper query, LabWorkerCertificateListReq req) { + query.like(StrUtil.isNotBlank(req.getCompanyName()), LabWorkerCertificate::getCompanyName, req.getCompanyName()) + .ge(Objects.nonNull(req.getStartDate()), LabWorkerCertificate::getConferDate, req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()), LabWorkerCertificate::getConferDate, req.getEndDate()) + .eq(Objects.nonNull(req.getCertificateType()), LabWorkerCertificate::getCertificateType, req.getCertificateType()) + .orderByDesc(LabWorkerCertificate::getUpdateOn); + } + + public void labWorkerCertificateExport(HttpServletResponse response, LabWorkerCertificateListReq req) { + req.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = this.labWorkerCertificateList(req); + List collect = page.getRecords().stream().map(w -> { + LabWorkerCertificateExportDto dto = BeanUtil.copyProperties(w, LabWorkerCertificateExportDto.class); + String conferDateStr= NdDateUtils.format(w.getConferDate(), NdDateUtils.DEFAULT_DATE_FORMAT); + dto.setConferDate(conferDateStr); + String validDateStr= NdDateUtils.format(w.getValidDate(), NdDateUtils.DEFAULT_DATE_FORMAT); + dto.setValidDate(validDateStr); + dto.setGender(GenderEnum.getDescByCode(w.getGender())); + return dto; + }).collect(Collectors.toList()); + String fileName; + if (req.getCertificateType() == LabWorkerCertificateTypeEnum.QUALIFICATION.getCode()) { + fileName = "试验室人员从业资格证-证书信息"; + } else { + fileName = "实验室人员继续教育合格证-证书信息"; + } + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), LabWorkerCertificateExportDto.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @EventListener(condition = "event.getTemplate() == T(com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum).LAB_WORKER_CERTIFICATE_QUA") + public void importDataListener(ImportDataEvent event) throws IOException { + MultipartFile file = (MultipartFile) event.getSource(); + EasyExcel.read(file.getInputStream(), LabWorkerCertificateImportDto.class, + new ReadListener() { + + final List insert = new ArrayList<>(); + + @Override + public void invoke(LabWorkerCertificateImportDto data, AnalysisContext context) { + String s = ValidUtil.validFast(data); + Assert.isTrue(StrUtil.isBlank(s), s); + insert.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + log.info("所有数据读取完成:{}", insert.size()); + importDataSave(insert); + } + }).sheet(0).doRead(); + } + + private void importDataSave(List records) { + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + List companyNames = CollUtils.fieldList(records, LabWorkerCertificateImportDto::getCompanyName); + List companies = companyService.listCompanyByCompanyNames(companyNames); + Map companyMap = CollUtils.listToMap(companies, Company::getName); + List list = new ArrayList<>(); + records.forEach(w -> { + Company company = companyMap.get(w.getCompanyName()); + if (company == null) { + return; + } + LabWorkerCertificate certificate = new LabWorkerCertificate(); + certificate.setCertificateNo(w.getCertificateNo()); + certificate.setIdCard(w.getIdCard()); + certificate.setRemark(w.getRemark()); + certificate.setGender(GenderEnum.getByValue(w.getGender()).getCode()); + certificate.setRegionId(company.getRegionId()); + certificate.setUserName(w.getUsername()); + certificate.setValidDate(NdDateUtils.date2LocalDate(w.getEndDate())); + certificate.setConferDate(NdDateUtils.date2LocalDate(w.getStartDate())); + certificate.setCompanyName(company.getName()); + certificate.setCompanyId(company.getId()); + certificate.setCreateBy(userId); + certificate.setCreateOn(now); + certificate.setUpdateBy(userId); + certificate.setUpdateOn(now); + list.add(certificate); + labWorkerCertificateService.saveBatch(list); + }); + } + + public void saveOrUpdate(LabWorkerCertificateReq req) { + Integer addType = req.getAddType(); + //说明是新增证书 + LabWorkerCertificate labWorkerCertificate = new LabWorkerCertificate(); + if (AddTypeEnum.NEW.getCode().equals(addType)) { + if (Objects.nonNull(req.getId())){ + // 说明为编辑 + labWorkerCertificate.setId(req.getId()); + } + labWorkerCertificate.setRegionId(req.getRegionId()); + labWorkerCertificate.setCompanyId(req.getCompanyId()); + labWorkerCertificate.setCompanyName(req.getCompanyName()); + labWorkerCertificate.setCreateOn(LocalDateTime.now()); + labWorkerCertificate.setCreateBy(LoginUserUtil.getUserId()); + labWorkerCertificate.setUpdateOn(LocalDateTime.now()); + labWorkerCertificate.setUpdateOn(LocalDateTime.now()); + labWorkerCertificate.setGender(req.getGender()); + labWorkerCertificate.setIdCard(req.getIdCard()); + labWorkerCertificate.setCertificateNo(req.getCertificateNo()); + labWorkerCertificate.setConferDate(req.getConferDate()); + labWorkerCertificate.setValidDate(req.getValidDate()); + labWorkerCertificate.setRemark(req.getRemark()); + labWorkerCertificate.setCertificateType(req.getCertificateType()); + labWorkerCertificate.setConferOrg(req.getConferOrg()); + labWorkerCertificateService.saveOrUpdate(labWorkerCertificate); + } else if (AddTypeEnum.REPLACE.getCode().equals(req.getAddType())) { + // 说明是换证 + //创建新的证书实体,并装配证书信息,保存到换证列表中 + String applicationItem = req.getApplicationItem(); + String applicationReason = req.getApplicationReason(); + if (Objects.isNull(applicationItem) || Objects.isNull(applicationReason)){ + throw new BizException("申请事项和申请原因不能为空!"); + } + LabWorkerCertificateChange labWorkerCertificateChange = new LabWorkerCertificateChange(); + if (Objects.nonNull(req.getId())){ + // 说明为编辑 + labWorkerCertificateChange.setId(req.getId()); + } + labWorkerCertificateChange.setCompanyName(req.getCompanyName()); + labWorkerCertificateChange.setCompanyId(req.getCompanyId()); + labWorkerCertificateChange.setRegionId(req.getRegionId()); + labWorkerCertificateChange.setUserName(req.getUserName()); + labWorkerCertificateChange.setGender(req.getGender()); + labWorkerCertificateChange.setIdCard(req.getIdCard()); + labWorkerCertificateChange.setCertificateNo(req.getCertificateNo()); + labWorkerCertificateChange.setReplacementTime(req.getReplaceDate()); + labWorkerCertificateChange.setValidDate(req.getValidDate()); + labWorkerCertificateChange.setRemark(req.getRemark()); + labWorkerCertificateChange.setCertificateType(req.getCertificateType()); + labWorkerCertificateChange.setApplicationItem(req.getApplicationItem()); + labWorkerCertificateChange.setApplicationReason(req.getApplicationReason()); + labWorkerCertificateChange.setConferOrg(req.getConferOrg()); + + labWorkerCertificateChange.setCreateOn(LocalDateTime.now()); + labWorkerCertificateChange.setCreateBy(LoginUserUtil.getUserId()); + labWorkerCertificateChange.setUpdateOn(LocalDateTime.now()); + labWorkerCertificateChange.setUpdateOn(LocalDateTime.now()); + + labWorkerCertificateChangeService.saveOrUpdate(labWorkerCertificateChange); + } + } + + public PageVo changeCertificate(LabWorkerCertificateListReq req) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(LabWorkerCertificateChange.class); + LabWorkerCertificateManage context = (LabWorkerCertificateManage) AopContext.currentProxy(); + context.buildLabWorkerCertificateChangeQuery(wrapper, req); + Page page = labWorkerCertificateChangeService.page(req.page(), wrapper); + if (page.getTotal() == 0) { + return PageVo.empty(); + } + List records = CollUtils.convert(page.getRecords(), w -> { + LabWorkerCertificateChangeListVo resVo = BeanUtil.copyProperties(w, LabWorkerCertificateChangeListVo.class); + resVo.setReplaceDate(w.getReplacementTime()); + resVo.setRegionName(regionsCacheHelper.getDisplayName(w.getRegionId())); + resVo.setGenderName(GenderEnum.getDescByCode(w.getGender())); + return resVo; + }); + return PageVo.of(records, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildLabWorkerCertificateChangeQuery(LambdaQueryWrapper wrapper, LabWorkerCertificateListReq req) { + wrapper.like(StrUtil.isNotBlank(req.getCompanyName()), LabWorkerCertificateChange::getCompanyName, req.getCompanyName()) + .ge(Objects.nonNull(req.getStartDate()), LabWorkerCertificateChange::getReplacementTime, req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()), LabWorkerCertificateChange::getReplacementTime, req.getEndDate()) + .eq(Objects.nonNull(req.getCertificateType()), LabWorkerCertificateChange::getCertificateType, req.getCertificateType()) + .orderByDesc(LabWorkerCertificateChange::getUpdateOn); + } + + public Boolean audit(LabWorkerCertificateAuditReq req, Long userId) { + return labWorkerCertificateService.audit(req, userId); + } + + public Boolean cancelAudit(LabWorkerCertificateAuditReq req, Long userId) { + return labWorkerCertificateService.cancelAudit(req, userId); + } + + public void delete(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(LabWorkerCertificate.class); + LabWorkerCertificateManage context = (LabWorkerCertificateManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + LabWorkerCertificate record = labWorkerCertificateService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法删除!"); + } + labWorkerCertificateService.removeById(id); + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(LabWorkerCertificate::getId,id); + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/MortarEnterpriseFilingCertificateManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/MortarEnterpriseFilingCertificateManage.java new file mode 100644 index 0000000..76b5073 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/MortarEnterpriseFilingCertificateManage.java @@ -0,0 +1,225 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificate; +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificateChange; +import com.ningdatech.carapi.industry.enums.AddTypeEnum; +import com.ningdatech.carapi.industry.model.dto.MortarEnterpriseFilingCertificateDTO; +import com.ningdatech.carapi.industry.model.dto.MortarEnterpriseFilingCertificateExportDto; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateListReq; +import com.ningdatech.carapi.industry.model.vo.MortarEnterpriseFilingCertificateChangeVO; +import com.ningdatech.carapi.industry.model.vo.MortarEnterpriseFilingCertificateVO; +import com.ningdatech.carapi.industry.service.IMortarEnterpriseFilingCertificateChangeService; +import com.ningdatech.carapi.industry.service.IMortarEnterpriseFilingCertificateService; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import lombok.AllArgsConstructor; + +/** + *

+ * MortarCompanyFilingCertificateManage + *

+ * + * @author WendyYang + * @since 21:16 2022/11/8 + */ +@Component +@AllArgsConstructor +public class MortarEnterpriseFilingCertificateManage { + + private final IMortarEnterpriseFilingCertificateService mortarEnterpriseFilingCertificateService; + + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + + private final IMortarEnterpriseFilingCertificateChangeService mortarEnterpriseFilingCertificateChangeService; + + public PageVo mortarEnterpriseFilingCertificateList(LabWorkerCertificateListReq req) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(MortarEnterpriseFilingCertificate.class); + MortarEnterpriseFilingCertificateManage context = (MortarEnterpriseFilingCertificateManage) AopContext.currentProxy(); + context.buildQuery(wrapper,req); + Page page = mortarEnterpriseFilingCertificateService.page(req.page(), wrapper); + if (page.getTotal() == 0) { + return PageVo.empty(); + } + List result = page.getRecords().stream().map(w -> { + MortarEnterpriseFilingCertificateVO vo = BeanUtil.copyProperties(w, MortarEnterpriseFilingCertificateVO.class); + vo.setProductionCapacity(w.getThroughput()); + vo.setRegionName(regionsCacheHelper.getDisplayName(w.getRegionId())); + vo.setValidDate(w.getValidDate()); + vo.setStandards(w.getStandards()); + CodeUtil.searchCompanyName(vo); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(result, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildQuery(LambdaQueryWrapper wrapper,LabWorkerCertificateListReq req) { + wrapper.ge(Objects.nonNull(req.getStartDate()), MortarEnterpriseFilingCertificate::getConferDate,req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()),MortarEnterpriseFilingCertificate::getConferDate,req.getEndDate()) + .like(StringUtils.isNotBlank(req.getCompanyName()),MortarEnterpriseFilingCertificate::getCompanyName,req.getCompanyName()) + .orderByDesc(MortarEnterpriseFilingCertificate::getUpdateOn); + } + + public void saveOrUpdate(MortarEnterpriseFilingCertificateDTO req) { + Long userId = LoginUserUtil.getUserId(); + Integer addType = req.getAddType(); + // 说明是新增证书 + if (AddTypeEnum.NEW.getCode().equals(addType)) { + MortarEnterpriseFilingCertificate mortarEnterpriseFilingCertificate = new MortarEnterpriseFilingCertificate(); + if (Objects.nonNull(req.getId())){ + // 说明为编辑 + mortarEnterpriseFilingCertificate.setId(req.getId()); + } + mortarEnterpriseFilingCertificate.setRegionId(req.getRegionId()); + mortarEnterpriseFilingCertificate.setCompanyId(req.getCompanyId()); + mortarEnterpriseFilingCertificate.setCompanyName(req.getCompanyName()); + mortarEnterpriseFilingCertificate.setRecordItem(req.getRecordItem()); + mortarEnterpriseFilingCertificate.setCertificateNo(req.getCertificateNo()); + mortarEnterpriseFilingCertificate.setConferDate(req.getConferDate()); + mortarEnterpriseFilingCertificate.setThroughput(req.getProductionCapacity()); + mortarEnterpriseFilingCertificate.setStandards(req.getStandards()); + mortarEnterpriseFilingCertificate.setRemark(req.getRemark()); + mortarEnterpriseFilingCertificate.setConferOrg(req.getConferOrg()); + + mortarEnterpriseFilingCertificate.setCreateOn(LocalDateTime.now()); + mortarEnterpriseFilingCertificate.setCreateBy(userId); + mortarEnterpriseFilingCertificate.setUpdateOn(LocalDateTime.now()); + mortarEnterpriseFilingCertificate.setUpdateBy(userId); + + mortarEnterpriseFilingCertificateService.saveOrUpdate(mortarEnterpriseFilingCertificate); + } else if (AddTypeEnum.REPLACE.getCode().equals(req.getAddType())) { + // 说明为换证 + MortarEnterpriseFilingCertificateChange mortarEnterpriseFilingCertificateChange = new MortarEnterpriseFilingCertificateChange(); + if (Objects.nonNull(req.getId())){ + // 说明为编辑 + mortarEnterpriseFilingCertificateChange.setId(req.getId()); + } + mortarEnterpriseFilingCertificateChange.setCompanyName(req.getCompanyName()); + mortarEnterpriseFilingCertificateChange.setRegionId(req.getRegionId()); + mortarEnterpriseFilingCertificateChange.setCompanyId(req.getCompanyId()); + mortarEnterpriseFilingCertificateChange.setCertificateNo(req.getCertificateNo()); + mortarEnterpriseFilingCertificateChange.setRecordItem(req.getRecordItem()); + mortarEnterpriseFilingCertificateChange.setReplacementTime(req.getReplaceDate()); + mortarEnterpriseFilingCertificateChange.setConferOrg(req.getConferOrg()); + mortarEnterpriseFilingCertificateChange.setRemark(req.getRemark()); + mortarEnterpriseFilingCertificateChange.setApplicationItem(req.getApplicationItem()); + mortarEnterpriseFilingCertificateChange.setApplicationReason(req.getApplicationReason()); + mortarEnterpriseFilingCertificateChange.setValidDate(req.getValidDate()); + mortarEnterpriseFilingCertificateChange.setStandards(req.getStandards()); + + mortarEnterpriseFilingCertificateChange.setCreateOn(LocalDateTime.now()); + mortarEnterpriseFilingCertificateChange.setCreateBy(userId); + mortarEnterpriseFilingCertificateChange.setUpdateOn(LocalDateTime.now()); + mortarEnterpriseFilingCertificateChange.setUpdateBy(userId); + mortarEnterpriseFilingCertificateChangeService.saveOrUpdate(mortarEnterpriseFilingCertificateChange); + } + } + + public void mortarEnterpriseFilingCertificateExport(HttpServletResponse response, LabWorkerCertificateListReq req) { + req.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = mortarEnterpriseFilingCertificateList(req); + List collect = page.getRecords().stream().map(w -> { + MortarEnterpriseFilingCertificateExportDto exportDto = new MortarEnterpriseFilingCertificateExportDto(); + BeanUtils.copyProperties(w, exportDto); + String conferDateStr = NdDateUtils.format(w.getConferDate(), NdDateUtils.DEFAULT_DATE_FORMAT); + exportDto.setConferDate(conferDateStr); + String validDateStr = NdDateUtils.format(w.getValidDate(), NdDateUtils.DEFAULT_DATE_FORMAT); + exportDto.setValidDate(validDateStr); + exportDto.setStandard(w.getStandards()); + return exportDto; + }).collect(Collectors.toList()); + String fileName = "砂浆企业备案证列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), MortarEnterpriseFilingCertificateExportDto.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public PageVo changeList(LabWorkerCertificateListReq req) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(MortarEnterpriseFilingCertificateChange.class); + MortarEnterpriseFilingCertificateManage context = (MortarEnterpriseFilingCertificateManage) AopContext.currentProxy(); + context.buildMortarEnterpriseFilingCertificateChangeListQuery(wrapper,req); + Page page = mortarEnterpriseFilingCertificateChangeService.page(req.page(), wrapper); + if (page.getTotal() == 0){ + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), w -> { + MortarEnterpriseFilingCertificateChangeVO resVo = BeanUtil.copyProperties(w, MortarEnterpriseFilingCertificateChangeVO.class); + resVo.setRegionName(regionsCacheHelper.getDisplayName(w.getRegionId())); + resVo.setReplaceDate(w.getReplacementTime()); + return resVo; + }); + return PageVo.of(data,page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildMortarEnterpriseFilingCertificateChangeListQuery(LambdaQueryWrapper wrapper, LabWorkerCertificateListReq req) { + wrapper.like(StrUtil.isNotBlank(req.getCompanyName()), MortarEnterpriseFilingCertificateChange::getCompanyName, req.getCompanyName()) + .ge(Objects.nonNull(req.getStartDate()),MortarEnterpriseFilingCertificateChange::getReplacementTime,req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()),MortarEnterpriseFilingCertificateChange::getReplacementTime,req.getEndDate()) + .orderByDesc(MortarEnterpriseFilingCertificateChange::getUpdateOn); + } + + public Boolean audit(LabWorkerCertificateAuditReq req, Long userId) { + return mortarEnterpriseFilingCertificateService.audit(req,userId); + } + + public void delete(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(MortarEnterpriseFilingCertificate.class); + MortarEnterpriseFilingCertificateManage context = (MortarEnterpriseFilingCertificateManage) AopContext.currentProxy(); + context.buildMortarQuery(wrapper, id); + MortarEnterpriseFilingCertificate record = mortarEnterpriseFilingCertificateService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法删除!"); + } + mortarEnterpriseFilingCertificateService.removeById(id); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildMortarQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(MortarEnterpriseFilingCertificate::getId,id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/OperatorAssessmentManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/OperatorAssessmentManage.java new file mode 100644 index 0000000..1ad56f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/OperatorAssessmentManage.java @@ -0,0 +1,246 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.industry.contants.CertificateContant; +import com.ningdatech.carapi.industry.entity.OperatorIndexScoreInfo; +import com.ningdatech.carapi.industry.entity.OperatorScoreInfo; +import com.ningdatech.carapi.industry.enums.OperatorAssessmentIndexEnum; +import com.ningdatech.carapi.industry.enums.QuarterEnum; +import com.ningdatech.carapi.industry.model.dto.OperatorAssessmentDTO; +import com.ningdatech.carapi.industry.model.dto.OperatorsAssessmentDetailsExportDTO; +import com.ningdatech.carapi.industry.model.vo.OperatorScoreDetailVO; +import com.ningdatech.carapi.industry.service.IOperatorIndexScoreInfoService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Operator; +import com.ningdatech.carapi.sys.service.IOperatorScoreInfoService; +import com.ningdatech.carapi.sys.service.OperatorService; + +import fr.opensagres.xdocreport.core.XDocReportException; +import fr.opensagres.xdocreport.document.IXDocReport; +import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; +import fr.opensagres.xdocreport.template.IContext; +import fr.opensagres.xdocreport.template.TemplateEngineKind; +import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/01/05 09:18 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class OperatorAssessmentManage { + + private final IOperatorScoreInfoService operatorScoreInfoService; + + private final IOperatorIndexScoreInfoService operatorIndexScoreInfoService; + + private final OperatorService operatorService; + + public OperatorScoreDetailVO getOperatorScore(OperatorAssessmentDTO data) { + OperatorScoreDetailVO operatorScoreDetailVO = new OperatorScoreDetailVO(); + Integer quarter = data.getQuarter(); + Long operatorId = data.getId(); + String year = data.getYear(); + LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(OperatorScoreInfo.class); + wrapper.eq(OperatorScoreInfo::getQuarter, quarter) + .eq(OperatorScoreInfo::getOperatorId, operatorId) + .eq(OperatorScoreInfo::getYear,year); + List operatorIndexScoreInfos = operatorIndexScoreInfoService.list(); + OperatorScoreInfo operatorScoreInfo = operatorScoreInfoService.getOne(wrapper); + assemblyOperatorIndexScore(operatorScoreDetailVO, operatorIndexScoreInfos); + if (Objects.isNull(operatorScoreInfo)){ + // 查询条件下没有该运营商的考核分数信息,各项分数默认显示满分 + log.info("未查询到运营商考核分数信息!"); + assemblyOperatorInitialScore(operatorScoreDetailVO,operatorIndexScoreInfos); + operatorScoreDetailVO.setTotalScore(TaskContant.Data.OPERATOR_ASSESSMENT_SCORE_HUNDRED); + return operatorScoreDetailVO; + } + assemblyOperatorScore(operatorScoreDetailVO, operatorScoreInfo); + return operatorScoreDetailVO; + } + + private void assemblyOperatorInitialScore(OperatorScoreDetailVO operatorScoreDetailVO,List operatorIndexScoreInfos) { + for (OperatorIndexScoreInfo operatorIndexScoreInfo : operatorIndexScoreInfos) { + switch (OperatorAssessmentIndexEnum.getEnumByValue(operatorIndexScoreInfo.getOperatorScoreIndex())) { + case UPLOAD_QUALIFICATION: + operatorScoreDetailVO.setUploadQualification(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case UPLOAD_FREQUENCY_QUANTITY: + operatorScoreDetailVO.setUploadFrequencyQuantity(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case FIELD_INTEGRITY: + operatorScoreDetailVO.setFieldIntegrity(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case TIME_SENSITIVE: + operatorScoreDetailVO.setTimeSensitive(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case POSITION_DIRECTION_CORRECTNESS_CONSISTENCY: + operatorScoreDetailVO.setPositionDirectionCorrectnessConsistency(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case SPEED_CORRECTNESS_CONSISTENCY: + operatorScoreDetailVO.setSpeedCorrectnessConsistency(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case TIME_CONSISTENCY: + operatorScoreDetailVO.setTimeConsistency(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + case POSITION_CONSISTENCY: + operatorScoreDetailVO.setPositionConsistency(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + break; + default: + throw new BizException("Unexpected value: " + operatorIndexScoreInfo.getOperatorScoreIndex()); + } + } + } + + private void assemblyOperatorIndexScore(OperatorScoreDetailVO operatorScoreDetailVO, List operatorIndexScoreInfos) { + for (OperatorIndexScoreInfo operatorIndexScoreInfo : operatorIndexScoreInfos) { + switch (OperatorAssessmentIndexEnum.getEnumByValue(operatorIndexScoreInfo.getOperatorScoreIndex())){ + case UPLOAD_QUALIFICATION: + operatorScoreDetailVO.setUploadQualificationIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setUploadQualificationName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case UPLOAD_FREQUENCY_QUANTITY: + operatorScoreDetailVO.setUploadFrequencyQuantityIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setUploadFrequencyQuantityName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case FIELD_INTEGRITY: + operatorScoreDetailVO.setFieldIntegrityIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setFieldIntegrityName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case TIME_SENSITIVE: + operatorScoreDetailVO.setTimeSensitiveIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setTimeSensitiveName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case POSITION_DIRECTION_CORRECTNESS_CONSISTENCY: + operatorScoreDetailVO.setPositionDirectionCorrectnessConsistencyIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setPositionDirectionCorrectnessConsistencyName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case SPEED_CORRECTNESS_CONSISTENCY: + operatorScoreDetailVO.setSpeedCorrectnessConsistencyIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setSpeedCorrectnessConsistencyName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case TIME_CONSISTENCY: + operatorScoreDetailVO.setTimeConsistencyIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setTimeConsistencyName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + case POSITION_CONSISTENCY: + operatorScoreDetailVO.setPositionConsistencyIndex(operatorIndexScoreInfo.getOperatorScoreIndexScore()); + operatorScoreDetailVO.setPositionConsistencyName(operatorIndexScoreInfo.getOperatorScoreIndexName()); + break; + default: + throw new BizException("Unexpected value: " + operatorIndexScoreInfo.getOperatorScoreIndex()); + } + } + } + + private void assemblyOperatorScore(OperatorScoreDetailVO operatorScoreDetailVO, OperatorScoreInfo operatorScoreInfo) { + Integer score = operatorScoreInfo.getUploadQualification(); + operatorScoreDetailVO.setUploadQualification(score); + Integer score2 = operatorScoreInfo.getUploadFrequencyQuantity(); + operatorScoreDetailVO.setUploadFrequencyQuantity(score2); + Integer score3 = operatorScoreInfo.getFieldIntegrity(); + operatorScoreDetailVO.setFieldIntegrity(score3); + Integer score4 = operatorScoreInfo.getTimeSensitive(); + operatorScoreDetailVO.setTimeSensitive(score4); + Integer score5 = operatorScoreInfo.getPositionDirectionCorrectnessConsistency(); + operatorScoreDetailVO.setPositionDirectionCorrectnessConsistency(score5); + Integer score6 = operatorScoreInfo.getSpeedCorrectnessConsistency(); + operatorScoreDetailVO.setSpeedCorrectnessConsistency(score6); + Integer score7 = operatorScoreInfo.getTimeConsistency(); + operatorScoreDetailVO.setTimeConsistency(score7); + Integer score8 = operatorScoreInfo.getPositionConsistency(); + operatorScoreDetailVO.setPositionConsistency(score8); + int totalScore = score + score2 + score3 + score4 + score5 + score6 + score7 + score8; + operatorScoreDetailVO.setTotalScore(totalScore); + } + + public void exportDocx(HttpServletResponse response, OperatorAssessmentDTO data) { + OperatorScoreDetailVO operatorScore = getOperatorScore(data); + Operator operator = operatorService.getById(data.getId()); + InputStream in = null; + String fileName = "运营商考核详情"; + try { + //获取本地目录的word模板 + in = this.getClass().getClassLoader().getResourceAsStream("template/" + fileName + ".docx"); + //注册xdocreport实例并加载FreeMarker模板引擎 + IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker); + //创建xdocreport上下文对象 + IContext context = report.createContext(); + + List oadList = new ArrayList<>(); + oadList.add(new OperatorsAssessmentDetailsExportDTO("1",OperatorAssessmentIndexEnum.UPLOAD_QUALIFICATION.getDesc(),CertificateContant.ScoringRubric.UPLOAD_QUALIFICATION_SCORING_RUBRIC,String.valueOf(operatorScore.getUploadQualificationIndex()),String.valueOf(operatorScore.getUploadQualification()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("2",OperatorAssessmentIndexEnum.UPLOAD_FREQUENCY_QUANTITY.getDesc(),CertificateContant.ScoringRubric.UPLOAD_FREQUENCY_QUANTITY_SCORING_RUBRIC,String.valueOf(operatorScore.getUploadFrequencyQuantityIndex()),String.valueOf(operatorScore.getUploadFrequencyQuantity()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("3",OperatorAssessmentIndexEnum.FIELD_INTEGRITY.getDesc(),CertificateContant.ScoringRubric.FIELD_INTEGRITY_SCORING_RUBRIC,String.valueOf(operatorScore.getFieldIntegrityIndex()),String.valueOf(operatorScore.getFieldIntegrity()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("4",OperatorAssessmentIndexEnum.TIME_SENSITIVE.getDesc(),CertificateContant.ScoringRubric.TIME_SENSITIVE_SCORING_RUBRIC,String.valueOf(operatorScore.getTimeSensitiveIndex()),String.valueOf(operatorScore.getTimeSensitive()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("5",OperatorAssessmentIndexEnum.POSITION_DIRECTION_CORRECTNESS_CONSISTENCY.getDesc(),CertificateContant.ScoringRubric.POSITION_DIRECTION_CORRECTNESS_CONSISTENCY_SCORING_RUBRIC,String.valueOf(operatorScore.getPositionDirectionCorrectnessConsistencyIndex()),String.valueOf(operatorScore.getPositionDirectionCorrectnessConsistency()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("6",OperatorAssessmentIndexEnum.SPEED_CORRECTNESS_CONSISTENCY.getDesc(),CertificateContant.ScoringRubric.SPEED_CORRECTNESS_CONSISTENCY_SCORING_RUBRIC,String.valueOf(operatorScore.getSpeedCorrectnessConsistencyIndex()),String.valueOf(operatorScore.getSpeedCorrectnessConsistency()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("7",OperatorAssessmentIndexEnum.TIME_CONSISTENCY.getDesc(),CertificateContant.ScoringRubric.TIME_CONSISTENCY_SCORING_RUBRIC,String.valueOf(operatorScore.getTimeConsistencyIndex()),String.valueOf(operatorScore.getTimeConsistency()))); + oadList.add(new OperatorsAssessmentDetailsExportDTO("8",OperatorAssessmentIndexEnum.POSITION_CONSISTENCY.getDesc(),CertificateContant.ScoringRubric.POSITION_CONSISTENCY_SCORING_RUBRIC,String.valueOf(operatorScore.getPositionConsistencyIndex()),String.valueOf(operatorScore.getPositionConsistency()))); + //将需要替换的数据数据添加到上下文中 + //其中key为word模板中的域名,value是需要替换的值 + context.put("operatorName",operator.getName()); + context.put("date", data.getYear() + "-" + QuarterEnum.getDescByCode(data.getQuarter())); + context.put("oadList",oadList); + context.put("totalScore",operatorScore.getTotalScore()); + + //创建字段元数据,需要表格才加下面这两行,否则不用 + FieldsMetadata fm = report.createFieldsMetadata(); + //Word模板中的表格数据对应的集合类型 + fm.load("oadList", OperatorsAssessmentDetailsExportDTO.class, true); + + // 将结果写入流中,供前端下载 + try { + response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodeName(fileName) + ".docx"); + OutputStream out = response.getOutputStream(); + //处理word文档并输出 + report.process(context, out); + response.flushBuffer(); + } catch (IOException e) { + log.error("流错误!"); + } + } catch (IOException e) { + log.error("读取Word模板异常",e); + } catch (XDocReportException e) { + log.error("word模板生成失败",e); + } finally { + if(in!=null){ + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + private static String encodeName(String name) { + String fileName; + try { + fileName = URLEncoder.encode(name, "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.error("文件名编码异常:", e); + fileName = UUID.randomUUID().toString().replace("-", ""); + } + return fileName; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PassportManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PassportManage.java new file mode 100644 index 0000000..f98d947 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PassportManage.java @@ -0,0 +1,181 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.PassportInfo; +import com.ningdatech.carapi.industry.model.dto.PassportExportDTO; +import com.ningdatech.carapi.industry.model.dto.PassportPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.PassportSaveDTO; +import com.ningdatech.carapi.industry.model.dto.PassportUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.PassportVO; +import com.ningdatech.carapi.industry.service.IPassportInfoService; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname PassportManage + * @Description + * @Date 2022/11/3 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class PassportManage { + + private final IPassportInfoService passportInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + + public PageVo infoList(PassportPageParamDTO param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PassportInfo.class); + PassportManage context = (PassportManage) AopContext.currentProxy(); + context.search(page,wrapper,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public PassportVO details(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PassportInfo.class); + PassportManage context = (PassportManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + PassportInfo record = passportInfoService.getOne(wrapper); + if (Objects.isNull(record)){ + return null; + } + //PassportInfo record = passportInfoService.getById(id); + + return convert(record); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(PassportInfo::getId,id); + } + + /** + * 查询 + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void search(Page page,LambdaQueryWrapper wrapper,PassportPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), PassportInfo::getCompanyName, param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getCarPlate()), PassportInfo::getCarPlate, param.getCarPlate()) + .eq(Objects.nonNull(param.getVehicleType()), PassportInfo::getVehicleType, param.getVehicleType()) + .ge(Objects.nonNull(param.getStartTime()), PassportInfo::getExpirationDate, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), PassportInfo::getExpirationDate, param.getEndTime()) + .orderBy(Boolean.TRUE,Boolean.FALSE, PassportInfo::getUpdateOn); + passportInfoService.page(page, wrapper); + } + + private PassportVO convert(PassportInfo passport) { + if(Objects.isNull(passport)){ + return null; + } + PassportVO vo = BeanUtil.copyProperties(passport, PassportVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + + public PassportVO save(PassportSaveDTO passportSave, Long userId) { + PassportInfo passportInfo = BeanUtil.copyProperties(passportSave, PassportInfo.class); + CodeUtil.searchCompanyNameAndRegionName(passportInfo); + if(Objects.nonNull(passportSave.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(passportSave.getVehicleType())).ifPresent(v -> + passportInfo.setVehicleTypeName(v)); + + } + passportInfo.setCreateBy(userId); + passportInfo.setUpdateBy(userId); + passportInfoService.save(passportInfo); + return BeanUtil.copyProperties(passportInfo, PassportVO.class); + } + + public PassportVO modify(PassportUpdateDTO passportUpdate, Long userId) { + PassportInfo passportInfo = BeanUtil.copyProperties(passportUpdate, PassportInfo.class); + CodeUtil.searchCompanyNameAndRegionName(passportInfo); + if(Objects.nonNull(passportUpdate.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(passportUpdate.getVehicleType())).ifPresent(v -> + passportInfo.setVehicleTypeName(v)); + } + passportInfo.setUpdateBy(userId); + passportInfoService.updateById(passportInfo); + return BeanUtil.copyProperties(passportInfo, PassportVO.class); + } + + public Boolean remove(Long id, Long userId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PassportInfo.class); + PassportManage context = (PassportManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + PassportInfo record = passportInfoService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法删除!"); + } + passportInfoService.removeById(id); + return Boolean.TRUE; + } + + public void infoListExport(HttpServletResponse response, PassportPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = infoList(param); + List collect = page.getRecords().stream().map(r -> { + PassportExportDTO exportDTO = new PassportExportDTO(); + BeanUtils.copyProperties(r, exportDTO); + String expirationDateStr = NdDateUtils.format(r.getExpirationDate(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + exportDTO.setExpirationDate(expirationDateStr); + return exportDTO; + }).collect(Collectors.toList()); + String fileName = "通行证证书列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), PassportExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseOilManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseOilManage.java new file mode 100644 index 0000000..270f982 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseOilManage.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.industry.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.entity.PurchaseOil; +import com.ningdatech.carapi.industry.model.req.PurchaseOilListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseOilListVo; +import com.ningdatech.carapi.industry.service.IPurchaseOilService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.AllArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + *

+ * PurchaseOilManage + *

+ * + * @author WendyYang + * @since 14:09 2022/11/9 + */ +@Component +@AllArgsConstructor +public class PurchaseOilManage { + + private final RegionsCacheHelper regionsCacheHelper; + private final IPurchaseOilService purchaseOilService; + + public PageVo purchaseOilList(PurchaseOilListReq req) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PurchaseOil.class); + PurchaseOilManage context = (PurchaseOilManage) AopContext.currentProxy(); + context.buildQuery(wrapper,req); + Page page = purchaseOilService.page(req.page(), wrapper); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> { + PurchaseOilListVo vo = BeanUtil.copyProperties(w, PurchaseOilListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + @LambdaDataScope + public void buildQuery(LambdaQueryWrapper wrapper,PurchaseOilListReq req) { + wrapper.in(Objects.nonNull(req.getRegionId()),PurchaseOil::getRegionId, regionsCacheHelper.listChildRegionId(req.getRegionId())) + .like(StrUtil.isNotBlank(req.getOilName()),PurchaseOil::getOilName, req.getOilName()) + .like(StrUtil.isNotBlank(req.getPurchaseOrg()),PurchaseOil::getPurchaseOrg, req.getPurchaseOrg()) + .ge(Objects.nonNull(req.getStartDate()),PurchaseOil::getPurchaseDate, req.getStartDate()) + .le(Objects.nonNull(req.getEndDate()),PurchaseOil::getPurchaseDate, req.getEndDate()) + .orderByDesc(PurchaseOil::getUpdateOn); + } + + public void saveOrUpdate(PurchaseOilListVo req) { + PurchaseOil oil = BeanUtil.copyProperties(req, PurchaseOil.class); + oil.setUpdateBy(LoginUserUtil.getUserId()); + if (Objects.isNull(oil.getId())) { + oil.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + oil.setCreateBy(oil.getUpdateBy()); + } + purchaseOilService.saveOrUpdate(oil); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseRawMaterialManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseRawMaterialManage.java new file mode 100644 index 0000000..c4f469c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseRawMaterialManage.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.industry.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.entity.PurchaseRawMaterial; +import com.ningdatech.carapi.industry.model.req.PurchaseRawMaterialListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseRawMaterialListVo; +import com.ningdatech.carapi.industry.service.IPurchaseRawMaterialService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.AllArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * PurchaseRawMaterialManage + *

+ * + * @author WendyYang + * @since 10:51 2022/11/9 + */ +@Component +@AllArgsConstructor +public class PurchaseRawMaterialManage { + + private final IPurchaseRawMaterialService purchaseRawMaterialService; + private final RegionsCacheHelper regionsCacheHelper; + + public PageVo list(PurchaseRawMaterialListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(PurchaseRawMaterial.class); + PurchaseRawMaterialManage context = (PurchaseRawMaterialManage) AopContext.currentProxy(); + context.buildQuery(query,req); + Page page = purchaseRawMaterialService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> { + PurchaseRawMaterialListVo vo = BeanUtil.copyProperties(w, PurchaseRawMaterialListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + @LambdaDataScope + public void buildQuery(LambdaQueryWrapper query,PurchaseRawMaterialListReq req) { + if (null != req.getRegionId()) { + query.in(PurchaseRawMaterial::getRegionId, regionsCacheHelper.listChildRegionId(req.getRegionId())); + } + if (StrUtil.isNotBlank(req.getRawMaterialName())) { + query.like(PurchaseRawMaterial::getRawMaterialName, req.getRawMaterialName()); + } + if (StrUtil.isNotBlank(req.getPurchaseOrg())) { + query.like(PurchaseRawMaterial::getPurchaseOrg, req.getPurchaseOrg()); + } + if (StrUtil.isNotBlank(req.getModel())) { + query.like(PurchaseRawMaterial::getModel, req.getModel()); + } + if (req.getStartDate() != null) { + query.ge(PurchaseRawMaterial::getPurchaseDate, req.getStartDate()); + } + if (req.getEndDate() != null) { + query.le(PurchaseRawMaterial::getPurchaseDate, req.getEndDate()); + } + query.orderByDesc(PurchaseRawMaterial::getUpdateOn); + } + + public void saveOrUpdate(PurchaseRawMaterialListVo req) { + PurchaseRawMaterial entity = BeanUtil.copyProperties(req, PurchaseRawMaterial.class); + entity.setUpdateBy(LoginUserUtil.getUserId()); + if (entity.getId() == null) { + entity.setCreateBy(entity.getUpdateBy()); + entity.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + } + purchaseRawMaterialService.saveOrUpdate(entity); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseVehicleManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseVehicleManage.java new file mode 100644 index 0000000..e8dfc4f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseVehicleManage.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.industry.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.entity.PurchaseVehicle; +import com.ningdatech.carapi.industry.model.req.PurchaseVehicleListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseVehicleListVo; +import com.ningdatech.carapi.industry.service.IPurchaseVehicleService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.AllArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * PurchaseVehicleManage + *

+ * + * @author WendyYang + * @since 14:09 2022/11/9 + */ +@Component +@AllArgsConstructor +public class PurchaseVehicleManage { + + private final RegionsCacheHelper regionsCacheHelper; + private final IPurchaseVehicleService purchaseVehicleService; + + public PageVo purchaseWheelList(PurchaseVehicleListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(PurchaseVehicle.class); + PurchaseVehicleManage context = (PurchaseVehicleManage) AopContext.currentProxy(); + context.buildQuery(query,req); + Page page = purchaseVehicleService.page(req.page(), query); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> { + PurchaseVehicleListVo vo = BeanUtil.copyProperties(w, PurchaseVehicleListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + @LambdaDataScope + public void buildQuery(LambdaQueryWrapper query,PurchaseVehicleListReq req) { + if (null != req.getRegionId()) { + query.in(PurchaseVehicle::getRegionId, regionsCacheHelper.listChildRegionId(req.getRegionId())); + } + if (StrUtil.isNotBlank(req.getVehicleType())) { + query.like(PurchaseVehicle::getVehicleType, req.getVehicleType()); + } + if (StrUtil.isNotBlank(req.getPurchaseOrg())) { + query.like(PurchaseVehicle::getPurchaseOrg, req.getPurchaseOrg()); + } + if (req.getStartDate() != null) { + query.ge(PurchaseVehicle::getPurchaseDate, req.getStartDate()); + } + if (req.getEndDate() != null) { + query.le(PurchaseVehicle::getPurchaseDate, req.getEndDate()); + } + query.orderByDesc(PurchaseVehicle::getUpdateOn); + } + + public void saveOrUpdate(PurchaseVehicleListVo req) { + PurchaseVehicle vehicle = BeanUtil.copyProperties(req, PurchaseVehicle.class); + vehicle.setUpdateBy(LoginUserUtil.getUserId()); + if (vehicle.getId() == null) { + vehicle.setCreateBy(vehicle.getUpdateBy()); + vehicle.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + } + purchaseVehicleService.saveOrUpdate(vehicle); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseWheelManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseWheelManage.java new file mode 100644 index 0000000..8ab6869 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/PurchaseWheelManage.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.industry.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.entity.PurchaseWheel; +import com.ningdatech.carapi.industry.model.req.PurchaseWheelListReq; +import com.ningdatech.carapi.industry.model.vo.PurchaseWheelListVo; +import com.ningdatech.carapi.industry.service.IPurchaseWheelService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.AllArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * PurchaseOilManage + *

+ * + * @author WendyYang + * @since 14:09 2022/11/9 + */ +@Component +@AllArgsConstructor +public class PurchaseWheelManage { + + private final RegionsCacheHelper regionsCacheHelper; + private final IPurchaseWheelService purchaseWheelService; + + public PageVo purchaseWheelList(PurchaseWheelListReq req) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(PurchaseWheel.class); + PurchaseWheelManage context = (PurchaseWheelManage) AopContext.currentProxy(); + context.buildQuery(query,req); + Page page = purchaseWheelService.page(req.page(), query); + if (page.getTotal() == 0) { + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> { + PurchaseWheelListVo vo = BeanUtil.copyProperties(w, PurchaseWheelListVo.class); + vo.setRegions(regionsCacheHelper.listParents(w.getRegionId())); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + @LambdaDataScope + public void buildQuery(LambdaQueryWrapper query,PurchaseWheelListReq req) { + if (null != req.getRegionId()) { + query.in(PurchaseWheel::getRegionId, regionsCacheHelper.listChildRegionId(req.getRegionId())); + } + if (StrUtil.isNotBlank(req.getWheelType())) { + query.like(PurchaseWheel::getWheelType, req.getWheelType()); + } + if (StrUtil.isNotBlank(req.getPurchaseOrg())) { + query.like(PurchaseWheel::getPurchaseOrg, req.getPurchaseOrg()); + } + if (req.getStartDate() != null) { + query.ge(PurchaseWheel::getPurchaseDate, req.getStartDate()); + } + if (req.getEndDate() != null) { + query.le(PurchaseWheel::getPurchaseDate, req.getEndDate()); + } + query.orderByDesc(PurchaseWheel::getUpdateOn); + } + + public void saveOrUpdate(PurchaseWheelListVo req) { + PurchaseWheel wheel = BeanUtil.copyProperties(req, PurchaseWheel.class); + wheel.setUpdateBy(LoginUserUtil.getUserId()); + if (wheel.getId() == null) { + wheel.setCreateBy(wheel.getUpdateBy()); + wheel.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + } + purchaseWheelService.saveOrUpdate(wheel); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/ReadyMixedMortarManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/ReadyMixedMortarManage.java new file mode 100644 index 0000000..1be5c6d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/ReadyMixedMortarManage.java @@ -0,0 +1,189 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.ReadyMixedMortarIndustryManage; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedMortarIndustryManageSaveDTO; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedMortarIndustryManageUpdateDTO; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedPageParamDTO; +import com.ningdatech.carapi.industry.model.vo.ReadyMixedMortarIndustryManageVO; +import com.ningdatech.carapi.industry.service.IReadyMixedMortarIndustryManageService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname ReadyMixedMortarManage + * @Description + * @Date 2022/11/17 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class ReadyMixedMortarManage { + + private final IReadyMixedMortarIndustryManageService readyMixedMortarIndustryManageService; + private final RegionsCacheHelper regionsCacheHelper; + + public PageVo list(ReadyMixedPageParamDTO param) { + + //Page page = param.page(); + + Integer pageNumber = param.getPageNumber(); + Integer pageSize = param.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ReadyMixedMortarIndustryManage.class); + //ReadyMixedMortarManage context = (ReadyMixedMortarManage) AopContext.currentProxy(); + //context.buildWrapper(wrapper,param); + + wrapper.like(StringUtils.isNotBlank(param.getTitle()), ReadyMixedMortarIndustryManage::getTitle, param.getTitle()) + .isNotNull(ReadyMixedMortarIndustryManage::getRegionId) + .orderBy(Boolean.TRUE, Boolean.FALSE, ReadyMixedMortarIndustryManage::getUpdateOn); + List resultList = readyMixedMortarIndustryManageService.dataScopeList(wrapper,param); + //List resultList = readyMixedMortarIndustryManageService.list(wrapper); + + // 省级部门上传的文件(所属区域为省级),下级账号也要能看到 + List list = readyMixedMortarIndustryManageService + .list(Wrappers.lambdaQuery(ReadyMixedMortarIndustryManage.class) + .eq(ReadyMixedMortarIndustryManage::getRegionId, DefValConstants.ZJREGION_ID)); + resultList.addAll(list); + + if (CollUtil.isEmpty(resultList)) { + return PageVo.empty(); + } + + List records = resultList.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + List data = records.stream().map(this::convert).collect(Collectors.toList()); + return PageVo.of(data, resultList.size()); + + //context.search(page, wrapper, param); + //if (CollUtil.isEmpty(page.getRecords())) { + // return PageVo.empty(); + //} + //List data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList()); + //return PageVo.of(data, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + private void buildWrapper(LambdaQueryWrapper wrapper, ReadyMixedPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getTitle()), ReadyMixedMortarIndustryManage::getTitle, param.getTitle()) + .isNotNull(ReadyMixedMortarIndustryManage::getRegionId) + .orderBy(Boolean.TRUE, Boolean.FALSE, ReadyMixedMortarIndustryManage::getUpdateOn); + } + + public ReadyMixedMortarIndustryManageVO details(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ReadyMixedMortarIndustryManage.class); + ReadyMixedMortarManage context = (ReadyMixedMortarManage) AopContext.currentProxy(); + context.buildStandardFileQuery(wrapper, id); + ReadyMixedMortarIndustryManage record = readyMixedMortarIndustryManageService.getOne(wrapper); + if (Objects.isNull(record)){ + return null; + } + // ReadyMixedMortarIndustryManage record = readyMixedMortarIndustryManageService.getById(id); + return convert(record); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildStandardFileQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(ReadyMixedMortarIndustryManage::getId,id); + } + + /** + * 查询 + * + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1, entityIndex = 2) + public void search(Page page, LambdaQueryWrapper wrapper, ReadyMixedPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getTitle()), ReadyMixedMortarIndustryManage::getTitle, param.getTitle()) + .orderBy(Boolean.TRUE, Boolean.FALSE, ReadyMixedMortarIndustryManage::getUpdateOn); + readyMixedMortarIndustryManageService.page(page, wrapper); + } + + private ReadyMixedMortarIndustryManageVO convert(ReadyMixedMortarIndustryManage data) { + if (Objects.isNull(data)) { + return null; + } + ReadyMixedMortarIndustryManageVO vo = BeanUtil.copyProperties(data, ReadyMixedMortarIndustryManageVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + + public ReadyMixedMortarIndustryManageVO save(ReadyMixedMortarIndustryManageSaveDTO data, UserInfoDetails user) { + ReadyMixedMortarIndustryManage record = BeanUtil.copyProperties(data, ReadyMixedMortarIndustryManage.class); + Long regionId = user.getRegionId(); + Long companyId = user.getCompanyId(); + record.setRegionId(regionId); + record.setCompanyId(companyId); + CodeUtil.searchCompanyNameAndRegionName(record); + record.setCreateBy(user.getUserId()); + record.setUpdateBy(user.getUserId()); + readyMixedMortarIndustryManageService.save(record); + return BeanUtil.copyProperties(record, ReadyMixedMortarIndustryManageVO.class); + } + + public ReadyMixedMortarIndustryManageVO modify(ReadyMixedMortarIndustryManageUpdateDTO data, UserInfoDetails user) { + ReadyMixedMortarIndustryManage record = BeanUtil.copyProperties(data, ReadyMixedMortarIndustryManage.class); + CodeUtil.searchCompanyNameAndRegionName(record); + record.setUpdateBy(user.getUserId()); + readyMixedMortarIndustryManageService.updateById(record); + return BeanUtil.copyProperties(record, ReadyMixedMortarIndustryManageVO.class); + } + + public Boolean remove(Long id, UserInfoDetails user) { + readyMixedMortarIndustryManageService.removeById(id); + return Boolean.TRUE; + } + + public void export(HttpServletResponse response, ReadyMixedPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = list(param); + Collection collect = page.getRecords(); + String fileName = "预拌砂浆行业管理信息"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), ReadyMixedMortarIndustryManageVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/RegistrationRecordManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/RegistrationRecordManage.java new file mode 100644 index 0000000..43c5de5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/RegistrationRecordManage.java @@ -0,0 +1,169 @@ +package com.ningdatech.carapi.industry.manage; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.RegistrationRecord; +import com.ningdatech.carapi.industry.model.dto.RegistrationRecordPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.RegistrationRecordSaveDTO; +import com.ningdatech.carapi.industry.model.dto.RegistrationRecordUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.RegistrationRecordVO; +import com.ningdatech.carapi.industry.service.IRegistrationRecordService; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname RegistrationRecordManage + * @Description + * @Date 2022/11/06 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class RegistrationRecordManage { + + private final IRegistrationRecordService registrationRecordService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + public PageVo infoList(RegistrationRecordPageParamDTO param) { + Page page = param.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + param.setCarPlateList(carPlateList); + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RegistrationRecord.class); + RegistrationRecordManage context = (RegistrationRecordManage) AopContext.currentProxy(); + context.search(page,wrapper,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.empty(); + } + List data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public RegistrationRecordVO details(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RegistrationRecord.class); + RegistrationRecordManage context = (RegistrationRecordManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + RegistrationRecord record = registrationRecordService.getOne(wrapper); + if (Objects.isNull(record)){ + return null; + } + //RegistrationRecord record = registrationRecordService.getById(id); + return convert(record); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(RegistrationRecord::getId,id); + } + + + /** + * 查询 + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void search(Page page,LambdaQueryWrapper wrapper,RegistrationRecordPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), RegistrationRecord::getCompanyName, param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getCarPlate()), RegistrationRecord::getCarPlate, param.getCarPlate()) + .like(StringUtils.isNotBlank(param.getRegistrationRecord()), RegistrationRecord::getRegistrationRecord, param.getRegistrationRecord()) + .eq(Objects.nonNull(param.getVehicleType()), RegistrationRecord::getVehicleType, param.getVehicleType()) + .in(CollUtil.isNotEmpty(param.getCarPlateList()),RegistrationRecord::getCarPlate,param.getCarPlateList()) + .orderBy(Boolean.TRUE,Boolean.FALSE, RegistrationRecord::getUpdateOn); + registrationRecordService.page(page, wrapper); + } + + private RegistrationRecordVO convert(RegistrationRecord record) { + if(Objects.isNull(record)){ + return null; + } + RegistrationRecordVO vo = BeanUtil.copyProperties(record, RegistrationRecordVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + + public RegistrationRecordVO save(RegistrationRecordSaveDTO data, Long userId) { + RegistrationRecord record = BeanUtil.copyProperties(data, RegistrationRecord.class); + CodeUtil.searchCompanyNameAndRegionName(record); + if(Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(v -> + record.setVehicleTypeName(v)); + } + record.setCreateBy(userId); + record.setUpdateBy(userId); + registrationRecordService.save(record); + return BeanUtil.copyProperties(record, RegistrationRecordVO.class); + } + + public RegistrationRecordVO modify(RegistrationRecordUpdateDTO data, Long userId) { + RegistrationRecord record = BeanUtil.copyProperties(data, RegistrationRecord.class); + CodeUtil.searchCompanyNameAndRegionName(record); + if(Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(v -> + record.setVehicleTypeName(v)); + } + record.setUpdateBy(userId); + registrationRecordService.updateById(record); + return BeanUtil.copyProperties(record, RegistrationRecordVO.class); + } + + public Boolean remove(Long id, Long userId) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(RegistrationRecord.class); + RegistrationRecordManage context = (RegistrationRecordManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + RegistrationRecord record = registrationRecordService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法删除!"); + } + + registrationRecordService.removeById(id); + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentInstallUseCertificateOperationManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentInstallUseCertificateOperationManage.java new file mode 100644 index 0000000..41679a4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentInstallUseCertificateOperationManage.java @@ -0,0 +1,134 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificateOperation; +import com.ningdatech.carapi.industry.model.dto.UseCertOperatePageParamDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertOperateUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.DriverTrainingCertificateVO; +import com.ningdatech.carapi.industry.model.vo.SafetyEquipmentInstallUseCertificateOperationVO; +import com.ningdatech.carapi.industry.service.ISafetyEquipmentInstallUseCertificateOperationService; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description + * @since 2022/11/26 17:02 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class SafetyEquipmentInstallUseCertificateOperationManage { + + private final ISafetyEquipmentInstallUseCertificateOperationService safetyEquipmentInstallUseCertificateOperationService; + + public PageVo list(UseCertOperatePageParamDTO param) { + Page page = param.page(); + LambdaQueryWrapper wrapper + = Wrappers.lambdaQuery(SafetyEquipmentInstallUseCertificateOperation.class); + SafetyEquipmentInstallUseCertificateOperationManage context + = (SafetyEquipmentInstallUseCertificateOperationManage) AopContext.currentProxy(); + context.buildQuery(page,wrapper,param); + if (CollectionUtil.isEmpty(page.getRecords())){ + return PageVo.empty(); + } + List data + = page.getRecords().stream().map(o -> convert(o)).collect(Collectors.toList()); + return PageVo.of(data,page.getTotal()); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void buildQuery(Page page, LambdaQueryWrapper wrapper, UseCertOperatePageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()),SafetyEquipmentInstallUseCertificateOperation::getCompanyName,param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getCarPlate()),SafetyEquipmentInstallUseCertificateOperation::getCarPlate,param.getCarPlate()) + .eq(Objects.nonNull(param.getVehicleType()),SafetyEquipmentInstallUseCertificateOperation::getVehicleType,param.getVehicleType()) + .eq(Objects.nonNull(param.getAnnualStatus()),SafetyEquipmentInstallUseCertificateOperation::getYearCheckStatus,param.getAnnualStatus()) + .eq(Objects.nonNull(param.getApplicationItem()),SafetyEquipmentInstallUseCertificateOperation::getApplicationItem,param.getApplicationItem()); + safetyEquipmentInstallUseCertificateOperationService.page(page,wrapper); + } + + private SafetyEquipmentInstallUseCertificateOperationVO convert(SafetyEquipmentInstallUseCertificateOperation certificateOperation) { + SafetyEquipmentInstallUseCertificateOperationVO vo = BeanUtil.copyProperties(certificateOperation, SafetyEquipmentInstallUseCertificateOperationVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + public SafetyEquipmentInstallUseCertificateOperationVO details(Long id) { + SafetyEquipmentInstallUseCertificateOperation resVo = safetyEquipmentInstallUseCertificateOperationService.getById(id); + return convert(resVo); + } + + public SafetyEquipmentInstallUseCertificateOperationVO modify(UseCertOperateUpdateDTO data, Long userId) { + SafetyEquipmentInstallUseCertificateOperation certificateOperation = BeanUtil.copyProperties(data, SafetyEquipmentInstallUseCertificateOperation.class); + CodeUtil.searchCompanyNameAndRegionName(certificateOperation); + if (Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(v -> + certificateOperation.setVehicleTypeName(v)); + } + if (Objects.nonNull(data.getYearCheckStatus())){ + Optional.ofNullable(data.getYearCheckStatus()).ifPresent(y -> + certificateOperation.setYearCheckStatus(y)); + + } + if (Objects.nonNull(data.getReplacementStatus())){ + Optional.ofNullable(data.getReplacementStatus()).ifPresent(r -> + certificateOperation.setReplacementStatus(r)); + + } + + certificateOperation.setUpdateBy(userId); + safetyEquipmentInstallUseCertificateOperationService.updateById(certificateOperation); + return BeanUtil.copyProperties(certificateOperation,SafetyEquipmentInstallUseCertificateOperationVO.class); + } + + public Boolean remove(Long id, Long userId) { + safetyEquipmentInstallUseCertificateOperationService.removeById(id); + return Boolean.TRUE; + } + + public void infoListExport(HttpServletResponse response, UseCertOperatePageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = list(param); + Collection collect = page.getRecords(); + String fileName = "安全设备安装使用证书列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), SafetyEquipmentInstallUseCertificateOperationVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentIntallUserCertificateManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentIntallUserCertificateManage.java new file mode 100644 index 0000000..0064043 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/manage/SafetyEquipmentIntallUserCertificateManage.java @@ -0,0 +1,173 @@ +package com.ningdatech.carapi.industry.manage; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificate; +import com.ningdatech.carapi.industry.model.dto.SafetyEqInsUseCertExportDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertPageParamDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertSaveDTO; +import com.ningdatech.carapi.industry.model.dto.UseCertUpdateDTO; +import com.ningdatech.carapi.industry.model.vo.SafetyEquipmentInstallUseCertificateVO; +import com.ningdatech.carapi.industry.service.ISafetyEquipmentInstallUseCertificateService; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname SafetyEquipmentIntallUserCertificateManage + * @Description + * @Date 2022/11/3 17:57 + * @Created by PoffyZhang + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class SafetyEquipmentIntallUserCertificateManage { + + private final ISafetyEquipmentInstallUseCertificateService safetyEquipmentInstallUseCertificateService; + + public PageVo list(UseCertPageParamDTO param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(SafetyEquipmentInstallUseCertificate.class); + SafetyEquipmentIntallUserCertificateManage context = (SafetyEquipmentIntallUserCertificateManage) AopContext.currentProxy(); + context.search(page,wrapper,param); + if(CollUtil.isEmpty(page.getRecords())){ + return PageVo.of(Collections.emptyList(), page.getTotal()); + } + List data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public SafetyEquipmentInstallUseCertificateVO details(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(SafetyEquipmentInstallUseCertificate.class); + SafetyEquipmentIntallUserCertificateManage context = (SafetyEquipmentIntallUserCertificateManage) AopContext.currentProxy(); + context.buildStandardFileQuery(wrapper, id); + SafetyEquipmentInstallUseCertificate record = safetyEquipmentInstallUseCertificateService.getOne(wrapper); + if (Objects.isNull(record)){ + return null; + } + //SafetyEquipmentInstallUseCertificate record = safetyEquipmentInstallUseCertificateService.getById(id); + return convert(record); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildStandardFileQuery(LambdaQueryWrapper wrapper, Long id) { + + } + + /** + * 查询 + * @param page + * @param param + */ + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void search(Page page,LambdaQueryWrapper wrapper,UseCertPageParamDTO param) { + wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), SafetyEquipmentInstallUseCertificate::getCompanyName, param.getCompanyName()) + .like(StringUtils.isNotBlank(param.getCarPlate()), SafetyEquipmentInstallUseCertificate::getCarPlate, param.getCarPlate()) + .eq(Objects.nonNull(param.getVehicleType()), SafetyEquipmentInstallUseCertificate::getVehicleType, param.getVehicleType()) + .ge(Objects.nonNull(param.getStartTime()), SafetyEquipmentInstallUseCertificate::getIssueDate, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), SafetyEquipmentInstallUseCertificate::getIssueDate, param.getEndTime()) + .like(Objects.nonNull(param.getAnnualInspectionRecords()), SafetyEquipmentInstallUseCertificate::getAnnualInspectionRecords, param.getAnnualInspectionRecords()) + .orderBy(Boolean.TRUE,Boolean.FALSE, SafetyEquipmentInstallUseCertificate::getUpdateOn); + safetyEquipmentInstallUseCertificateService.page(page, wrapper); + } + + private SafetyEquipmentInstallUseCertificateVO convert(SafetyEquipmentInstallUseCertificate certificate) { + SafetyEquipmentInstallUseCertificateVO vo = BeanUtil.copyProperties(certificate, SafetyEquipmentInstallUseCertificateVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + } + + + public SafetyEquipmentInstallUseCertificateVO save(UseCertSaveDTO data, Long userId) { + SafetyEquipmentInstallUseCertificate certificate = BeanUtil.copyProperties(data, SafetyEquipmentInstallUseCertificate.class); + CodeUtil.searchCompanyNameAndRegionName(certificate); + if(Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(v -> + certificate.setVehicleTypeName(v)); + } + certificate.setCreateBy(userId); + certificate.setUpdateBy(userId); + safetyEquipmentInstallUseCertificateService.save(certificate); + return BeanUtil.copyProperties(certificate, SafetyEquipmentInstallUseCertificateVO.class); + } + + public SafetyEquipmentInstallUseCertificateVO modify(UseCertUpdateDTO data, Long userId) { + SafetyEquipmentInstallUseCertificate certificate = BeanUtil.copyProperties(data, SafetyEquipmentInstallUseCertificate.class); + CodeUtil.searchCompanyNameAndRegionName(certificate); + if(Objects.nonNull(data.getVehicleType())){ + Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(v -> + certificate.setVehicleTypeName(v)); + } + certificate.setUpdateBy(userId); + safetyEquipmentInstallUseCertificateService.updateById(certificate); + return BeanUtil.copyProperties(certificate, SafetyEquipmentInstallUseCertificateVO.class); + } + + public Boolean remove(Long id, Long userId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(SafetyEquipmentInstallUseCertificate.class); + SafetyEquipmentIntallUserCertificateManage context = (SafetyEquipmentIntallUserCertificateManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + SafetyEquipmentInstallUseCertificate record = safetyEquipmentInstallUseCertificateService.getOne(wrapper); + if (Objects.isNull(record)){ + throw new BizException("无法删除!"); + } + safetyEquipmentInstallUseCertificateService.removeById(id); + return Boolean.TRUE; + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(SafetyEquipmentInstallUseCertificate::getId,id); + } + + public void infoListExport(HttpServletResponse response, UseCertPageParamDTO param) { + param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + PageVo page = list(param); + List collect = page.getRecords().stream().map(r -> { + SafetyEqInsUseCertExportDTO certExportDTO = new SafetyEqInsUseCertExportDTO(); + BeanUtils.copyProperties(r, certExportDTO); + return certExportDTO; + }).collect(Collectors.toList()); + String fileName = "安全设备安装使用证书信息列表"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), SafetyEqInsUseCertExportDTO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.java new file mode 100644 index 0000000..e23382e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorDynamics; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 异常GPS数据监控 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface DataQualityMonitorDynamicsMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.xml new file mode 100644 index 0000000..7b0ae41 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorDynamicsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.java new file mode 100644 index 0000000..b5e0566 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorGps; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 动态数据质量监控 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface DataQualityMonitorGpsMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.xml new file mode 100644 index 0000000..17e9543 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorGpsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.java new file mode 100644 index 0000000..3d0a71b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorStatic; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 静态数据质量监控 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface DataQualityMonitorStaticMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.xml new file mode 100644 index 0000000..1de41e0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataQualityMonitorStaticMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.java new file mode 100644 index 0000000..806ec2a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.industry.model.po.CeriticatePO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface DataScreenMapper { + + List tainCertificate(@Param("param") DataScreenParam param); + + List laboratoryQualificationCertificate(@Param("param") DataScreenParam param); + + List laboratoryAcceptanceCertificate(@Param("param") DataScreenParam param); + + List recordCertificateMortarEnterprise(@Param("param") DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.xml new file mode 100644 index 0000000..b6ca06d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DataScreenMapper.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.java new file mode 100644 index 0000000..91bdc8b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.industry.mapper; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateJoin; + +/** + *

+ * 驾驶员合格证 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +public interface DriverTrainingCertificateJoinMapper extends BaseMapper { + String QUERY_SQL = "SELECT cc.*, " + + " d.id_card,cc.issue_date training_time," + + " '合格' training_result,cc.expiry_date effective_time,'浙江省散装水泥、预拌混凝土、预拌砂浆专用车辆驾驶员业务技能和安全知识培训' training_program " + + " FROM nd_certificate cc " + + " LEFT JOIN nd_driver_info d ON cc.driver_id = d.id " + + " LEFT JOIN nd_company_info c ON d.company_id = c.id "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoin(Page page, @Param("ew") LambdaQueryWrapper wrapper); + @Select(WRAPPER_SQL) + DriverTrainingCertificateJoin getOneJoin(@Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.xml new file mode 100644 index 0000000..9945f71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateJoinMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperJoinMapper.java new file mode 100644 index 0000000..266b6c5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperJoinMapper.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.industry.mapper; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOperJoin; + +/** + *

+ * 驾驶员合格证操作 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +public interface DriverTrainingCertificateOperJoinMapper extends BaseMapper { + String QUERY_SQL = "SELECT cp.*, d.driver_name," + + " d.id_card,c.name company_name,cp.issue_date training_time," + + " '合格' training_result,cp.expiry_date effective_time,'浙江省散装水泥、预拌混凝土、预拌砂浆专用车辆驾驶员业务技能和安全知识培训' training_program " + + " FROM nd_driver_training_certificate_oper AS cp " + + //" LEFT JOIN nd_certificate AS cc ON cp.certificate_id = cc.id" + + " LEFT JOIN nd_driver_info d ON cp.driver_id = d.id " + + " LEFT JOIN nd_company_info c ON d.company_id = c.id "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoin(Page page, @Param("ew") LambdaQueryWrapper wrapper); + @Select(WRAPPER_SQL) + DriverTrainingCertificateOperJoin getOneJoin(@Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.java new file mode 100644 index 0000000..a691eda --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 驾驶员合格证操作 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +public interface DriverTrainingCertificateOperMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.xml new file mode 100644 index 0000000..31a2e28 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/DriverTrainingCertificateOperMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.java new file mode 100644 index 0000000..637f529 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificateChange; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 实验室验收合格证换证 Mapper 接口 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +public interface LabAcceptanceCertificateChangeMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.xml new file mode 100644 index 0000000..f3fd425 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateChangeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.java new file mode 100644 index 0000000..363dfcc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 实验室验收合格证 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +public interface LabAcceptanceCertificateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.xml new file mode 100644 index 0000000..c94c5be --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabAcceptanceCertificateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.java new file mode 100644 index 0000000..0c6b39b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.LabWorkerCertificateChange; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 实验室人员从业资格证更换 Mapper 接口 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +public interface LabWorkerCertificateChangeMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.xml new file mode 100644 index 0000000..b939b05 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateChangeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.java new file mode 100644 index 0000000..57d50d0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.LabWorkerCertificate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 实验室人员从业资格证 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-04 + */ +public interface LabWorkerCertificateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.xml new file mode 100644 index 0000000..6842b6c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/LabWorkerCertificateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.java new file mode 100644 index 0000000..bc44b18 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificateChange; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 砂浆企业备案证换证 Mapper 接口 + *

+ * + * @author CMM + * @since 2022-12-15 + */ +public interface MortarEnterpriseFilingCertificateChangeMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.xml new file mode 100644 index 0000000..aff52ea --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateChangeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.java new file mode 100644 index 0000000..ceda75b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 砂浆企业备案证 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +public interface MortarEnterpriseFilingCertificateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.xml new file mode 100644 index 0000000..8f1e9f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/MortarEnterpriseFilingCertificateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.java new file mode 100644 index 0000000..7c91ddc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.OperatorIndexScoreInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2023-01-04 + */ +public interface OperatorIndexScoreInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.xml new file mode 100644 index 0000000..c81bfbe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/OperatorIndexScoreInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.java new file mode 100644 index 0000000..17d5bd8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.PassportInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 通行证信息 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +public interface PassportInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.xml new file mode 100644 index 0000000..6ff0830 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PassportInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.java new file mode 100644 index 0000000..eef6577 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.PurchaseOil; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 油品采购信息表 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface PurchaseOilMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.xml new file mode 100644 index 0000000..fce3d2a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseOilMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.java new file mode 100644 index 0000000..499c20f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.PurchaseRawMaterial; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 原材料采购信息表 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface PurchaseRawMaterialMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.xml new file mode 100644 index 0000000..80a0ca9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseRawMaterialMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.java new file mode 100644 index 0000000..0b11b6a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.PurchaseVehicle; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆采购信息表 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface PurchaseVehicleMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.xml new file mode 100644 index 0000000..c212d00 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseVehicleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.java new file mode 100644 index 0000000..d77bc99 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.PurchaseWheel; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 轮胎采购信息表 Mapper 接口 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface PurchaseWheelMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.xml new file mode 100644 index 0000000..57f1dce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/PurchaseWheelMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.java new file mode 100644 index 0000000..7c72d29 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.ReadyMixedMortarIndustryManage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 预拌砂浆行业管理 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +public interface ReadyMixedMortarIndustryManageMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.xml new file mode 100644 index 0000000..bdac2ea --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/ReadyMixedMortarIndustryManageMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.java new file mode 100644 index 0000000..391d322 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.RegistrationRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 新车上牌记录 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +public interface RegistrationRecordMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.xml new file mode 100644 index 0000000..cbf3cfb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/RegistrationRecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.java new file mode 100644 index 0000000..96c0047 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全设备安装使用证书信息 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface SafetyEquipmentInstallUseCertificateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.xml new file mode 100644 index 0000000..85db2a7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.java new file mode 100644 index 0000000..551203c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificateOperation; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 安全设备安装使用证书操作信息 Mapper 接口 + *

+ * + * @author CMM + * @since 2022-11-26 + */ +public interface SafetyEquipmentInstallUseCertificateOperationMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.xml new file mode 100644 index 0000000..6ca97d2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/SafetyEquipmentInstallUseCertificateOperationMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.java new file mode 100644 index 0000000..34d0680 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.mapper; + +import com.ningdatech.carapi.industry.entity.VehicleAnnualInspectionReview; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆年检年审 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +public interface VehicleAnnualInspectionReviewMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.xml new file mode 100644 index 0000000..8d13480 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/mapper/VehicleAnnualInspectionReviewMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsExportDTO.java new file mode 100644 index 0000000..4178cdc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsExportDTO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 动态数据监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@ApiModel(value = "DataQualityMonitorDynamicsExportDTO", description = "动态数据监控") +public class DataQualityMonitorDynamicsExportDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("企业ID") + @ExcelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + @ExcelProperty("企业名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("0正常 1异常") + @ExcelProperty("0正常 1异常") + private Integer state; + + @ApiModelProperty("驾驶员ID") + @ExcelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("驾驶员名字") + @ExcelProperty("驾驶员名字") + private String driverName; + + @ApiModelProperty("数据时间") + @ExcelProperty("数据时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsPageParamDTO.java new file mode 100644 index 0000000..cd6001c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorDynamicsPageParamDTO.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 动态数据质量分页传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@Builder +@ApiModel(value = "DataQualityMonitorDynamicsPageParamDTO", description = "动态数据质量分页传参") +public class DataQualityMonitorDynamicsPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车牌号列表") + private List carPlateList; + + @ApiModelProperty("数据异常状态 0正常 1异常") + private Integer state; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsExportDTO.java new file mode 100644 index 0000000..a8f2df4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsExportDTO.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; +import java.math.BigDecimal; + +import com.alibaba.excel.annotation.ExcelProperty; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +/** + *

+ * GPS数据质量监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@ApiModel(value = "DataQualityMonitorGpsExportDTO", description = "GPS数据质量监控") +public class DataQualityMonitorGpsExportDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ExcelProperty("车牌号") + private String carPlate; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("车辆类型") + private String vehicleTypeName; + + @ExcelProperty("运营商") + private String operatorName; + + @ExcelProperty("经度") + private BigDecimal longitude; + + @ExcelProperty("纬度") + private BigDecimal latitude; + + @ExcelProperty("速度") + private BigDecimal velocity; + + @ExcelProperty("方向角度") + private BigDecimal direction; + + @ExcelProperty("状态 0离线 1在线") + private String state; + + @ExcelProperty("时间") + private String dataTime; + + @ExcelProperty("报警") + private String alarmName; + + @ExcelProperty("异常原因") + private Integer abnormalCausesName; + + @ExcelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsPageParamDTO.java new file mode 100644 index 0000000..31486ef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorGpsPageParamDTO.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * GPS数据质量分页传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@Builder +@ApiModel(value = "DataQualityMonitorDynamicsPageParamDTO", description = "GPS数据质量分页传参") +public class DataQualityMonitorGpsPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("运营商") + private String operatorName; + + @ApiModelProperty("车辆颜色") + private String plateColor; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticExportDTO.java new file mode 100644 index 0000000..5fe236a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticExportDTO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 静态数据质量监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@ApiModel(value = "DataQualityMonitorStaticExportDTO", description = "静态数据质量监控") +public class DataQualityMonitorStaticExportDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + @ExcelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + @ExcelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + @ExcelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("数据类型") + @ExcelProperty("数据类型") + private Integer dataType; + + @ApiModelProperty("数据类型名") + @ExcelProperty("数据类型名") + private String dataTypeName; + + @ApiModelProperty("数据异常状态 0正常 1不正常") + @ExcelProperty("数据异常状态 0正常 1不正常") + private Integer state; + + @ApiModelProperty("批次号") + @ExcelProperty("批次号") + private String batchNo; + + @ApiModelProperty("数据采集时间") + @ExcelProperty("数据采集时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticPageParamDTO.java new file mode 100644 index 0000000..412c5a1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DataQualityMonitorStaticPageParamDTO.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 静态数据质量分页传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@Builder +@ApiModel(value = "DataQualityMonitorDynamicsPageParamDTO", description = "静态数据质量分页传参") +public class DataQualityMonitorStaticPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("企业集合") + private List companyIds; + + @ApiModelProperty("批次号") + private String batchNo; + + @ApiModelProperty("数据异常状态 0正常 1异常") + private Integer state; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateExportDTO.java new file mode 100644 index 0000000..221f93f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateExportDTO.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 驾驶员培训合格证导出实体 + * + * @author CMM + * @since 2023/02/20 15:27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DriverTrainingCertificateExportDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("驾驶员姓名") + private String driverName; + + @ExcelProperty("身份证号") + private String idCard; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("培训时间") + private String trainingTime; + + @ExcelProperty("培训结果") + private String trainingResult; + + @ExcelProperty("有效时间") + private String effectiveTime; + + @ExcelProperty("培训项目") + private String trainingProgram; +} + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificatePageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificatePageParamDTO.java new file mode 100644 index 0000000..d60a54c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificatePageParamDTO.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 驾驶员合格证 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Data +@Builder +@ApiModel(value = "DriverTrainingCertificatePageParamDTO", description = "驾驶员合格证分页传参") +public class DriverTrainingCertificatePageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("驾驶员名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("培训结果 合格") + private String trainingResult; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateUpdateDTO.java new file mode 100644 index 0000000..6cb0736 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/DriverTrainingCertificateUpdateDTO.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 驾驶员培训合格证编辑信息 + * + * @author CMM + * @since 2023/03/02 11:12 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DriverTrainingCertificateUpdateDTO", description = "行业服务-驾驶员培训合格证") +public class DriverTrainingCertificateUpdateDTO { + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("驾驶员名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证单位") + private String issuedBy; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty("有效期至") + private LocalDateTime expiryDate; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("申请事项") + private String application; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("合格证类型") + private Integer certificateType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewSaveDTO.java new file mode 100644 index 0000000..9f0b4cb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewSaveDTO.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 车辆年检年审 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "InspectionReviewSaveDTO", description = "车辆年检年审") +public class InspectionReviewSaveDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年检记录") + private String inspectionRecords; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型") + private String vehicleTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewUpdateDTO.java new file mode 100644 index 0000000..508b436 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/InspectionReviewUpdateDTO.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * 车辆年检年审 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "InspectionReviewSaveDTO", description = "车辆年检年审") +public class InspectionReviewUpdateDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年检记录") + private String inspectionRecords; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型") + private String vehicleTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateExportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateExportDto.java new file mode 100644 index 0000000..64f5d70 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateExportDto.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + *

+ * LabAcceptanceCertificateImportDto + *

+ * + * @author WendyYang + * @since 21:34 2022/11/4 + */ +@Data +public class LabAcceptanceCertificateExportDto { + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("证书编号") + private String certificateNo; + + @ExcelProperty("备案项目") + private String recordItem; + + @ExcelProperty("执行标准") + private String standard; + + @ExcelProperty("检测项目") + private String testItem; + + @ExcelProperty("发证机关") + private String conferOrg; + + @ExcelProperty("发证日期") + private String conferDate; + + @ExcelProperty("有效日期") + private String validDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateImportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateImportDto.java new file mode 100644 index 0000000..80e6e33 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabAcceptanceCertificateImportDto.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + *

+ * LabAcceptanceCertificateImportDto + *

+ * + * @author WendyYang + * @since 21:34 2022/11/4 + */ +@Data +public class LabAcceptanceCertificateImportDto { + + @ExcelProperty("企业完整名称") + @NotBlank(message = "企业完整名称不能为空") + private String companyName; + + @ExcelProperty("备案项目") + @NotBlank(message = "备案项目不能为空") + private String recordItem; + + @ExcelProperty("执行标准") + @NotBlank(message = "执行标准不能为空") + private String standard; + + @ExcelProperty("发证机关") + @NotBlank(message = "发证机关不能为空") + private String conferOrg; + + @ExcelProperty("证书编号") + @NotBlank(message = "证书编号不能为空") + private String certificateNo; + + @ExcelProperty(value = "发证日期") + @DateTimeFormat("yyyy-MM-dd") + @NotNull(message = "发证日期不能为空") + private Date conferDate; + + @ExcelProperty(value = "换证日期") + @DateTimeFormat("yyyy-MM-dd") + @NotNull(message = "换证日期不能为空") + private Date validDate; + + @ExcelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateExportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateExportDto.java new file mode 100644 index 0000000..c5e3f47 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateExportDto.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + *

+ * LabWorkerCertificateImportDto + *

+ * + * @author WendyYang + * @since 21:34 2022/11/4 + */ +@Data +public class LabWorkerCertificateExportDto implements Serializable { + + private static final long serialVersionUID = 1L; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("姓名") + private String userName; + + @ExcelProperty("性别") + private String gender; + + @ExcelProperty("身份证号码") + private String idCard; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("证书编号") + private String certificateNo; + + @ExcelProperty("发证时间") + private String conferDate; + + @ExcelProperty("有效期") + private String validDate; + + @ExcelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateImportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateImportDto.java new file mode 100644 index 0000000..48f547c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/LabWorkerCertificateImportDto.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + *

+ * LabWorkerCertificateImportDto + *

+ * + * @author WendyYang + * @since 21:34 2022/11/4 + */ +@Data +public class LabWorkerCertificateImportDto { + + @ExcelProperty("企业完整名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ExcelProperty("姓名") + @NotBlank(message = "姓名不能为空") + private String username; + + @ExcelProperty("性别") + @NotBlank(message = "性别不能为空") + private String gender; + + @ExcelProperty("身份证号码") + @NotBlank(message = "身份证号码不能为空") + private String idCard; + + @ExcelProperty("证照编号") + @NotBlank(message = "证照编号不能为空") + private String certificateNo; + + @ExcelProperty(value = "有效开始日期") + @DateTimeFormat("yyyy-MM-dd") + @NotNull(message = "有效开始日期不能为空") + private Date startDate; + + @ExcelProperty(value = "有效结束日期") + @DateTimeFormat("yyyy-MM-dd") + @NotNull(message = "有效结束日期不能为空") + private Date endDate; + + @ExcelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateDTO.java new file mode 100644 index 0000000..f09b4be --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateDTO.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.time.LocalDate; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class MortarEnterpriseFilingCertificateDTO { + + @ApiModelProperty("ID") + private Integer id; + + @ApiModelProperty("证书编号") + @NotBlank(message = "证书编号不能为空") + private String certificateNo; + + @ApiModelProperty("企业") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("备案项目") + @NotBlank(message = "备案项目不能为空") + private String recordItem; + + @ApiModelProperty("生产能力") + @NotBlank(message = "生产能力不能为空") + private String productionCapacity; + + @ApiModelProperty("执行标准") + @NotBlank(message = "执行标准不能为空") + private String standards; + + @ApiModelProperty("有效期") + @NotNull(message = "有效期不能为空") + private LocalDate validDate; + + @ApiModelProperty("发证机关") + @NotNull(message = "发证机关不能为空") + private String conferOrg; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("换证时间") + private LocalDate replaceDate; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + + @ApiModelProperty("新增类型") + private Integer addType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateExportDto.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateExportDto.java new file mode 100644 index 0000000..cb07f0c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/MortarEnterpriseFilingCertificateExportDto.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + *

+ * LabAcceptanceCertificateImportDto + *

+ * + * @author WendyYang + * @since 21:34 2022/11/4 + */ +@Data +public class MortarEnterpriseFilingCertificateExportDto { + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("证书编号") + private String certificateNo; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("备案项目") + private String recordItem; + + @ExcelProperty("生产能力") + private String productionCapacity; + + @ExcelProperty("发证机关") + private String conferOrg; + + @ExcelProperty("发证日期") + private String conferDate; + + @ExcelProperty("有效日期") + private String validDate; + + @ExcelProperty("执行标准") + private String standard; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorAssessmentDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorAssessmentDTO.java new file mode 100644 index 0000000..cc194d8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorAssessmentDTO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * @author CMM + * @since 2023/01/04 10:14 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "OperatorAssessmentDTO", description = "运营商考核分数查询") +public class OperatorAssessmentDTO extends PagePo { + + @ApiModelProperty(value = "运营商id") + @NotNull(message = "运营商ID不能为空!") + private Long id; + + @ApiModelProperty(value = "季度") + @NotNull(message = "请选择季度!") + private Integer quarter; + + @ApiModelProperty(value = "年份") + @NotNull(message = "请选择年份!") + private String year; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorsAssessmentDetailsExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorsAssessmentDetailsExportDTO.java new file mode 100644 index 0000000..dcc5417 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/OperatorsAssessmentDetailsExportDTO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 运营商考核详情导出实体类 + * + * @author CMM + * @since 2023/01/16 10:06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OperatorsAssessmentDetailsExportDTO { + + @ExcelProperty(value = "序号") + private String id; + + @ExcelProperty(value = "考核指标名称") + private String assessmentIndicators; + + @ExcelProperty(value = "评分细则") + private String scoringRubric; + + @ExcelProperty(value = "指标分值") + private String indexScore; + + @ExcelProperty(value = "实际得分") + private String actualScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportExportDTO.java new file mode 100644 index 0000000..3f1f2c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportExportDTO.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 通行证导出实体 + * + * @author CMM + * @since 2023/02/20 15:53 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PassportExportDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("车辆所有人") + private String vehicleOwner; + + @ExcelProperty("车牌号") + private String carPlate; + + @ExcelProperty("车辆类型") + private String vehicleTypeName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("可同行区域") + private String accessibleArea; + + @ExcelProperty("有效期") + private String expirationDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportPageParamDTO.java new file mode 100644 index 0000000..09b1663 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportPageParamDTO.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 驾驶员合格证 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Data +@Builder +@ApiModel(value = "PassportPageParamDTO", description = "通行证分页传参") +public class PassportPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportSaveDTO.java new file mode 100644 index 0000000..c2a56eb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportSaveDTO.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.industry.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 通行证信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "PassportSaveDTO", description = "通行证信息save") +public class PassportSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆所有人") + private String vehicleOwner; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("可通行区域") + private String accessibleArea; + + @ApiModelProperty("有效期") + private LocalDateTime expirationDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportUpdateDTO.java new file mode 100644 index 0000000..d78747e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/PassportUpdateDTO.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.industry.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 通行证信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "PassportUpdateDTO", description = "通行证信息update") +public class PassportUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆所有人") + private String vehicleOwner; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("可通行区域") + private String accessibleArea; + + @ApiModelProperty("有效期") + private LocalDateTime expirationDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageSaveDTO.java new file mode 100644 index 0000000..60151f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageSaveDTO.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 预拌砂浆行业管理 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +@Data +@ApiModel(value = "ReadyMixedMortarIndustryManageSaveDTO", description = "预拌砂浆行业管理") +public class ReadyMixedMortarIndustryManageSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("0启用 1禁用") + private Integer state; + + @ApiModelProperty("file id") + private Long fileId; + + @ApiModelProperty("文件名") + private String fileName; + + @ApiModelProperty("下载次数") + private Integer downTimes; + + @ApiModelProperty("内容") + private String content; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageUpdateDTO.java new file mode 100644 index 0000000..a6b5dd5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedMortarIndustryManageUpdateDTO.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * 预拌砂浆行业管理 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +@Data +@ApiModel(value = "ReadyMixedMortarIndustryManageSaveDTO", description = "预拌砂浆行业管理") +public class ReadyMixedMortarIndustryManageUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "请传id") + private Long id; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("0启用 1禁用") + private Integer state; + + @ApiModelProperty("file id") + private Long fileId; + + @ApiModelProperty("文件名") + private String fileName; + + @ApiModelProperty("下载次数") + private Integer downTimes; + + @ApiModelProperty("内容") + private String content; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedPageParamDTO.java new file mode 100644 index 0000000..626a329 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReadyMixedPageParamDTO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 预拌砂浆行业管理分页传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +@Data +@Builder +@ApiModel(value = "ReadyMixedPageParamDTO", description = "预拌砂浆行业管理分页传参") +public class ReadyMixedPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("区域ID") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordPageParamDTO.java new file mode 100644 index 0000000..64936bf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordPageParamDTO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 新车上牌 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Data +@Builder +@ApiModel(value = "RegistrationRecordPageParamDTO", description = "新车上牌") +public class RegistrationRecordPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("上牌记录") + private String registrationRecord; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车牌号列表") + private List carPlateList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordSaveDTO.java new file mode 100644 index 0000000..8efc7f0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordSaveDTO.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 新车上牌记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +@Data +@ApiModel(value = "RegistrationRecordSaveDTO", description = "新车上牌记录") +public class RegistrationRecordSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车架号") + private String vin; + + @ApiModelProperty("引擎号") + private String engineNo; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("已上牌 未上牌") + private String registrationRecord; + + @ApiModelProperty("车辆品牌") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + private String vehicleModels; + + @ApiModelProperty("购买价格") + private BigDecimal purchasePrice; + + @ApiModelProperty("购买日期") + private LocalDateTime purchaseDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordUpdateDTO.java new file mode 100644 index 0000000..3555570 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/RegistrationRecordUpdateDTO.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 新车上牌记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +@Data +@ApiModel(value = "RegistrationRecordUpdateDTO", description = "新车上牌记录") +public class RegistrationRecordUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车架号") + private String vin; + + @ApiModelProperty("引擎号") + private String engineNo; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("已上牌 未上牌") + private String registrationRecord; + + @ApiModelProperty("车辆品牌") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + private String vehicleModels; + + @ApiModelProperty("购买价格") + private BigDecimal purchasePrice; + + @ApiModelProperty("购买日期") + private LocalDateTime purchaseDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReviewPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReviewPageParamDTO.java new file mode 100644 index 0000000..69272c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/ReviewPageParamDTO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 年检年审分页传参 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Data +@Builder +@ApiModel(value = "ReviewPageParamDTO", description = "年检年审分页传参") +public class ReviewPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车牌号列表") + private List carPlateList; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("年检记录") + private String inspectionRecords; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/SafetyEqInsUseCertExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/SafetyEqInsUseCertExportDTO.java new file mode 100644 index 0000000..26c5b35 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/SafetyEqInsUseCertExportDTO.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 安全设备安装使用证书导出实体 + * + * @author CMM + * @since 2023/02/20 15:42 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SafetyEqInsUseCertExportDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("车牌号") + private String carPlate; + + @ExcelProperty("车辆类型") + private String vehicleTypeName; + + @ExcelProperty("终端运营商") + private String endOperator; + + @ExcelProperty("年检记录") + private String annualInspectionRecords; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperatePageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperatePageParamDTO.java new file mode 100644 index 0000000..3919b11 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperatePageParamDTO.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author CMM + * @description + * @since 2022/11/26 17:10 + */ +@Data +@Builder +@ApiModel(value = "UseCertOperatePageParamDTO", description = "使用证书操作分页传参") +public class UseCertOperatePageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 134356701632333300L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("证书年检状态") + private String annualStatus; + + @ApiModelProperty("申请事项") + private String applicationItem; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperateUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperateUpdateDTO.java new file mode 100644 index 0000000..b8d573f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertOperateUpdateDTO.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.industry.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author CMM + * @description + * @since 2022/11/27 11:46 + */ +@Data +@ApiModel("安全设备安装使用证书操作信息") +public class UseCertOperateUpdateDTO implements Serializable { + private static final long serialVersionUID = -7585902492215261079L; + + @ApiModelProperty("id") + @NotNull(message = "id必传!") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("申请状态") + private String applicationStatus; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("年检状态") + private String yearCheckStatus; + + @ApiModelProperty("补换状态") + private String replacementStatus; + + @ApiModelProperty("视频运营商") + private String videoOperator; + + @ApiModelProperty("证书编号") + private Long certificateNumber; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertPageParamDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertPageParamDTO.java new file mode 100644 index 0000000..2c8cc29 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertPageParamDTO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.industry.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 使用证书 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Data +@Builder +@ApiModel(value = "UseCertPageParamDTO", description = "使用证书分页传参") +public class UseCertPageParamDTO extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("年检记录") + private String annualInspectionRecords; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertSaveDTO.java new file mode 100644 index 0000000..17e9409 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertSaveDTO.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.industry.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全设备安装使用证书信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "SafetyEquipmentInstallUseCertificateVO", description = "安全设备安装使用证书信息") +public class UseCertSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertUpdateDTO.java new file mode 100644 index 0000000..5a9d66a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/UseCertUpdateDTO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.industry.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全设备安装使用证书信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "SafetyEquipmentInstallUseCertificateVO", description = "安全设备安装使用证书信息") +public class UseCertUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id必传!") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/VehicleAnnualInspectionExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/VehicleAnnualInspectionExportDTO.java new file mode 100644 index 0000000..c8cd0d3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/dto/VehicleAnnualInspectionExportDTO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.industry.model.dto; + +import java.io.Serializable; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 车辆年检年审记录导出实体类 + * + * @author CMM + * @since 2023/02/20 14:54 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class VehicleAnnualInspectionExportDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ExcelProperty("所属区域") + private String regionName; + + @ExcelProperty("所属企业") + private String companyName; + + @ExcelProperty("车牌号") + private String carPlate; + + @ExcelProperty("车辆类型") + private String vehicleTypeName; + + @ExcelProperty("年检记录") + private String inspectionRecords; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/po/CeriticatePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/po/CeriticatePO.java new file mode 100644 index 0000000..d8e97c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/po/CeriticatePO.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.industry.model.po; + +import lombok.Data; + +/** + * @author PoffyZhang + * @Classname TainCeriticatePO + * @Description + * @Date 2022/12/15 19:11 + */ +@Data +public class CeriticatePO { + + private Long regionId; + private String regionName; + private Integer count; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateListReq.java new file mode 100644 index 0000000..f56278c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateListReq.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.industry.model.req; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDate; + +/** + *

+ * LabAcceptanceCertificateListReq + *

+ * + * @author WendyYang + * @since 14:50 2022/11/4 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class LabAcceptanceCertificateListReq extends PagePo { + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("发证日期") + private LocalDate startDate; + + @ApiModelProperty("发证日期") + private LocalDate endDate; + + @ApiModelProperty("审核状态:0 待审核、1 已审核") + private Integer auditStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateReq.java new file mode 100644 index 0000000..ea07755 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabAcceptanceCertificateReq.java @@ -0,0 +1,91 @@ +package com.ningdatech.carapi.industry.model.req; + +import java.time.LocalDate; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class LabAcceptanceCertificateReq { + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("企业") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("备案项目") + @NotBlank(message = "备案项目不能为空") + private String recordItem; + + @ApiModelProperty("发证时间") + @DateTimeFormat("yyyy-MM-dd") + private LocalDate conferDate; + + @ApiModelProperty("换证时间") + @DateTimeFormat("yyyy-MM-dd") + private LocalDate replaceDate; + + @ApiModelProperty("证书编号") + @NotBlank(message = "证书编号不能为空") + private String certificateNo; + + @ApiModelProperty("发证机关") + @NotNull(message = "发证机关不能为空") + private String conferOrg; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + + @ApiModelProperty("执行标准") + @NotNull(message = "执行标准不能为空") + private String standard; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("检测项目") + @NotNull(message = "检测项目不能为空") + private String testItem; + + @ApiModelProperty("有效期限") + @NotNull(message = "有效期限不能为空") + @DateTimeFormat("yyyy-MM-dd") + private LocalDate validDate; + + @ApiModelProperty("新增类型") + private Integer addType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateAuditReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateAuditReq.java new file mode 100644 index 0000000..1e19be3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateAuditReq.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.industry.model.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author CMM + * @description + * @since 2022/11/29 15:27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("换证申请审核") +public class LabWorkerCertificateAuditReq implements Serializable { + private static final long serialVersionUID = -3678789250665879763L; + @ApiModelProperty(value = "ID",required = true) + @NotNull(message = "ID不能为空!") + private Integer id; + + @ApiModelProperty("审核状态 0 待审核 1 审核通过") + @NotNull(message = "审核状态不能为空!") + private Integer auditStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateListReq.java new file mode 100644 index 0000000..5b030ca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateListReq.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.industry.model.req; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotNull; +import java.time.LocalDate; + +/** + *

+ * LabWorkerCertificateListReq + *

+ * + * @author WendyYang + * @since 14:50 2022/11/4 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class LabWorkerCertificateListReq extends PagePo { + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("发证日期") + private LocalDate startDate; + + @ApiModelProperty("发证日期") + private LocalDate endDate; + + @ApiModelProperty("审核状态:0 待审核、1 已审核") + private Integer auditStatus; + + @ApiModelProperty("证书类型:1 从业资格证、2 继续教育合格证") + @NotNull(message = "证书类型不能为空") + private Integer certificateType; + + public QueryWrapper listQuery() { + QueryWrapper query = Wrappers.query(); + if (StrUtil.isNotBlank(this.companyName)) { + query.like("company_name", this.companyName); + } + if (this.startDate != null) { + query.ge("confer_date", this.startDate); + } + if (this.endDate != null) { + query.le("confer_date", this.endDate); + } + query.orderByDesc("update_on"); + return query; + } + + public QueryWrapper changeListQuery() { + QueryWrapper query = listQuery(); + query.eq(this.auditStatus != null, "audit_status", this.auditStatus); + return query; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateReq.java new file mode 100644 index 0000000..808c473 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/LabWorkerCertificateReq.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.industry.model.req; + +import java.time.LocalDate; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class LabWorkerCertificateReq { + + @ApiModelProperty("ID") + private Integer id; + + @ApiModelProperty("企业") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + private String userName; + + @ApiModelProperty("身份证号") + @NotBlank(message = "身份证号不能为空") + private String idCard; + + @ApiModelProperty("有效期") + @NotNull(message = "有效期不能为空") + private LocalDate validDate; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("发证机关") + @NotBlank(message = "发证机关不能为空") + private String conferOrg; + + @ApiModelProperty("换证时间") + private LocalDate replaceDate; + + @ApiModelProperty("证书编号") + @NotBlank(message = "证书编号不能为空") + private String certificateNo; + + @ApiModelProperty("性别:0 女、1 男、2 未知、3 其他") + @NotNull(message = "性别不能为空") + private Integer gender; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + + @ApiModelProperty("证书类型") + @NotNull(message = "证书类型不能为空") + private Integer certificateType; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("新增类型") + @NotNull(message = "新增类型不能为空!") + private Integer addType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseListReq.java new file mode 100644 index 0000000..8797220 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseListReq.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.industry.model.req; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDate; + +/** + *

+ * PurchaseRawMaterialListReq + *

+ * + * @author WendyYang + * @since 10:56 2022/11/9 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PurchaseListReq extends PagePo { + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("采购企业") + private String purchaseOrg; + + @ApiModelProperty("采购开始日期") + private LocalDate startDate; + + @ApiModelProperty("采购结束日期") + private LocalDate endDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseOilListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseOilListReq.java new file mode 100644 index 0000000..ccc7bcf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseOilListReq.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.industry.model.req; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * PurchaseRawMaterialListReq + *

+ * + * @author WendyYang + * @since 10:56 2022/11/9 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PurchaseOilListReq extends PurchaseListReq { + + @ApiModelProperty("油品名称") + private String oilName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseRawMaterialListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseRawMaterialListReq.java new file mode 100644 index 0000000..b75c1bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseRawMaterialListReq.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.industry.model.req; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * PurchaseRawMaterialListReq + *

+ * + * @author WendyYang + * @since 10:56 2022/11/9 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PurchaseRawMaterialListReq extends PurchaseListReq { + + @ApiModelProperty("原材料名称") + private String rawMaterialName; + + @ApiModelProperty("原材料型号") + private String model; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseVehicleListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseVehicleListReq.java new file mode 100644 index 0000000..6f3c558 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseVehicleListReq.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.industry.model.req; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * PurchaseVehicleListReq + *

+ * + * @author WendyYang + * @since 10:56 2022/11/9 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PurchaseVehicleListReq extends PurchaseListReq { + + @ApiModelProperty("车辆类型") + private String vehicleType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseWheelListReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseWheelListReq.java new file mode 100644 index 0000000..420df99 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/req/PurchaseWheelListReq.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.industry.model.req; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * PurchaseWheelListReq + *

+ * + * @author WendyYang + * @since 10:56 2022/11/9 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PurchaseWheelListReq extends PurchaseListReq { + + @ApiModelProperty("轮胎类型") + private String wheelType; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorDynamicsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorDynamicsVO.java new file mode 100644 index 0000000..88ab180 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorDynamicsVO.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 动态数据监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@ApiModel(value = "DataQualityMonitorDynamics对象", description = "动态数据监控") +public class DataQualityMonitorDynamicsVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("0正常 1异常") + private Integer state; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("驾驶员名字") + private String driverName; + + @ApiModelProperty("数据时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorGpsVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorGpsVO.java new file mode 100644 index 0000000..09d76b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorGpsVO.java @@ -0,0 +1,101 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * GPS数据质量监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@ApiModel(value = "DataQualityMonitorGps对象", description = "GPS数据质量监控") +public class DataQualityMonitorGpsVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("运营商ID") + private Long operatorId; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; + + @ApiModelProperty("速度") + private String velocity; + + @ApiModelProperty("方向") + private String direction; + + @ApiModelProperty("0离线 1在线") + private Integer state; + + @ApiModelProperty("告警级别") + private Integer alarm; + + @ApiModelProperty("告警级别名称") + private String alarmName; + + @ApiModelProperty("异常原因") + private Integer abnormalCauses; + + @ApiModelProperty("异常原因名称") + private String abnormalCausesName; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("数据采集时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorStaticVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorStaticVO.java new file mode 100644 index 0000000..388c9b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DataQualityMonitorStaticVO.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 静态数据质量监控 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Data +@ApiModel(value = "DataQualityMonitorStatic对象", description = "静态数据质量监控") +public class DataQualityMonitorStaticVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("数据类型") + private Integer dataType; + + @ApiModelProperty("数据类型名") + private String dataTypeName; + + @ApiModelProperty("数据异常状态 0正常 1不正常") + private Integer state; + + @ApiModelProperty("批次号") + private String batchNo; + + @ApiModelProperty("数据采集时间") + private LocalDateTime dataTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateOperVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateOperVO.java new file mode 100644 index 0000000..6844689 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateOperVO.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 驾驶员合格证操作 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +@Data +@Builder +@ApiModel(value = "DriverTrainingCertificateOper", description = "驾驶员合格证操作VO") +public class DriverTrainingCertificateOperVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("驾驶员名") + private String driverName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("培训时间") + private LocalDateTime trainingTime; + + @ApiModelProperty("培训结果 合格") + private String trainingResult; + + @ApiModelProperty("有效时间") + private LocalDateTime effectiveTime; + + @ApiModelProperty("培训项目") + private String trainingProgram; + + @ApiModelProperty("合格证id") + private Long certificateId; + + @ApiModelProperty("操作类型 1.申请 2.补发") + private Integer operationTypeId; + + @ApiModelProperty("操作类型") + private String operationTypeName; + + @ApiModelProperty("审核状态 0待审核 1已审核") + private Integer auditState; + + @ApiModelProperty("已通过") + private String auditStateName; + + @ApiModelProperty("申请时间") + private LocalDateTime operationTime; + + @ApiModelProperty("申请事项") + private String application; + + @ApiModelProperty("申请原因") + private String applicationReason; + + protected LocalDateTime createOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateVO.java new file mode 100644 index 0000000..c5576af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/DriverTrainingCertificateVO.java @@ -0,0 +1,120 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 驾驶员合格证 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DriverTrainingCertificate", description = "驾驶员合格证VO") +public class DriverTrainingCertificateVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + @ExcelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + @ExcelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + @ExcelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("驾驶员ID") + @ExcelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("驾驶员名") + @ExcelProperty("驾驶员名") + private String driverName; + + @ApiModelProperty("身份证号") + @ExcelProperty("身份证号") + private String idCard; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证单位") + private String issuedBy; + + @ApiModelProperty("发证日期") + private LocalDateTime issueDate; + + @ApiModelProperty("驾驶员证号") + private String driverLicenseNo; + + @ApiModelProperty("有效期至") + private LocalDateTime expiryDate; + + @ApiModelProperty("企业ID") + @ExcelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + @ExcelProperty("企业名") + private String companyName; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("培训时间") + @ExcelProperty("培训时间") + private LocalDateTime trainingTime; + + @ApiModelProperty("培训结果 合格") + @ExcelProperty("培训结果 合格") + private String trainingResult; + + @ApiModelProperty("有效时间") + @ExcelProperty("有效时间") + private LocalDateTime effectiveTime; + + @ApiModelProperty("培训项目") + @ExcelProperty("培训项目") + private String trainingProgram; + + @ApiModelProperty("类型") + @ExcelProperty("类型") + private Integer certificateType; + + @ApiModelProperty("类型") + @ExcelProperty("类型") + private String certificateTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateChangeListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateChangeListVo.java new file mode 100644 index 0000000..22b8695 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateChangeListVo.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.time.LocalDate; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class LabAcceptanceCertificateChangeListVo { + + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("企业") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("备案项目") + @NotBlank(message = "备案项目不能为空") + private String recordItem; + + @ApiModelProperty("有效期") + @DateTimeFormat("yyyy-MM-dd") + @NotNull(message = "有效期不能为空") + private LocalDate validDate; + + @ApiModelProperty("发证时间") + @DateTimeFormat("yyyy-MM-dd") + @NotNull(message = "发证时间不能为空") + private LocalDate conferDate; + + @ApiModelProperty("证书编号") + @NotBlank(message = "证书编号不能为空") + private String certificateNo; + + @ApiModelProperty("发证机关") + @NotNull(message = "发证机关不能为空") + private String conferOrg; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + + @ApiModelProperty("执行标准") + private String standard; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("检测项目") + private String testItem; + + @ApiModelProperty("换证时间") + private LocalDate replaceDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateListVo.java new file mode 100644 index 0000000..ed7a277 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabAcceptanceCertificateListVo.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.time.LocalDate; +import java.util.List; + +import javax.validation.constraints.NotNull; + +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class LabAcceptanceCertificateListVo { + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("企业") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("检测项目") + private String testItem; + + @ApiModelProperty("有效期") + @DateTimeFormat("yyyy-MM-dd") + private LocalDate validDate; + + @ApiModelProperty("发证时间") + @DateTimeFormat("yyyy-MM-dd") + private LocalDate conferDate; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("换证时间") + private LocalDate replacementTime; + + @ApiModelProperty("执行标准") + private String standard; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateChangeListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateChangeListVo.java new file mode 100644 index 0000000..e0bbcda --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateChangeListVo.java @@ -0,0 +1,93 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class LabWorkerCertificateChangeListVo { + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("企业") + private Long companyId; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("姓名") + private String userName; + + @ApiModelProperty("身份证号") + private String idCard; + + @ApiModelProperty("有效期") + private LocalDate validDate; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("性别:0 女、1 男、2 未知、3 其他") + private Integer gender; + + @ApiModelProperty("性别:0 女、1 男、2 未知、3 其他") + private String genderName; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + + @ApiModelProperty("证书类型") + @NotNull(message = "证书类型不能为空") + private Integer certificateType; + + @ApiModelProperty("审核状态:0 待审核、1 已审核") + private Integer auditStatus; + + @ApiModelProperty("申请时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime applicationTime; + + @ApiModelProperty("换证时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate replaceDate; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("申请事项") + private String applicationItem; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateListVo.java new file mode 100644 index 0000000..b18e46b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/LabWorkerCertificateListVo.java @@ -0,0 +1,86 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.time.LocalDate; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * LabWorkerCertificateListVo + *

+ * + * @author WendyYang + * @since 15:06 2022/11/4 + */ +@Data +public class LabWorkerCertificateListVo { + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("企业") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + private String userName; + + @ApiModelProperty("身份证号") + @NotBlank(message = "身份证号不能为空") + private String idCard; + + @ApiModelProperty("有效期") + @NotNull(message = "有效期不能为空") + private LocalDate validDate; + + @ApiModelProperty("发证时间") + @NotNull(message = "发证时间不能为空") + private LocalDate conferDate; + + @ApiModelProperty("发证机关") + @NotNull(message = "发证机关不能为空") + private String conferOrg; + + @ApiModelProperty("证书编号") + @NotBlank(message = "证书编号不能为空") + private String certificateNo; + + @ApiModelProperty("性别:0 未知、1 男、2 女、3 其他") + @NotNull(message = "性别不能为空") + private Integer gender; + + @ApiModelProperty("性别:0 未知、1 男、2 女、3 其他") + @NotNull(message = "性别不能为空") + private String genderName; + + @ApiModelProperty("企业名称") + @NotBlank(message = "企业名称不能为空") + private String companyName; + + @ApiModelProperty("备注") + @Length(max = 500, message = "备注最多500个字符") + private String remark; + + @ApiModelProperty("证书类型") + @NotNull(message = "证书类型不能为空") + private Integer certificateType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateChangeVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateChangeVO.java new file mode 100644 index 0000000..d4c4a73 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateChangeVO.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.time.LocalDate; +import java.util.List; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * MortarEnterpriseFilingCertificateChangeVO + *

+ * + * @author WendyYang + * @since 21:34 2022/11/8 + */ +@Data +public class MortarEnterpriseFilingCertificateChangeVO { + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("企业") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("申请事项") + private String applicationItem; + + @ApiModelProperty("申请原因") + private String applicationReason; + + @ApiModelProperty("换证时间") + private LocalDate replaceDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateVO.java new file mode 100644 index 0000000..b3630aa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/MortarEnterpriseFilingCertificateVO.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * MortarEnterpriseFilingCertificateVO + *

+ * + * @author WendyYang + * @since 21:34 2022/11/8 + */ +@Data +public class MortarEnterpriseFilingCertificateVO { + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("证书编号") + private String certificateNo; + + @ApiModelProperty("企业") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("区域信息") + private List regions; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("备案项目") + private String recordItem; + + @ApiModelProperty("换证时间") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDateTime replacementTime; + + @ApiModelProperty("发证机关") + private String conferOrg; + + @ApiModelProperty("发证时间") + private LocalDate conferDate; + + @ApiModelProperty("生产能力") + private String productionCapacity; + + @ApiModelProperty("有效时间") + private LocalDate validDate; + + @ApiModelProperty("执行标准") + private String standards; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/OperatorScoreDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/OperatorScoreDetailVO.java new file mode 100644 index 0000000..9547edd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/OperatorScoreDetailVO.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.industry.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 运营商考核分数详情 + * + * @author CMM + * @since 2023/01/04 16:00 + */ +@Data +public class OperatorScoreDetailVO { + + @ApiModelProperty(value = "运营商考核总分") + private Integer totalScore; + + @ApiModelProperty(value = "上传资质指标分值") + private Integer uploadQualificationIndex; + + @ApiModelProperty(value = "上传资质实际分值") + private Integer uploadQualification; + + @ApiModelProperty(value = "上传资质指标名称") + private String uploadQualificationName; + + @ApiModelProperty(value = "上传频率、数量指标分值") + private Integer uploadFrequencyQuantityIndex; + + @ApiModelProperty(value = "上传频率、数量实际分值") + private Integer uploadFrequencyQuantity; + + @ApiModelProperty(value = "上传频率、数量指标名称") + private String uploadFrequencyQuantityName; + + @ApiModelProperty(value = "字段完整性指标分值") + private Integer fieldIntegrityIndex; + + @ApiModelProperty(value = "字段完整性实际分值") + private Integer fieldIntegrity; + + @ApiModelProperty(value = "字段完整性指标名称") + private String fieldIntegrityName; + + @ApiModelProperty(value = "时效性指标分值") + private Integer timeSensitiveIndex; + + @ApiModelProperty(value = "时效性实际分值") + private Integer timeSensitive; + + @ApiModelProperty(value = "时效性指标名称") + private String timeSensitiveName; + + @ApiModelProperty(value = "位置及方向的正确性、一致性指标分值") + private Integer positionDirectionCorrectnessConsistencyIndex; + + @ApiModelProperty(value = "位置及方向的正确性、一致性实际分值") + private Integer positionDirectionCorrectnessConsistency; + + @ApiModelProperty(value = "位置及方向的正确性、一致性指标名称") + private String positionDirectionCorrectnessConsistencyName; + + @ApiModelProperty(value = "速度的正确性、一致性指标分值") + private Integer speedCorrectnessConsistencyIndex; + + @ApiModelProperty(value = "速度的正确性、一致性实际分值") + private Integer speedCorrectnessConsistency; + + @ApiModelProperty(value = "速度的正确性、一致性指标名称") + private String speedCorrectnessConsistencyName; + + @ApiModelProperty(value = "时间一致性指标分值") + private Integer timeConsistencyIndex; + + @ApiModelProperty(value = "时间一致性实际分值") + private Integer timeConsistency; + + @ApiModelProperty(value = "时间一致性指标名称") + private String timeConsistencyName; + + @ApiModelProperty(value = "位置一致性指标分值") + private Integer positionConsistencyIndex; + + @ApiModelProperty(value = "位置一致性实际分值") + private Integer positionConsistency; + + @ApiModelProperty(value = "位置一致性指标名称") + private String positionConsistencyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PassportVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PassportVO.java new file mode 100644 index 0000000..d889883 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PassportVO.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 通行证信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "PassportInfo对象", description = "通行证信息") +public class PassportVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("车辆所有人") + @ExcelProperty("车辆所有人") + private String vehicleOwner; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("企业ID") + @ExcelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名") + @ExcelProperty("企业名") + private String companyName; + + @ApiModelProperty("可通行区域") + @ExcelProperty("可同行区域") + private String accessibleArea; + + @ApiModelProperty("有效期") + @ExcelProperty("有效期") + private LocalDateTime expirationDate; + + @ApiModelProperty("备注") + @ExcelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseOilListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseOilListVo.java new file mode 100644 index 0000000..1214664 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseOilListVo.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * 油品采购信息列表视图 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@ApiModel("油品采购信息列表视图") +public class PurchaseOilListVo { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("区域") + private List regions; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("油品名称") + @NotBlank(message = "油品名称不能为空") + private String oilName; + + @ApiModelProperty("质量等级") + @NotBlank(message = "质量等级不能为空") + private String qualityLevel; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空") + private Integer number; + + @ApiModelProperty("单价") + @NotNull(message = "单价不能为空") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + @NotNull(message = "采购日期不能为空") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + @NotBlank(message = "采购单位不能为空") + private String purchaseOrg; + + @ApiModelProperty("采购单位ID") + @NotNull(message = "采购单位ID不能为空") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + @NotBlank(message = "批准部门不能为空") + private String approvalDept; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseRawMaterialListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseRawMaterialListVo.java new file mode 100644 index 0000000..80ed8e4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseRawMaterialListVo.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * 原材料采购信息列表视图 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@ApiModel("原材料采购信息列表视图") +public class PurchaseRawMaterialListVo { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("区域") + private List regions; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("原材料名称") + @NotBlank(message = "原材料名称不能为空") + private String rawMaterialName; + + @ApiModelProperty("规格型号") + @NotBlank(message = "规格型号不能为空") + private String model; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空") + private Integer number; + + @ApiModelProperty("计量单位") + @NotBlank(message = "计量单位不能为空") + private String unit; + + @ApiModelProperty("单价") + @NotNull(message = "单价不能为空") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额(保存/修改无需计算)") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + @NotNull(message = "采购日期不能为空") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + @NotBlank(message = "采购单位不能为空") + private String purchaseOrg; + + @ApiModelProperty("采购单位ID") + @NotNull(message = "采购单位ID不能为空") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + @NotBlank(message = "批准部门不能为空") + private String approvalDept; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseVehicleListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseVehicleListVo.java new file mode 100644 index 0000000..a3d9ea4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseVehicleListVo.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * 车辆采购信息列表视图 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@ApiModel("车辆采购信息列表视图") +public class PurchaseVehicleListVo { + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("区域") + private List regions; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("车辆品牌") + @NotBlank(message = "车辆品牌不能为空") + private String vehicleBrand; + + @ApiModelProperty("车辆类型") + @NotBlank(message = "车辆类型不能为空") + private String vehicleType; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空") + private Integer number; + + @ApiModelProperty("单价") + @NotNull(message = "单价不能为空") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + @NotNull(message = "采购日期不能为空") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + @NotBlank(message = "采购单位不能为空") + private String purchaseOrg; + + @ApiModelProperty("采购单位ID") + @NotNull(message = "采购单位ID不能为空") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + @NotBlank(message = "批准部门不能为空") + private String approvalDept; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseWheelListVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseWheelListVo.java new file mode 100644 index 0000000..cbab194 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/PurchaseWheelListVo.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * 轮胎采购信息列表视图 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Data +@ApiModel("轮胎采购信息列表视图") +public class PurchaseWheelListVo { + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("区域") + private List regions; + + @ApiModelProperty("区域ID") + @NotNull(message = "区域ID不能为空") + private Long regionId; + + @ApiModelProperty("轮胎品牌") + @NotBlank(message = "轮胎品牌不能为空") + private String wheelBrand; + + @ApiModelProperty("轮胎类型") + @NotBlank(message = "轮胎类型不能为空") + private String wheelType; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空") + private Integer number; + + @ApiModelProperty("单价") + @NotNull(message = "单价不能为空") + private BigDecimal unitPrice; + + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("采购日期") + @NotNull(message = "采购日期不能为空") + private LocalDate purchaseDate; + + @ApiModelProperty("采购单位") + @NotBlank(message = "采购单位不能为空") + private String purchaseOrg; + + @ApiModelProperty("采购单位ID") + @NotNull(message = "采购单位ID不能为空") + private Long purchaseOrgId; + + @ApiModelProperty("批准部门") + @NotBlank(message = "批准部门不能为空") + private String approvalDept; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/ReadyMixedMortarIndustryManageVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/ReadyMixedMortarIndustryManageVO.java new file mode 100644 index 0000000..c84f328 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/ReadyMixedMortarIndustryManageVO.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 预拌砂浆行业管理 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +@Data +@ApiModel(value = "ReadyMixedMortarIndustryManageVO", description = "预拌砂浆行业管理") +public class ReadyMixedMortarIndustryManageVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + @ExcelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + @ExcelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("修改人") + @ExcelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("标题") + @ExcelProperty("标题") + private String title; + + @ApiModelProperty("0启用 1禁用") + @ExcelProperty("0启用 1禁用") + private Integer state; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司id") + @ExcelProperty("公司id") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("file id") + @ExcelProperty("file id") + private Long fileId; + + @ApiModelProperty("文件名") + @ExcelProperty("文件名") + private String fileName; + + @ApiModelProperty("下载次数") + @ExcelProperty("下载次数") + private Integer downTimes = 0; + + @ApiModelProperty("内容") + @ExcelProperty("内容") + private String content; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/RegistrationRecordVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/RegistrationRecordVO.java new file mode 100644 index 0000000..e2b4503 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/RegistrationRecordVO.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 新车上牌记录 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +@ApiModel(value = "RegistrationRecordVO", description = "新车上牌记录") +@Data +public class RegistrationRecordVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车架号") + private String vin; + + @ApiModelProperty("引擎号") + private String engineNo; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("已上牌 未上牌") + private String registrationRecord; + + @ApiModelProperty("车辆品牌") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + private String vehicleModels; + + @ApiModelProperty("购买价格") + private BigDecimal purchasePrice; + + @ApiModelProperty("购买日期") + private LocalDateTime purchaseDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateOperationVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateOperationVO.java new file mode 100644 index 0000000..fd01d35 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateOperationVO.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author CMM + * @description + * @since 2022/11/26 17:20 + */ +@Data +@ApiModel(value = "SafetyEquipmentInstallUseCertificateOperationVO", description = "安全设备安装使用证书操作信息") +public class SafetyEquipmentInstallUseCertificateOperationVO implements Serializable { + + private static final long serialVersionUID = -8673410031588377038L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + @ExcelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + @ExcelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + @ExcelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + @ExcelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + @ExcelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + @ExcelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + @ExcelProperty("发证日期") + private LocalDateTime issueDate; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateVO.java new file mode 100644 index 0000000..c472f84 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/SafetyEquipmentInstallUseCertificateVO.java @@ -0,0 +1,88 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 安全设备安装使用证书信息 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Data +@ApiModel(value = "SafetyEquipmentInstallUseCertificateVO", description = "安全设备安装使用证书信息") +public class SafetyEquipmentInstallUseCertificateVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + @ExcelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + @ExcelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + @ExcelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆类型") + @ExcelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("终端运营商") + @ExcelProperty("终端运营商") + private String endOperator; + + @ApiModelProperty("年检记录") + @ExcelProperty("年检记录") + private String annualInspectionRecords; + + @ApiModelProperty("安装凭证") + @ExcelProperty("安装凭证") + private String installCertificate; + + @ApiModelProperty("发证日期") + @ExcelProperty("发证日期") + private LocalDateTime issueDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewApplicationVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewApplicationVO.java new file mode 100644 index 0000000..af09e22 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewApplicationVO.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.industry.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 车辆年检年审 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "VehicleAnnualInspectionReviewApplicationVO", description = "车辆年检年审申请") +public class VehicleAnnualInspectionReviewApplicationVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年检记录") + private String inspectionRecords; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型") + private String vehicleTypeName; + + @ApiModelProperty("状态") + private String status; + + @ApiModelProperty("操作") + private String operation; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewVO.java new file mode 100644 index 0000000..1d39682 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/model/vo/VehicleAnnualInspectionReviewVO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.industry.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆年检年审 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Data +@ApiModel(value = "VehicleAnnualInspectionReview对象", description = "车辆年检年审") +public class VehicleAnnualInspectionReviewVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + @ExcelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + @ExcelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + @ExcelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + @ApiModelProperty("公司ID") + @ExcelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + @ExcelProperty("公司名") + private String companyName; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年检记录") + @ExcelProperty("年检记录") + private String inspectionRecords; + + @ApiModelProperty("车辆类型") + @ExcelProperty("年车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @ExcelProperty("车辆类型名") + private String vehicleTypeName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/DataScreenService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/DataScreenService.java new file mode 100644 index 0000000..94840a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/DataScreenService.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.industry.model.po.CeriticatePO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface DataScreenService { + + List tainCertificate(DataScreenParam param); + + List laboratoryQualificationCertificate(DataScreenParam param); + + List laboratoryAcceptanceCertificate(DataScreenParam param); + + List recordCertificateMortarEnterprise(DataScreenParam param); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorDynamicsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorDynamicsService.java new file mode 100644 index 0000000..19c7b65 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorDynamicsService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorDynamics; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 异常GPS数据监控 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface IDataQualityMonitorDynamicsService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorGpsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorGpsService.java new file mode 100644 index 0000000..0585ed7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorGpsService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorGps; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 动态数据质量监控 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface IDataQualityMonitorGpsService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorStaticService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorStaticService.java new file mode 100644 index 0000000..817d233 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDataQualityMonitorStaticService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorStatic; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 静态数据质量监控 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +public interface IDataQualityMonitorStaticService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateJoinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateJoinService.java new file mode 100644 index 0000000..d633792 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateJoinService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.industry.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateJoin; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOperJoin; + +/** + *

+ * 驾驶员合格证 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +public interface IDriverTrainingCertificateJoinService extends IService { + + Page pageJoin(Page page, LambdaQueryWrapper wrapper); + + DriverTrainingCertificateJoin getOneJoin(LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperJoinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperJoinService.java new file mode 100644 index 0000000..1a628a7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperJoinService.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.industry.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOperJoin; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 驾驶员合格证操作 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +public interface IDriverTrainingCertificateOperJoinService extends IService { + + Page pageJoin(Page page,LambdaQueryWrapper wrapper); + + DriverTrainingCertificateOperJoin getOneJoin(LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperService.java new file mode 100644 index 0000000..e1bd4b9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IDriverTrainingCertificateOperService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOper; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 驾驶员合格证操作 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +public interface IDriverTrainingCertificateOperService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateChangeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateChangeService.java new file mode 100644 index 0000000..f25540b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateChangeService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificateChange; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 实验室验收合格证换证 服务类 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +public interface ILabAcceptanceCertificateChangeService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateService.java new file mode 100644 index 0000000..9cee7c6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabAcceptanceCertificateService.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; + +/** + *

+ * 实验室验收合格证 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +public interface ILabAcceptanceCertificateService extends IService { + + Boolean audit(LabWorkerCertificateAuditReq req, Long userId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateChangeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateChangeService.java new file mode 100644 index 0000000..be31da6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateChangeService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.LabWorkerCertificateChange; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 实验室人员从业资格证更换 服务类 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +public interface ILabWorkerCertificateChangeService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateService.java new file mode 100644 index 0000000..013fe86 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ILabWorkerCertificateService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.LabWorkerCertificate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; + +/** + *

+ * 实验室人员从业资格证 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-04 + */ +public interface ILabWorkerCertificateService extends IService { + + Boolean audit(LabWorkerCertificateAuditReq req, Long userId); + + Boolean cancelAudit(LabWorkerCertificateAuditReq req, Long userId); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateChangeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateChangeService.java new file mode 100644 index 0000000..7928e93 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateChangeService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificateChange; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 砂浆企业备案证换证 服务类 + *

+ * + * @author CMM + * @since 2022-12-15 + */ +public interface IMortarEnterpriseFilingCertificateChangeService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateService.java new file mode 100644 index 0000000..2a1d010 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IMortarEnterpriseFilingCertificateService.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; + +/** + *

+ * 砂浆企业备案证 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +public interface IMortarEnterpriseFilingCertificateService extends IService { + + Boolean audit(LabWorkerCertificateAuditReq req, Long userId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IOperatorIndexScoreInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IOperatorIndexScoreInfoService.java new file mode 100644 index 0000000..5ddb09f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IOperatorIndexScoreInfoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.OperatorIndexScoreInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2023-01-04 + */ +public interface IOperatorIndexScoreInfoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPassportInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPassportInfoService.java new file mode 100644 index 0000000..9d5a4cd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPassportInfoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.PassportInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 通行证信息 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +public interface IPassportInfoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseOilService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseOilService.java new file mode 100644 index 0000000..ea92f81 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseOilService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.PurchaseOil; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 油品采购信息表 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface IPurchaseOilService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseRawMaterialService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseRawMaterialService.java new file mode 100644 index 0000000..3989b60 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseRawMaterialService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.PurchaseRawMaterial; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 原材料采购信息表 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface IPurchaseRawMaterialService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseVehicleService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseVehicleService.java new file mode 100644 index 0000000..0ea27c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseVehicleService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.PurchaseVehicle; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆采购信息表 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface IPurchaseVehicleService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseWheelService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseWheelService.java new file mode 100644 index 0000000..53c721f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IPurchaseWheelService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.PurchaseWheel; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 轮胎采购信息表 服务类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +public interface IPurchaseWheelService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IReadyMixedMortarIndustryManageService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IReadyMixedMortarIndustryManageService.java new file mode 100644 index 0000000..ee1960b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IReadyMixedMortarIndustryManageService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.industry.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.industry.entity.ReadyMixedMortarIndustryManage; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedPageParamDTO; + +import java.util.List; + +/** + *

+ * 预拌砂浆行业管理 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +public interface IReadyMixedMortarIndustryManageService extends IService { + + List dataScopeList(LambdaQueryWrapper wrapper, ReadyMixedPageParamDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IRegistrationRecordService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IRegistrationRecordService.java new file mode 100644 index 0000000..cfcc4ff --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IRegistrationRecordService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.RegistrationRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 新车上牌记录 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +public interface IRegistrationRecordService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateOperationService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateOperationService.java new file mode 100644 index 0000000..196e0b5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateOperationService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificateOperation; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 安全设备安装使用证书操作信息 服务类 + *

+ * + * @author CMM + * @since 2022-11-26 + */ +public interface ISafetyEquipmentInstallUseCertificateOperationService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateService.java new file mode 100644 index 0000000..4623069 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/ISafetyEquipmentInstallUseCertificateService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificate; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 安全设备安装使用证书信息 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +public interface ISafetyEquipmentInstallUseCertificateService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IVehicleAnnualInspectionReviewService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IVehicleAnnualInspectionReviewService.java new file mode 100644 index 0000000..40683d9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/IVehicleAnnualInspectionReviewService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.industry.service; + +import com.ningdatech.carapi.industry.entity.VehicleAnnualInspectionReview; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆年检年审 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +public interface IVehicleAnnualInspectionReviewService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorDynamicsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorDynamicsServiceImpl.java new file mode 100644 index 0000000..13482cb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorDynamicsServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorDynamics; +import com.ningdatech.carapi.industry.mapper.DataQualityMonitorDynamicsMapper; +import com.ningdatech.carapi.industry.service.IDataQualityMonitorDynamicsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 异常GPS数据监控 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Service +public class DataQualityMonitorDynamicsServiceImpl extends ServiceImpl implements IDataQualityMonitorDynamicsService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorGpsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorGpsServiceImpl.java new file mode 100644 index 0000000..7924f3a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorGpsServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorGps; +import com.ningdatech.carapi.industry.mapper.DataQualityMonitorGpsMapper; +import com.ningdatech.carapi.industry.service.IDataQualityMonitorGpsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 动态数据质量监控 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Service +public class DataQualityMonitorGpsServiceImpl extends ServiceImpl implements IDataQualityMonitorGpsService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorStaticServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorStaticServiceImpl.java new file mode 100644 index 0000000..c6a28da --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataQualityMonitorStaticServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.DataQualityMonitorStatic; +import com.ningdatech.carapi.industry.mapper.DataQualityMonitorStaticMapper; +import com.ningdatech.carapi.industry.service.IDataQualityMonitorStaticService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 静态数据质量监控 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-07 + */ +@Service +public class DataQualityMonitorStaticServiceImpl extends ServiceImpl implements IDataQualityMonitorStaticService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataScreenServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataScreenServiceImpl.java new file mode 100644 index 0000000..7c45af5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DataScreenServiceImpl.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.industry.mapper.DataScreenMapper; +import com.ningdatech.carapi.industry.model.po.CeriticatePO; +import com.ningdatech.carapi.industry.service.DataScreenService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author PoffyZhang + * @Classname DataScreenServiceImpl + * @Description + * @Date 2022/12/15 19:09 + */ +@Service +@RequiredArgsConstructor +public class DataScreenServiceImpl implements DataScreenService { + + private final DataScreenMapper mapper; + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List tainCertificate(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return mapper.tainCertificate(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List laboratoryQualificationCertificate(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return mapper.laboratoryQualificationCertificate(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List laboratoryAcceptanceCertificate(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return mapper.laboratoryAcceptanceCertificate(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List recordCertificateMortarEnterprise(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return mapper.recordCertificateMortarEnterprise(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateJoinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateJoinServiceImpl.java new file mode 100644 index 0000000..95dd7c9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateJoinServiceImpl.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateJoin; +import com.ningdatech.carapi.industry.mapper.DriverTrainingCertificateJoinMapper; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateJoinService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 驾驶员合格证 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-03 + */ +@Service +@RequiredArgsConstructor +public class DriverTrainingCertificateJoinServiceImpl extends ServiceImpl implements IDriverTrainingCertificateJoinService { + + private final DriverTrainingCertificateJoinMapper driverTrainingCertificateJoinMapper; + + @Override + public Page pageJoin(Page page, LambdaQueryWrapper wrapper) { + return driverTrainingCertificateJoinMapper.pageJoin(page,wrapper); + } + + @Override + public DriverTrainingCertificateJoin getOneJoin(LambdaQueryWrapper wrapper) { + return driverTrainingCertificateJoinMapper.getOneJoin(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperJoinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperJoinServiceImpl.java new file mode 100644 index 0000000..e08facb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperJoinServiceImpl.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOper; +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOperJoin; +import com.ningdatech.carapi.industry.mapper.DriverTrainingCertificateOperJoinMapper; +import com.ningdatech.carapi.industry.mapper.DriverTrainingCertificateOperMapper; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateOperJoinService; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateOperService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 驾驶员合格证操作 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +@Service +@RequiredArgsConstructor +public class DriverTrainingCertificateOperJoinServiceImpl extends ServiceImpl implements IDriverTrainingCertificateOperJoinService { + private final DriverTrainingCertificateOperJoinMapper driverTrainingCertificateOperJoinMapper; + + @Override + public Page pageJoin(Page page, LambdaQueryWrapper wrapper) { + return driverTrainingCertificateOperJoinMapper.pageJoin(page, wrapper); + } + + @Override + public DriverTrainingCertificateOperJoin getOneJoin(LambdaQueryWrapper wrapper) { + return driverTrainingCertificateOperJoinMapper.getOneJoin(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperServiceImpl.java new file mode 100644 index 0000000..4b30008 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/DriverTrainingCertificateOperServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.DriverTrainingCertificateOper; +import com.ningdatech.carapi.industry.mapper.DriverTrainingCertificateOperMapper; +import com.ningdatech.carapi.industry.service.IDriverTrainingCertificateOperService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 驾驶员合格证操作 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-04 + */ +@Service +public class DriverTrainingCertificateOperServiceImpl extends ServiceImpl implements IDriverTrainingCertificateOperService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateChangeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateChangeServiceImpl.java new file mode 100644 index 0000000..d8043ae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateChangeServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificateChange; +import com.ningdatech.carapi.industry.mapper.LabAcceptanceCertificateChangeMapper; +import com.ningdatech.carapi.industry.service.ILabAcceptanceCertificateChangeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 实验室验收合格证换证 服务实现类 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +@Service +public class LabAcceptanceCertificateChangeServiceImpl extends ServiceImpl implements ILabAcceptanceCertificateChangeService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateServiceImpl.java new file mode 100644 index 0000000..4b6194c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabAcceptanceCertificateServiceImpl.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.industry.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificate; +import com.ningdatech.carapi.industry.entity.LabAcceptanceCertificateChange; +import com.ningdatech.carapi.industry.mapper.LabAcceptanceCertificateChangeMapper; +import com.ningdatech.carapi.industry.mapper.LabAcceptanceCertificateMapper; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.service.ILabAcceptanceCertificateService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + *

+ * 实验室验收合格证 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class LabAcceptanceCertificateServiceImpl extends ServiceImpl implements ILabAcceptanceCertificateService { + + private final LabAcceptanceCertificateMapper labAcceptanceCertificateMapper; + private final LabAcceptanceCertificateChangeMapper labAcceptanceCertificateChangeMapper; + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean audit(LabWorkerCertificateAuditReq req, Long userId) { + LabAcceptanceCertificateChange labAcceptanceCertificateChange = labAcceptanceCertificateChangeMapper.selectById(req.getId()); + if (Objects.isNull(labAcceptanceCertificateChange)){ + throw new BizException("证书信息不存在!"); + } + // labAcceptanceCertificateChange.setAuditStatus(1); + labAcceptanceCertificateChange.setUpdateOn(LocalDateTime.now()); + labAcceptanceCertificateChange.setUpdateBy(userId); + labAcceptanceCertificateChange.setReplacementTime(LocalDate.now()); + labAcceptanceCertificateChangeMapper.updateById(labAcceptanceCertificateChange); + LabAcceptanceCertificate labAcceptanceCertificate = BeanUtil.copyProperties(labAcceptanceCertificateChange, LabAcceptanceCertificate.class); + labAcceptanceCertificate.setId(null); + labAcceptanceCertificate.setCreateOn(LocalDateTime.now()); + labAcceptanceCertificate.setCreateBy(userId); + labAcceptanceCertificateMapper.insert(labAcceptanceCertificate); + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateChangeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateChangeServiceImpl.java new file mode 100644 index 0000000..50a918f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateChangeServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.LabWorkerCertificateChange; +import com.ningdatech.carapi.industry.mapper.LabWorkerCertificateChangeMapper; +import com.ningdatech.carapi.industry.service.ILabWorkerCertificateChangeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 实验室人员从业资格证更换 服务实现类 + *

+ * + * @author CMM + * @since 2022-12-16 + */ +@Service +public class LabWorkerCertificateChangeServiceImpl extends ServiceImpl implements ILabWorkerCertificateChangeService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateServiceImpl.java new file mode 100644 index 0000000..6dd4953 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/LabWorkerCertificateServiceImpl.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.industry.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.industry.entity.LabWorkerCertificate; +import com.ningdatech.carapi.industry.entity.LabWorkerCertificateChange; +import com.ningdatech.carapi.industry.mapper.LabWorkerCertificateChangeMapper; +import com.ningdatech.carapi.industry.mapper.LabWorkerCertificateMapper; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.service.ILabWorkerCertificateService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + *

+ * 实验室人员从业资格证 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-04 + */ +@Service +@RequiredArgsConstructor +public class LabWorkerCertificateServiceImpl extends ServiceImpl implements ILabWorkerCertificateService { + + private final LabWorkerCertificateMapper labWorkerCertificateMapper; + private final LabWorkerCertificateChangeMapper labWorkerCertificateChangeMapper; + + /** + * 从业资格证|继续教育合格证换证申请审核 + * @param req + * @param userId + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean audit(LabWorkerCertificateAuditReq req, Long userId) { + LabWorkerCertificateChange labWorkerCertificateChange = labWorkerCertificateChangeMapper.selectById(req.getId()); + if (Objects.isNull(labWorkerCertificateChange)){ + throw new BizException("证书信息不存在!"); + } + // labWorkerCertificateChange.setAuditStatus(1); + labWorkerCertificateChange.setUpdateBy(userId); + labWorkerCertificateChange.setUpdateOn(LocalDateTime.now()); + labWorkerCertificateChange.setReplacementTime(LocalDate.now()); + labWorkerCertificateChangeMapper.updateById(labWorkerCertificateChange); + LabWorkerCertificate labWorkerCertificate = BeanUtil.copyProperties(labWorkerCertificateChange, LabWorkerCertificate.class); + labWorkerCertificate.setId(null); + labWorkerCertificate.setCreateOn(LocalDateTime.now()); + labWorkerCertificate.setCreateBy(userId); + labWorkerCertificateMapper.insert(labWorkerCertificate); + return Boolean.TRUE; + } + + /** + * 从业资格证取消审核 + * @param req + * @param userId + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean cancelAudit(LabWorkerCertificateAuditReq req, Long userId) { + LabWorkerCertificateChange labWorkerCertificateChange = labWorkerCertificateChangeMapper.selectById(req.getId()); + if (Objects.isNull(labWorkerCertificateChange)){ + throw new BizException("证书信息不存在!"); + } + // labWorkerCertificateChange.setAuditStatus(0); + labWorkerCertificateChange.setUpdateBy(userId); + labWorkerCertificateChange.setUpdateOn(LocalDateTime.now()); + labWorkerCertificateChangeMapper.updateById(labWorkerCertificateChange); + labWorkerCertificateMapper.delete(Wrappers.lambdaQuery(LabWorkerCertificate.class) + .eq(Objects.nonNull(labWorkerCertificateChange.getCertificateNo()),LabWorkerCertificate::getCertificateNo,labWorkerCertificateChange.getCertificateNo())); + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateChangeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateChangeServiceImpl.java new file mode 100644 index 0000000..5493e98 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateChangeServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificateChange; +import com.ningdatech.carapi.industry.mapper.MortarEnterpriseFilingCertificateChangeMapper; +import com.ningdatech.carapi.industry.service.IMortarEnterpriseFilingCertificateChangeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 砂浆企业备案证换证 服务实现类 + *

+ * + * @author CMM + * @since 2022-12-15 + */ +@Service +public class MortarEnterpriseFilingCertificateChangeServiceImpl extends ServiceImpl implements IMortarEnterpriseFilingCertificateChangeService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateServiceImpl.java new file mode 100644 index 0000000..103c749 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/MortarEnterpriseFilingCertificateServiceImpl.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.industry.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificate; +import com.ningdatech.carapi.industry.entity.MortarEnterpriseFilingCertificateChange; +import com.ningdatech.carapi.industry.mapper.MortarEnterpriseFilingCertificateChangeMapper; +import com.ningdatech.carapi.industry.mapper.MortarEnterpriseFilingCertificateMapper; +import com.ningdatech.carapi.industry.model.req.LabWorkerCertificateAuditReq; +import com.ningdatech.carapi.industry.service.IMortarEnterpriseFilingCertificateService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + *

+ * 砂浆企业备案证 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-08 + */ +@Service +@RequiredArgsConstructor +public class MortarEnterpriseFilingCertificateServiceImpl extends ServiceImpl implements IMortarEnterpriseFilingCertificateService { + + private final MortarEnterpriseFilingCertificateMapper mortarEnterpriseFilingCertificateMapper; + private final MortarEnterpriseFilingCertificateChangeMapper mortarEnterpriseFilingCertificateChangeMapper; + + @Override + public Boolean audit(LabWorkerCertificateAuditReq req, Long userId) { + MortarEnterpriseFilingCertificateChange mortarEnterpriseFilingCertificateChange = mortarEnterpriseFilingCertificateChangeMapper.selectById(req.getId()); + if (Objects.isNull(mortarEnterpriseFilingCertificateChange)){ + throw new BizException("证书信息不存在!"); + } + // mortarEnterpriseFilingCertificateChange.setAuditStatus(1); + mortarEnterpriseFilingCertificateChange.setUpdateOn(LocalDateTime.now()); + mortarEnterpriseFilingCertificateChange.setUpdateBy(userId); + mortarEnterpriseFilingCertificateChange.setReplacementTime(LocalDate.now()); + mortarEnterpriseFilingCertificateChangeMapper.updateById(mortarEnterpriseFilingCertificateChange); + MortarEnterpriseFilingCertificate mortarEnterpriseFilingCertificate + = BeanUtil.copyProperties(mortarEnterpriseFilingCertificateChange, MortarEnterpriseFilingCertificate.class); + mortarEnterpriseFilingCertificate.setId(null); + mortarEnterpriseFilingCertificate.setCreateOn(LocalDateTime.now()); + mortarEnterpriseFilingCertificate.setCreateBy(userId); + mortarEnterpriseFilingCertificateMapper.insert(mortarEnterpriseFilingCertificate); + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/OperatorIndexScoreInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/OperatorIndexScoreInfoServiceImpl.java new file mode 100644 index 0000000..7d037c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/OperatorIndexScoreInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.OperatorIndexScoreInfo; +import com.ningdatech.carapi.industry.mapper.OperatorIndexScoreInfoMapper; +import com.ningdatech.carapi.industry.service.IOperatorIndexScoreInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2023-01-04 + */ +@Service +public class OperatorIndexScoreInfoServiceImpl extends ServiceImpl implements IOperatorIndexScoreInfoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PassportInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PassportInfoServiceImpl.java new file mode 100644 index 0000000..8fb8012 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PassportInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.PassportInfo; +import com.ningdatech.carapi.industry.mapper.PassportInfoMapper; +import com.ningdatech.carapi.industry.service.IPassportInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 通行证信息 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Service +public class PassportInfoServiceImpl extends ServiceImpl implements IPassportInfoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseOilServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseOilServiceImpl.java new file mode 100644 index 0000000..8e27971 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseOilServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.PurchaseOil; +import com.ningdatech.carapi.industry.mapper.PurchaseOilMapper; +import com.ningdatech.carapi.industry.service.IPurchaseOilService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 油品采购信息表 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Service +public class PurchaseOilServiceImpl extends ServiceImpl implements IPurchaseOilService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseRawMaterialServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseRawMaterialServiceImpl.java new file mode 100644 index 0000000..1ae83a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseRawMaterialServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.PurchaseRawMaterial; +import com.ningdatech.carapi.industry.mapper.PurchaseRawMaterialMapper; +import com.ningdatech.carapi.industry.service.IPurchaseRawMaterialService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 原材料采购信息表 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Service +public class PurchaseRawMaterialServiceImpl extends ServiceImpl implements IPurchaseRawMaterialService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseVehicleServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseVehicleServiceImpl.java new file mode 100644 index 0000000..fdd8bb3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseVehicleServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.PurchaseVehicle; +import com.ningdatech.carapi.industry.mapper.PurchaseVehicleMapper; +import com.ningdatech.carapi.industry.service.IPurchaseVehicleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆采购信息表 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Service +public class PurchaseVehicleServiceImpl extends ServiceImpl implements IPurchaseVehicleService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseWheelServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseWheelServiceImpl.java new file mode 100644 index 0000000..75e01b2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/PurchaseWheelServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.PurchaseWheel; +import com.ningdatech.carapi.industry.mapper.PurchaseWheelMapper; +import com.ningdatech.carapi.industry.service.IPurchaseWheelService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 轮胎采购信息表 服务实现类 + *

+ * + * @author WendyYang + * @since 2022-11-09 + */ +@Service +public class PurchaseWheelServiceImpl extends ServiceImpl implements IPurchaseWheelService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/ReadyMixedMortarIndustryManageServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/ReadyMixedMortarIndustryManageServiceImpl.java new file mode 100644 index 0000000..e7a321c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/ReadyMixedMortarIndustryManageServiceImpl.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.industry.service.impl; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.industry.entity.ReadyMixedMortarIndustryManage; +import com.ningdatech.carapi.industry.mapper.ReadyMixedMortarIndustryManageMapper; +import com.ningdatech.carapi.industry.model.dto.ReadyMixedPageParamDTO; +import com.ningdatech.carapi.industry.service.IReadyMixedMortarIndustryManageService; + +/** + *

+ * 预拌砂浆行业管理 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-18 + */ +@Service +public class ReadyMixedMortarIndustryManageServiceImpl extends ServiceImpl implements IReadyMixedMortarIndustryManageService { + + @Override + @BuildChildrenRegionWrapper + @LambdaDataScope + public List dataScopeList(LambdaQueryWrapper wrapper, ReadyMixedPageParamDTO param) { + return baseMapper.selectList(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/RegistrationRecordServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/RegistrationRecordServiceImpl.java new file mode 100644 index 0000000..bc5b587 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/RegistrationRecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.RegistrationRecord; +import com.ningdatech.carapi.industry.mapper.RegistrationRecordMapper; +import com.ningdatech.carapi.industry.service.IRegistrationRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 新车上牌记录 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-06 + */ +@Service +public class RegistrationRecordServiceImpl extends ServiceImpl implements IRegistrationRecordService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateOperationServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateOperationServiceImpl.java new file mode 100644 index 0000000..5a58e57 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateOperationServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificateOperation; +import com.ningdatech.carapi.industry.mapper.SafetyEquipmentInstallUseCertificateOperationMapper; +import com.ningdatech.carapi.industry.service.ISafetyEquipmentInstallUseCertificateOperationService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全设备安装使用证书操作信息 服务实现类 + *

+ * + * @author CMM + * @since 2022-11-26 + */ +@Service +public class SafetyEquipmentInstallUseCertificateOperationServiceImpl extends ServiceImpl implements ISafetyEquipmentInstallUseCertificateOperationService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateServiceImpl.java new file mode 100644 index 0000000..54c0009 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/SafetyEquipmentInstallUseCertificateServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.SafetyEquipmentInstallUseCertificate; +import com.ningdatech.carapi.industry.mapper.SafetyEquipmentInstallUseCertificateMapper; +import com.ningdatech.carapi.industry.service.ISafetyEquipmentInstallUseCertificateService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 安全设备安装使用证书信息 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-09 + */ +@Service +public class SafetyEquipmentInstallUseCertificateServiceImpl extends ServiceImpl implements ISafetyEquipmentInstallUseCertificateService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/VehicleAnnualInspectionReviewServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/VehicleAnnualInspectionReviewServiceImpl.java new file mode 100644 index 0000000..9e2f004 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/industry/service/impl/VehicleAnnualInspectionReviewServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.industry.service.impl; + +import com.ningdatech.carapi.industry.entity.VehicleAnnualInspectionReview; +import com.ningdatech.carapi.industry.mapper.VehicleAnnualInspectionReviewMapper; +import com.ningdatech.carapi.industry.service.IVehicleAnnualInspectionReviewService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆年检年审 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-05 + */ +@Service +public class VehicleAnnualInspectionReviewServiceImpl extends ServiceImpl implements IVehicleAnnualInspectionReviewService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/constant/SmsConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/constant/SmsConstant.java new file mode 100644 index 0000000..3b3fe19 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/constant/SmsConstant.java @@ -0,0 +1,12 @@ +package com.ningdatech.carapi.irs.constant; + +/** + * 短信验证常量 + * @return + * @author CMM + * @since 2023/06/02 11:31 + */ +public interface SmsConstant { + + public final String SMS_CONSTANT_TEMPLATE = "验证码:%s(有效期为10分钟),请勿泄露给他人,如非本人操作,请忽略此信息。"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentController.java new file mode 100644 index 0000000..91a0054 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentController.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.irs.controller; + +import com.ningdatech.carapi.irs.service.AccidentService; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @Classname SmsService + * @Description + * @Date 2023/3/23 17:06 + * @Author PoffyZhang + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/accident/") +@RequiredArgsConstructor +public class AccidentController { + + private final AccidentService accidentService; + + private final RefreshKeyService refreshKeyService; + + @ApiOperation(value = "刷新密钥 测试", notes = "刷新密钥 测试") + @GetMapping("/refresh") + public String refresh() { + return refreshKeyService.refresh(); + } + + @ApiOperation(value = "事故责任认定书 测试", notes = "事故责任认定书 测试") + @GetMapping("/test") + public List test() { + return accidentService.getAccident(); + } + + @ApiOperation(value = "更新事故责任认定书数据", notes = "更新事故责任认定书数据") + @GetMapping("/update") + public String update() { + return accidentService.updateAccident(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentQueryController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentQueryController.java new file mode 100644 index 0000000..1b84fd1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/AccidentQueryController.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.irs.controller; + +import java.io.FileNotFoundException; +import java.util.List; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.irs.manage.DataInitManage; +import com.ningdatech.carapi.irs.service.AccidentService; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 事故查询 + * + * @author CMM + * @since 2023/04/23 14:25 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/accident/query") +@RequiredArgsConstructor +public class AccidentQueryController { + + private final AccidentService accidentService; + + private final DataInitManage dataInitManage; + + @ApiOperation(value = "事故查询 测试", notes = "事故查询 测试") + @GetMapping("/test") + public List test() { + return accidentService.accidentQuery(); + } + + + @ApiOperation(value = "事故查询数据初始化", notes = "事故查询数据初始化") + @GetMapping("/accidentQueryDataInit") + public String dataInit() { + return dataInitManage.dataInit(); + } + + @ApiOperation(value = "事故查询数据批量保存", notes = "事故查询数据批量保存") + @GetMapping("/accidentQueryDataSave") + public void dataSave() throws InterruptedException { + dataInitManage.accidentQueryDataSave(); + } + + @ApiOperation(value = "事故查询数据逐个保存", notes = "事故查询数据逐个保存") + @GetMapping("/accidentQueryDataSingleSave") + public void dataSingleSave() { + dataInitManage.accidentQueryDataSingleSave(); + } + + @ApiOperation(value = "事故查询数据逐个保存", notes = "事故查询数据逐个保存") + @GetMapping("/dataSingleSave") + public void singleSave() throws FileNotFoundException { + dataInitManage.singleSave(); + } + + @ApiOperation(value = "事故查询数据更新", notes = "事故查询数据更新") + @GetMapping("/updateAccidentData") + public void updateAccidentData() throws FileNotFoundException { + dataInitManage.updateAccidentData(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsController.java new file mode 100644 index 0000000..d4528aa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsController.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.irs.controller; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.irs.manage.DataInitManage; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/05/16 00:01 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/irs") +@RequiredArgsConstructor +public class IrsController { + + private final DataInitManage dataInitManage; + + @ApiOperation(value = "车牌号初始化保存", notes = "车牌号初始化保存") + @GetMapping("/carPlate/save") + public void carPlateSave() { + dataInitManage.carPlateSave(); + } + + @ApiOperation(value = "日志分析保存", notes = "日志分析保存") + @GetMapping("/log/save") + public void logSave() { + dataInitManage.logSave(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsDriversLicensePullController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsDriversLicensePullController.java new file mode 100644 index 0000000..61e86ed --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/IrsDriversLicensePullController.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.irs.controller; + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.irs.manage.IrsDriversLicenseManage; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 驾驶证信息查询 + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@RestController +@RequestMapping("/open/api/irs") +@RequiredArgsConstructor +public class IrsDriversLicensePullController { + + private final IrsDriversLicenseManage irsDriversLicenseManage; + + @ApiOperation("驾驶证信拉取") + @GetMapping("/driver-license/refresh") + public void driverLicenseRefresh() { + irsDriversLicenseManage.submitDriverLicensePullTask(); + } + + @ApiOperation("行驶证信息拉取") + @GetMapping("/driving-license/refresh") + public void drivingLicenseRefresh() { + irsDriversLicenseManage.submitDrivingLicensePullTask(); + } + + @ApiOperation(value = "行驶证查询数据逐个保存", notes = "行驶证查询数据逐个保存") + @GetMapping("/vehicleLicenseSingleSave") + public void vehicleLicenseSingleSave(){ + irsDriversLicenseManage.vehicleLicenseSingleSave(); + } + + @ApiOperation(value = "驾驶证查询数据逐个保存", notes = "驾驶证查询数据逐个保存") + @GetMapping("/drivingLicenseSingleSave") + public void drivingLicenseSingleSave(){ + irsDriversLicenseManage.drivingLicenseSingleSave(); + } + + @ApiOperation(value = "根据车架号查询行驶证数据", notes = "根据车架号查询行驶证数据") + @GetMapping("/vehicleLicenseTest") + public List vehicleLicenseTest(){ + return irsDriversLicenseManage.vehicleLicenseTest(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/SmsController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/SmsController.java new file mode 100644 index 0000000..fc074a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/SmsController.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.irs.controller; + +import com.ningdatech.carapi.irs.manage.SmsManage; +import com.ningdatech.carapi.irs.service.SmsService; +import com.ningdatech.carapi.open.model.dto.UserLoginDTO; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @Classname SmsController + * @Description + * @Date 2023/3/1 17:06 + * @Author PoffyZhang + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/sms/") +@RequiredArgsConstructor +public class SmsController { + + private final SmsService service; + + private final SmsManage smsManage; + + @ApiOperation(value = "sms send", notes = "sms") + @GetMapping("/send") + public String send(@RequestParam String content) { + String mobile = "15058187290"; + return service.sendMessage(mobile, content); + } + + @ApiOperation("获取验证码") + @PostMapping("/get-code") + public String getCode(@RequestBody UserLoginDTO param) { + return smsManage.getCode(param); + } + + @ApiOperation(value = "send sms code", notes = "get sms code") + @PostMapping("/send-sms-code") + public String sendSmsCode(@RequestBody UserLoginDTO param) { + return smsManage.sendSmsCode(param.getMobile(), param.getVerificationCode()); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/VehicleIllegalQueryController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/VehicleIllegalQueryController.java new file mode 100644 index 0000000..e92fc37 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/controller/VehicleIllegalQueryController.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.irs.controller; + +import com.ningdatech.carapi.irs.manage.DataInitManage; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.irs.service.CarService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.io.FileNotFoundException; + +/** + * 车辆违法查询 + * + * @author CMM + * @since 2023/04/23 15:18 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/vehicle/illegal/query") +@RequiredArgsConstructor +public class VehicleIllegalQueryController { + + private final CarService carService; + + private final DataInitManage dataInitManage; + + @ApiOperation(value = "车辆违法查询 测试", notes = "车辆违法查询 测试") + @GetMapping("/test") + public String test() { + return carService.vehicleIllegalQuery(); + } + + @ApiOperation(value = "车辆违法数据初始化", notes = "车辆违法数据初始化") + @GetMapping("/vehicleIllegalDataInit") + public String dataInit() { + return dataInitManage.vehicleIllegaldataInit(); + } + + @ApiOperation(value = "车辆违法数据保存", notes = "车辆违法数据数据保存") + @GetMapping("/vehicleIllegalDataSave") + public void dataSave() throws InterruptedException { + dataInitManage.vehicleIllegalDataSave(); + } + + @ApiOperation(value = "车辆违法查询数据逐个保存", notes = "车辆违法查询数据逐个保存") + @GetMapping("/illegalDataSingleSave") + public void illegalDataSingleSave() throws FileNotFoundException { + dataInitManage.illegalDataSingleSave(); + } + + @ApiOperation(value = "车辆违章数据更新", notes = "车辆违章数据更新") + @GetMapping("/updateViolationData") + public void updateViolationData() throws FileNotFoundException { + dataInitManage.updateViolationData(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/entity/DriversLicenseRaw.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/entity/DriversLicenseRaw.java new file mode 100644 index 0000000..640d920 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/entity/DriversLicenseRaw.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.irs.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author WendyYang + * @since 2023-05-16 + */ +@Data +@TableName("nd_drivers_license_raw") +@ApiModel(value = "DriversLicense对象", description = "") +public class DriversLicenseRaw implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("身份证号") + private String idcard; + + @ApiModelProperty("驾驶证信息") + private String driverLicenseDetail; + + @ApiModelProperty("行驶证信息") + private String drivingLicenseDetail; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("车牌号") + private String carPlate; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/DataInitManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/DataInitManage.java new file mode 100644 index 0000000..6c24de8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/DataInitManage.java @@ -0,0 +1,1408 @@ +package com.ningdatech.carapi.irs.manage; + +import java.io.*; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.config.DefaultAsyncTaskConfig; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.cache.lock.DistributedLock; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.redis.RedisOps; +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.ningdatech.carapi.car.position.service.IVehiclePositionInfoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.MissCertEnum; +import com.ningdatech.carapi.common.constant.ViolationTypeEnum; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.irs.model.entity.IrsTempCarplate; +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.ningdatech.carapi.irs.model.entity.VehicleViolationIrsData; +import com.ningdatech.carapi.irs.service.*; +import com.ningdatech.carapi.qrcode.service.VehicleGetOnService; +import com.ningdatech.carapi.safe.constant.AccidentTypeEnum; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportStatusEnum; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.file.utils.StrPool; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/05/11 10:57 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class DataInitManage { + + @Value("${spring.redis.host}") + public String REDIS_HOST; + + @Value("${spring.redis.port}") + public String REDIS_PORT; + + private static final int GROUP_SIZE = 500; + private static final int QUERY_SIZE = 2000; + private static final long BIG_EXPIRE_TIME = 60 * 60 * 1000; + + private final DefaultAsyncTaskConfig defaultAsyncTaskConfig; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final AccidentService accidentService; + private final RegionsCacheHelper regionsCacheHelper; + private final VehicleGetOnService vehicleGetOnService; + private final INdVehicleAccidentService vehicleAccidentService; + private final INdVehicleAccidentDeadService vehicleAccidentDeadService; + private final CarService carService; + private final VehiclesCacheHelper vehiclesCacheHelper; + private final INdVehicleViolationService vehicleViolationService; + private final IDriverInfoService driverInfoService; + private final CompanyService companyService; + private final DistributedLock distributedLock; + private final IVehicleAccidentIrsDataService accidentIrsDataService; + private final IVehicleViolationIrsDataService violationIrsDataService; + private final RedisOps redisOps; + private final IIrsTempCarplateService irsTempCarplateService; + private final IVehiclePositionInfoService iVehiclePositionInfoService; + + /** + * 无驾驶证违法行为code列表 + */ + private static final List NO_DRIVING_LICENSE_LIST = + Arrays.asList("5075", "5072", "5077", "5057", "10159", "1082", "70619", "6018", "7503", "7504", "7006", "70069", + "1015", "16444", "1644", "50411", "60182", "8005", "80059", "8605", "5603", "5703", "1610", "5041", "60541", + "1110", "7061", "10050", "10051", "10052", "10059", "1006", "1010", "10109", "1013", "1014", "6086", "5006", + "1005", "56031", "60181", "57021", "57031", "1704", "1701"); + + /** + * 无行驶证违法行为code列表 + */ + private static final List NO_VEHICLE_LICENSE_LIST = Arrays.asList("5071", "5069", "1088", "5702", "5705", + "7216", "7218", "1109", "6085", "5003", "57051", "50031", "57021", "5009", "5015"); + + /** + * 闯红灯(违反交通信号灯) + */ + private static final List VIOLATION_TRAFFIC_LIGHTS_LIST = Arrays.asList("13029", "1625", "16259", "1302"); + + /** + * 违规时段行驶 + */ + private static final List VIOLATION_TIME_LIST = Arrays.asList("8025"); + + /** + * 违规路段行驶 + */ + private static final List VIOLATION_ROAD_LIST = + Arrays.asList("1048", "10489", "40099", "8004", "8803", "11229", "8005J", "8002", "8048", "4009", "10393", + "10397", "1045", "10459", "1310", "13109", "1023", "10239", "8005", "8001C", "1122", "8014"); + + public String dataInit() { + LambdaQueryWrapper query = Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate).isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + + // 获取此次任务要查询的车牌号 + List carPlates = list.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + + List vehicleBaseInfos = vehicleBaseInfoService + .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).in(NdVehicleBaseInfo::getCarPlate, carPlates)); + Map vehicleBaseInfoMap = + vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + Map companyMap = + companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + + // 获取已经存在的事故数据 + List accidentTmpVas = vehicleAccidentService + .list(Wrappers.lambdaQuery(NdVehicleAccident.class).in(NdVehicleAccident::getCarPlate, carPlates)); + Map> accidentMap = + CollUtils.group(accidentTmpVas, NdVehicleAccident::getCarPlate); + + // 获取已经存在的死亡事故数据 + List deadAccidentTmpVas = vehicleAccidentDeadService + .list(Wrappers.lambdaQuery(NdVehicleAccidentDead.class).in(NdVehicleAccidentDead::getCarPlate, carPlates)); + Map> deadAccidentMap = + CollUtils.group(deadAccidentTmpVas, NdVehicleAccidentDead::getCarPlate); + + log.info("此次任务数据量为 {}", list.size()); + + List lists = Lists.newArrayList(); + lists.add("浙B1Q567"); + lists.add("浙B3R397"); + lists.add("浙BE5516"); + lists.add("浙B1E907"); + lists.add("浙B0J292"); + lists.add("浙A8Y637"); + lists.add("浙C52502"); + lists.add("浙CL0175"); + lists.add("浙FM8020"); + lists.add("浙J61963"); + + // 调用IRS接口,返回数据 + for (String carPlate : lists) { + if (StrUtil.isNotBlank(carPlate)) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + Long companyId = vehicleBaseInfo.getCompanyId(); + Company company = companyMap.get(companyId); + String dataJsonStr = accidentService.accidentQuery(carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + for (JSONObject jsonObject : accidentArray) { + // 获取行政区划 + String xzqh = jsonObject.getString("XZQH"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + + // 获取事故地点 + String sgdd = jsonObject.getString("SGDD"); + + // 先查出对应车牌号关联的责任驾驶员 + String driverName = vehicleBaseInfo.getResponsibleDriverFirst(); + + if (Objects.isNull(driverName)) { + log.info("该车牌号没有责任驾驶员!"); + continue; + } + // 获取车辆类型 + Integer vehicleType = vehicleBaseInfo.getVehicleType(); + // 获取当场、24小时、3日内、7日内、30日内死亡人数 + Integer swrs = jsonObject.getInteger("SWRS"); + Integer swrs24 = jsonObject.getInteger("SWRS24"); + Integer swrs3 = jsonObject.getInteger("SWRS3"); + Integer swrs7 = jsonObject.getInteger("SWRS7"); + Integer swrs30 = jsonObject.getInteger("SWRS30"); + // 获取受伤人数 + Integer ssrs = jsonObject.getInteger("SSRS"); + // 没有死亡人数 + // 插入到事故表中 + if (swrs == 0 && swrs24 == 0 && swrs3 == 0 && swrs7 == 0 && swrs30 == 0) { + NdVehicleAccident accident = new NdVehicleAccident(); + // 判断当前事故对应的车牌号是否在在事故表中已存在事故数据 + List accidents = accidentMap.get(carPlate); + if (CollUtil.isNotEmpty(accidents)) { + List timeList = accidents.stream() + .map(NdVehicleAccident::getAccidentTime).collect(Collectors.toList()); + // 如果该数据已经录入,直接跳过 + if (timeList.contains(accidentTime)) { + log.info("该事故数据已录入!"); + continue; + } + } + accident.setInjuries(ssrs); + accident.setRegionId(regionId); + accident.setRegionName(regionName); + // 获取事故时间 + accident.setAccidentTime(accidentTime); + accident.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、车辆类型、企业名称 + accident.setCarPlate(carPlate); + accident.setAccidentDriver(driverName); + accident.setVehicleType(vehicleType); + accident.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accident.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accident.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + vehicleAccidentService.saveOrUpdate(accident); + } else { + // 插入数据到死亡事故表中 + NdVehicleAccidentDead accidentDead = new NdVehicleAccidentDead(); + // 判断当前事故对应的车牌号是否在在事故表中已存在事故数据 + List deadAccidents = deadAccidentMap.get(carPlate); + if (CollUtil.isNotEmpty(deadAccidents)) { + List timeList = deadAccidents.stream() + .map(NdVehicleAccidentDead::getAccidentTime).collect(Collectors.toList()); + // 如果该数据已经录入,直接跳过 + if (timeList.contains(accidentTime)) { + log.info("该死亡数据已录入!"); + continue; + } + } + if (swrs30 != 0) { + accidentDead.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accidentDead.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accidentDead.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accidentDead.setDeathToll(swrs24); + } else { + accidentDead.setDeathToll(swrs); + } + accidentDead.setInjuries(ssrs); + accidentDead.setRegionId(regionId); + accidentDead.setRegionName(regionName); + // 获取事故时间 + accidentDead.setAccidentTime(accidentTime); + accidentDead.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、企业名称 + accidentDead.setCarPlate(carPlate); + accidentDead.setAccidentDriver(driverName); + accidentDead.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accidentDead.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accidentDead.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + vehicleAccidentDeadService.saveOrUpdate(accidentDead); + } + } + } + } + } + } + return "更新完成"; + } + + public String vehicleIllegaldataInit() { + LambdaQueryWrapper query = Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate).isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + + List carPlates = CollUtils.fieldList(list, NdVehicleBaseInfo::getCarPlate); + + // 获取车辆违章时间信息 + List vioList = vehicleViolationService + .list(Wrappers.lambdaQuery(NdVehicleViolation.class).in(NdVehicleViolation::getCarPlate, carPlates)); + Map> listMap = CollUtils.group(vioList, NdVehicleViolation::getCarPlate); + log.info("此次任务数据量为 {}", list.size()); + + // 调用IRS接口,返回数据 + for (String hphm : carPlates) { + String dataJsonStr = carService.vehicleIllegalQuery(hphm); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String datas = object.getString("datas"); + List vehicleIllegalArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(vehicleIllegalArray)) { + log.info("该车牌号没有违章信息!"); + continue; + } + // 获取当前车牌号已经存在的违章时间数据 + List violationList = listMap.get(hphm); + List vehicleIllegalInfo = null; + if (CollUtil.isNotEmpty(violationList)) { + List violationTimeList = violationList.stream() + .map(v -> LocalDateTimeUtil.of(v.getViolationDate()) + .format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN))) + .collect(Collectors.toList()); + // 筛选出不在车辆违法信息表中的数据 + vehicleIllegalInfo = vehicleIllegalArray.stream() + .filter(v -> !violationTimeList.contains(LocalDateTimeUtil.of(v.getTimestamp("wfsj")) + .format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)))) + .collect(Collectors.toList()); + if (CollUtil.isEmpty(vehicleIllegalInfo)) { + log.info("该车牌号没有新增的违章信息"); + continue; + } + } else { + vehicleIllegalInfo = vehicleIllegalArray; + } + for (JSONObject jsonObject : vehicleIllegalInfo) { + NdVehicleViolation vehicleViolation = new NdVehicleViolation(); + vehicleViolation.setCarPlate(hphm); + // 获取行政区划 + String xzqh = jsonObject.getString("xzqh"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + vehicleViolation.setRegionId(regionId); + vehicleViolation.setRegionName(regionName); + // 获取违法日期 + Timestamp wfsj = jsonObject.getTimestamp("wfsj"); + LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj); + vehicleViolation.setViolationDate(vehicleIllegalTime); + // 获取违法地址 + String wfdz = jsonObject.getString("wfdz"); + + // 获取违法行为 + String wfxw = jsonObject.getString("wfxw"); + // 如果是闯红灯 + if (VIOLATION_TRAFFIC_LIGHTS_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.RED_LIGHT.getCode()); + vehicleViolation.setAddressRedLight(wfdz); + } else if (NO_DRIVING_LICENSE_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode()); + vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVER_LINCENSE.getCode()); + } else if (NO_VEHICLE_LICENSE_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode()); + vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVE_PERMIT.getCode()); + } else if (VIOLATION_TIME_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.PERIOD.getCode()); + int hour = vehicleIllegalTime.getHour(); + String period = null; + if (hour >= TaskContant.Data.VIOLATION_TIME_SEVEN && hour <= TaskContant.Data.VIOLATION_TIME_NINE) { + period = TaskContant.Data.VIOLATION_TIME_AM_START + StrPool.DASH + + TaskContant.Data.VIOLATION_TIME_AM_END; + vehicleViolation.setViolationPeriod(period); + } else if (hour >= TaskContant.Data.VIOLATION_TIME_SIXTEEN + && hour <= TaskContant.Data.VIOLATION_TIME_EIGHTEEN) { + period = TaskContant.Data.VIOLATION_TIME_PM_START + StrPool.DASH + + TaskContant.Data.VIOLATION_TIME_PM_END; + vehicleViolation.setViolationPeriod(period); + } + } else if (VIOLATION_ROAD_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.SECTION.getCode()); + vehicleViolation.setWaySection(wfdz); + } + // 获取当事人(驾驶员) + String driverName = jsonObject.getString("dsr"); + // 根据车牌号获取企业信息 + NdVehicleBaseInfo vehicleBaseInfo = vehiclesCacheHelper.getByCarPlate(hphm); + Long companyId = vehicleBaseInfo.getCompanyId(); + vehicleBaseInfo.setCompanyId(companyId); + // 驾驶员姓名和企业名称获取驾驶员信息 + List driverInfoList = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getDriverName, driverName).eq(DriverInfo::getCompanyId, companyId)); + if (CollUtil.isEmpty(driverInfoList)) { + log.info("该车牌号对应的企业下没有该驾驶员信息"); + } else { + // 获取最后一个 + DriverInfo driverInfo = driverInfoList.get(driverInfoList.size() - 1); + vehicleViolation.setDriverId(driverInfo.getId()); + } + vehicleViolation.setDriverName(driverName); + vehicleViolationService.save(vehicleViolation); + } + } + return "更新完成"; + + } + + private ThreadPoolTaskExecutor getThreadPoolTaskExecutor() { + return (ThreadPoolTaskExecutor)defaultAsyncTaskConfig.getAsyncExecutor(); + } + + @Async + @Transactional + public void accidentQueryDataSave() throws InterruptedException { + String key = "ACCIDENT_QUERY_DATA_SAVE"; + if (!distributedLock.lock(key, BIG_EXPIRE_TIME)) { + log.warn("正在执行中:{}", key); + return; + } + try { + List carPlateList = getAccidentQueryCarPlateList(); + if (CollUtil.isEmpty(carPlateList)) { + log.info("本月事故数据已更新完成!"); + return; + } + // 调用IRS接口,返回数据 + ThreadPoolTaskExecutor executor = getThreadPoolTaskExecutor(); + List> partition = ListUtil.partition(carPlateList, GROUP_SIZE); + CountDownLatch cdl = new CountDownLatch(partition.size()); + List>> futures = partition.stream().map(w -> executor.submit(() -> { + List tmpList = new ArrayList<>(); + for (String carPlate : w) { + try { + tmpList.addAll(getVehicleAccidentByCarPlate(carPlate)); + } catch (Exception e) { + log.info("获取车辆违法信息异常:{}", carPlate); + } + } + cdl.countDown(); + return tmpList; + })).collect(Collectors.toList()); + cdl.await(); + List irsData = collectResultByFutureTasks(futures); + ListUtil.partition(irsData, GROUP_SIZE).forEach(accidentIrsDataService::saveBatch); + log.info("共插入了:{} {} 条数据", key, irsData.size()); + } finally { + distributedLock.releaseLock(key); + } + } + + private static List collectResultByFutureTasks(List>> futureTasks) { + List irsData = new ArrayList<>(); + futureTasks.forEach(w -> { + try { + irsData.addAll(w.get()); + } catch (Exception e) { + log.warn("本组数据为空"); + } + }); + return irsData; + } + + private List getAccidentQueryCarPlateList() { + // 获取此次任务要查询的车牌号 + List result = new ArrayList<>(); + List carPlateList; + String key = TaskContant.RedisKey.ACCIDENT_QUERY_IRS; + List objectList = redisOps.get(key); + // 存储的车牌号为空 + if (CollUtil.isEmpty(objectList)) { + List carPlates = getCarPlates(); + // 将所有车牌号存入redis缓存中 + carPlates.stream().limit(QUERY_SIZE).forEach(result::add); + if (carPlates.size() > result.size()) { + carPlates.removeAll(result); + redisOps.lPush(key, carPlates); + } + } else { + // 每次获取缓存中的2000个车牌号 + List tmpCarPlates = redisOps.lRange(key, 0, (QUERY_SIZE - 1)); + if (CollUtil.isNotEmpty(tmpCarPlates)) { + result = CollUtils.convert(tmpCarPlates, Object::toString); + // 删除取出的数据 + redisOps.lRem(key, 0, result); + } + } + return result; + } + + private List getVehicleIllegalCarPlateList(List carPlates) { + // 获取此次任务要查询的车牌号 + List carPlateList = Lists.newArrayList(); + + CacheKey cacheKey = new CacheKey(TaskContant.RedisKey.VEHICLE_ILLEGAL_QUERY_IRS, Duration.ofDays(20)); + Object object = redisOps.get(cacheKey, false); + // key不存在(过期) + if (Objects.isNull(object)) { + // 将所有车牌号存入redis缓存中 + redisOps.sAdd(cacheKey, carPlates); + } + + // 获取redis中的所有数据 + List objectList = redisOps.lRange(cacheKey.getKey(), 0, -1); + + // key未过期且车牌号已经查询完成 + if (Objects.nonNull(object) && CollUtil.isEmpty(objectList)) { + return Collections.emptyList(); + } else if (Objects.nonNull(object) && CollUtil.isNotEmpty(objectList)) { + // 每次获取缓存中的2000个车牌号 + List range = redisOps.lRange(cacheKey.getKey(), 0, (QUERY_SIZE - 1)); + carPlateList = range.stream().map(Object::toString).collect(Collectors.toList()); + // 去除已经取出的数据,仅保留第2000条之后的数据 + if (objectList.size() > QUERY_SIZE) { + redisOps.lTrim(cacheKey.getKey(), QUERY_SIZE, -1); + } else { + // 数据全部取出后,删除key + redisOps.del(cacheKey); + } + } + return carPlateList; + } + + private List getVehicleAccidentByCarPlate(String carPlate) { + String dataJsonStr = accidentService.accidentQuery(carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + return Collections.emptyList(); + } + List irsData = new ArrayList<>(); + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + for (JSONObject jsonObject : accidentArray) { + VehicleAccidentIrsData accidentIrsData = new VehicleAccidentIrsData(); + accidentIrsData.setCarPlate(carPlate); + accidentIrsData.setJsonStrData(datas); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + accidentIrsData.setAccidentTime(accidentTime); + accidentIrsData.setCreateOn(LocalDateTime.now()); + accidentIrsData.setUpdateOn(LocalDateTime.now()); + irsData.add(accidentIrsData); + } + } + } + return irsData; + } + + @Async + @Transactional + public void vehicleIllegalDataSave() throws InterruptedException { + String key = "VEHICLE_ILLEGAL_DATA_SAVE"; + if (!distributedLock.lock(key, BIG_EXPIRE_TIME)) { + log.warn("正在执行中:{}", key); + return; + } + try { + // 获取此次任务要查询的车牌号 + List carPlateList = getVehicleIllegalCarPlateList(getCarPlates()); + if (CollUtil.isEmpty(carPlateList)) { + log.info("本月车辆违法数据已更新完成!"); + return; + } + // 调用IRS接口,返回数据 + ThreadPoolTaskExecutor executor = getThreadPoolTaskExecutor(); + List> partition = ListUtil.partition(carPlateList, GROUP_SIZE); + CountDownLatch cdl = new CountDownLatch(partition.size()); + List>> futures = partition.stream().map(w -> executor.submit(() -> { + List tmpList = new ArrayList<>(); + for (String carPlate : w) { + try { + tmpList.addAll(getVehicleIllegalByCarPlate(carPlate)); + } catch (Exception e) { + log.info("获取车辆违法信息异常:{}", carPlate); + } + } + cdl.countDown(); + return tmpList; + })).collect(Collectors.toList()); + cdl.await(); + List irsData = collectResultByFutureTasks(futures); + ListUtil.partition(irsData, GROUP_SIZE).forEach(violationIrsDataService::saveBatch); + log.info("共插入了:{} {} 条数据", key, irsData.size()); + } finally { + distributedLock.releaseLock(key); + } + } + + private List getCarPlates() { + LambdaQueryWrapper query = Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate).isNotNull(NdVehicleBaseInfo::getCarPlate); + HashSet carPlateSet = new HashSet<>(); + // 获取去重后的车辆信息 + List list = vehicleBaseInfoService.list(query).stream() + .filter(v -> carPlateSet.add(v.getCarPlate())).collect(Collectors.toList()); + // 获取所有车牌号 + List carPlates = CollUtils.fieldList(list, NdVehicleBaseInfo::getCarPlate); + return carPlates; + } + + private List getVehicleIllegalByCarPlate(String carPlate) { + String dataJsonStr = carService.vehicleIllegalQuery(carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有违法行为信息!"); + return Collections.emptyList(); + } + List irsData = new ArrayList<>(); + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + VehicleViolationIrsData vid = new VehicleViolationIrsData(); + vid.setCarPlate(carPlate); + // 获取违法日期 + Timestamp wfsj = jsonObject.getTimestamp("wfsj"); + LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj); + vid.setViolationTime(vehicleIllegalTime); + vid.setJsonStrData(data); + String wfxw = jsonObject.getString("wfxw"); + vid.setViolationType(wfxw); + String cfzl = jsonObject.getString("cfzl"); + vid.setViolationKind(cfzl); + vid.setCreateOn(LocalDateTime.now()); + vid.setUpdateOn(LocalDateTime.now()); + irsData.add(vid); + } + } + return irsData; + } + + public void accidentQueryDataSingleSave() { + List carPlateList = getAccidentQueryCarPlateList(); + if (CollUtil.isEmpty(carPlateList)) { + log.info("本月事故数据已更新完成!"); + return; + } + + // 调用IRS接口,返回数据 + // 访问计数 + int count = 0; + for (String carPlate : carPlateList) { + String dataJsonStr = accidentService.accidentQuery(carPlate); + count++; + log.info("已访问事故查询IRS接口 {} 次", count); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + continue; + } + // 获取车牌号的所有事故信息 + Map> accidentIrsDataMap = accidentIrsDataService.list().stream() + .collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + + for (JSONObject jsonObject : accidentArray) { + VehicleAccidentIrsData accidentIrsData = new VehicleAccidentIrsData(); + accidentIrsData.setCarPlate(carPlate); + accidentIrsData.setJsonStrData(datas); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + if (accidentIrsDataMap.containsKey(carPlate)) { + List dataList = accidentIrsDataMap.get(carPlate); + Map dataMap = dataList.stream() + .collect(Collectors.toMap(VehicleAccidentIrsData::getAccidentTime, v -> v)); + if (dataMap.containsKey(accidentTime)) { + VehicleAccidentIrsData irsData = dataMap.get(accidentTime); + // 数据已经存在 + accidentIrsData.setId(irsData.getId()); + } + } + accidentIrsData.setAccidentTime(accidentTime); + accidentIrsData.setCreateOn(LocalDateTime.now()); + accidentIrsData.setUpdateOn(LocalDateTime.now()); + accidentIrsDataService.saveOrUpdate(accidentIrsData); + } + } + } + } + } + + public void singleSave() throws FileNotFoundException { + + List list = new ArrayList<>(); + Set set = new HashSet<>(); + + File directory = new File(""); + //临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File f = new File( filePath + File.separator + "事故查询车牌号.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + list.add(carPlate); + } + } + + // 去重 + List carPlateList = list.stream() + .filter(set::add) + .collect(Collectors.toList()); + + // 调用IRS接口,返回数据 + // 访问计数 + int count = 0; + for (String carPlate : carPlateList) { + String dataJsonStr = accidentService.accidentQuery(carPlate); + count++; + log.info("已访问事故查询IRS接口 {} 次", count); + log.info("此次访问的事故车牌号为 {}",carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + continue; + } + // 获取车牌号的所有事故信息 + Map> accidentIrsDataMap = accidentIrsDataService.list().stream() + .collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + + for (JSONObject jsonObject : accidentArray) { + VehicleAccidentIrsData accidentIrsData = new VehicleAccidentIrsData(); + accidentIrsData.setCarPlate(carPlate); + String jsonString = jsonObject.toJSONString(); + accidentIrsData.setJsonStrData(jsonString); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + + if (accidentIrsDataMap.containsKey(carPlate)) { + List dataList = accidentIrsDataMap.get(carPlate); + Map dataMap = dataList.stream() + .collect(Collectors.toMap(v -> v.getCarPlate() + v.getAccidentTime(),v -> v)); + String key = accidentTime + carPlate; + if (dataMap.containsKey(key)) { + VehicleAccidentIrsData irsData = dataMap.get(key); + // 数据已经存在 + accidentIrsData.setId(irsData.getId()); + } + } + accidentIrsData.setAccidentTime(accidentTime); + accidentIrsData.setCreateOn(LocalDateTime.now()); + accidentIrsData.setUpdateOn(LocalDateTime.now()); + accidentIrsDataService.saveOrUpdate(accidentIrsData); + } + } + } + } + } + + //这个下面是单独函数 + public static Workbook readExcel(InputStream is, String extString) { + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if (".xls".equals(extString)) { + return wb = new HSSFWorkbook(is); + } else if (".xlsx".equals(extString)) { + return wb = new XSSFWorkbook(is); + } else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } + + public void illegalDataSingleSave() throws FileNotFoundException { + List list = new ArrayList<>(); + Set set = new HashSet<>(); + + File directory = new File(""); + //临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File f = new File( filePath + File.separator + "车辆违法车牌号.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + list.add(carPlate); + } + } + + // 去重 + List carPlateList = list.stream() + .filter(set::add) + .collect(Collectors.toList()); + + // 调用IRS接口,返回数据 + // 访问计数 + int count = 0; + for (String carPlate : carPlateList) { + String dataJsonStr = carService.vehicleIllegalQuery(carPlate); + log.info("获取到的数据为:" + dataJsonStr); + count++; + log.info("已访问车辆违法查询IRS接口 {} 次", count); + log.info("此次访问的违法车牌号为 {}",carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + log.info("data为:" + data); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有违法行为信息!"); + continue; + } + // 获取车牌号的所有违章信息 + Map> violationIrsDataMap = violationIrsDataService.list().stream() + .collect(Collectors.groupingBy(VehicleViolationIrsData::getCarPlate)); + + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + VehicleViolationIrsData vid = new VehicleViolationIrsData(); + vid.setCarPlate(carPlate); + // 获取违法日期 + Timestamp wfsj = jsonObject.getTimestamp("wfsj"); + LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj); + + String wfxw = jsonObject.getString("wfxw"); + vid.setViolationType(wfxw); + + if (violationIrsDataMap.containsKey(carPlate)) { + List dataList = violationIrsDataMap.get(carPlate); + // 对集合进行去重 + HashSet hashSet = new HashSet<>(); + List violationIrsDataList = dataList.stream() + .filter(d -> hashSet.add(d.getCarPlate() + d.getViolationTime() + d.getViolationType())) + .collect(Collectors.toList()); + Map dataMap = violationIrsDataList.stream() + .collect(Collectors.toMap(v -> v.getCarPlate() + v.getViolationTime() + v.getViolationType(),v -> v)); + String key = carPlate + vehicleIllegalTime + wfxw; + if (dataMap.containsKey(key)) { + VehicleViolationIrsData irsData = dataMap.get(key); + // 数据已经存在 + vid.setId(irsData.getId()); + } + } + vid.setViolationTime(vehicleIllegalTime); + String jsonStr = jsonObject.toJSONString(); + vid.setJsonStrData(jsonStr); + String cfzl = jsonObject.getString("cfzl"); + vid.setViolationKind(cfzl); + vid.setCreateOn(LocalDateTime.now()); + vid.setUpdateOn(LocalDateTime.now()); + violationIrsDataService.saveOrUpdate(vid); + } + } + } + } + + // 保存不重复的车牌号到数据库中 + public void carPlateSave() { + LambdaQueryWrapper query = Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate).isNotNull(NdVehicleBaseInfo::getCarPlate); + HashSet carPlateSet = new HashSet<>(); + // 获取去重后的车辆信息 + List list = vehicleBaseInfoService.list(query).stream() + .filter(v -> carPlateSet.add(v.getCarPlate())).collect(Collectors.toList()); + // 获取所有车牌号 + List carPlates = CollUtils.fieldList(list, NdVehicleBaseInfo::getCarPlate); + + List tempList = carPlates.stream().map(c -> { + IrsTempCarplate tempCarPlate = new IrsTempCarplate(); + tempCarPlate.setCarPlate(c); + return tempCarPlate; + }).collect(Collectors.toList()); + irsTempCarplateService.saveBatch(tempList); + } + + + // 日志分析 + public void logSave() { + // 关键词 + String keyword = "此次访问的车牌号为"; + + try (BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\CMM\\Desktop\\0515\\info.log")); + BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\Users\\CMM\\Desktop\\0515\\output.log"))) { + String line; + while ((line = reader.readLine()) != null) { + if (line.matches(".*" + keyword + ".*")) { + // 获取指定内容在行中的起始位置 + int startIndex = line.indexOf("为"); + // 截取指定内容及其后面的内容 + String extractedContent = line.substring(startIndex + 1); + // 将截取的内容写入输出文件 + writer.write(extractedContent); + // 换行 + writer.newLine(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + //// 关键词 + //String keyword = "此次访问的违法车牌号为"; + // + //try (BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0517\\info.log")); + // BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0517\\output.log"))) { + // String line; + // while ((line = reader.readLine()) != null) { + // if (line.matches(".*" + keyword + ".*")) { + // // 获取指定内容在行中的起始位置 + // int startIndex = line.indexOf("为"); + // // 截取指定内容及其后面的内容 + // String extractedContent = line.substring(startIndex + 1); + // // 将截取的内容写入输出文件 + // writer.write(extractedContent); + // // 换行 + // writer.newLine(); + // } + // } + //} catch (IOException e) { + // e.printStackTrace(); + //} + LocalDateTime startTime = LocalDateTimeUtil.parse(NdDateUtils.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + LocalDateTime endTime = LocalDateTimeUtil.parse(NdDateUtils.format(LocalDateTime.now().plusMinutes(1), DatePattern.NORM_DATETIME_MINUTE_PATTERN), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + System.out.println(startTime); + System.out.println(endTime); + + } + + /** + * 从IRS事故数据表中更新数据到车辆事故数据表中 + * @return void + * @author CMM + * @since 2023/05/16 10:26 + */ + public void updateAccidentData() { + + // 从IRS事故数据表中更新数据到车辆事故数据表中 + Map> listMap = + accidentIrsDataService.list().stream().collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + + // 获取车牌号 + Set carPlateList = + accidentIrsDataService.list().stream().map(VehicleAccidentIrsData::getCarPlate).collect(Collectors.toSet()); + + // 获取车辆基本信息 + List vehicleBaseInfos = vehicleBaseInfoService + .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).in(NdVehicleBaseInfo::getCarPlate, carPlateList)); + Map vehicleBaseInfoMap = + vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取企业信息 + Map companyMap = + companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + + // 获取已经存在的事故数据 + List accidentTmpVas = vehicleAccidentService + .list(Wrappers.lambdaQuery(NdVehicleAccident.class).in(NdVehicleAccident::getCarPlate, carPlateList)); + Map accidentMap = accidentTmpVas.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>( + Comparator.comparing(a -> a.getCarPlate() + StrPool.SEMICOLON + a.getAccidentTime()))), + ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getAccidentTime(), d -> d)); + + // 获取已经存在的死亡事故数据 + List deadAccidentTmpVas = vehicleAccidentDeadService.list( + Wrappers.lambdaQuery(NdVehicleAccidentDead.class).in(NdVehicleAccidentDead::getCarPlate, carPlateList)); + Map deadAccidentMap = deadAccidentTmpVas.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>( + Comparator.comparing(a -> a.getCarPlate() + StrPool.SEMICOLON + a.getAccidentTime()))), + ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getAccidentTime(), d -> d)); + + for (String carPlate : carPlateList) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + + //if (Objects.isNull(vehicleBaseInfo)) { + // log.info("该车牌号不在系统中!"); + // continue; + //} + //// 查出对应车牌号关联的责任驾驶员 + // String driverName = vehicleBaseInfo.getResponsibleDriverFirst(); + // + // if (Objects.isNull(driverName)) { + // log.info("该车牌号没有责任驾驶员!"); + // continue; + // } + + Long companyId = null; + Company company = null; + if (Objects.nonNull(vehicleBaseInfo)) { + companyId = vehicleBaseInfo.getCompanyId(); + company = companyMap.get(companyId); + } + + // 获取IRS事故数据 + List accidentIrsDataList = listMap.get(carPlate); + + for (VehicleAccidentIrsData accidentIrsData : accidentIrsDataList) { + // 解析获取事故时间等信息 + String jsonStrData = accidentIrsData.getJsonStrData(); + JSONObject jsonObject = JSON.parseObject(jsonStrData); + + // 获取行政区划 + String xzqh = jsonObject.getString("XZQH"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + // 获取事故地点 + String sgdd = jsonObject.getString("SGDD"); + // 获取车辆类型 + Integer vehicleType = null; + if (Objects.nonNull(vehicleBaseInfo)) { + vehicleType = vehicleBaseInfo.getVehicleType(); + } + // 获取受伤人数 + Integer ssrs = jsonObject.getInteger("SSRS"); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + // 获取简要案情 + String jyaq = jsonObject.getString("JYAQ"); + // 获取事故编号 + String sgbh = jsonObject.getString("SGBH"); + // 获取经纬度电子坐标 + String dzzb = jsonObject.getString("DZZB"); + String longitude = null; + String latitude = null; + if (StringUtils.isNotBlank(dzzb) && dzzb.contains(StrPool.COMMA)) { + String[] split = dzzb.split(StrPool.COMMA); + Double longitudeD = Double.valueOf(split[0]); + Double latitudeD = Double.valueOf(split[1]); + DecimalFormat df = new DecimalFormat("#.###"); + longitude = df.format(longitudeD); + latitude = df.format(latitudeD); + } else { + // 交管事故数据未上传经纬度坐标,从当天的GPS数据中根据车牌号和事故时间查询经纬度 + LocalDateTime startTime = LocalDateTimeUtil.parse( + NdDateUtils.format(accidentTime, DatePattern.NORM_DATETIME_MINUTE_PATTERN), + DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + LocalDateTime endTime = LocalDateTimeUtil.parse( + NdDateUtils.format(accidentTime.plusMinutes(1), DatePattern.NORM_DATETIME_MINUTE_PATTERN), + DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + // 如果跨天了就设置相同地查询边界 + if (!NdDateUtils.format(startTime, DatePattern.NORM_DATE_PATTERN) + .equals(NdDateUtils.format(endTime, DatePattern.NORM_DATE_PATTERN))) { + endTime = startTime; + } + + List vehiclePositionInfos; + try { + vehiclePositionInfos = iVehiclePositionInfoService.dynamicGpsTableHistorySearch(carPlate, + accidentTime, endTime, NdDateUtils.format(startTime, "yyyy_MM_dd")); + if (CollUtil.isNotEmpty(vehiclePositionInfos)) { + VehiclePositionInfo positionInfo; + List positionInfoList = vehiclePositionInfos.stream() + .filter(v -> v.getUpdateTime().equals(accidentTime)).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(positionInfoList)) { + positionInfo = positionInfoList.get(0); + } else { + // 没有时间完全一样的GPS数据,就取第一个 + positionInfo = vehiclePositionInfos.get(0); + } + longitude = String.valueOf(positionInfo.getCarLongitude()); + latitude = String.valueOf(positionInfo.getCarLatitude()); + } + } catch (Exception e) { + // GPS数据中查询不到数据(GPS表可能被删除) + log.error(e.getMessage()); + } + } + + // 获取当场、24小时、3日内、7日内、30日内死亡人数 + Integer swrs = Objects.nonNull(jsonObject.getInteger("SWRS")) ? jsonObject.getInteger("SWRS") : 0; + Integer swrs24 = Objects.nonNull(jsonObject.getInteger("SWRS24")) ? jsonObject.getInteger("SWRS24") : 0; + Integer swrs3 = Objects.nonNull(jsonObject.getInteger("SWRS3")) ? jsonObject.getInteger("SWRS3") : 0; + Integer swrs7 = Objects.nonNull(jsonObject.getInteger("SWRS7")) ? jsonObject.getInteger("SWRS7") : 0; + Integer swrs30 = Objects.nonNull(jsonObject.getInteger("SWRS30")) ? jsonObject.getInteger("SWRS30") : 0; + // 有死亡人数,再插入到死亡事故表中 + if (swrs != 0 || swrs24 != 0 || swrs3 != 0 || swrs7 != 0 || swrs30 != 0) { + // 插入数据到死亡事故表中 + NdVehicleAccidentDead accidentDead = new NdVehicleAccidentDead(); + // 判断是否已经插入过 + if (deadAccidentMap.containsKey(carPlate + accidentTime)) { + NdVehicleAccidentDead dead = deadAccidentMap.get(carPlate + accidentTime); + accidentDead.setId(dead.getId()); + } + if (swrs30 != 0) { + accidentDead.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accidentDead.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accidentDead.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accidentDead.setDeathToll(swrs24); + } else { + accidentDead.setDeathToll(swrs); + } + accidentDead.setInjuries(ssrs); + accidentDead.setRegionId(regionId); + accidentDead.setRegionName(regionName); + // 获取事故时间 + accidentDead.setAccidentTime(accidentTime); + accidentDead.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、企业名称 + accidentDead.setCarPlate(carPlate); + // accidentDead.setAccidentDriver(driverName); + accidentDead.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accidentDead.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accidentDead.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + accidentDead.setBriefCase(jyaq); + accidentDead.setAccidentNo(sgbh); + accidentDead.setLongitude(longitude); + accidentDead.setLatitude(latitude); + vehicleAccidentDeadService.saveOrUpdate(accidentDead); + } + // 插入到事故表中 + NdVehicleAccident accident = new NdVehicleAccident(); + // 判断事故类型 + if (swrs != 0 || swrs24 != 0 || swrs3 != 0 || swrs7 != 0 || swrs30 != 0){ + accident.setAccidentType(AccidentTypeEnum.DEAD.getCode()); + } else if (Objects.nonNull(ssrs) && ssrs > 0) { + accident.setAccidentType(AccidentTypeEnum.INJURY.getCode()); + }else { + accident.setAccidentType(AccidentTypeEnum.OTHER.getCode()); + } + // 获取已经存在的事故信息 + NdVehicleAccident vehicleAccident = accidentMap.get(carPlate + accidentTime); + // 获取事故时间 + if (accidentMap.containsKey(carPlate + accidentTime)) { + accident.setId(vehicleAccident.getId()); + } + accident.setInjuries(ssrs); + if (swrs30 != 0) { + accident.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accident.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accident.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accident.setDeathToll(swrs24); + } else { + accident.setDeathToll(swrs); + } + accident.setRegionId(regionId); + accident.setRegionName(regionName); + // 获取事故时间 + accident.setAccidentTime(accidentTime); + accident.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、车辆类型、企业名称 + accident.setCarPlate(carPlate); + + // accident.setAccidentDriver(driverName); + accident.setVehicleType(vehicleType); + accident.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accident.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accident.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + accident.setBriefCase(jyaq); + accident.setAccidentNo(sgbh); + accident.setLongitude(longitude); + accident.setLatitude(latitude); + vehicleAccidentService.saveOrUpdate(accident); + } + } + log.info("事故数据更新完成!"); + } + + public void updateViolationData() { + Map map = violationIrsDataService + .list(Wrappers.lambdaQuery(VehicleViolationIrsData.class) + .select(VehicleViolationIrsData::getId, VehicleViolationIrsData::getViolationType)) + .stream() + .collect(Collectors.toMap(VehicleViolationIrsData::getId, VehicleViolationIrsData::getViolationType)); + + List violationIdList = map.keySet().stream().filter(c -> { + String type = map.get(c); + return NO_DRIVING_LICENSE_LIST.contains(type) || NO_VEHICLE_LICENSE_LIST.contains(type) + || VIOLATION_TRAFFIC_LIGHTS_LIST.contains(type) || VIOLATION_TIME_LIST.contains(type) + || VIOLATION_ROAD_LIST.contains(type); + }).collect(Collectors.toList()); + + // 获取需要更新的数据 + Map> listMap = + violationIrsDataService.list(Wrappers.lambdaQuery(VehicleViolationIrsData.class) + .select(VehicleViolationIrsData::getId,VehicleViolationIrsData::getCarPlate, + VehicleViolationIrsData::getJsonStrData)) + .stream().filter(v -> violationIdList.contains(v.getId())) + .collect(Collectors.groupingBy(VehicleViolationIrsData::getCarPlate)); + + // 获取车牌号 + Set carPlateList = listMap.keySet(); + // 过滤掉不在系统中的车牌号 + List carPlates = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).select(NdVehicleBaseInfo::getCarPlate)); + List carPlateLists = carPlateList.stream().filter(carPlates::contains).collect(Collectors.toList()); + // 违章数据的车牌号都不在系统中,不需要更新 + if (CollUtil.isEmpty(carPlateLists)){ + log.info("没有需要更新的数据!"); + return; + } + // 获取车辆基本信息 + List vehicleBaseInfos = vehicleBaseInfoService + .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getCompanyId) + .in(NdVehicleBaseInfo::getCarPlate, carPlateLists)); + Map vehicleBaseInfoMap = + vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取企业信息 + Map companyMap = + companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + + // 获取已经存在的违章数据 + List violationTmpVas = vehicleViolationService + .list(Wrappers.lambdaQuery(NdVehicleViolation.class).in(NdVehicleViolation::getCarPlate, carPlateLists)); + Map violationMap = violationTmpVas.stream() + .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(a -> a.getCarPlate() + + StrPool.SEMICOLON + a.getViolationDate() + StrPool.SEMICOLON + a.getViolationType()))), ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getViolationDate() + d.getViolationType() + d.getViolationAddress(), d -> d)); + + for (String carPlate : carPlateLists) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + + Long companyId = vehicleBaseInfo.getCompanyId(); + Company company = null; + if (Objects.nonNull(companyId)) { + company = companyMap.get(companyId); + } + + // 获取IRS违章数据 + List violationIrsDataList = listMap.get(carPlate); + + for (VehicleViolationIrsData violationIrsData : violationIrsDataList) { + + // 解析获取事故时间等信息 + String jsonStrData = violationIrsData.getJsonStrData(); + JSONObject jsonObject = JSON.parseObject(jsonStrData); + + NdVehicleViolation vehicleViolation = new NdVehicleViolation(); + + // 获取违法日期 + Timestamp wfsj = jsonObject.getTimestamp("wfsj"); + LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj); + vehicleViolation.setViolationDate(vehicleIllegalTime); + // 获取违法地址 + String wfdz = jsonObject.getString("wfdz"); + // 获取违法行为 + String wfxw = jsonObject.getString("wfxw"); + // 获取违法编号 + String wfbh = jsonObject.getString("wfbh"); + + // 获取经纬度 + String longitude = jsonObject.getString("jd"); + String latitude = jsonObject.getString("wd"); + + // 判断是否已经插入过 + String key = carPlate + vehicleIllegalTime + wfdz + wfxw; + if (violationMap.containsKey(key)) { + NdVehicleViolation violation = violationMap.get(key); + vehicleViolation.setId(violation.getId()); + } + vehicleViolation.setCarPlate(carPlate); + // 获取行政区划 + String xzqh = jsonObject.getString("xzqh"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + vehicleViolation.setRegionId(regionId); + vehicleViolation.setRegionName(regionName); + // 如果是闯红灯 + if (VIOLATION_TRAFFIC_LIGHTS_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.RED_LIGHT.getCode()); + vehicleViolation.setAddressRedLight(wfdz); + } else if (NO_DRIVING_LICENSE_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode()); + vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVER_LINCENSE.getCode()); + } else if (NO_VEHICLE_LICENSE_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode()); + vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVE_PERMIT.getCode()); + } else if (VIOLATION_TIME_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.PERIOD.getCode()); + int hour = vehicleIllegalTime.getHour(); + int minute = vehicleIllegalTime.getMinute(); + String period = null; + // 时间段暂时设置为违章时间所在小时的前后半小时 + if (minute < 30) { + period = vehicleIllegalTime.minusHours(1).getHour() + TaskContant.Data.VIOLATION_TIME_HALF + + StrPool.DASH + hour + TaskContant.Data.VIOLATION_TIME_HALF; + } else { + period = hour + TaskContant.Data.VIOLATION_TIME_START + StrPool.DASH + + vehicleIllegalTime.plusHours(1).getHour() + TaskContant.Data.VIOLATION_TIME_START; + } + vehicleViolation.setViolationPeriod(period); + // if (hour >= TaskContant.Data.VIOLATION_TIME_SEVEN && hour <= + // TaskContant.Data.VIOLATION_TIME_NINE) { + // period = TaskContant.Data.VIOLATION_TIME_AM_START + StrPool.DASH + // + TaskContant.Data.VIOLATION_TIME_AM_END; + // vehicleViolation.setViolationPeriod(period); + // } else if (hour >= TaskContant.Data.VIOLATION_TIME_SIXTEEN + // && hour <= TaskContant.Data.VIOLATION_TIME_EIGHTEEN) { + // period = TaskContant.Data.VIOLATION_TIME_PM_START + StrPool.DASH + // + TaskContant.Data.VIOLATION_TIME_PM_END; + // vehicleViolation.setViolationPeriod(period); + // } + } else if (VIOLATION_ROAD_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.SECTION.getCode()); + vehicleViolation.setWaySection(wfdz); + } + // 获取当事人(驾驶员) + String driverName = jsonObject.getString("dsr"); + + vehicleViolation.setCompanyId(companyId); + if (Objects.nonNull(company)) { + vehicleViolation.setCompanyName(company.getName()); + } + // 驾驶员姓名和企业名称获取驾驶员信息 + List driverInfoList = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getDriverName, driverName).eq(DriverInfo::getCompanyId, companyId)); + if (CollUtil.isEmpty(driverInfoList)) { + log.info("该车牌号对应的企业下没有该驾驶员信息"); + } else { + // 获取最后一个 + DriverInfo driverInfo = driverInfoList.get(driverInfoList.size() - 1); + vehicleViolation.setDriverId(driverInfo.getId()); + } + vehicleViolation.setDriverName(driverName); + vehicleViolation.setLongitude(longitude); + vehicleViolation.setLatitude(latitude); + vehicleViolation.setViolationNo(wfbh); + vehicleViolation.setViolationAddress(wfdz); + vehicleViolationService.saveOrUpdate(vehicleViolation); + } + } + log.info("违章数据更新完成!"); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/IrsDriversLicenseManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/IrsDriversLicenseManage.java new file mode 100644 index 0000000..df4f5bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/IrsDriversLicenseManage.java @@ -0,0 +1,284 @@ +package com.ningdatech.carapi.irs.manage; + +import static com.ningdatech.carapi.irs.service.AbstractLicenseGetByIrsService.DELAY_MINUTES; + +import java.io.*; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Lists; +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.ningdatech.carapi.irs.service.DriverService; +import com.ningdatech.carapi.irs.service.IDriversLicenseRawService; +import com.ningdatech.carapi.irs.service.PullLicenseByIrsService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdcardUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * IrsLicensePullTask + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@Component +@Slf4j +public class IrsDriversLicenseManage { + + + private final PullLicenseByIrsService driverLicenseGetService; + private final PullLicenseByIrsService drivingLicenseGetService; + private final DriverService driverService; + private final IDriversLicenseRawService driversLicenseRawService; + + + public IrsDriversLicenseManage(@Qualifier("drivingLicensePullByIrsService") PullLicenseByIrsService driverLicenseGetService, + @Qualifier("drivingLicensePullByIrsService") PullLicenseByIrsService drivingLicenseGetService, + DriverService driverService, + IDriversLicenseRawService driversLicenseRawService) { + this.driverLicenseGetService = driverLicenseGetService; + this.drivingLicenseGetService = drivingLicenseGetService; + this.driverService = driverService; + this.driversLicenseRawService = driversLicenseRawService; + } + + @PostConstruct + public void initTask() { + driverLicenseGetService.initPullLicenseTask(); + drivingLicenseGetService.initPullLicenseTask(); + } + + public void submitDriverLicensePullTask() { + driverLicenseGetService.startPullLicenseTask(DELAY_MINUTES); + } + + public void submitDrivingLicensePullTask() { + drivingLicenseGetService.startPullLicenseTask(DELAY_MINUTES); + } + + public void vehicleLicenseSingleSave() { + List list = new ArrayList<>(); + Set set = new HashSet<>(); + + File directory = new File(""); + //临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File f = new File( filePath + File.separator + "行驶证身份证号.xlsx"); + Workbook wb = null; + try { + wb = readExcel(new FileInputStream(f), f.getName()); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 身份证号 + String idCard = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + list.add(idCard); + } + } + + // 去重并校验身份证号 + List idCardList = list.stream() + .filter(set::add) + .filter(IdcardUtil::isValidCard) + .collect(Collectors.toList()); + + // 调用IRS接口,返回数据 + // 访问计数 + int count = 0; + for (String idCard : idCardList) { + String dataJsonStr = driverService.vehicleLicenseQuery(idCard); + count++; + log.info("已访问行驶证查询IRS接口 {} 次", count); + log.info("此次访问的行驶证身份证号为 {}",idCard); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该身份证号没有行驶证信息!"); + continue; + } + // 获取身份证号的所有行驶证信息 + Map> drivingLicenseMap = driversLicenseRawService.list().stream() + .collect(Collectors.groupingBy(DriversLicenseRaw::getIdcard)); + + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + // 获取发证日期,判断是否重复 + Timestamp fZRQ = jsonObject.getTimestamp("fZRQ"); + + List driversLicenseRaws = drivingLicenseMap.get(idCard); + + List licenseRaws = Lists.newArrayList(); + if (CollUtil.isNotEmpty(driversLicenseRaws)) { + licenseRaws = driversLicenseRaws.stream().filter(d -> { + String detail = d.getDrivingLicenseDetail(); + JSONObject json = JSON.parseObject(detail, JSONObject.class); + Timestamp timestamp = json.getTimestamp("fZRQ"); + if (timestamp.equals(fZRQ)) { + return true; + } else { + return false; + } + }).collect(Collectors.toList()); + } + // 保存新增的行驶证信息 + if (CollUtil.isNotEmpty(licenseRaws)) { + DriversLicenseRaw driversLicenseRaw = new DriversLicenseRaw(); + driversLicenseRaw.setIdcard(idCard); + String jsonString = jsonObject.toJSONString(); + driversLicenseRaw.setDrivingLicenseDetail(jsonString); + driversLicenseRaw.setCreateOn(LocalDateTime.now()); + driversLicenseRaw.setUpdateOn(LocalDateTime.now()); + driversLicenseRawService.save(driversLicenseRaw); + } + + } + } + } + } + + public void drivingLicenseSingleSave() { + List list = new ArrayList<>(); + Set set = new HashSet<>(); + + File directory = new File(""); + //临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File f = new File( filePath + File.separator + "驾驶证身份证号.xlsx"); + Workbook wb = null; + try { + wb = readExcel(new FileInputStream(f), f.getName()); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 身份证号 + String idCard = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + list.add(idCard); + } + } + + // 去重并校验身份证号 + List idCardList = list.stream() + .filter(set::add) + .filter(IdcardUtil::isValidCard) + .collect(Collectors.toList()); + + // 调用IRS接口,返回数据 + // 访问计数 + int count = 0; + for (String idCard : idCardList) { + String dataJsonStr = driverService.vehicleLicenseQuery(idCard); + count++; + log.info("已访问驾驶证查询IRS接口 {} 次", count); + log.info("此次访问的驾驶证身份证号为 {}",idCard); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该身份证号没有驾驶证信息!"); + continue; + } + // 获取身份证号的所有驾驶证信息 + Map> drivingLicenseMap = driversLicenseRawService.list().stream() + .collect(Collectors.groupingBy(DriversLicenseRaw::getIdcard)); + + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + // 获取发证日期,判断是否重复 + Timestamp fZRQ = jsonObject.getTimestamp("fZRQ"); + + List driversLicenseRaws = drivingLicenseMap.get(idCard); + List licenseRaws = Lists.newArrayList(); + if (CollUtil.isNotEmpty(driversLicenseRaws)) { + licenseRaws = driversLicenseRaws.stream().filter(d -> { + String detail = d.getDriverLicenseDetail(); + JSONObject json = JSON.parseObject(detail, JSONObject.class); + Timestamp timestamp = json.getTimestamp("fZRQ"); + if (timestamp.equals(fZRQ)) { + return true; + } else { + return false; + } + }).collect(Collectors.toList()); + } + // 保存新增的驾驶证信息 + if (CollUtil.isNotEmpty(licenseRaws)) { + DriversLicenseRaw driversLicenseRaw = new DriversLicenseRaw(); + driversLicenseRaw.setIdcard(idCard); + String jsonString = jsonObject.toJSONString(); + driversLicenseRaw.setDriverLicenseDetail(jsonString); + driversLicenseRaw.setCreateOn(LocalDateTime.now()); + driversLicenseRaw.setUpdateOn(LocalDateTime.now()); + driversLicenseRawService.save(driversLicenseRaw); + } + } + } + } + } + + //这个下面是单独函数 + public static Workbook readExcel(InputStream is, String extString) { + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if (".xls".equals(extString)) { + return wb = new HSSFWorkbook(is); + } else if (".xlsx".equals(extString)) { + return wb = new XSSFWorkbook(is); + } else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } + + public List vehicleLicenseTest() { + return driverService.vehicleLicenseTest(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/SmsManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/SmsManage.java new file mode 100644 index 0000000..ec6b723 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/manage/SmsManage.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.irs.manage; + +import com.ningdatech.carapi.irs.service.SmsService; +import com.ningdatech.carapi.open.model.dto.UserLoginDTO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @Classname SmsManage + * @Description 短信通 + * @Date 2023/3/1 16:53 + * @Author PoffyZhang + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class SmsManage { + + private final SmsService service; + public String sendSmsCode(String mobile, String verificationCode) { + return service.sendSmsCode(mobile,verificationCode); + } + + public String getCode(UserLoginDTO param) { + return service.getCode(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.java new file mode 100644 index 0000000..ed8b23b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.mapper; + +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author WendyYang + * @since 2023-05-16 + */ +public interface DriversLicenseMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.xml new file mode 100644 index 0000000..13e9548 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/DriversLicenseMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.java new file mode 100644 index 0000000..3712f22 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.mapper; + +import com.ningdatech.carapi.irs.model.entity.IrsTempCarplate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2023-05-15 + */ +public interface IrsTempCarplateMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.xml new file mode 100644 index 0000000..2709044 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/IrsTempCarplateMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.java new file mode 100644 index 0000000..c4bc416 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.mapper; + +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2023-05-12 + */ +public interface VehicleAccidentIrsDataMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.xml new file mode 100644 index 0000000..9b7ff59 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleAccidentIrsDataMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.java new file mode 100644 index 0000000..3d1353f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.mapper; + +import com.ningdatech.carapi.irs.model.entity.VehicleViolationIrsData; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2023-05-12 + */ +public interface VehicleViolationIrsDataMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.xml new file mode 100644 index 0000000..2bd62ae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/mapper/VehicleViolationIrsDataMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DriverLicenseDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DriverLicenseDTO.java new file mode 100644 index 0000000..1ccac7b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DriverLicenseDTO.java @@ -0,0 +1,81 @@ +package com.ningdatech.carapi.irs.model.dto.irs; + +import lombok.Data; + +/** + *

+ * DriverLicenseDTO + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@Data +@SuppressWarnings("all") +public class DriverLicenseDTO { + + private String sfbd; + private String syyxqz; + private String bzcs; + private String ccfzjg; + private String ryzt; + private String signvalue; + private String zt; + private String dzyx; + private String csrq; + private String signcert; + private String lxzsyzbm; + private String signhashcode; + private String ljjf; + private String syrq; + private String ydabh; + private String hmcd; + private String bz; + private String jbr; + private String zjcx; + private String qfrq; + private String lsh; + private String lxdh; + private String gj; + private String sjhm; + private String lxzsxxdz; + private String xb; + private String xzqj; + private String lxzsxzqh; + private String dabh; + private String yzjcx; + private String xzqh; + private String cclzrq; + private String yxqz; + private String xh; + private String xm; + private String dwbh; + private String gxsj; + private String yxqs; + private String zxbh; + private String fzrq; + private String fzjg; + private String xczg; + private String xxtzrq; + private String djzsxxdz; + private String xzcrq; + private String jzqx; + private String djzsxzqh; + private String sfzmhm; + private String zzzm; + private String cfrq; + private String ly; + private String xczjcx; + private String sqdm; + private String sxqksbj; + private String jxmc; + private String zzfzjg; + private String jly; + private String xgzl; + private String zzfzrq; + private String sxbj; + private String sfzmmc; + private String tong_time; + private String glbm; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DrivingLicenseDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DrivingLicenseDTO.java new file mode 100644 index 0000000..3742603 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/DrivingLicenseDTO.java @@ -0,0 +1,153 @@ +package com.ningdatech.carapi.irs.model.dto.irs; + +import lombok.Data; + +/** + *

+ * irs返回行驶证详情 + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@Data +@SuppressWarnings("all") +public class DrivingLicenseDTO { + + private String zbzl; + private String zqyzl; + private String jyw; + private String xnyzl; + private String clyt; + private String djrq; + private String hdwjcd; + private String cdqdxslcds; + private String qzbfqz; + private String zj; + private String llpz1; + private String tnsvalue; + private String fdjrq; + private String signvalue; + private String zzcmc; + private String jkpzhm; + private String zs; + private String zt; + private String llpz2; + private String signcert; + private String signhashcode; + private String zzg; + private String jyhgbzbh; + private String yxh; + private String hpzk; + private String hpzl; + private String zzl; + private String fhgzrq; + private String bpcs; + private String cyry; + private String bz; + private String ccdjrq; + private String hgzbh; + private String zzz; + private String jbr; + private String dzyx; + private String hdzk; + private String gbthps; + private String csys; + private String djzsbh; + private String qpzk; + private String fprq; + private String sjhm; + private String dabh; + private String ncdqsy; + private String xzqh; + private String yxqz; + private String ccrq; + private String dybj; + private String cnzzzl; + private String wxmbc; + private String bdjcs; + private String dphgzbh; + private String dzbsxlh; + private String hpqysj; + private String cnzzxs; + private String sfxny; + private String hdzzl; + private String sfzmhm; + private String xsrq; + private String syqsrq; + private String xsjg; + private String hxnbcd; + private String sqdm; + private String fdjh; + private String yzbm2; + private String yzbm1; + private String qmbh; + private String xgzl; + private String ltgg; + private String zdjzshs; + private String tong_time; + private String cwkc; + private String cnzzzdy; + private String bzcs; + private String bxzzrq; + private String hxnbkd; + private String cnzzdtdy; + private String ytsx; + private String clsbdh; + private String xsdw; + private String hdfs; + private String cwkk; + private String cwkg; + private String zxxs; + private String xszbh; + private String nszm; + private String qlj; + private String nszmbh; + private String clly; + private String cllx; + private String lsh; + private String lxdh; + private String zsxxdz; + private String gl; + private String yqjyqz2; + private String syq; + private String hbdbqk; + private String syr; + private String xh; + private String gcjk; + private String pzbh1; + private String yqjyqzbfqz; + private String pzbh2; + private String clxh; + private String dwbh; + private String zsxzqh; + private String qddjxh; + private String jkpz; + private String hmbh; + private String pl; + private String fzrq; + private String hphm; + private String clpp1; + private String zdyzt; + private String fzjg; + private String clpp2; + private String gxrq; + private String fdjxh; + private String fdjgs; + private String hlj; + private String lts; + private String sfyzhgn; + private String qddjgl; + private String zzjglx; + private String cdqdxslcgk; + private String zzxzqh; + private String hxnbgd; + private String cnzzzdl; + private String qddjh; + private String rlzl; + private String zzxxdz; + private String syxz; + private String sfzmmc; + private String glbm; + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/ResponseDataDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/ResponseDataDTO.java new file mode 100644 index 0000000..bdbc85c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/dto/irs/ResponseDataDTO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.irs.model.dto.irs; + +import lombok.Data; + +import java.util.List; + +/** + *

+ * irs接口返回数据格式 + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@Data +public class ResponseDataDTO { + + private String code; + + private String msg; + + private T data; + + private List datas; + + private int dataCount; + + public boolean succeed() { + return "00".equals(code); + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/IrsTempCarplate.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/IrsTempCarplate.java new file mode 100644 index 0000000..9e0b437 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/IrsTempCarplate.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.irs.model.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2023-05-15 + */ +@Data +@TableName("nd_irs_temp_carplate") +@ApiModel(value = "IrsTempCarplate对象", description = "") +public class IrsTempCarplate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleAccidentIrsData.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleAccidentIrsData.java new file mode 100644 index 0000000..12f6ad3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleAccidentIrsData.java @@ -0,0 +1,98 @@ +package com.ningdatech.carapi.irs.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2023-05-12 + */ +@TableName("nd_vehicle_accident_irs_data") +@ApiModel(value = "AccidentIrsData对象", description = "") +public class VehicleAccidentIrsData implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("事故发生时间") + private LocalDateTime accidentTime; + + @ApiModelProperty("irs返回事故数据字符串") + private String jsonStrData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public String getCarPlate() { + return carPlate; + } + + public void setCarPlate(String carPlate) { + this.carPlate = carPlate; + } + public LocalDateTime getAccidentTime() { + return accidentTime; + } + + public void setAccidentTime(LocalDateTime accidentTime) { + this.accidentTime = accidentTime; + } + public String getJsonStrData() { + return jsonStrData; + } + + public void setJsonStrData(String jsonStrData) { + this.jsonStrData = jsonStrData; + } + public LocalDateTime getCreateOn() { + return createOn; + } + + public void setCreateOn(LocalDateTime createOn) { + this.createOn = createOn; + } + public LocalDateTime getUpdateOn() { + return updateOn; + } + + public void setUpdateOn(LocalDateTime updateOn) { + this.updateOn = updateOn; + } + + @Override + public String toString() { + return "AccidentIrsData{" + + "id=" + id + + ", carPlate=" + carPlate + + ", accidentTime=" + accidentTime + + ", jsonStrData=" + jsonStrData + + ", createOn=" + createOn + + ", updateOn=" + updateOn + + "}"; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleViolationIrsData.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleViolationIrsData.java new file mode 100644 index 0000000..dfd57d6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/model/entity/VehicleViolationIrsData.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.irs.model.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2023-05-12 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("nd_vehicle_violation_irs_data") +@ApiModel(value = "VehicleViolationIrsData对象", description = "") +public class VehicleViolationIrsData implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆违章时间") + private LocalDateTime violationTime; + + @ApiModelProperty("irs返回车辆违章数据字符串") + private String jsonStrData; + + @ApiModelProperty("车辆违章类型") + private String violationType; + + @ApiModelProperty("车辆违章种类") + private String violationKind; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AbstractLicenseGetByIrsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AbstractLicenseGetByIrsService.java new file mode 100644 index 0000000..0c9ae6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AbstractLicenseGetByIrsService.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.cache.redis.RedisOps; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; +import java.util.concurrent.*; + +/** + *

+ * AbstractLicenseGetByIrsService + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@RequiredArgsConstructor +public abstract class AbstractLicenseGetByIrsService { + + protected final IDriverInfoService driverInfoService; + protected final RestTemplate restTemplate; + protected final RefreshKeyService refreshKeyService; + protected final RedisOps redisOps; + protected final IDriversLicenseRawService driversLicenseRawService; + + public static final String RK_DRIVER_LICENSE = "DRIVER_LICENSE_IRS"; + public static final String RK_DRIVING_LICENSE = "DRIVING_LICENSE_IRS"; + + protected static final int LIMIT_BY_DAY = 100; + + // 应用appKey + protected static final String APP_KEY = "A330000100000202105003941"; + protected static final String APP_SECRET = "e07fd4471e92410d9860282d939b1217"; + + protected static final Map> FUTURE_MAP = new ConcurrentHashMap<>(); + public static ScheduledExecutorService scheduler; + + protected static final int MINUTES_DAY = 24 * 60; + protected static final int INIT_DELAY_MINUTES = 5; + + public static final int DELAY_MINUTES = 2; + + /** + * 开启证件信息获取任务 + * + * @param rk 证件类型 + * @param service 证件信息获取实现类 + * @param delayMinutes 延迟执行时间 + */ + protected void startLicensePullTask(String rk, PullLicenseByIrsService service, Integer delayMinutes) { + if (scheduler == null || scheduler.isShutdown()) { + scheduler = Executors.newScheduledThreadPool(2); + } + Future future = scheduler.scheduleAtFixedRate(() -> { + service.pullLicense(); + try { + long leftCnt = service.getLeftCount(); + boolean status = service.runningStatus(); + if (!status && leftCnt == 0) { + Future self = FUTURE_MAP.remove(rk); + if (self != null && !self.isCancelled()) { + self.cancel(true); + } + if (FUTURE_MAP.isEmpty()) { + scheduler.shutdown(); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + }, delayMinutes, MINUTES_DAY, TimeUnit.MINUTES); + FUTURE_MAP.put(rk, future); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AccidentService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AccidentService.java new file mode 100644 index 0000000..3a58ec1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/AccidentService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.irs.service; + +import java.util.List; + +public interface AccidentService { + + List getAccident(); + + List accidentQuery(); + + /** + * 根据车牌号查询IRS数据 + * @param hphm + * @return + */ + String accidentQuery(String hphm); + + String accidentQuery(String hphm,Integer index); + + String getAccident(String sgbh); + + String updateAccident(); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/CarService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/CarService.java new file mode 100644 index 0000000..b1f9011 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/CarService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.irs.service; + +/** + * CarService + * @author CMM + * @since 2023/04/23 15:20 + */ +public interface CarService { + + String vehicleIllegalQuery(); + + /** + * 根据号牌号码(车牌号)查询车辆违法数据 + * @param hphm + * @return + */ + String vehicleIllegalQuery(String hphm); + + /** + * 根据号牌号码(车牌号)查询车辆违法数据 + * @param hphm + * @return + */ + String vehicleIllegalQuery(String hphm,Integer index); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/DriverService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/DriverService.java new file mode 100644 index 0000000..1a8c67e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/DriverService.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.irs.service; + +import java.util.List; + +/** + * DriverService + * @author CMM + * @since 2023/05/21 19:01 + */ + +public interface DriverService { + /** + * 根据车牌号查询驾驶员行驶证 + * @return + */ + String vehicleLicenseQuery(String carPlate); + + /** + * 根据车牌号查询驾驶员行驶证 + * @return + */ + String vehicleLicenseQuery(String carPlate,Integer index); + + /** + * 根据身份证号查询驾驶员驾驶证 + * @return + */ + + String drivingLicenseQuery(String idCard); + + List vehicleLicenseTest(); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/FilePreviewService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/FilePreviewService.java new file mode 100644 index 0000000..a01e761 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/FilePreviewService.java @@ -0,0 +1,13 @@ +package com.ningdatech.carapi.irs.service; + +public interface FilePreviewService { + /** + * 文件预览 + * @param ext 附件后缀 + * @param remoteUrl 附件下载地址 + * @param markText 自定义水印(false 不显示水印) + * @param upt true 表示强制更新预览(可不传) + * @return + */ + String filePreview(String ext,String remoteUrl,String markText,String upt); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IDriversLicenseRawService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IDriversLicenseRawService.java new file mode 100644 index 0000000..4036f62 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IDriversLicenseRawService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author WendyYang + * @since 2023-05-16 + */ +public interface IDriversLicenseRawService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IIrsTempCarplateService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IIrsTempCarplateService.java new file mode 100644 index 0000000..a656c05 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IIrsTempCarplateService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.carapi.irs.model.entity.IrsTempCarplate; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2023-05-15 + */ +public interface IIrsTempCarplateService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleAccidentIrsDataService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleAccidentIrsDataService.java new file mode 100644 index 0000000..0fdd988 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleAccidentIrsDataService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2023-05-12 + */ +public interface IVehicleAccidentIrsDataService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleViolationIrsDataService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleViolationIrsDataService.java new file mode 100644 index 0000000..ded3a38 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/IVehicleViolationIrsDataService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.carapi.irs.model.entity.VehicleViolationIrsData; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2023-05-12 + */ +public interface IVehicleViolationIrsDataService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/PullLicenseByIrsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/PullLicenseByIrsService.java new file mode 100644 index 0000000..b89575b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/PullLicenseByIrsService.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.irs.service; + +/** + *

+ * LicensePullService + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +public interface PullLicenseByIrsService { + + /** + * 是否正在获取 + * + * @return / + */ + boolean runningStatus(); + + /** + * 剩余待处理数量 + * + * @return / + */ + long getLeftCount(); + + /** + * 调用irs接口获取证件信息 + * + * @param cardId 车牌号 + * @return / + */ + String getLicenseDetail(String cardId); + + /** + * 证件信息获取(设置执行状态) + */ + void pullLicense(); + + /** + * 证件信息获取 + */ + void pullLicenseDetail(); + + void initPullLicenseTask(); + + void startPullLicenseTask(int delayMinutes); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/RefreshKeyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/RefreshKeyService.java new file mode 100644 index 0000000..a8d18ca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/RefreshKeyService.java @@ -0,0 +1,15 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.cache.model.cache.CacheKey; + +public interface RefreshKeyService { + + String refresh(); + + String getRequestSecret(String appKey, String appSecret); + String getRefreshSecret(String appKey, String appSecret); + String refreshSecret(String appKey, String refreshSecret); + + String getRequestSecret(String appKey, String appSecret, CacheKey requestKey, CacheKey refreshKey); + String refreshRequestSecret(String appKey, CacheKey requestKey, CacheKey refreshKey, String refreshSecret); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/SmsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/SmsService.java new file mode 100644 index 0000000..08659c4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/SmsService.java @@ -0,0 +1,12 @@ +package com.ningdatech.carapi.irs.service; + +import com.ningdatech.carapi.open.model.dto.UserLoginDTO; + +public interface SmsService { + + String sendMessage(String mobile,String content); + + String sendSmsCode(String mobile, String verificationCode); + + String getCode(UserLoginDTO param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/AccidentServieImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/AccidentServieImpl.java new file mode 100644 index 0000000..9423696 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/AccidentServieImpl.java @@ -0,0 +1,806 @@ +package com.ningdatech.carapi.irs.service.impl; + +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.ningdatech.carapi.car.position.service.IVehiclePositionInfoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.ningdatech.carapi.irs.service.AccidentService; +import com.ningdatech.carapi.irs.service.IVehicleAccidentIrsDataService; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import com.ningdatech.carapi.irs.utils.Md5Utils; +import com.ningdatech.carapi.safe.constant.AccidentTypeEnum; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportStatusEnum; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.file.utils.StrPool; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname AccidentServieImpl + * @Description + * @Date 2023/3/1 16:58 + * @Author PoffyZhang + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class AccidentServieImpl implements AccidentService { + + private final RestTemplate restTemplate; + private final RefreshKeyService refreshKeyService; + private final INdVehicleAccidentService vehicleAccidentService; + private final INdVehicleAccidentDeadService vehicleAccidentDeadService; + private final CachePlusOps cachePlusOps; + private final IVehicleAccidentIrsDataService accidentIrsDataService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final CompanyService companyService; + private final RegionsCacheHelper regionsCacheHelper; + private final IVehiclePositionInfoService iVehiclePositionInfoService; + + @Override + public List getAccident() { + // 应用appKey + String appKey = "A330000100000202105003941"; + // app密钥 + String appSecret = "e07fd4471e92410d9860282d939b1217"; + + // 刷新秘钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + log.info("requestSecret : {}",requestSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/certificate/4c7ECl4H7xX309J8.htm"; + + // 事故编号 + String sgbh1 = "330783120230000035"; + + List sgbhList = Lists.newArrayList(); + sgbhList.add(sgbh1); + + List resList = Lists.newArrayList(); + for (String sgbh : sgbhList) { + + MultiValueMap map = new LinkedMultiValueMap(); + String projectId = "9000001120230507162550676"; + map.add("appKey", appKey); + map.add("requestTime", requestTime); + map.add("projectId", projectId); + map.add("sgbh", sgbh); + map.add("sign", sign); + map.add("additional", "{}"); + map.add("Organization", "测试部门"); + map.add("Organization_ID", "123123"); + map.add("powerMatters", "12131212"); + map.add("subPowerMatters", "123"); + map.add("User_ID", "11111"); + map.add("User_Name", "sasasa"); + ResponseEntity responseEntity = null; + String res = null; + + try { + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, map, String.class); + log.info("[RestTemplateTest-事故责任认定书] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-事故责任认定书] http request error:" + e); + } + resList.add(res); + } + return resList; + } + + @Override + public List accidentQuery() { + + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + String innerAppKey = "210a2657177f478c808381deb13a4dac"; + + // 刷新秘钥 + //String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + + String url = "https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003007/dataSharing/YT9d9lbynbdwae2a.htm"; + // 获取车牌号的所有事故信息 + Map> accidentIrsDataMap = accidentIrsDataService.list().stream() + .collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + // 车牌号 + //List hphmList = Lists.newArrayList("浙FQ0350", "浙FQ9133", "浙A5W918", "皖CE7498", "浙A08C01", "浙A10B67", + // "浙A2X587", "浙A32C01", "浙A58D51", "浙A5W612", "浙A6T266", "浙A7T769", "浙A87A99", "浙A8V378", + // "浙A8X675", "浙A9W395", "浙C10503", "浙C18690", "浙C29834", "浙C31707", "浙C50774", "浙C52266", + // "浙C60570", "浙CB1067", "浙CD7156", "浙CD9307", "浙CM0185", "浙CM0530", "浙D06281", "浙D21710", + // "浙DE6628", "浙DK8334", "浙DR7626", "浙DS4531", "浙DT9961", "浙DW0280", "浙E22736", "浙E26621", + // "浙E35787", "浙E36017", "浙E61296", "浙E65230", "浙E66392", "浙E68952", "浙E69691", "浙FDJ589", + // "浙FDS332", "浙FG1096", "浙FL9735", "浙FN0693", "浙FN3161", "浙FP2719", "浙FV1233", "浙G26527", + // "浙G56057", "浙G57250", "浙G57322", "浙G59700", "浙G59773", "浙G71275", "浙G72831", "浙G72953", + // "浙G80298", "浙G97198", "浙H22426", "浙JB0993", "浙JB9232", "浙KK3520", "浙KK9576", "浙KM1560", + // "浙A5U783", "浙DJ3611", "浙A6Y375", "浙A6U922", "浙A6W577", "浙E28698", "浙EA7598", "浙E26285", + // "浙FH5719", "浙FQ0535", "浙G95837", "浙G88336", "浙G83080", "浙G83221", "浙KK9580", "浙KF2283", + // "浙J53439", "浙J96011", "浙J36206", "浙JB7869", "浙J21786", "浙JA6561", "浙J02703", "浙CD0103", + // "浙CH9707", "浙CM9758", "浙CL3917", "浙L17121", "浙D05980", "浙J17217", "浙H38803", "浙JA5611", + // "浙DH3577", "浙A32C01", "浙D18098", "浙A3Z386", "浙FAG361", "浙A8V905", "浙A98A65", "浙DV2412", + // "浙D16351", "浙H26806", "浙CL1381", "浙KK7680", "浙J00625", "浙G82887", "浙CJ3879", "浙L26560", + // "浙J36737", "浙A83C69", "浙L23611", "浙A10B22", "浙B0M838", "浙BX9108"); + + //List hphmList = Lists.newArrayList("浙E69638", "浙FN3726", "浙E67275", "浙DJ9937", "浙G27718"); + //List hphmList = Lists.newArrayList("浙A7V557", "浙A37B22", "浙G50189", "浙CH6355", + // "浙A03E89", "浙DS6620"); + List hphmList = Lists.newArrayList("浙A6P887", "浙G63797", "浙J01696", "浙C37222"); + + + // 号牌种类 + String hpzl = "01"; + int cnt = 0; + List resList = Lists.newArrayList(); + String[] carPlates = hphmList.stream().toArray(String[]::new); + for (int i = 0; i < carPlates.length; i++) { + String carPlate = carPlates[i]; + String dataJsonStr; + dataJsonStr = accidentQuery(carPlate,i); + log.info("此次访问的事故车牌号为 {}", carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + continue; + } + cnt = i + 1; + log.info("已访问事故查询IRS接口 {} 次", cnt); + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + + for (JSONObject jsonObject : accidentArray) { + VehicleAccidentIrsData accidentIrsData = new VehicleAccidentIrsData(); + accidentIrsData.setCarPlate(carPlate); + String jsonString = jsonObject.toJSONString(); + accidentIrsData.setJsonStrData(jsonString); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + if (accidentIrsDataMap.containsKey(carPlate)) { + List dataList = accidentIrsDataMap.get(carPlate); + Map dataMap = dataList.stream() + .collect(Collectors.toMap(VehicleAccidentIrsData::getAccidentTime, v -> v)); + if (dataMap.containsKey(accidentTime)) { + VehicleAccidentIrsData irsData = dataMap.get(accidentTime); + // 数据已经存在 + accidentIrsData.setId(irsData.getId()); + } + } + accidentIrsData.setAccidentTime(accidentTime); + accidentIrsData.setCreateOn(LocalDateTime.now()); + accidentIrsData.setUpdateOn(LocalDateTime.now()); + accidentIrsDataService.saveOrUpdate(accidentIrsData); + } + } + } + resList.add(dataJsonStr); + } + + //for (String hphm : hphmList) { + // + // // 请求秘钥 + // CacheKey requestKey = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_QUERY_REQUEST_SECRET_TEST); + // // 刷新密钥 + // CacheKey refreshKey = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_QUERY_REFRESH_SECRET_TEST); + // // 根据key获取缓存中的请求秘钥和刷新密钥 + // String requestSecret = cachePlusOps.get(requestKey); + // String refreshSecret = cachePlusOps.get(refreshKey); + // + // // 任务第一次调用接口,获取刷新秘钥和请求秘钥,并保存到redis中 + // try { + // if (Objects.nonNull(refreshSecret)) { + // requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + // if (requestSecret == null) { + // requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + // } + // } else { + // requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + // } + // } catch (Exception e) { + // log.error("获取刷新密钥失败:{},此次事故查询车牌号为{}", e.getMessage(), hphm); + // return null; + // } + // if (Objects.isNull(refreshSecret)) { + // try { + // requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + // if (requestSecret == null) { + // return null; + // } + // } catch (Exception e) { + // log.error("获取刷新密钥失败:{},此次事故查询车牌号为{}", e.getMessage(), hphm); + // return null; + // } + // } + // // 不是第一次调用,看请求秘钥是否过期 + // // 刷新密钥有效期两天,而定时任务每天都会执行一次,每次任务执行又会更新刷新密钥,所以刷新密钥不会过期 + // // 只需判断请求秘钥是否过期 + // else if (Objects.isNull(requestSecret)) { + // try { + // // 调用IRS刷新秘钥接口,更新刷新密钥和请求秘钥 + // requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + // if (requestSecret == null) { + // requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + // } + // } catch (Exception e) { + // log.error("刷新请求密钥失败:{},此次事故查询车牌号为{}", e.getMessage(), hphm); + // return null; + // } + // } + // + // // 请求签名 + // Long requestTime = System.currentTimeMillis(); + // String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + // + // MultiValueMap map = new LinkedMultiValueMap(); + // // 附加信息 + // map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\"}"); + // map.add("appKey",appKey); + // map.add("requestTime",requestTime); + // map.add("sign",sign); + // map.add("hpzl",hpzl); + // map.add("hphm",hphm); + // String res = null; + // try { + // HttpHeaders headers = new HttpHeaders(); + // headers.add("innerAppKey",innerAppKey); + // HttpEntity httpEntity = new HttpEntity<>(map,headers); + // log.info("请求参数 :{}", JSON.toJSONString(map)); + // res = restTemplate.postForObject(url, httpEntity ,String.class); + // log.info("[RestTemplateTest-事故查询] http request :{}", res); + // } catch (Exception e) { + // log.error("[RestTemplateTest-事故查询] http request error", e); + // } + // resList.add(res); + //} + + // 更新事故数据 + updateAccidentData(); + log.info("更新事故数据完成!"); + String s = resList.toString(); + log.info("查询结果为:" + s); + + return resList; + } + + @Override + public String accidentQuery(String hphm) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + String innerAppKey = "210a2657177f478c808381deb13a4dac"; + String hpzl = "01"; + + // 刷新秘钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003007/dataSharing/YT9d9lbynbdwae2a.htm"; + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + map.add("hpzl",hpzl); + map.add("hphm",hphm); + String res = null; + try { + HttpHeaders headers = new HttpHeaders(); + headers.add("innerAppKey",innerAppKey); + HttpEntity httpEntity = new HttpEntity<>(map,headers); + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, httpEntity ,String.class); + log.info("[RestTemplateTest-事故查询] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-事故查询] http request error", e); + } + return res; + } + + @Override + public String accidentQuery(String hphm,Integer index) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + String innerAppKey = "210a2657177f478c808381deb13a4dac"; + String hpzl = "01"; + + // 请求秘钥 + CacheKey requestKey = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_QUERY_REQUEST_SECRET); + // 刷新密钥 + CacheKey refreshKey = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_QUERY_REFRESH_SECRET); + // 根据key获取缓存中的请求秘钥和刷新密钥 + String requestSecret = cachePlusOps.get(requestKey); + String refreshSecret = cachePlusOps.get(refreshKey); + if (index == 0) { + // 任务第一次调用接口,获取刷新秘钥和请求秘钥,并保存到redis中 + try { + if (Objects.nonNull(refreshSecret)){ + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + }else { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次事故查询车牌号为{}", e.getMessage(), hphm); + return null; + } + } else if (Objects.isNull(refreshSecret)) { + try { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + if (requestSecret == null) { + return null; + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次事故查询车牌号为{}", e.getMessage(), hphm); + return null; + } + } + // 不是第一次调用,看请求秘钥是否过期 + // 刷新密钥有效期两天,而定时任务每天都会执行一次,每次任务执行又会更新刷新密钥,所以刷新密钥不会过期 + // 只需判断请求秘钥是否过期 + else if (Objects.isNull(requestSecret)) { + try { + // 调用IRS刷新秘钥接口,更新刷新密钥和请求秘钥 + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("刷新请求密钥失败:{},此次事故查询车牌号为{}", e.getMessage(), hphm); + return null; + } + } + + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + log.info("请求参数中请求秘钥为:" + requestSecret); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003007/dataSharing/YT9d9lbynbdwae2a.htm"; + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + map.add("hpzl",hpzl); + map.add("hphm",hphm); + HttpHeaders headers = new HttpHeaders(); + headers.add("innerAppKey", innerAppKey); + HttpEntity httpEntity = new HttpEntity<>(map, headers); + log.info("请求参数 :{}", JSON.toJSONString(map)); + String res = restTemplate.postForObject(url, httpEntity, String.class); + log.info("[RestTemplateTest-事故查询] http request :{}", res); + return res; + } + + @Override + public String getAccident(String sgbh) { + // 应用appKey + String appKey = "A330000100000202105003941"; + // app密钥 + String appSecret = "e07fd4471e92410d9860282d939b1217"; + + // 请求秘钥 + CacheKey requestKey = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_DUTY_REQUEST_SECRET); + // 刷新密钥 + CacheKey refreshKey = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_DUTY_REFRESH_SECRET); + // 根据key获取缓存中的请求秘钥和刷新密钥 + String requestSecret = cachePlusOps.get(requestKey); + String refreshSecret = cachePlusOps.get(refreshKey); + + try { + // 不是第一次调用接口,获取刷新秘钥和请求秘钥,并保存到redis中 + if (Objects.nonNull(refreshSecret)) { + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } else { + // 第一次调用接口,获取刷新秘钥和请求秘钥,并保存到redis中 + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次事故责任认定书事故编号为{}", e.getMessage(), sgbh); + return null; + } + + log.info("requestSecret : {}",requestSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/certificate/4c7ECl4H7xX309J8.htm"; + + MultiValueMap map = new LinkedMultiValueMap(); + String projectId = "9000001120230507162550676"; + map.add("appKey", appKey); + map.add("requestTime", requestTime); + map.add("projectId", projectId); + map.add("sgbh", sgbh); + map.add("sign", sign); + map.add("additional", "{}"); + map.add("Organization", "测试部门"); + map.add("Organization_ID", "123123"); + map.add("powerMatters", "12131212"); + map.add("subPowerMatters", "123"); + map.add("User_ID", "11111"); + map.add("User_Name", "sasasa"); + ResponseEntity responseEntity = null; + String res = null; + + try { + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, map, String.class); + log.info("[RestTemplateTest-事故责任认定书] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-事故责任认定书] http request error:" + e); + } + + return res; + } + + @Override + public String updateAccident() { + // 获取认定内容为空,事故编号不为空的事故数据 + List accidents = vehicleAccidentService.list().stream() + .filter(v -> Objects.nonNull(v.getAccidentNo()) && Objects.isNull(v.getFirmContent())) + .collect(Collectors.toList()); + + // 从车辆死亡事故信息表中获取事故编号 + Map deadAccidentNoMap = vehicleAccidentDeadService.list(Wrappers.lambdaQuery(NdVehicleAccidentDead.class) + .select(NdVehicleAccidentDead::getAccidentNo,NdVehicleAccidentDead::getId)).stream() + // 筛选出事故编号不为空,但没有认定内容的死亡事故数据 + .filter(v -> Objects.nonNull(v.getAccidentNo()) && Objects.isNull(v.getFirmContent())) + .collect(Collectors.toMap(v -> v.getAccidentNo() + StrPool.DASH + v.getCarPlate(),NdVehicleAccidentDead::getId)); + + // 如果有事故编号且都已经有了认定内容,则不运行 + if (CollUtil.isEmpty(accidents)){ + log.info("此次任务数据量为空!"); + return null; + } + + for (NdVehicleAccident accident : accidents) { + String carPlate = accident.getCarPlate(); + String sgbh = accident.getAccidentNo(); + // 获取事故责任认定书返回结果 + String dataJsonStr = getAccident(sgbh); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + // 获取返回数据 + String datas = object.getString("datas"); + JSONObject jsonObject = JSON.parseObject(datas, JSONObject.class); + // 获取结构化数据签名结果 + // 未查询到结果 + if (Objects.isNull(jsonObject)){ + log.info("事故编号{}未查询到事故责任认定书数据",sgbh); + continue; + } + String elcLicenceStruct = jsonObject.getString("ELC_LICENCE_STRUCT"); + JSONObject elcLicenceStructObject = JSON.parseObject(elcLicenceStruct, JSONObject.class); + // 未查询到结果 + if (Objects.isNull(elcLicenceStructObject)){ + log.info("事故编号{}未查询到事故责任认定书数据",sgbh); + continue; + } + // 获取结构化数据 + String data = elcLicenceStructObject.getString("DATA"); + JSONObject dataObject = JSON.parseObject(data, JSONObject.class); + // 未查询到结果 + if (Objects.isNull(dataObject)){ + log.info("事故编号{}未查询到事故责任认定书数据",sgbh); + continue; + } + // 获取认定内容 + String rdnr = dataObject.getString("RDNR"); + // 更新认定内容到车辆事故信息表 + accident.setFirmContent(rdnr); + vehicleAccidentService.updateById(accident); + // 如果是亡人事故,更新认定内容到车辆死亡事故信息表 + String key = sgbh + StrPool.DASH + carPlate; + if (deadAccidentNoMap.containsKey(key)){ + Long deadAccidentId = deadAccidentNoMap.get(key); + NdVehicleAccidentDead deadAccident = vehicleAccidentDeadService.getById(deadAccidentId); + deadAccident.setFirmContent(rdnr); + vehicleAccidentDeadService.updateById(deadAccident); + } + } + return "更新成功"; + } + + /** + * 从IRS事故数据表中更新数据到车辆事故数据表中 + * + * @return void + * @author CMM + * @since 2023/05/16 10:26 + */ + private void updateAccidentData() { + + // 从IRS事故数据表中更新数据到车辆事故数据表中 + Map> listMap = + accidentIrsDataService.list().stream().collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + + // 获取车牌号 + Set carPlateList = + accidentIrsDataService.list().stream().map(VehicleAccidentIrsData::getCarPlate).collect(Collectors.toSet()); + + // 获取车辆基本信息 + List vehicleBaseInfos = vehicleBaseInfoService + .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).in(NdVehicleBaseInfo::getCarPlate, carPlateList)); + Map vehicleBaseInfoMap = + vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取企业信息 + Map companyMap = + companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + + // 获取已经存在的事故数据 + List accidentTmpVas = vehicleAccidentService + .list(Wrappers.lambdaQuery(NdVehicleAccident.class).in(NdVehicleAccident::getCarPlate, carPlateList)); + Map accidentMap = accidentTmpVas.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>( + Comparator.comparing(a -> a.getCarPlate() + StrPool.SEMICOLON + a.getAccidentTime()))), + ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getAccidentTime(), d -> d)); + + // 获取已经存在的死亡事故数据 + List deadAccidentTmpVas = vehicleAccidentDeadService.list( + Wrappers.lambdaQuery(NdVehicleAccidentDead.class).in(NdVehicleAccidentDead::getCarPlate, carPlateList)); + Map deadAccidentMap = deadAccidentTmpVas.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>( + Comparator.comparing(a -> a.getCarPlate() + StrPool.SEMICOLON + a.getAccidentTime()))), + ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getAccidentTime(), d -> d)); + + for (String carPlate : carPlateList) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + //if (Objects.isNull(vehicleBaseInfo)) { + // log.info("该车牌号不在系统中!"); + // continue; + //} + //// 查出对应车牌号关联的责任驾驶员 + // String driverName = vehicleBaseInfo.getResponsibleDriverFirst(); + // + // if (Objects.isNull(driverName)) { + // log.info("该车牌号没有责任驾驶员!"); + // continue; + // } + Long companyId = null; + Company company = null; + if (Objects.nonNull(vehicleBaseInfo)) { + companyId = vehicleBaseInfo.getCompanyId(); + company = companyMap.get(companyId); + } + + // 获取IRS事故数据 + List accidentIrsDataList = listMap.get(carPlate); + + for (VehicleAccidentIrsData accidentIrsData : accidentIrsDataList) { + // 解析获取事故时间等信息 + String jsonStrData = accidentIrsData.getJsonStrData(); + JSONObject jsonObject = JSON.parseObject(jsonStrData); + + // 获取行政区划 + String xzqh = jsonObject.getString("XZQH"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + // 获取事故地点 + String sgdd = jsonObject.getString("SGDD"); + // 获取车辆类型 + Integer vehicleType = null; + if (Objects.nonNull(vehicleBaseInfo)) { + vehicleType = vehicleBaseInfo.getVehicleType(); + } + // 获取受伤人数 + Integer ssrs = jsonObject.getInteger("SSRS"); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + // 获取简要案情 + String jyaq = jsonObject.getString("JYAQ"); + // 获取事故编号 + String sgbh = jsonObject.getString("SGBH"); + // 获取经纬度电子坐标 + String dzzb = jsonObject.getString("DZZB"); + String longitude = null; + String latitude = null; + if (StringUtils.isNotBlank(dzzb) && dzzb.contains(StrPool.COMMA)) { + String[] split = dzzb.split(StrPool.COMMA); + Double longitudeD = Double.valueOf(split[0]); + Double latitudeD = Double.valueOf(split[1]); + DecimalFormat df = new DecimalFormat("#.###"); + longitude = df.format(longitudeD); + latitude = df.format(latitudeD); + } else { + // 交管事故数据未上传经纬度坐标,从当天的GPS数据中根据车牌号和事故时间查询经纬度 + LocalDateTime startTime = LocalDateTimeUtil.parse( + NdDateUtils.format(accidentTime, DatePattern.NORM_DATETIME_MINUTE_PATTERN), + DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + LocalDateTime endTime = LocalDateTimeUtil.parse( + NdDateUtils.format(accidentTime.plusMinutes(1), DatePattern.NORM_DATETIME_MINUTE_PATTERN), + DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + // 如果跨天了就设置相同地查询边界 + if (!NdDateUtils.format(startTime, DatePattern.NORM_DATE_PATTERN) + .equals(NdDateUtils.format(endTime, DatePattern.NORM_DATE_PATTERN))) { + endTime = startTime; + } + + List vehiclePositionInfos; + try { + vehiclePositionInfos = iVehiclePositionInfoService.dynamicGpsTableHistorySearch(carPlate, + accidentTime, endTime, NdDateUtils.format(startTime, "yyyy_MM_dd")); + if (CollUtil.isNotEmpty(vehiclePositionInfos)) { + VehiclePositionInfo positionInfo; + List positionInfoList = vehiclePositionInfos.stream() + .filter(v -> v.getUpdateTime().equals(accidentTime)).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(positionInfoList)) { + positionInfo = positionInfoList.get(0); + } else { + // 没有时间完全一样的GPS数据,就取第一个 + positionInfo = vehiclePositionInfos.get(0); + } + longitude = String.valueOf(positionInfo.getCarLongitude()); + latitude = String.valueOf(positionInfo.getCarLatitude()); + } + } catch (Exception e) { + // GPS数据中查询不到数据(GPS表可能被删除) + log.error(e.getMessage()); + } + } + + // 获取当场、24小时、3日内、7日内、30日内死亡人数 + Integer swrs = Objects.nonNull(jsonObject.getInteger("SWRS")) ? jsonObject.getInteger("SWRS") : 0; + Integer swrs24 = Objects.nonNull(jsonObject.getInteger("SWRS24")) ? jsonObject.getInteger("SWRS24") : 0; + Integer swrs3 = Objects.nonNull(jsonObject.getInteger("SWRS3")) ? jsonObject.getInteger("SWRS3") : 0; + Integer swrs7 = Objects.nonNull(jsonObject.getInteger("SWRS7")) ? jsonObject.getInteger("SWRS7") : 0; + Integer swrs30 = Objects.nonNull(jsonObject.getInteger("SWRS30")) ? jsonObject.getInteger("SWRS30") : 0; + // 有死亡人数,再插入到死亡事故表中 + if (swrs != 0 || swrs24 != 0 || swrs3 != 0 || swrs7 != 0 || swrs30 != 0) { + // 插入数据到死亡事故表中 + NdVehicleAccidentDead accidentDead = new NdVehicleAccidentDead(); + // 判断是否已经插入过 + if (deadAccidentMap.containsKey(carPlate + accidentTime)) { + NdVehicleAccidentDead dead = deadAccidentMap.get(carPlate + accidentTime); + accidentDead.setId(dead.getId()); + } + if (swrs30 != 0) { + accidentDead.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accidentDead.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accidentDead.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accidentDead.setDeathToll(swrs24); + } else { + accidentDead.setDeathToll(swrs); + } + accidentDead.setInjuries(ssrs); + accidentDead.setRegionId(regionId); + accidentDead.setRegionName(regionName); + // 获取事故时间 + accidentDead.setAccidentTime(accidentTime); + accidentDead.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、企业名称 + accidentDead.setCarPlate(carPlate); + // accidentDead.setAccidentDriver(driverName); + accidentDead.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accidentDead.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accidentDead.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + accidentDead.setBriefCase(jyaq); + accidentDead.setAccidentNo(sgbh); + accidentDead.setLongitude(longitude); + accidentDead.setLatitude(latitude); + vehicleAccidentDeadService.saveOrUpdate(accidentDead); + } + // 插入到事故表中 + NdVehicleAccident accident = new NdVehicleAccident(); + // 判断事故类型 + if (swrs != 0 || swrs24 != 0 || swrs3 != 0 || swrs7 != 0 || swrs30 != 0){ + accident.setAccidentType(AccidentTypeEnum.DEAD.getCode()); + } else if (Objects.nonNull(ssrs) && ssrs > 0) { + accident.setAccidentType(AccidentTypeEnum.INJURY.getCode()); + }else { + accident.setAccidentType(AccidentTypeEnum.OTHER.getCode()); + } + // 获取已经存在的事故信息 + NdVehicleAccident vehicleAccident = accidentMap.get(carPlate + accidentTime); + // 获取事故时间 + if (accidentMap.containsKey(carPlate + accidentTime)) { + accident.setId(vehicleAccident.getId()); + } + accident.setInjuries(ssrs); + if (swrs30 != 0) { + accident.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accident.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accident.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accident.setDeathToll(swrs24); + } else { + accident.setDeathToll(swrs); + } + accident.setRegionId(regionId); + accident.setRegionName(regionName); + // 获取事故时间 + accident.setAccidentTime(accidentTime); + accident.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、车辆类型、企业名称 + accident.setCarPlate(carPlate); + + // accident.setAccidentDriver(driverName); + accident.setVehicleType(vehicleType); + accident.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accident.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accident.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + accident.setBriefCase(jyaq); + accident.setAccidentNo(sgbh); + accident.setLongitude(longitude); + accident.setLatitude(latitude); + vehicleAccidentService.saveOrUpdate(accident); + } + } + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/CarServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/CarServiceImpl.java new file mode 100644 index 0000000..967ba47 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/CarServiceImpl.java @@ -0,0 +1,239 @@ +package com.ningdatech.carapi.irs.service.impl; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Objects; + +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSON; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.irs.service.CarService; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import com.ningdatech.carapi.irs.utils.Md5Utils; +import com.ningdatech.carapi.scheduler.contants.TaskContant; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/04/23 15:21 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class CarServiceImpl implements CarService { + + private final RestTemplate restTemplate; + private final RefreshKeyService refreshKeyService; + private final CachePlusOps cachePlusOps; + + @Override + public String vehicleIllegalQuery() { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + String innerAppKey = "210a2657177f478c808381deb13a4dac"; + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003007/dataSharing/Czp71c3856d9gf1a.htm"; + //// 车辆分类 + //String clfl = "abc"; + //// 当事人 -- + //String dsr = "abc"; + //// 号牌号码 -- + //String hphm = "abc"; + //// 号牌种类 + //String hpzl = "abc"; + //// 决定书编号 -- + //String jdsbh = "abc"; + // 驾驶证号 -- + String jszh = "330382198711014059"; + //// 违法编号 -- + //String wfbh = "abc"; + //// 机动车使用性质 + //String syxz = "abc"; + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + //map.add("dsr",dsr); + //map.add("hphm",hphm); + //map.add("jdsbh",jdsbh); + map.add("jszh",jszh); + //map.add("wfbh",wfbh); + //map.add("hpzl",hpzl); + //map.add("syxz",syxz); + //map.add("clfl",clfl); + String res = null; + try { + HttpHeaders headers = new HttpHeaders(); + headers.add("innerAppKey",innerAppKey); + HttpEntity httpEntity = new HttpEntity<>(map,headers); + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, httpEntity ,String.class); + log.info("[RestTemplateTest-车辆违法查询] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-车辆违法查询] http request error", e); + } + return res; + } + + @Override + public String vehicleIllegalQuery(String hphm) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + String innerAppKey = "210a2657177f478c808381deb13a4dac"; + // 根据传入的时间判断是否需要刷新密钥 + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + // 号牌种类 + String hpzl = "01"; + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003007/dataSharing/Czp71c3856d9gf1a.htm"; + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + map.add("hphm",hphm); + map.add("hpzl",hpzl); + String res = null; + try { + HttpHeaders headers = new HttpHeaders(); + headers.add("innerAppKey",innerAppKey); + HttpEntity httpEntity = new HttpEntity<>(map,headers); + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, httpEntity ,String.class); + log.info("[RestTemplateTest-车辆违法查询] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-车辆违法查询] http request error", e); + } + return res; + } + + @Override + public String vehicleIllegalQuery(String hphm, Integer index) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + String innerAppKey = "210a2657177f478c808381deb13a4dac"; + + // 请求秘钥 + CacheKey requestKey = new CacheKey(TaskContant.RedisKey.IRS_VEHICLE_ILLEGAL_REQUEST_SECRET); + // 刷新密钥 + CacheKey refreshKey = new CacheKey(TaskContant.RedisKey.IRS_VEHICLE_ILLEGAL_REFRESH_SECRET); + // 根据key获取缓存中的请求秘钥和刷新密钥 + String requestSecret = cachePlusOps.get(requestKey); + String refreshSecret = cachePlusOps.get(refreshKey); + if (index == 0) { + // 任务第一次调用接口,获取刷新秘钥和请求秘钥,并保存到redis中 + try { + if (Objects.nonNull(refreshSecret)){ + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + }else { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次车辆违法查询车牌号为{}", e.getMessage(), hphm); + return null; + } + } + // 如果获取不到刷新密钥,重新生成 + else if (Objects.isNull(refreshSecret)) { + try { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + if (requestSecret == null) { + return null; + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次车辆违法查询车牌号为{}", e.getMessage(), hphm); + return null; + } + } + // 不是第一次调用,看请求秘钥是否过期 + // 刷新密钥有效期两天,而定时任务每天都会执行一次,每次任务执行又会更新刷新密钥,所以刷新密钥不会过期 + // 只需判断请求秘钥是否过期 + else if (Objects.isNull(requestSecret)) { + try { + // 调用IRS刷新秘钥接口,更新刷新密钥和请求秘钥 + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("刷新请求密钥失败:{},此次车辆违法查询车牌号为{}", e.getMessage(), hphm); + return null; + } + } + + // 号牌种类 + String hpzl = "01"; + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + log.info("请求参数中请求秘钥为:" + requestSecret); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003007/dataSharing/Czp71c3856d9gf1a.htm"; + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + map.add("hphm",hphm); + map.add("hpzl",hpzl); + HttpHeaders headers = new HttpHeaders(); + headers.add("innerAppKey", innerAppKey); + HttpEntity httpEntity = new HttpEntity<>(map, headers); + log.info("请求参数 :{}", JSON.toJSONString(map)); + String res = restTemplate.postForObject(url, httpEntity, String.class); + log.info("[RestTemplateTest-车辆违法查询] http request :{}", res); + return res; + } + + public static void main(String[] args) { + // 请求秘钥过期时间 + Long requestSecretEndTime = 1688746680035L; + //Long requestSecretEndTime = 1688574780035L; + // 将时间戳转换为Instant对象 + Instant instant = Instant.ofEpochMilli(requestSecretEndTime); + // 将Instant对象转换为LocalDateTime对象 + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + int minute = localDateTime.getMinute(); + System.out.println(minute); + System.out.println(localDateTime); + + Duration duration = Duration.between(LocalDateTime.now(), localDateTime); + // 获取相差的小时数 + long hours = duration.toHours(); + + System.out.println("相差的小时数:" + hours); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriverServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriverServiceImpl.java new file mode 100644 index 0000000..c8f6071 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriverServiceImpl.java @@ -0,0 +1,234 @@ +package com.ningdatech.carapi.irs.service.impl; + +import java.util.List; +import java.util.Objects; + +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.irs.service.DriverService; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import com.ningdatech.carapi.irs.utils.Md5Utils; +import com.ningdatech.carapi.scheduler.contants.TaskContant; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/04/23 15:21 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class DriverServiceImpl implements DriverService { + + private final RestTemplate restTemplate; + private final RefreshKeyService refreshKeyService; + private final CachePlusOps cachePlusOps; + + @Override + public String vehicleLicenseQuery(String carPlate) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/dataSharing/vehicleQmInfo.htm"; + + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可0000-00\",\"subPowerMatters\":\"许可0000-0101\",\"accesscardId\":\"33071918******784523\",\"materialName\":\"社会团体变更登记申请表\",\"sponsorName\":\"阿里巴巴(中国)有限公司\",\"sponsorCode\":\"91330100799655058B\",\"projectId\":\"330000261711151100004\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + //map.add("sfzmhm",idCard); + map.add("HPHM",carPlate); + String res = null; + try { + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, map ,String.class); + log.info("[RestTemplateTest-行驶证信息查询] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-行驶证信息查询] http request error", e); + } + return res; + } + + @Override + public String vehicleLicenseQuery(String carPlate,Integer index) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + + // 请求秘钥 + CacheKey requestKey = new CacheKey(TaskContant.RedisKey.IRS_VEHICLE_LICENSE_REQUEST_SECRET); + // 刷新密钥 + CacheKey refreshKey = new CacheKey(TaskContant.RedisKey.IRS_VEHICLE_LICENSE_REFRESH_SECRET); + + // 根据key获取缓存中的请求秘钥和刷新密钥 + String requestSecret = cachePlusOps.get(requestKey); + String refreshSecret = cachePlusOps.get(refreshKey); + if (index == 0) { + // 任务第一次调用接口,获取刷新秘钥和请求秘钥,并保存到redis中 + try { + if (Objects.nonNull(refreshSecret)){ + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + }else { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次车辆行驶证查询车牌号为{}", e.getMessage(), carPlate); + return null; + } + } else if (Objects.isNull(refreshSecret)) { + try { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + if (requestSecret == null) { + return null; + } + } catch (Exception e) { + log.error("获取刷新密钥失败:{},此次车辆行驶证查询车牌号为{}", e.getMessage(), carPlate); + return null; + } + } + // 不是第一次调用,看请求秘钥是否过期 + // 刷新密钥有效期两天,而定时任务每天都会执行一次,每次任务执行又会更新刷新密钥,所以刷新密钥不会过期 + // 只需判断请求秘钥是否过期 + else if (Objects.isNull(requestSecret)) { + try { + // 调用IRS刷新秘钥接口,更新刷新密钥和请求秘钥 + requestSecret = refreshKeyService.refreshRequestSecret(appKey, requestKey, refreshKey, refreshSecret); + if (requestSecret == null) { + requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret, requestKey, refreshKey); + } + } catch (Exception e) { + log.error("刷新请求密钥失败:{},此次车辆行驶证查询车牌号为{}", e.getMessage(), carPlate); + return null; + } + } + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + log.info("请求参数中请求秘钥为:" + requestSecret); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/dataSharing/vehicleQmInfo.htm"; + + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可0000-00\",\"subPowerMatters\":\"许可0000-0101\",\"accesscardId\":\"33071918******784523\",\"materialName\":\"社会团体变更登记申请表\",\"sponsorName\":\"阿里巴巴(中国)有限公司\",\"sponsorCode\":\"91330100799655058B\",\"projectId\":\"330000261711151100004\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + //map.add("sfzmhm",idCard); + map.add("HPHM",carPlate); + log.info("请求参数 :{}", JSON.toJSONString(map)); + String res = restTemplate.postForObject(url, map, String.class); + log.info("[RestTemplateTest-行驶证信息查询] http request :{}", res); + return res; + } + + @Override + public String drivingLicenseQuery(String idCard) { + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/dataSharing/driverLicenseInfo.htm"; + + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional","{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\",\"materialName\":\"社会团体变更登记申请表\",\"sponsorName\":\"阿里巴巴(中国)有限公司\",\"sponsorCode\":\"91330100799655058B\",\"projectId\":\"330000261711151100004\"}"); + map.add("appKey",appKey); + map.add("requestTime",requestTime); + map.add("sign",sign); + map.add("cardId",idCard); + String res = null; + try { + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, map ,String.class); + log.info("[RestTemplateTest-驾驶证查询] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-驾驶证查询] http request error", e); + } + return res; + } + + /** + * 根据车架号查询行驶证信息 + * @return java.lang.String + * @author CMM + * @since 2023/05/22 21:23 + */ + @Override + public List vehicleLicenseTest() { + + // 应用appKey + String appKey = "A330000100000202105003941"; + String appSecret = "e07fd4471e92410d9860282d939b1217"; + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(appKey, appSecret); + + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(appKey + requestSecret + requestTime); + String url = "https://interface.zjzwfw.gov.cn/gateway/api/001003007/dataSharing/vehicleQmInfo.htm"; + + List cjhList = Lists.newArrayList(); + + //cjhList.add("LZ5N2DE57HB611625"); + //cjhList.add("LZ5N2DE57HB611623"); + //cjhList.add("LZ5N2DE57HB611633"); + //cjhList.add("LZ5N2DE57HB611626"); + //cjhList.add("LZ5N2DE57HB611632"); + //cjhList.add("LZ5N2DE57HB611624"); + + cjhList.add("LUZAGBGA3NA136300"); + cjhList.add("LUZAGBGA7NA168084"); + + //String hphm = "浙C52502"; + //cjhList.add(hphm); + + List resList = Lists.newArrayList(); + for (String cjh : cjhList) { + MultiValueMap map = new LinkedMultiValueMap(); + // 附加信息 + map.add("additional", "{\"powerMatters\":\"许可0000-00\",\"subPowerMatters\":\"许可0000-0101\",\"accesscardId\":\"33071918******784523\",\"materialName\":\"社会团体变更登记申请表\",\"sponsorName\":\"阿里巴巴(中国)有限公司\",\"sponsorCode\":\"91330100799655058B\",\"projectId\":\"330000261711151100004\"}"); + map.add("appKey", appKey); + map.add("requestTime", requestTime); + map.add("sign", sign); + map.add("clsbdh", cjh); + //map.add("HPHM",cjh); + String res = null; + try { + log.info("请求参数 :{}", JSON.toJSONString(map)); + res = restTemplate.postForObject(url, map, String.class); + log.info("[RestTemplateTest-行驶证信息查询] http request :{}", res); + } catch (Exception e) { + log.error("[RestTemplateTest-行驶证信息查询] http request error", e); + } + resList.add(res); + } + return resList; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriversLicenseImplRawService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriversLicenseImplRawService.java new file mode 100644 index 0000000..933eff3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/DriversLicenseImplRawService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.irs.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.ningdatech.carapi.irs.mapper.DriversLicenseMapper; +import com.ningdatech.carapi.irs.service.IDriversLicenseRawService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author WendyYang + * @since 2023-05-16 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class DriversLicenseImplRawService extends ServiceImpl implements IDriversLicenseRawService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/FilePreviewServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/FilePreviewServiceImpl.java new file mode 100644 index 0000000..ee305c6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/FilePreviewServiceImpl.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.irs.service.impl; + +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.ningdatech.carapi.irs.service.FilePreviewService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author CMM + * @since 2023/03/07 15:36 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class FilePreviewServiceImpl implements FilePreviewService { + + @Override + public String filePreview(String ext,String remoteUrl,String markText,String upt) { + return null; + } + + + public static void main(String[] args) { + RestTemplate restTemplate = new RestTemplate(); + Map map = new HashMap<>(); + map.put("ext","png"); + map.put("remoteUrl","http://pic37.nipic.com/20140113/9900276_184927469000_2.png"); + map.put("markText","false"); + map.put("upt",null); + ResponseEntity responseEntity = null; + //发送post请求 + RequestEntity> requestEntity = RequestEntity + .post("") + .header("Accept", MediaType.APPLICATION_JSON.toString()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .body(map); + + try { + responseEntity= restTemplate.exchange(requestEntity,String.class); + } catch (Exception e) { + log.error("[RestTemplateTest-test] http request error", e); + } + + System.out.println(responseEntity.toString()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/IrsTempCarplateServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/IrsTempCarplateServiceImpl.java new file mode 100644 index 0000000..77aae85 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/IrsTempCarplateServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.irs.service.impl; + +import com.ningdatech.carapi.irs.model.entity.IrsTempCarplate; +import com.ningdatech.carapi.irs.mapper.IrsTempCarplateMapper; +import com.ningdatech.carapi.irs.service.IIrsTempCarplateService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2023-05-15 + */ +@Service +public class IrsTempCarplateServiceImpl extends ServiceImpl implements IIrsTempCarplateService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDriverLicenseByIrsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDriverLicenseByIrsServiceImpl.java new file mode 100644 index 0000000..87a71a1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDriverLicenseByIrsServiceImpl.java @@ -0,0 +1,185 @@ +package com.ningdatech.carapi.irs.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.IdcardUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.cache.redis.RedisOps; +import com.ningdatech.carapi.common.contants.IrsConst; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.ningdatech.carapi.irs.model.dto.irs.DriverLicenseDTO; +import com.ningdatech.carapi.irs.model.dto.irs.ResponseDataDTO; +import com.ningdatech.carapi.irs.service.AbstractLicenseGetByIrsService; +import com.ningdatech.carapi.irs.service.IDriversLicenseRawService; +import com.ningdatech.carapi.irs.service.PullLicenseByIrsService; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import com.ningdatech.carapi.irs.utils.Md5Utils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + *

+ * DriverLicensePullServiceImpl + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@Slf4j +@Service("driverLicensePullByIrsService") +public class PullDriverLicenseByIrsServiceImpl extends AbstractLicenseGetByIrsService implements PullLicenseByIrsService { + + public PullDriverLicenseByIrsServiceImpl(IDriverInfoService driverInfoService, + RestTemplate restTemplate, + RefreshKeyService refreshKeyService, + RedisOps redisOps, + IDriversLicenseRawService driversLicenseRawService) { + super(driverInfoService, restTemplate, refreshKeyService, redisOps, driversLicenseRawService); + } + + @Override + public boolean runningStatus() { + String statusKey = RK_DRIVER_LICENSE + StrPool.COLON + "STATUS"; + return Boolean.TRUE.equals(redisOps.exists(statusKey)); + } + + @Override + public long getLeftCount() { + String dataKey = RK_DRIVER_LICENSE + StrPool.COLON + "IDCARD"; + return ObjectUtil.defaultIfNull(redisOps.lLen(dataKey), 0L); + } + + /** + * 获取驾驶证信息 + * + * @param cardId 身份证号 + * @return irs接口返回值 + */ + @Override + public String getLicenseDetail(String cardId) { + MultiValueMap reqParam = new LinkedMultiValueMap<>(); + // 附加信息 + reqParam.add("additional", "{\"powerMatters\":\"许可-0000-00\",\"subPowerMatters\":\"许可-0000-0101\",\"accesscardId\":\"33071918111111784523\",\"materialName\":\"社会团体变更登记申请表\",\"sponsorName\":\"阿里巴巴(中国)有限公司\",\"sponsorCode\":\"91330100799655058B\",\"projectId\":\"330000261711151100004\"}"); + reqParam.add("appKey", APP_KEY); + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(APP_KEY, APP_SECRET); + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(APP_KEY + requestSecret + requestTime); + // irs驾驶证查询接口 + reqParam.set("requestTime", requestTime); + reqParam.set("sign", sign); + reqParam.set("cardId", cardId); + + String res; + try { + log.info("请求参数:{}", reqParam); + res = restTemplate.postForObject(IrsConst.DRIVER_LICENSE_URL, reqParam, String.class); + log.info("驾驶证查询:{}", res); + } catch (Exception e) { + log.error("驾驶证查询:", e); + res = null; + } + return res; + } + + @Override + public void pullLicense() { + String statusKey = RK_DRIVER_LICENSE + StrPool.COLON + "STATUS"; + try { + if (Boolean.FALSE.equals(redisOps.setNx(statusKey, "RUNNING"))) { + return; + } + pullLicenseDetail(); + } finally { + redisOps.del(statusKey); + } + } + + @Override + public void pullLicenseDetail() { + String dataKey = RK_DRIVER_LICENSE + StrPool.COLON + "IDCARDS"; + List currIdcards = redisOps.lPop(dataKey); + if (CollUtil.isEmpty(currIdcards)) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(DriverInfo.class) + .select(DriverInfo::getIdCard); + List driverInfos = driverInfoService.list(query); + Set idCards = driverInfos.stream() + .map(DriverInfo::getIdCard) + .filter(IdcardUtil::isValidCard) + .collect(Collectors.toSet()); + if (idCards.isEmpty()) { + return; + } + List> parts = new ArrayList<>(ListUtil.partition(new ArrayList<>(idCards), LIMIT_BY_DAY)); + currIdcards = parts.remove(0); + if (!parts.isEmpty()) { + redisOps.lPush(dataKey, parts.toArray()); + } + } + List failedIdcards = currIdcards.stream().filter(idcard -> { + try { + String resData = getLicenseDetail(idcard); + if (StrUtil.isBlank(resData)) { + return true; + } + ResponseDataDTO response = JSON.parseObject(resData, + new TypeReference>() { + }); + if (response.succeed()) { + List list = response.getDatas(); + if (CollUtil.isNotEmpty(list)) { + DriverLicenseDTO dl = list.get(0); + DriversLicenseRaw raw = new DriversLicenseRaw(); + raw.setIdcard(idcard); + raw.setDriverLicenseDetail(JSONUtil.toJsonStr(dl)); + LambdaQueryWrapper query = Wrappers + .lambdaQuery(DriversLicenseRaw.class) + .eq(DriversLicenseRaw::getIdcard, idcard); + driversLicenseRawService.saveOrUpdate(raw, query); + return false; + } + } + return true; + } catch (Exception e) { + log.error("获取驾驶证信息异常:", e); + return true; + } + }).collect(Collectors.toList()); + if (!failedIdcards.isEmpty()) { + redisOps.lPush(dataKey, failedIdcards.toArray()); + } + } + + @Override + public void initPullLicenseTask() { + long leftCnt = getLeftCount(); + boolean runningStatus = runningStatus(); + if (runningStatus || leftCnt > 0) { + startPullLicenseTask(INIT_DELAY_MINUTES); + } + } + + @Override + public void startPullLicenseTask(int delayMinutes) { + startLicensePullTask(RK_DRIVER_LICENSE, this, delayMinutes); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDrivingLicenseByIrsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDrivingLicenseByIrsServiceImpl.java new file mode 100644 index 0000000..e9c1bc8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/PullDrivingLicenseByIrsServiceImpl.java @@ -0,0 +1,185 @@ +package com.ningdatech.carapi.irs.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.IdcardUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.cache.redis.RedisOps; +import com.ningdatech.carapi.common.contants.IrsConst; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.ningdatech.carapi.irs.model.dto.irs.DrivingLicenseDTO; +import com.ningdatech.carapi.irs.model.dto.irs.ResponseDataDTO; +import com.ningdatech.carapi.irs.service.AbstractLicenseGetByIrsService; +import com.ningdatech.carapi.irs.service.IDriversLicenseRawService; +import com.ningdatech.carapi.irs.service.PullLicenseByIrsService; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import com.ningdatech.carapi.irs.utils.Md5Utils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + *

+ * DriverLicensePullServiceImpl + *

+ * + * @author WendyYang + * @since 2023/5/16 + **/ +@Slf4j +@Service("drivingLicensePullByIrsService") +public class PullDrivingLicenseByIrsServiceImpl extends AbstractLicenseGetByIrsService implements PullLicenseByIrsService { + + + public PullDrivingLicenseByIrsServiceImpl(IDriverInfoService driverInfoService, + RestTemplate restTemplate, + RefreshKeyService refreshKeyService, + RedisOps redisOps, + IDriversLicenseRawService driversLicenseRawService) { + super(driverInfoService, restTemplate, refreshKeyService, redisOps, driversLicenseRawService); + } + + @Override + public boolean runningStatus() { + String statusKey = RK_DRIVING_LICENSE + StrPool.COLON + "STATUS"; + return Boolean.TRUE.equals(redisOps.exists(statusKey)); + } + + @Override + public long getLeftCount() { + String dataKey = RK_DRIVING_LICENSE + StrPool.COLON + "IDCARD"; + return ObjectUtil.defaultIfNull(redisOps.lLen(dataKey), 0L); + } + + /** + * 获取行驶证信息 + * + * @param idcard 身份正好 + * @return / + */ + @Override + public String getLicenseDetail(String idcard) { + // 刷新密钥 + String requestSecret = refreshKeyService.getRequestSecret(APP_KEY, APP_SECRET); + // 请求签名 + Long requestTime = System.currentTimeMillis(); + String sign = Md5Utils.hash(APP_KEY + requestSecret + requestTime); + + MultiValueMap map = new LinkedMultiValueMap<>(); + // 附加信息 + map.add("additional", "{\"powerMatters\":\"许可0000-00\",\"subPowerMatters\":\"许可0000-0101\",\"accesscardId\":\"33071918******784523\",\"materialName\":\"社会团体变更登记申请表\",\"sponsorName\":\"阿里巴巴(中国)有限公司\",\"sponsorCode\":\"91330100799655058B\",\"projectId\":\"330000261711151100004\"}"); + map.add("appKey", APP_KEY); + map.add("requestTime", requestTime); + map.add("sign", sign); + map.add("sfzmhm", idcard); + String res; + try { + log.info("请求参数:{}", map); + res = restTemplate.postForObject(IrsConst.DRIVING_LICENSE_URL, map, String.class); + log.info("行驶证信息查询:{}", res); + } catch (Exception e) { + log.error("行驶证信息查询:", e); + res = null; + } + return res; + } + + @Override + public void pullLicense() { + String statusKey = RK_DRIVING_LICENSE + StrPool.COLON + "STATUS"; + try { + if (Boolean.FALSE.equals(redisOps.setNx(statusKey, "RUNNING"))) { + return; + } + pullLicenseDetail(); + } finally { + redisOps.del(statusKey); + } + } + + @Override + public void pullLicenseDetail() { + String dataKey = RK_DRIVING_LICENSE + StrPool.COLON + "IDCARD"; + List currIdcards = redisOps.lPop(dataKey); + if (CollUtil.isEmpty(currIdcards)) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(DriverInfo.class) + .select(DriverInfo::getIdCard); + List driverInfos = driverInfoService.list(query); + Set idCards = driverInfos.stream() + .map(DriverInfo::getIdCard) + .filter(IdcardUtil::isValidCard) + .collect(Collectors.toSet()); + if (idCards.isEmpty()) { + return; + } + List> parts = new ArrayList<>(ListUtil.partition(new ArrayList<>(idCards), LIMIT_BY_DAY)); + currIdcards = parts.remove(0); + if (!parts.isEmpty()) { + redisOps.lPush(dataKey, parts.toArray()); + } + } + List failedIdcards = currIdcards.stream().filter(idcard -> { + try { + String resData = getLicenseDetail(idcard); + if (StrUtil.isBlank(resData)) { + return true; + } + ResponseDataDTO response = JSON.parseObject(resData, + new TypeReference>() { + }); + if (response.succeed()) { + List list = response.getDatas(); + if (CollUtil.isNotEmpty(list)) { + DrivingLicenseDTO dl = list.get(0); + DriversLicenseRaw raw = new DriversLicenseRaw(); + raw.setIdcard(idcard); + raw.setDrivingLicenseDetail(JSONUtil.toJsonStr(dl)); + LambdaQueryWrapper query = Wrappers + .lambdaQuery(DriversLicenseRaw.class) + .eq(DriversLicenseRaw::getIdcard, idcard); + driversLicenseRawService.saveOrUpdate(raw, query); + return false; + } + } + return true; + } catch (Exception e) { + log.error("获取行驶证信息异常:", e); + return true; + } + }).collect(Collectors.toList()); + if (!failedIdcards.isEmpty()) { + redisOps.lPush(dataKey, failedIdcards.toArray()); + } + } + + @Override + public void initPullLicenseTask() { + long leftCnt = getLeftCount(); + boolean runningStatus = runningStatus(); + if (runningStatus || leftCnt > 0) { + startPullLicenseTask(INIT_DELAY_MINUTES); + } + } + + @Override + public void startPullLicenseTask(int delayMinutes) { + startLicensePullTask(RK_DRIVING_LICENSE, this, delayMinutes); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/RefreshServieImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/RefreshServieImpl.java new file mode 100644 index 0000000..fd6bd28 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/RefreshServieImpl.java @@ -0,0 +1,232 @@ +package com.ningdatech.carapi.irs.service.impl; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.HashMap; +import java.util.Objects; + +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.irs.service.RefreshKeyService; +import com.ningdatech.carapi.irs.utils.HttpUtil; +import com.ningdatech.carapi.irs.utils.Md5Utils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname RefreshServieImpl + * @Description + * @Date 2023/3/1 16:58 + * @Author PoffyZhang + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class RefreshServieImpl implements RefreshKeyService { + private final CachePlusOps cachePlusOps; + @Override + public String refresh() { + String appkey = "A330000100000202105003941"; // appkey + Long requestTime = System.currentTimeMillis (); + HttpUtil httpUtil = HttpUtil.getInstance(); + String requstSecret = "e07fd4471e92410d9860282d939b1217"; // app密钥 + log.info("请求密钥" + requstSecret); + String sign = Md5Utils.hash (appkey + requstSecret + requestTime); + String url = String.format ("http://59.202.38.178/gateway/app/refreshTokenByKey.htm" + + "?appKey=%s&requestTime=%s&sign=%s",appkey,requestTime+"",sign); + log.info(url); + String result = httpUtil.sendHttpGet(url); + log.info(result); + JSONObject dataJson = JSON.parseObject(result).getJSONObject("datas"); + if(Objects.nonNull(dataJson)){ + return dataJson.getString("requestSecret"); + } + return result; + } + + @Override + public String getRequestSecret(String appKey, String appSecret) { + Long requestTime = System.currentTimeMillis(); + // 刷新秘钥 + HttpUtil httpUtil = HttpUtil.getInstance(); + log.info("请求密钥" + appSecret); + String refreshSign = Md5Utils.hash (appKey + appSecret + requestTime); + String refreshUrl = String.format ("http://59.202.38.178/gateway/app/refreshTokenByKey.htm" + + "?appKey=%s&requestTime=%s&sign=%s", appKey, requestTime +"",refreshSign); + log.info(refreshUrl); + String result = httpUtil.sendHttpGet(refreshUrl); + log.info(result); + JSONObject dataJson = JSON.parseObject(result).getJSONObject("datas"); + if(Objects.nonNull(dataJson)){ + return dataJson.getString("requestSecret"); + } + return result; + } + + /** + * 获取应用的刷新密钥和请求秘钥 + * @param appKey + * @param appSecret + * @return + */ + @Override + public String getRefreshSecret(String appKey, String appSecret) { + Long requestTime = System.currentTimeMillis(); + // 刷新秘钥 + HttpUtil httpUtil = HttpUtil.getInstance(); + log.info("请求密钥" + appSecret); + String sign = Md5Utils.hash (appKey + appSecret + requestTime); + HashMap params = new HashMap<>(); + //String refreshUrl = String.format ("http://59.202.38.178/gateway/app/refreshTokenByKey.htm" + + // "?appKey=%s&requestTime=%s&sign=%s", appKey, requestTime +"",refreshSign); + + String refreshUrl = "https://interface.zjzwfw.gov.cn/gateway/app/refreshTokenByKey.htm"; + params.put("appKey",appKey); + params.put("sign",sign); + params.put("requestTime",requestTime + ""); + String result = httpUtil.sendHttpPost(refreshUrl,params); + log.info(result); + JSONObject jsonObject = JSON.parseObject(result, JSONObject.class); + if(Objects.nonNull(jsonObject)){ + return jsonObject.getString("datas"); + } + return result; + } + + @Override + public String refreshSecret(String appKey, String refreshSecret) { + Long requestTime = System.currentTimeMillis(); + // 刷新秘钥 + HttpUtil httpUtil = HttpUtil.getInstance(); + log.info("刷新密钥" + refreshSecret); + String refreshSign = Md5Utils.hash (appKey + refreshSecret + requestTime); + HashMap params = new HashMap<>(); + + String refreshUrl = "https://interface.zjzwfw.gov.cn/gateway/app/refreshTokenBySec.htm"; + params.put("appKey",appKey); + params.put("sign",refreshSign); + params.put("requestTime",requestTime + ""); + String result = httpUtil.sendHttpPost(refreshUrl,params); + log.info(result); + JSONObject jsonObject = JSON.parseObject(result, JSONObject.class); + if(Objects.nonNull(jsonObject)){ + return jsonObject.getString("datas"); + } + return result; + } + + @Override + public String getRequestSecret(String appKey, String appSecret, CacheKey requestKey, CacheKey refreshKey) { + String requestSecret; + String refreshSecret; + String result = getRefreshSecret(appKey, appSecret); + JSONObject jsonObject = JSON.parseObject(result, JSONObject.class); + if (Objects.nonNull(jsonObject)) { + refreshSecret = jsonObject.getString("refreshSecret"); + requestSecret = jsonObject.getString("requestSecret"); + // 请求秘钥过期时间 + Long requestSecretEndTime = jsonObject.getLong("requestSecretEndTime"); + // 刷新密钥过期时间 + Long refreshSecretEndTime = jsonObject.getLong("refreshSecretEndTime"); + + LocalDateTime requestEndTime = getEndTime(requestSecretEndTime); + LocalDateTime refreshEndTime = getEndTime(refreshSecretEndTime); + LocalDateTime startTime = LocalDateTime.now(); + // 请求秘钥有效期(分钟),提前1分钟刷新 + Duration minuteDuration = Duration.between(startTime, requestEndTime); + long minute = minuteDuration.toMinutes() - 1; + // 刷新密钥有效期(小时),提前1小时刷新 + Duration hourDuration = Duration.between(startTime, refreshEndTime); + // 获取相差的小时数,并提前1小时刷新 + long hour = hourDuration.toHours() - 1; + log.info("刷新秘钥有效期:" + hour); + if (Objects.nonNull(requestSecret)) { + // 请求秘钥,有效期15分钟 + requestKey.setExpire(Duration.ofMinutes(minute)); + cachePlusOps.set(requestKey, requestSecret, Boolean.TRUE); + }else { + return null; + } + if (Objects.nonNull(refreshSecret)) { + // 刷新密钥,有效期48小时 + refreshKey.setExpire(Duration.ofHours(hour)); + cachePlusOps.set(refreshKey, refreshSecret, Boolean.TRUE); + }else { + return null; + } + }else { + return null; + } + return requestSecret; + } + + private LocalDateTime getEndTime(Long requestSecretEndTime) { + // 将时间戳转换为Instant对象 + Instant instant = Instant.ofEpochMilli(requestSecretEndTime); + // 将Instant对象转换为LocalDateTime对象 + return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + } + + @Override + public String refreshRequestSecret(String appKey, CacheKey requestKey, CacheKey refreshKey, String refreshSecret) { + String requestSecret; + String result = refreshSecret(appKey, refreshSecret); + JSONObject jsonObject = JSON.parseObject(result, JSONObject.class); + if (Objects.nonNull(jsonObject)) { + refreshSecret = jsonObject.getString("refreshSecret"); + requestSecret = jsonObject.getString("requestSecret"); + // 请求秘钥过期时间 + Long requestSecretEndTime = jsonObject.getLong("requestSecretEndTime"); + // 刷新密钥过期时间 + Long refreshSecretEndTime = jsonObject.getLong("refreshSecretEndTime"); + + LocalDateTime requestEndTime = getEndTime(requestSecretEndTime); + LocalDateTime refreshEndTime = getEndTime(refreshSecretEndTime); + LocalDateTime startTime = LocalDateTime.now(); + // 请求秘钥有效期(分钟),提前1分钟刷新 + Duration minuteDuration = Duration.between(startTime, requestEndTime); + long minute = minuteDuration.toMinutes() - 1; + log.info("请求秘钥有效期:" + minute); + // 刷新密钥有效期(小时),提前1小时刷新 + Duration duration = Duration.between(startTime, refreshEndTime); + // 获取相差的小时数,并提前1小时刷新 + long hour = duration.toHours() - 1; + log.info("刷新秘钥有效期:" + hour); + if (Objects.nonNull(requestSecret)) { + // 请求秘钥,有效期15分钟 + requestKey.setExpire(Duration.ofMinutes(minute)); + cachePlusOps.set(requestKey, requestSecret, Boolean.TRUE); + }else { + return null; + } + if (Objects.nonNull(refreshSecret)) { + // 刷新密钥,有效期48小时 + refreshKey.setExpire(Duration.ofHours(hour)); + cachePlusOps.set(refreshKey, refreshSecret, Boolean.TRUE); + }else { + return null; + } + }else { + return null; + } + return requestSecret; + } + + public static void main(String[] args) { +// String appkey = "A330000100000202105003941"; // appkey +// Long requestTime = System.currentTimeMillis (); +// System.out.println(requestTime); +// String requstSecret = "e07fd4471e92410d9860282d939b1217"; // app密钥 +// String sign = Md5Utils.hash (appkey + requstSecret + requestTime); +// System.out.println(sign); + + System.out.println("7520d721086111e7985b008cfaeb3d74".length()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/SmsServieImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/SmsServieImpl.java new file mode 100644 index 0000000..aa123b0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/SmsServieImpl.java @@ -0,0 +1,240 @@ +package com.ningdatech.carapi.irs.service.impl; + +import java.security.MessageDigest; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.irs.constant.SmsConstant; +import com.ningdatech.carapi.irs.service.SmsService; +import com.ningdatech.carapi.open.model.dto.UserLoginDTO; +import com.ningdatech.carapi.sys.contants.UserLoginConstant; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.crypto.digest.MD5; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname SmsServieImpl + * @Description + * @Date 2023/3/1 16:58 + * @Author PoffyZhang + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class SmsServieImpl implements SmsService { + + private final RestTemplate restTemplate; + private final INdUserInfoService ndUserInfoService; + private final INdUserAuthService ndUserAuthService; + private final CachePlusOps cachePlusOps; + + @Value("${sms.user}") + private String user; + + @Value("${sms.siid}") + private String siid; + + @Value("${sms.secretKey}") + private String secretKey; + + @Value("${sms.url}") + private String url; + + @Override + public String sendMessage(String mobile, String content) { + String secretKey = "082e691f65fd4a4d9f353b9c54b6735e"; + String accessKey = "bff297b3ac7f45f293de72087ba6d095"; + + String timeStamp = LocalDateTimeUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS"); + String transactionID = timeStamp; + String streamingNo = "9000001120230507162550676"; + String authenticator = Base64.getEncoder().encodeToString((timeStamp + transactionID + streamingNo + secretKey).getBytes()); + + Map map = new HashMap<>(); + map.put("siid","zhejiang1"); + map.put("user","httpadmin"); + map.put("authenticator",authenticator); + map.put("timeStamp",timeStamp); + map.put("transactionID",transactionID); + map.put("streamingNo",streamingNo); + map.put("mobile",mobile); + map.put("content",content); + ResponseEntity responseEntity = null; + + //发送post请求 + RequestEntity> requestEntity = RequestEntity + .post("http://115.239.134.217/smsservice/httpservices/capService") + .header("Accept", MediaType.APPLICATION_JSON.toString()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .body(map); //也可以是DTO + //http://115.239.134.217/smsservice/httpservices/capService + //https://interface.zjzwfw.gov.cn/gateway/component/routing/agent.htm + try { + responseEntity= restTemplate.exchange(requestEntity,String.class); + } catch (Exception e) { + log.error("[RestTemplateTest-test] http request error", e); + } + //请求参数 参数类型 是否必填 描述 示例值 + //siid String 否 客户编号 + // user String 否 HTTP帐号 + // authenticator String 否 认证码 参数4.4 BASE64(timeStamp+transactionID + streamingNO + 接口密钥) + // timestamp String 否 当前时间戳 + //transactionID String 否 事务号 + //streamingNo String 否 流水号 + //mobile String 否 多个号码用英文逗号分隔 + //extcode String 否 扩展码 + // contet String 否 内容 + return responseEntity.toString(); + } + + @Override + public String sendSmsCode(String mobile, String verificationCode) { + String timeStamp = LocalDateTimeUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS"); + String transactionID = timeStamp; + String streamingNo = siid + transactionID; + String authenticator = encoderByMd5(timeStamp + transactionID + streamingNo + secretKey); + + Map map = new HashMap<>(); + map.put("siid",siid); + map.put("user",user); + map.put("authenticator",authenticator); + map.put("timeStamp",timeStamp); + map.put("transactionID",transactionID); + map.put("streamingNo",streamingNo); + map.put("mobile",mobile); + String content = String.format(SmsConstant.SMS_CONSTANT_TEMPLATE,verificationCode); + map.put("content",content); + ResponseEntity responseEntity = null; + + //发送post请求 + RequestEntity> requestEntity = RequestEntity + .post(url) + .header("Accept", MediaType.APPLICATION_JSON.toString()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + //也可以是DTO + .body(map); + try { + responseEntity= restTemplate.exchange(requestEntity,String.class); + } catch (Exception e) { + log.error("[RestTemplateTest-test] http request error", e); + } + return responseEntity.toString(); + } + private String encoderByMd5(String str) { + try { + // 确定计算方法 + MessageDigest md5 = MessageDigest.getInstance("MD5"); + // 加密后的字符串 + return cn.hutool.core.codec.Base64.encode(md5.digest(str.getBytes("UTF-8"))); + } catch (Exception e) { + return ""; + } + } + + @Override + public String getCode(UserLoginDTO param) { + // 获取用户名入参信息 + String userName = param.getUsername(); + // 根据用户名获取用户账号信息 + NdUserAuth userAuth = ndUserAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getIdentifier, userName)); + VUtils.isTrue(Objects.isNull(userAuth)).throwMessage("该用户不存在!"); + // 根据用户ID获取用户信息 + NdUserInfo ndUserInfo = ndUserInfoService.getOne(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getId, userAuth.getUserId())); + VUtils.isTrue(Objects.isNull(ndUserInfo)).throwMessage("该用户不存在!"); + String mobile = ndUserInfo.getMobile(); + VUtils.isTrue(StringUtils.isBlank(mobile)).throwMessage("该用户没有设置手机号!"); + + String verificationCode = CodeUtil.codeFen(6); + // 将验证码保存到redis中,并设置过期时间 + CacheKey key = new CacheKey(UserLoginConstant.RedisKey.USER_LOGIN + userName); + key.setExpire(Duration.ofMinutes(10)); + cachePlusOps.set(key,verificationCode,false); + + String url = "http://shuiniche.ningdatech.com/cm/open/api/sms/send-sms-code"; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + Map requestBody = new HashMap<>(); + requestBody.put("mobile", mobile); + requestBody.put("verificationCode", verificationCode); + HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); + try { + ResponseEntity responseEntity = restTemplate.postForEntity(url, requestEntity, String.class); + return responseEntity.getBody(); + } catch (RestClientException e) { + throw new BizException("调用短信转发服务失败!"); + } + } + + public static void main(String[] args) { + //String mobile = "15058187290"; + String mobile = "18556991003"; + String content = "司机爱UI时候爱US哈UI晒u"; + RestTemplate restTemplate = new RestTemplate(); + +// String secretKey = "082e691f65fd4a4d9f353b9c54b6735e"; +// String accessKey = "bff297b3ac7f45f293de72087ba6d095"; + String secretKey = "ZjHc5%7&"; + + String timeStamp = LocalDateTimeUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS"); + String transactionID = timeStamp; + String streamingNo = "9000001120230507162550677"; + String authenticator = Base64.getEncoder().encodeToString( + MD5.create().digest((timeStamp + transactionID + streamingNo + secretKey).getBytes())); + + Map map = new HashMap<>(); + map.put("siid","ZJHCJSJXTYXGS9"); + map.put("user","zjhc9"); + map.put("authenticator",authenticator); + map.put("timeStamp",timeStamp); + map.put("transactionID",transactionID); + map.put("streamingNo",streamingNo); + map.put("mobile",mobile); + map.put("content",content); + ResponseEntity responseEntity = null; + + //发送post请求 + RequestEntity> requestEntity = RequestEntity + .post("http://115.239.134.217/smsservice/httpservices/capService") + .header("Accept", MediaType.APPLICATION_JSON.toString()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .body(map); //也可以是DTO + + try { + responseEntity= restTemplate.exchange(requestEntity,String.class); + } catch (Exception e) { + log.error("[RestTemplateTest-test] http request error", e); + } + + System.out.println(responseEntity.toString()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleAccidentIrsDataServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleAccidentIrsDataServiceImpl.java new file mode 100644 index 0000000..3290478 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleAccidentIrsDataServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.irs.service.impl; + +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.ningdatech.carapi.irs.mapper.VehicleAccidentIrsDataMapper; +import com.ningdatech.carapi.irs.service.IVehicleAccidentIrsDataService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2023-05-12 + */ +@Service +public class VehicleAccidentIrsDataServiceImpl extends ServiceImpl implements IVehicleAccidentIrsDataService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleViolationIrsDataServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleViolationIrsDataServiceImpl.java new file mode 100644 index 0000000..419c52b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/service/impl/VehicleViolationIrsDataServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.irs.service.impl; + +import com.ningdatech.carapi.irs.model.entity.VehicleViolationIrsData; +import com.ningdatech.carapi.irs.mapper.VehicleViolationIrsDataMapper; +import com.ningdatech.carapi.irs.service.IVehicleViolationIrsDataService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2023-05-12 + */ +@Service +public class VehicleViolationIrsDataServiceImpl extends ServiceImpl implements IVehicleViolationIrsDataService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyAccidentQueryTask.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyAccidentQueryTask.java new file mode 100644 index 0000000..9eaa3a9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyAccidentQueryTask.java @@ -0,0 +1,569 @@ +package com.ningdatech.carapi.irs.task; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.ningdatech.carapi.car.position.service.IVehiclePositionInfoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.ningdatech.carapi.irs.service.AccidentService; +import com.ningdatech.carapi.irs.service.IVehicleAccidentIrsDataService; +import com.ningdatech.carapi.safe.constant.AccidentTypeEnum; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportStatusEnum; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.file.utils.StrPool; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description + * @since 2023/05/21 15:38 + */ +@Component +@Slf4j +@Data +public class MyAccidentQueryTask implements Runnable { + + private final AccidentService accidentService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final IVehicleAccidentIrsDataService accidentIrsDataService; + private final CompanyService companyService; + private final INdVehicleAccidentService vehicleAccidentService; + private final INdVehicleAccidentDeadService vehicleAccidentDeadService; + private final RegionsCacheHelper regionsCacheHelper; + private final IVehiclePositionInfoService iVehiclePositionInfoService; + + /** + * 接口访问次数限制 + */ + private Integer BIGGEST_ACCESS_NUM = 2950; + /** + * 存储数据下标的文件名 + */ + private String ACCIDENT_QUERY_INDEX_FILE = "accidentIndex.txt"; + /** + * 上次中断的车牌号下标 + */ + private Long lastIndex = 0L; + /** + * 上次执行的次数 + */ + private Integer lastCount = 0; + /** + * 是否继续执行任务 + */ + private boolean isRunning = true; + + public MyAccidentQueryTask(AccidentService accidentService, IVehicleBaseInfoService vehicleBaseInfoService, + IVehicleAccidentIrsDataService accidentIrsDataService, CompanyService companyService, + INdVehicleAccidentService vehicleAccidentService, INdVehicleAccidentDeadService vehicleAccidentDeadService, + RegionsCacheHelper regionsCacheHelper, IVehiclePositionInfoService iVehiclePositionInfoService) { + this.accidentService = accidentService; + this.vehicleBaseInfoService = vehicleBaseInfoService; + this.accidentIrsDataService = accidentIrsDataService; + this.companyService = companyService; + this.vehicleAccidentService = vehicleAccidentService; + this.vehicleAccidentDeadService = vehicleAccidentDeadService; + this.regionsCacheHelper = regionsCacheHelper; + this.iVehiclePositionInfoService = iVehiclePositionInfoService; + } + + @Override + public void run() { + + log.info("========== 根据IRS更新事故数据 ==========任务开始"); + // 判断当前执行任务的时间是否为月初的1号 如果是月初1号,任务应该从下标1重新开始跑 + LocalDateTime now = LocalDateTime.now(); + int dayOfMonth = now.getDayOfMonth(); + if (TaskContant.Data.MONTH_VALUE_ONE.equals(dayOfMonth)){ + // 重置文件中的下标 + saveLastIndex(1L, 0); + } + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + while (isRunning) { + // 读取上次中断的数据下标和和已经执行的次数 + readLastIndex(); + log.info("读取到的下标为{}", lastIndex); + log.info("已访问接口次数{}", lastCount); + Map infoMap = + vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getId,NdVehicleBaseInfo::getCarPlate)) + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getId, NdVehicleBaseInfo::getCarPlate)); + OptionalLong maxKey = infoMap.keySet().stream().mapToLong(Long::longValue).max(); + Long maxIndex = null; + if (maxKey.isPresent()){ + maxIndex = maxKey.getAsLong(); + } + // 校验下标对应的车牌号是否一致 + String carNo; + carNo = infoMap.get(lastIndex); + while (Objects.isNull(carNo)) { + log.info("车辆id{}不存在,请检查该车辆信息是否已经被删除!", lastIndex); + // 查找下一个车辆信息,直到车辆信息存在 + lastIndex++; + if (Objects.nonNull(maxIndex) && lastIndex.compareTo(maxIndex) > 0){ + log.info("系统中没有待查询的车牌号"); + return; + } + carNo = infoMap.get(lastIndex); + } + + // 从车辆信息表中从上次执行中断的下标获取一定数量的车牌号 + int cnt = BIGGEST_ACCESS_NUM - lastCount; + LambdaQueryWrapper query = + Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .ge(NdVehicleBaseInfo::getId, lastIndex) + .last("limit " + cnt) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId) + .isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + log.info("此次任务车辆数量为:" + list.size()); + if (CollUtil.isNotEmpty(list)) { + List carPlateList = list.stream().sorted(Comparator.comparing(NdVehicleBaseInfo::getId)) + .map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + Map carMap = list.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId)); + String[] carPlates = carPlateList.stream().toArray(String[]::new); + // 执行查询任务 + executeTask(carPlates,carMap); + // 当访问次数达到当日设定数量时,结束循环,初始化累计访问次数,并更新事故数据 + if (BIGGEST_ACCESS_NUM.equals(lastCount) || lastIndex.equals(maxIndex)) { + isRunning = false; + // 任务执行完毕后保存最终的数据下标 + TreeMap sortedMap = new TreeMap<>(infoMap); + Map.Entry higherEntry = sortedMap.higherEntry(lastIndex); + if (Objects.nonNull(higherEntry)){ + lastIndex = higherEntry.getKey(); + } + saveLastIndex(lastIndex, 0); + // 更新事故数据 + updateAccidentData(); + log.info("事故数据更新完成!"); + } + } else { + log.info("本月任务已查询完成!"); + return; + } + } + stopWatch.stop(); + log.info("共更新事故数据:" + lastCount + "条"); + log.info("========== 根据IRS更新事故数据==========任务结束 {}s", stopWatch.getTotalTimeSeconds()); + + } + + private void executeTask(String[] carPlates, Map carMap) { + // 获取车牌号的所有事故信息 + Map> accidentIrsDataMap = accidentIrsDataService.list().stream() + .collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + for (int i = 0; i < carPlates.length; i++) { + // 执行任务代码 + String carPlate = carPlates[i]; + String dataJsonStr; + try { + dataJsonStr = accidentService.accidentQuery(carPlate,i); + if (Objects.nonNull(dataJsonStr)) { + JSONObject jsonObject = JSON.parseObject(dataJsonStr, JSONObject.class); + String msg = jsonObject.getString("msg"); + if (msg.contains("签名错误")) { + // 签名错误 + lastIndex = carMap.get(carPlate); + lastCount++; + saveLastIndex(lastIndex, lastCount); + log.error("签名错误,任务中断时车牌号下标为{}", lastIndex); + break; + } + } + } catch (Exception e) { + // 接口请求异常,结束循环 + lastIndex = carMap.get(carPlate); + lastCount++; + saveLastIndex(lastIndex, lastCount); + log.error("任务中断时车牌号下标为{},中断原因:{}", lastIndex,e.getMessage()); + break; + } + if (Objects.isNull(dataJsonStr)) { + // 刷新请求秘钥失败,接口调用内容返回空,任务中断,保存下标 + lastIndex = carMap.get(carPlate); + saveLastIndex(lastIndex, lastCount); + log.error("车辆事故查询接口调用失败,车牌号为:" + carPlate); + break; + } + int index = i + 1; + // 如果还有下一个待查询车牌号 + if (index < carPlates.length) { + lastIndex = carMap.get(carPlates[index]); + }else { + // 已经是最后一个车牌号 + lastIndex = carMap.get(carPlates[i]); + } + log.info("下次待查询车牌号下标为:" + lastIndex); + lastCount++; + log.info("已访问事故查询IRS接口 {} 次", lastCount); + log.info("此次访问的事故车牌号为 {}", carPlate); + + try { + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + continue; + } + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + + for (JSONObject jsonObject : accidentArray) { + VehicleAccidentIrsData accidentIrsData = new VehicleAccidentIrsData(); + accidentIrsData.setCarPlate(carPlate); + String jsonString = jsonObject.toJSONString(); + accidentIrsData.setJsonStrData(jsonString); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + if (accidentIrsDataMap.containsKey(carPlate)) { + List dataList = accidentIrsDataMap.get(carPlate); + Map dataMap = dataList.stream() + .collect(Collectors.toMap(VehicleAccidentIrsData::getAccidentTime, v -> v)); + if (dataMap.containsKey(accidentTime)) { + VehicleAccidentIrsData irsData = dataMap.get(accidentTime); + // 数据已经存在 + accidentIrsData.setId(irsData.getId()); + } + } + accidentIrsData.setAccidentTime(accidentTime); + accidentIrsData.setCreateOn(LocalDateTime.now()); + accidentIrsData.setUpdateOn(LocalDateTime.now()); + accidentIrsDataService.saveOrUpdate(accidentIrsData); + } + } + } + } catch (Exception e) { + throw new BizException("数据保存失败"); + } finally { + // 每次执行保存一次下标 + saveLastIndex(lastIndex,lastCount); + } + } + } + + private void saveLastIndex(Long lastIndex, Integer lastCount) { + + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + ACCIDENT_QUERY_INDEX_FILE); + + try { + FileWriter fileWriter = new FileWriter(file); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + bufferedWriter.write(Long.toString(lastIndex)); + bufferedWriter.newLine(); + bufferedWriter.write(Integer.toString(lastCount)); + bufferedWriter.newLine(); + + bufferedWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void readLastIndex() { + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + ACCIDENT_QUERY_INDEX_FILE); + + try { + List dataList = FileUtil.readLines(file, StandardCharsets.UTF_8); + if (CollUtil.isNotEmpty(dataList) && dataList.size() == 2) { + lastIndex = Long.valueOf(dataList.get(0)); + lastCount = Integer.valueOf(dataList.get(1)); + } + } catch (Exception e) { + log.info("读取下标和车牌号失败!"); + e.printStackTrace(); + } + } + + /** + * 从IRS事故数据表中更新数据到车辆事故数据表中 + * + * @return void + * @author CMM + * @since 2023/05/16 10:26 + */ + private void updateAccidentData() { + + // 从IRS事故数据表中更新数据到车辆事故数据表中 + Map> listMap = + accidentIrsDataService.list().stream().collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + + // 获取车牌号 + Set carPlateList = + accidentIrsDataService.list().stream().map(VehicleAccidentIrsData::getCarPlate).collect(Collectors.toSet()); + + // 获取车辆基本信息 + List vehicleBaseInfos = vehicleBaseInfoService + .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).in(NdVehicleBaseInfo::getCarPlate, carPlateList)); + Map vehicleBaseInfoMap = + vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取企业信息 + Map companyMap = + companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + + // 获取已经存在的事故数据 + List accidentTmpVas = vehicleAccidentService + .list(Wrappers.lambdaQuery(NdVehicleAccident.class).in(NdVehicleAccident::getCarPlate, carPlateList)); + Map accidentMap = accidentTmpVas.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>( + Comparator.comparing(a -> a.getCarPlate() + StrPool.SEMICOLON + a.getAccidentTime()))), + ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getAccidentTime(), d -> d)); + + // 获取已经存在的死亡事故数据 + List deadAccidentTmpVas = vehicleAccidentDeadService.list( + Wrappers.lambdaQuery(NdVehicleAccidentDead.class).in(NdVehicleAccidentDead::getCarPlate, carPlateList)); + Map deadAccidentMap = deadAccidentTmpVas.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>( + Comparator.comparing(a -> a.getCarPlate() + StrPool.SEMICOLON + a.getAccidentTime()))), + ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getAccidentTime(), d -> d)); + + for (String carPlate : carPlateList) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + if (Objects.isNull(vehicleBaseInfo)) { + //log.info("该车牌号不在系统中!"); + continue; + } + //// 查出对应车牌号关联的责任驾驶员 + // String driverName = vehicleBaseInfo.getResponsibleDriverFirst(); + // + // if (Objects.isNull(driverName)) { + // log.info("该车牌号没有责任驾驶员!"); + // continue; + // } + Long companyId = vehicleBaseInfo.getCompanyId(); + Company company = companyMap.get(companyId); + + // 获取IRS事故数据 + List accidentIrsDataList = listMap.get(carPlate); + + for (VehicleAccidentIrsData accidentIrsData : accidentIrsDataList) { + // 解析获取事故时间等信息 + String jsonStrData = accidentIrsData.getJsonStrData(); + JSONObject jsonObject = JSON.parseObject(jsonStrData); + + // 获取行政区划 + String xzqh = jsonObject.getString("XZQH"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + // 获取事故地点 + String sgdd = jsonObject.getString("SGDD"); + // 获取车辆类型 + Integer vehicleType = null; + if (Objects.nonNull(vehicleBaseInfo)) { + vehicleType = vehicleBaseInfo.getVehicleType(); + } + // 获取受伤人数 + Integer ssrs = jsonObject.getInteger("SSRS"); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + // 获取简要案情 + String jyaq = jsonObject.getString("JYAQ"); + // 获取事故编号 + String sgbh = jsonObject.getString("SGBH"); + // 获取经纬度电子坐标 + String dzzb = jsonObject.getString("DZZB"); + String longitude = null; + String latitude = null; + if (StringUtils.isNotBlank(dzzb) && dzzb.contains(StrPool.COMMA)) { + String[] split = dzzb.split(StrPool.COMMA); + Double longitudeD = Double.valueOf(split[0]); + Double latitudeD = Double.valueOf(split[1]); + DecimalFormat df = new DecimalFormat("#.###"); + longitude = df.format(longitudeD); + latitude = df.format(latitudeD); + } else { + // 交管事故数据未上传经纬度坐标,从当天的GPS数据中根据车牌号和事故时间查询经纬度 + LocalDateTime startTime = LocalDateTimeUtil.parse( + NdDateUtils.format(accidentTime, DatePattern.NORM_DATETIME_MINUTE_PATTERN), + DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + LocalDateTime endTime = LocalDateTimeUtil.parse( + NdDateUtils.format(accidentTime.plusMinutes(1), DatePattern.NORM_DATETIME_MINUTE_PATTERN), + DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + // 如果跨天了就设置相同地查询边界 + if (!NdDateUtils.format(startTime, DatePattern.NORM_DATE_PATTERN) + .equals(NdDateUtils.format(endTime, DatePattern.NORM_DATE_PATTERN))) { + endTime = startTime; + } + + List vehiclePositionInfos; + try { + vehiclePositionInfos = iVehiclePositionInfoService.dynamicGpsTableHistorySearch(carPlate, + accidentTime, endTime, NdDateUtils.format(startTime, "yyyy_MM_dd")); + if (CollUtil.isNotEmpty(vehiclePositionInfos)) { + VehiclePositionInfo positionInfo; + List positionInfoList = vehiclePositionInfos.stream() + .filter(v -> v.getUpdateTime().equals(accidentTime)).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(positionInfoList)) { + positionInfo = positionInfoList.get(0); + } else { + // 没有时间完全一样的GPS数据,就取第一个 + positionInfo = vehiclePositionInfos.get(0); + } + longitude = String.valueOf(positionInfo.getCarLongitude()); + latitude = String.valueOf(positionInfo.getCarLatitude()); + } + } catch (Exception e) { + // GPS数据中查询不到数据(GPS表可能被删除) + log.error(e.getMessage()); + } + } + + // 获取当场、24小时、3日内、7日内、30日内死亡人数 + Integer swrs = Objects.nonNull(jsonObject.getInteger("SWRS")) ? jsonObject.getInteger("SWRS") : 0; + Integer swrs24 = Objects.nonNull(jsonObject.getInteger("SWRS24")) ? jsonObject.getInteger("SWRS24") : 0; + Integer swrs3 = Objects.nonNull(jsonObject.getInteger("SWRS3")) ? jsonObject.getInteger("SWRS3") : 0; + Integer swrs7 = Objects.nonNull(jsonObject.getInteger("SWRS7")) ? jsonObject.getInteger("SWRS7") : 0; + Integer swrs30 = Objects.nonNull(jsonObject.getInteger("SWRS30")) ? jsonObject.getInteger("SWRS30") : 0; + // 有死亡人数,再插入到死亡事故表中 + if (swrs != 0 || swrs24 != 0 || swrs3 != 0 || swrs7 != 0 || swrs30 != 0) { + // 插入数据到死亡事故表中 + NdVehicleAccidentDead accidentDead = new NdVehicleAccidentDead(); + // 判断是否已经插入过 + if (deadAccidentMap.containsKey(carPlate + accidentTime)) { + NdVehicleAccidentDead dead = deadAccidentMap.get(carPlate + accidentTime); + accidentDead.setId(dead.getId()); + } + if (swrs30 != 0) { + accidentDead.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accidentDead.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accidentDead.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accidentDead.setDeathToll(swrs24); + } else { + accidentDead.setDeathToll(swrs); + } + accidentDead.setInjuries(ssrs); + accidentDead.setRegionId(regionId); + accidentDead.setRegionName(regionName); + // 获取事故时间 + accidentDead.setAccidentTime(accidentTime); + accidentDead.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、企业名称 + accidentDead.setCarPlate(carPlate); + // accidentDead.setAccidentDriver(driverName); + accidentDead.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accidentDead.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accidentDead.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + accidentDead.setBriefCase(jyaq); + accidentDead.setAccidentNo(sgbh); + accidentDead.setLongitude(longitude); + accidentDead.setLatitude(latitude); + vehicleAccidentDeadService.saveOrUpdate(accidentDead); + } + // 插入到事故表中 + NdVehicleAccident accident = new NdVehicleAccident(); + // 判断事故类型 + if (swrs != 0 || swrs24 != 0 || swrs3 != 0 || swrs7 != 0 || swrs30 != 0){ + accident.setAccidentType(AccidentTypeEnum.DEAD.getCode()); + } else if (Objects.nonNull(ssrs) && ssrs > 0) { + accident.setAccidentType(AccidentTypeEnum.INJURY.getCode()); + }else { + accident.setAccidentType(AccidentTypeEnum.OTHER.getCode()); + } + // 获取已经存在的事故信息 + NdVehicleAccident vehicleAccident = accidentMap.get(carPlate + accidentTime); + // 获取事故时间 + if (accidentMap.containsKey(carPlate + accidentTime)) { + accident.setId(vehicleAccident.getId()); + } + accident.setInjuries(ssrs); + if (swrs30 != 0) { + accident.setDeathToll(swrs30); + } else if (swrs7 != 0) { + accident.setDeathToll(swrs7); + } else if (swrs3 != 0) { + accident.setDeathToll(swrs3); + } else if (swrs24 != 0) { + accident.setDeathToll(swrs24); + } else { + accident.setDeathToll(swrs); + } + accident.setRegionId(regionId); + accident.setRegionName(regionName); + // 获取事故时间 + accident.setAccidentTime(accidentTime); + accident.setAccidentAddress(sgdd); + // 装配车牌号、事故驾驶员、车辆类型、企业名称 + accident.setCarPlate(carPlate); + + // accident.setAccidentDriver(driverName); + accident.setVehicleType(vehicleType); + accident.setCompanyId(companyId); + if (Objects.nonNull(company)) { + accident.setCompanyName(company.getName()); + } + // 是否上报默认为未上报 + accident.setReportStatus(VehicleAccidentReportStatusEnum.UNDER_REPORT.getCode()); + accident.setBriefCase(jyaq); + accident.setAccidentNo(sgbh); + accident.setLongitude(longitude); + accident.setLatitude(latitude); + vehicleAccidentService.saveOrUpdate(accident); + } + } + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyDrivingLicenseQueryTask.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyDrivingLicenseQueryTask.java new file mode 100644 index 0000000..e971761 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyDrivingLicenseQueryTask.java @@ -0,0 +1,219 @@ +package com.ningdatech.carapi.irs.task; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.StopWatch; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.ningdatech.carapi.irs.service.DriverService; +import com.ningdatech.carapi.irs.service.IDriversLicenseRawService; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author CMM + * @description + * @since 2023/05/21 15:38 + */ +@Component +@Slf4j +@Data +public class MyDrivingLicenseQueryTask implements Runnable { + + private final DriverService driverService; + private final IDriverInfoService driverInfoService; + private final IDriversLicenseRawService driversLicenseRawService; + + /** + * 接口访问次数限制 + */ + private Integer BIGGEST_ACCESS_NUM = 95; + /** + * 存储数据下标的文件名 + */ + private String ACCIDENT_QUERY_INDEX_FILE = "vehicleLicenseIndex.txt"; + /** + * 上次中断的驾驶员下标 + */ + private Long lastIndex = 0L; + /** + * 上次执行的次数 + */ + private Integer lastCount = 0; + /** + * 是否继续执行任务 + */ + private boolean isRunning = true; + + public MyDrivingLicenseQueryTask(DriverService driverService, IDriverInfoService driverInfoService, IDriversLicenseRawService driversLicenseRawService) { + this.driverService = driverService; + this.driverInfoService = driverInfoService; + this.driversLicenseRawService = driversLicenseRawService; + } + + @Override + public void run() { + + log.info("========== 根据IRS更新驾驶证数据 ==========任务开始"); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + while (isRunning) { + + // 读取上次中断的数据下标和和已经执行的次数 + readLastIndex(); + Map infoMap = driverInfoService.list().stream() + .collect(Collectors.toMap(DriverInfo::getId, v -> v)); + // 校验文件中存储的下标对应的身份证号是否一致 + DriverInfo info; + info = infoMap.get(lastIndex); + while (Objects.isNull(info)) { + log.error("文件中存储的驾驶员id{}不存在,请检查该驾驶员信息是否已经被删除!",lastIndex); + // 查找下一个驾驶员信息,直到驾驶员信息存在 + lastIndex++; + info = infoMap.get(lastIndex); + } + + // 从车辆信息表中从上次执行中断的下标获取一定数量的车牌号 + LambdaQueryWrapper query = + Wrappers.lambdaQuery(DriverInfo.class).ge(DriverInfo::getId, lastIndex) + .le(DriverInfo::getId, BIGGEST_ACCESS_NUM - lastCount + lastIndex - 1) + .select(DriverInfo::getIdCard).isNotNull(DriverInfo::getIdCard); + List list = driverInfoService.list(query); + + Set idCardSet = list.stream().map(DriverInfo::getIdCard).collect(Collectors.toSet()); + String[] idCards = idCardSet.toArray(new String[idCardSet.size()]); + try { + executeTask(idCards); + } catch (Exception e) { + // 下标恢复到上次执行失败的驾驶员下标 + lastIndex--; + // 线程被中断,退出循环 + isRunning = false; + e.printStackTrace(); + } finally { + // 任务执行完毕后保存最终的数据下标 + saveLastIndex(lastIndex, lastCount); + } + + stopWatch.stop(); + log.info("共更新驾驶证数据:" + lastCount + "条"); + log.info("========== 根据IRS更新驾驶证数据==========任务结束 {}s", stopWatch.getTotalTimeSeconds()); + } + + } + + private void executeTask(String[] idCards) { + for (int i = lastIndex.intValue(); i < idCards.length; i++) { + // 执行任务代码 + String idCard = idCards[i]; + String dataJsonStr = driverService.vehicleLicenseQuery(idCard); + lastIndex++; + lastCount++; + log.info("已访问驾驶证查询IRS接口 {} 次", lastCount); + log.info("此次访问的身份证号为 {}", idCard); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该身份证号没有驾驶证信息!"); + continue; + } + // 获取身份证号的所有行驶证信息 + Map> vehicleLicenseMap = driversLicenseRawService.list().stream() + .collect(Collectors.groupingBy(DriversLicenseRaw::getIdcard)); + + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + // 获取发证日期,判断是否重复 + Timestamp fZRQ = jsonObject.getTimestamp("fZRQ"); + + List driversLicenseRaws = vehicleLicenseMap.get(idCard); + List licenseRaws = driversLicenseRaws.stream().filter(d -> { + String detail = d.getDriverLicenseDetail(); + JSONObject json = JSON.parseObject(detail, JSONObject.class); + Timestamp timestamp = json.getTimestamp("fZRQ"); + if (timestamp.equals(fZRQ)) { + return true; + } else { + return false; + } + }).collect(Collectors.toList()); + + // 保存新增的驾驶证信息 + if (CollUtil.isNotEmpty(licenseRaws)) { + DriversLicenseRaw driversLicenseRaw = new DriversLicenseRaw(); + driversLicenseRaw.setIdcard(idCard); + String jsonString = jsonObject.toJSONString(); + driversLicenseRaw.setDrivingLicenseDetail(jsonString); + driversLicenseRaw.setCreateOn(LocalDateTime.now()); + driversLicenseRaw.setUpdateOn(LocalDateTime.now()); + driversLicenseRawService.save(driversLicenseRaw); + } + } + } + } + } + + private void saveLastIndex(Long lastIndex, Integer lastCount) { + + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + ACCIDENT_QUERY_INDEX_FILE); + + try { + FileWriter fileWriter = new FileWriter(file); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + bufferedWriter.write(Long.toString(lastIndex)); + bufferedWriter.newLine(); + bufferedWriter.write(Integer.toString(lastCount)); + bufferedWriter.newLine(); + + bufferedWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void readLastIndex() { + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + ACCIDENT_QUERY_INDEX_FILE); + + try { + // 创建Scanner对象并指定文件路径 + Scanner scanner = new Scanner(file); + + // 读取下标数据 + while (scanner.hasNextLong()) { + long num = scanner.nextLong(); + lastIndex = num; + } + + // 读取字符串数据 + scanner = new Scanner(file); + while (scanner.hasNextInt()) { + int cnt = scanner.nextInt(); + lastCount = cnt; + } + // 关闭Scanner对象 + scanner.close(); + } catch (FileNotFoundException e) { + log.info("读取下标和车牌号失败!"); + e.printStackTrace(); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleIllegalQueryTask.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleIllegalQueryTask.java new file mode 100644 index 0000000..8ab072e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleIllegalQueryTask.java @@ -0,0 +1,512 @@ +package com.ningdatech.carapi.irs.task; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.MissCertEnum; +import com.ningdatech.carapi.common.constant.ViolationTypeEnum; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.irs.model.entity.VehicleViolationIrsData; +import com.ningdatech.carapi.irs.service.CarService; +import com.ningdatech.carapi.irs.service.IVehicleViolationIrsDataService; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.file.utils.StrPool; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.io.FileUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description + * @since 2023/05/21 15:38 + */ +@Component +@Slf4j +@Data +public class MyVehicleIllegalQueryTask implements Runnable { + + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final CarService carService; + private final IVehicleViolationIrsDataService violationIrsDataService; + private final CompanyService companyService; + private final RegionsCacheHelper regionsCacheHelper; + private final INdVehicleViolationService vehicleViolationService; + private final IDriverInfoService driverInfoService; + + /** + * 无驾驶证违法行为code列表 + */ + private static final List NO_DRIVING_LICENSE_LIST = + Arrays.asList("5075", "5072", "5077", "5057", "10159", "1082", "70619", "6018", "7503", "7504", "7006", "70069", + "1015", "16444", "1644", "50411", "60182", "8005", "80059", "8605", "5603", "5703", "1610", "5041", "60541", + "1110", "7061", "10050", "10051", "10052", "10059", "1006", "1010", "10109", "1013", "1014", "6086", "5006", + "1005", "56031", "60181", "57021", "57031", "1704", "1701"); + + /** + * 无行驶证违法行为code列表 + */ + private static final List NO_VEHICLE_LICENSE_LIST = Arrays.asList("5071", "5069", "1088", "5702", "5705", + "7216", "7218", "1109", "6085", "5003", "57051", "50031", "57021", "5009", "5015"); + + /** + * 闯红灯(违反交通信号灯) + */ + private static final List VIOLATION_TRAFFIC_LIGHTS_LIST = Arrays.asList("13029", "1625", "16259", "1302"); + + /** + * 违规时段行驶 + */ + private static final List VIOLATION_TIME_LIST = Arrays.asList("8025"); + + /** + * 违规路段行驶 + */ + private static final List VIOLATION_ROAD_LIST = + Arrays.asList("1048", "10489", "40099", "8004", "8803", "11229", "8005J", "8002", "8048", "4009", "10393", + "10397", "1045", "10459", "1310", "13109", "1023", "10239", "8005", "8001C", "1122", "8014"); + + /** + * 接口访问次数限制 + */ + private Integer BIGGEST_ACCESS_NUM = 2950; + /** + * 存储数据下标的文件名 + */ + private String VEHICLE_ILLEGAL_QUERY_INDEX_FILE = "vehicleIllegalIndex.txt"; + /** + * 上次中断的车牌号下标 + */ + private Long lastIndex = 0L; + /** + * 上次执行的次数 + */ + private Integer lastCount = 0; + /** + * 是否继续执行任务 + */ + private boolean isRunning = true; + + public MyVehicleIllegalQueryTask(IVehicleBaseInfoService vehicleBaseInfoService, CarService carService, + IVehicleViolationIrsDataService violationIrsDataService, CompanyService companyService, + RegionsCacheHelper regionsCacheHelper, INdVehicleViolationService vehicleViolationService, + IDriverInfoService driverInfoService) { + this.vehicleBaseInfoService = vehicleBaseInfoService; + this.carService = carService; + this.violationIrsDataService = violationIrsDataService; + this.companyService = companyService; + this.regionsCacheHelper = regionsCacheHelper; + this.vehicleViolationService = vehicleViolationService; + this.driverInfoService = driverInfoService; + } + + @Override + public void run() { + log.info("========== 根据IRS更新车辆违法数据 ==========任务开始"); + // 判断当前执行任务的时间是否为月初的1号 如果是月初1号,任务应该从下标1重新开始跑 + LocalDateTime now = LocalDateTime.now(); + int dayOfMonth = now.getDayOfMonth(); + if (TaskContant.Data.MONTH_VALUE_ONE.equals(dayOfMonth)){ + // 重置文件中的下标 + saveLastIndex(1L, 0); + } + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + while (isRunning) { + // 读取上次中断的数据下标和和已经执行的次数 + readLastIndex(); + log.info("读取到的下标为{}", lastIndex); + log.info("已访问接口次数{}", lastCount); + Map infoMap = + vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getId,NdVehicleBaseInfo::getCarPlate)) + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getId, NdVehicleBaseInfo::getCarPlate)); + OptionalLong maxKey = infoMap.keySet().stream().mapToLong(Long::longValue).max(); + Long maxIndex = null; + if (maxKey.isPresent()){ + maxIndex = maxKey.getAsLong(); + } + // 校验文件中存储的下标对应的车牌号是否一致 + String carNo; + carNo = infoMap.get(lastIndex); + while (Objects.isNull(carNo)) { + log.error("车辆id{}不存在,请检查该车辆信息是否已经被删除!", lastIndex); + // 查找下一个车辆信息,直到车辆信息存在 + lastIndex++; + if (Objects.nonNull(maxIndex) && lastIndex.compareTo(maxIndex) > 0){ + log.info("系统中没有待查询的车牌号"); + return; + } + carNo = infoMap.get(lastIndex); + } + + // 从车辆信息表中从上次执行中断的下标获取一定数量的车牌号 + int cnt = BIGGEST_ACCESS_NUM - lastCount; + LambdaQueryWrapper query = + Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .ge(NdVehicleBaseInfo::getId, lastIndex) + .last("limit " + cnt) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId) + .isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + log.info("此次任务车辆数量为:" + list.size()); + if (CollUtil.isNotEmpty(list)) { + List carPlateList = list.stream().sorted(Comparator.comparing(NdVehicleBaseInfo::getId)) + .map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + Map carMap = list.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId)); + String[] carPlates = carPlateList.stream().toArray(String[]::new); + // 执行查询任务 + executeTask(carPlates,carMap); + // 当访问次数达到当日设定数量时,结束循环,初始化累计访问次数,并更新车辆违章数据 + if (BIGGEST_ACCESS_NUM.equals(lastCount) || lastIndex.equals(maxIndex)) { + isRunning = false; + // 任务执行完毕后保存最终的数据下标 + TreeMap sortedMap = new TreeMap<>(infoMap); + Map.Entry higherEntry = sortedMap.higherEntry(lastIndex); + if (Objects.nonNull(higherEntry)){ + lastIndex = higherEntry.getKey(); + } + saveLastIndex(lastIndex, 0); + updateViolationData(); + log.info("违法数据更新完成!"); + } + } else { + log.info("本月任务已查询完成!"); + return; + } + } + stopWatch.stop(); + log.info("共更新车辆违法数据:" + lastCount + "条"); + log.info("========== 根据IRS更新车辆违法数据==========任务结束 {}s", stopWatch.getTotalTimeSeconds()); + + } + + private void executeTask(String[] carPlates, Map carMap) { + // 获取车牌号的所有违章信息 + Map> violationIrsDataMap = violationIrsDataService.list(Wrappers.lambdaQuery(VehicleViolationIrsData.class) + .select(VehicleViolationIrsData::getId,VehicleViolationIrsData::getCarPlate, VehicleViolationIrsData::getViolationTime, + VehicleViolationIrsData::getViolationType,VehicleViolationIrsData::getViolationKind)).stream() + .collect(Collectors.groupingBy(VehicleViolationIrsData::getCarPlate)); + for (int i = 0; i < carPlates.length; i++) { + // 执行任务代码 + String carPlate = carPlates[i]; + String dataJsonStr; + try { + dataJsonStr = carService.vehicleIllegalQuery(carPlate, i); + if (Objects.nonNull(dataJsonStr)) { + JSONObject jsonObject = JSON.parseObject(dataJsonStr, JSONObject.class); + String msg = jsonObject.getString("msg"); + if (msg.contains("签名错误")) { + // 签名错误 + lastIndex = carMap.get(carPlate); + lastCount++; + saveLastIndex(lastIndex, lastCount); + log.error("签名错误,任务中断时车牌号下标为{}", lastIndex); + break; + } + } + } catch (Exception e) { + // 接口请求异常,结束循环 + lastIndex = carMap.get(carPlate); + lastCount++; + saveLastIndex(lastIndex, lastCount); + log.error("任务中断时车牌号下标为{},中断原因:{}", lastIndex,e.getMessage()); + break; + } + if (Objects.isNull(dataJsonStr)) { + // 刷新请求秘钥失败,接口调用内容返回空,任务中断,保存下标 + lastIndex = carMap.get(carPlate); + saveLastIndex(lastIndex, lastCount); + log.error("车辆违法查询接口调用失败,车牌号为:" + carPlate); + break; + } + int index = i + 1; + // 如果还有下一个待查询车牌号 + if (index < carPlates.length) { + lastIndex = carMap.get(carPlates[index]); + }else { + // 已经是最后一个车牌号 + lastIndex = carMap.get(carPlates[i]); + } + log.info("下次待查询车牌号下标为:" + lastIndex); + lastCount++; + log.info("已访问车辆违法查询IRS接口 {} 次", lastCount); + log.info("此次访问的违法车牌号为 {}", carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有违法行为信息!"); + continue; + } + + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + VehicleViolationIrsData vid = new VehicleViolationIrsData(); + vid.setCarPlate(carPlate); + // 获取违法日期 + Timestamp wfsj = jsonObject.getTimestamp("wfsj"); + LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj); + // 获取违法行为 + String wfxw = jsonObject.getString("wfxw"); + // 获取处罚种类 + String cfzl = jsonObject.getString("cfzl"); + String key = vehicleIllegalTime + wfxw + cfzl; + HashSet hashSet = new HashSet<>(); + + if (violationIrsDataMap.containsKey(carPlate)) { + List dataList = violationIrsDataMap.get(carPlate); + Map dataMap = dataList.stream() + .filter(v -> hashSet.add(v.getViolationTime() + v.getViolationType() + v.getViolationKind())) + .collect(Collectors.toMap(v -> v.getViolationTime() + v.getViolationType() + v.getViolationKind(), v -> v)); + if (dataMap.containsKey(key)) { + VehicleViolationIrsData irsData = dataMap.get(key); + // 数据已经存在 + vid.setId(irsData.getId()); + } + } + vid.setViolationTime(vehicleIllegalTime); + String jsonStr = jsonObject.toJSONString(); + vid.setJsonStrData(jsonStr); + vid.setViolationType(wfxw); + vid.setViolationKind(cfzl); + vid.setCreateOn(LocalDateTime.now()); + vid.setUpdateOn(LocalDateTime.now()); + violationIrsDataService.saveOrUpdate(vid); + } + } + } + } + + private void saveLastIndex(Long lastIndex, Integer lastCount) { + + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + VEHICLE_ILLEGAL_QUERY_INDEX_FILE); + + try { + FileWriter fileWriter = new FileWriter(file); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + bufferedWriter.write(Long.toString(lastIndex)); + bufferedWriter.newLine(); + bufferedWriter.write(Integer.toString(lastCount)); + bufferedWriter.newLine(); + + bufferedWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void readLastIndex() { + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + VEHICLE_ILLEGAL_QUERY_INDEX_FILE); + try { + List dataList = FileUtil.readLines(file, StandardCharsets.UTF_8); + if (CollUtil.isNotEmpty(dataList) && dataList.size() == 2) { + lastIndex = Long.valueOf(dataList.get(0)); + lastCount = Integer.valueOf(dataList.get(1)); + } + } catch (Exception e) { + log.info("读取下标和车牌号失败!"); + e.printStackTrace(); + } + } + + public void updateViolationData() { + + Map map = violationIrsDataService + .list(Wrappers.lambdaQuery(VehicleViolationIrsData.class) + .select(VehicleViolationIrsData::getId, VehicleViolationIrsData::getViolationType)) + .stream() + .collect(Collectors.toMap(VehicleViolationIrsData::getId, VehicleViolationIrsData::getViolationType)); + + List violationIdList = map.keySet().stream().filter(c -> { + String type = map.get(c); + return NO_DRIVING_LICENSE_LIST.contains(type) || NO_VEHICLE_LICENSE_LIST.contains(type) + || VIOLATION_TRAFFIC_LIGHTS_LIST.contains(type) || VIOLATION_TIME_LIST.contains(type) + || VIOLATION_ROAD_LIST.contains(type); + }).collect(Collectors.toList()); + + // 获取需要更新的数据 + Map> listMap = + violationIrsDataService.list(Wrappers.lambdaQuery(VehicleViolationIrsData.class) + .select(VehicleViolationIrsData::getId,VehicleViolationIrsData::getCarPlate, + VehicleViolationIrsData::getJsonStrData)) + .stream().filter(v -> violationIdList.contains(v.getId())) + .collect(Collectors.groupingBy(VehicleViolationIrsData::getCarPlate)); + + // 获取车牌号 + Set carPlateList = listMap.keySet(); + // 过滤掉不在系统中的车牌号 + List carPlates = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).select(NdVehicleBaseInfo::getCarPlate)); + List carPlateLists = carPlateList.stream().filter(carPlates::contains).collect(Collectors.toList()); + // 违章数据的车牌号都不在系统中,不需要更新 + if (CollUtil.isEmpty(carPlateLists)){ + log.info("没有需要更新的数据!"); + return; + } + // 获取车辆基本信息 + List vehicleBaseInfos = vehicleBaseInfoService + .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getCompanyId) + .in(NdVehicleBaseInfo::getCarPlate, carPlateLists)); + Map vehicleBaseInfoMap = + vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取企业信息 + Map companyMap = + companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + + // 获取已经存在的违章数据 + List violationTmpVas = vehicleViolationService + .list(Wrappers.lambdaQuery(NdVehicleViolation.class).in(NdVehicleViolation::getCarPlate, carPlateLists)); + Map violationMap = violationTmpVas.stream() + .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(a -> a.getCarPlate() + + StrPool.SEMICOLON + a.getViolationDate() + StrPool.SEMICOLON + a.getViolationType()))), ArrayList::new)) + .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getViolationDate() + d.getViolationType() + d.getViolationAddress(), d -> d)); + + for (String carPlate : carPlateLists) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + + Long companyId = vehicleBaseInfo.getCompanyId(); + Company company = null; + if (Objects.nonNull(companyId)) { + company = companyMap.get(companyId); + } + + // 获取IRS违章数据 + List violationIrsDataList = listMap.get(carPlate); + + for (VehicleViolationIrsData violationIrsData : violationIrsDataList) { + + // 解析获取事故时间等信息 + String jsonStrData = violationIrsData.getJsonStrData(); + JSONObject jsonObject = JSON.parseObject(jsonStrData); + + NdVehicleViolation vehicleViolation = new NdVehicleViolation(); + + // 获取违法日期 + Timestamp wfsj = jsonObject.getTimestamp("wfsj"); + LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj); + vehicleViolation.setViolationDate(vehicleIllegalTime); + // 获取违法地址 + String wfdz = jsonObject.getString("wfdz"); + // 获取违法行为 + String wfxw = jsonObject.getString("wfxw"); + // 获取违法编号 + String wfbh = jsonObject.getString("wfbh"); + + // 获取经纬度 + String longitude = jsonObject.getString("jd"); + String latitude = jsonObject.getString("wd"); + + // 判断是否已经插入过 + String key = carPlate + vehicleIllegalTime + wfdz + wfxw; + if (violationMap.containsKey(key)) { + NdVehicleViolation violation = violationMap.get(key); + vehicleViolation.setId(violation.getId()); + } + vehicleViolation.setCarPlate(carPlate); + // 获取行政区划 + String xzqh = jsonObject.getString("xzqh"); + // 获取区域信息 + Long regionId = regionsCacheHelper.getIdByCode(xzqh); + String regionName = regionsCacheHelper.getDisplayName(regionId); + vehicleViolation.setRegionId(regionId); + vehicleViolation.setRegionName(regionName); + // 如果是闯红灯 + if (VIOLATION_TRAFFIC_LIGHTS_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.RED_LIGHT.getCode()); + vehicleViolation.setAddressRedLight(wfdz); + } else if (NO_DRIVING_LICENSE_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode()); + vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVER_LINCENSE.getCode()); + } else if (NO_VEHICLE_LICENSE_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode()); + vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVE_PERMIT.getCode()); + } else if (VIOLATION_TIME_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.PERIOD.getCode()); + int hour = vehicleIllegalTime.getHour(); + int minute = vehicleIllegalTime.getMinute(); + String period = null; + // 时间段暂时设置为违章时间所在小时的前后半小时 + if (minute < 30) { + period = vehicleIllegalTime.minusHours(1).getHour() + TaskContant.Data.VIOLATION_TIME_HALF + + StrPool.DASH + hour + TaskContant.Data.VIOLATION_TIME_HALF; + } else { + period = hour + TaskContant.Data.VIOLATION_TIME_START + StrPool.DASH + + vehicleIllegalTime.plusHours(1).getHour() + TaskContant.Data.VIOLATION_TIME_START; + } + vehicleViolation.setViolationPeriod(period); + // if (hour >= TaskContant.Data.VIOLATION_TIME_SEVEN && hour <= + // TaskContant.Data.VIOLATION_TIME_NINE) { + // period = TaskContant.Data.VIOLATION_TIME_AM_START + StrPool.DASH + // + TaskContant.Data.VIOLATION_TIME_AM_END; + // vehicleViolation.setViolationPeriod(period); + // } else if (hour >= TaskContant.Data.VIOLATION_TIME_SIXTEEN + // && hour <= TaskContant.Data.VIOLATION_TIME_EIGHTEEN) { + // period = TaskContant.Data.VIOLATION_TIME_PM_START + StrPool.DASH + // + TaskContant.Data.VIOLATION_TIME_PM_END; + // vehicleViolation.setViolationPeriod(period); + // } + } else if (VIOLATION_ROAD_LIST.contains(wfxw)) { + vehicleViolation.setViolationType(ViolationTypeEnum.SECTION.getCode()); + vehicleViolation.setWaySection(wfdz); + } + // 获取当事人(驾驶员) + String driverName = jsonObject.getString("dsr"); + + vehicleViolation.setCompanyId(companyId); + if (Objects.nonNull(company)) { + vehicleViolation.setCompanyName(company.getName()); + } + // 驾驶员姓名和企业名称获取驾驶员信息 + List driverInfoList = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getDriverName, driverName).eq(DriverInfo::getCompanyId, companyId)); + if (CollUtil.isEmpty(driverInfoList)) { + log.info("该车牌号对应的企业下没有该驾驶员信息"); + } else { + // 获取最后一个 + DriverInfo driverInfo = driverInfoList.get(driverInfoList.size() - 1); + vehicleViolation.setDriverId(driverInfo.getId()); + } + vehicleViolation.setDriverName(driverName); + vehicleViolation.setLongitude(longitude); + vehicleViolation.setLatitude(latitude); + vehicleViolation.setViolationNo(wfbh); + vehicleViolation.setViolationAddress(wfdz); + vehicleViolationService.saveOrUpdate(vehicleViolation); + } + } + log.info("违章数据更新完成!"); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleLicenseQueryTask.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleLicenseQueryTask.java new file mode 100644 index 0000000..0326489 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/task/MyVehicleLicenseQueryTask.java @@ -0,0 +1,275 @@ +package com.ningdatech.carapi.irs.task; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.irs.entity.DriversLicenseRaw; +import com.ningdatech.carapi.irs.service.DriverService; +import com.ningdatech.carapi.irs.service.IDriversLicenseRawService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.io.FileUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description + * @since 2023/05/21 15:38 + */ +@Component +@Slf4j +@Data +public class MyVehicleLicenseQueryTask implements Runnable { + + private final DriverService driverService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final IDriversLicenseRawService driversLicenseRawService; + + /** + * 接口访问次数限制 + */ + private Integer BIGGEST_ACCESS_NUM = 95; + /** + * 存储数据下标的文件名 + */ + private String ACCIDENT_QUERY_INDEX_FILE = "vehicleLicenseIndex.txt"; + /** + * 上次中断的驾驶员下标 + */ + private Long lastIndex = 0L; + /** + * 上次执行的次数 + */ + private Integer lastCount = 0; + /** + * 是否继续执行任务 + */ + private boolean isRunning = true; + + public MyVehicleLicenseQueryTask(DriverService driverService, IVehicleBaseInfoService vehicleBaseInfoService, + IDriversLicenseRawService driversLicenseRawService) { + this.driverService = driverService; + this.vehicleBaseInfoService = vehicleBaseInfoService; + this.driversLicenseRawService = driversLicenseRawService; + } + + @Override + public void run() { + + log.info("========== 根据IRS更新行驶证数据 ==========任务开始"); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + while (isRunning) { + // 读取上次中断的数据下标和和已经执行的次数 + readLastIndex(); + Map infoMap = + vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getId,NdVehicleBaseInfo::getCarPlate)) + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getId, NdVehicleBaseInfo::getCarPlate)); + OptionalLong maxKey = infoMap.keySet().stream().mapToLong(Long::longValue).max(); + Long maxIndex = null; + if (maxKey.isPresent()){ + maxIndex = maxKey.getAsLong(); + } + // 校验下标对应的车牌号是否一致 + String carNo; + carNo = infoMap.get(lastIndex); + while (Objects.isNull(carNo)) { + log.info("车辆id{}不存在,请检查该车辆信息是否已经被删除!", lastIndex); + // 查找下一个车辆信息,直到车辆信息存在 + lastIndex++; + if (Objects.nonNull(maxIndex) && lastIndex.compareTo(maxIndex) > 0){ + log.info("系统中没有待查询的车牌号"); + return; + } + carNo = infoMap.get(lastIndex); + } + + // 从车辆信息表中从上次执行中断的下标获取一定数量的车牌号 + int cnt = BIGGEST_ACCESS_NUM - lastCount; + LambdaQueryWrapper query = + Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .ge(NdVehicleBaseInfo::getId, lastIndex) + .last("limit " + cnt) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId) + .isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + log.info("此次任务车辆数量为:" + list.size()); + if (CollUtil.isNotEmpty(list)) { + List carPlateList = list.stream().sorted(Comparator.comparing(NdVehicleBaseInfo::getId)) + .map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + Map carMap = list.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId)); + String[] carPlates = carPlateList.stream().toArray(String[]::new); + // 执行查询任务 + executeTask(carPlates,carMap); + // 当访问次数达到当日设定数量时,结束循环,初始化累计访问次数 + if (BIGGEST_ACCESS_NUM.equals(lastCount) || lastIndex.equals(maxIndex)) { + isRunning = false; + // 任务执行完毕后保存最终的数据下标 + TreeMap sortedMap = new TreeMap<>(infoMap); + Map.Entry higherEntry = sortedMap.higherEntry(lastIndex); + if (Objects.nonNull(higherEntry)){ + lastIndex = higherEntry.getKey(); + } + saveLastIndex(lastIndex, 0); + } + } else { + log.info("本月任务已查询完成!"); + return; + } + } + stopWatch.stop(); + log.info("共更新行驶证数据:" + lastCount + "条"); + log.info("========== 根据IRS更新行驶证数据==========任务结束 {}s", stopWatch.getTotalTimeSeconds()); + + } + + private void executeTask(String[] carPlates, Map carMap) { + for (int i = 0; i < carPlates.length; i++) { + // 执行任务代码 + String carPlate = carPlates[i]; + String dataJsonStr; + try { + dataJsonStr = driverService.vehicleLicenseQuery(carPlate,i); + if (Objects.nonNull(dataJsonStr)) { + JSONObject jsonObject = JSON.parseObject(dataJsonStr, JSONObject.class); + String msg = jsonObject.getString("msg"); + if (msg.contains("签名错误")) { + // 签名错误 + lastIndex = carMap.get(carPlate); + lastCount++; + saveLastIndex(lastIndex, lastCount); + log.error("签名错误,任务中断时车牌号下标为{}", lastIndex); + break; + } + } + } catch (Exception e) { + // 接口请求异常,结束循环 + lastIndex = carMap.get(carPlate); + lastCount++; + saveLastIndex(lastIndex, lastCount); + log.error("任务中断时车牌号下标为{},中断原因:{}", lastIndex,e.getMessage()); + break; + } + if (Objects.isNull(dataJsonStr)) { + // 刷新请求秘钥失败,接口调用内容返回空,任务中断,保存下标 + lastIndex = carMap.get(carPlate); + saveLastIndex(lastIndex, lastCount); + log.error("车辆行驶证查询接口调用失败,车牌号为:" + carPlate); + break; + } + int index = i + 1; + // 如果还有下一个待查询车牌号 + if (index < carPlates.length) { + lastIndex = carMap.get(carPlates[index]); + }else { + // 已经是最后一个车牌号 + lastIndex = carMap.get(carPlates[i]); + } + log.info("下次待查询车牌号下标为:" + lastIndex); + lastCount++; + log.info("已访问行驶证查询IRS接口 {} 次", lastCount); + log.info("此次访问的车牌号为 {}", carPlate); + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, JSONObject.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有行驶证信息!"); + continue; + } + // 获取身份证号的所有行驶证信息 + Map> vehicleLicenseMap = + driversLicenseRawService.list().stream().collect(Collectors.groupingBy(DriversLicenseRaw::getCarPlate)); + + for (JSONObject jsonObject : array) { + if (Objects.nonNull(jsonObject)) { + // 获取发证日期,判断是否重复 + Timestamp fZRQ = jsonObject.getTimestamp("fZRQ"); + + List licenseRaws = Lists.newArrayList(); + List driversLicenseRaws = vehicleLicenseMap.get(carPlate); + if (CollUtil.isNotEmpty(driversLicenseRaws)) { + licenseRaws = driversLicenseRaws.stream().filter(d -> { + String detail = d.getDrivingLicenseDetail(); + JSONObject json = JSON.parseObject(detail, JSONObject.class); + Timestamp timestamp = json.getTimestamp("fZRQ"); + if (timestamp.equals(fZRQ)) { + return true; + } else { + return false; + } + }).collect(Collectors.toList()); + } + + // 没有跟当前发证日期相同地行驶证信息,保存新增的行驶证信息 + if (CollUtil.isEmpty(licenseRaws)) { + DriversLicenseRaw driversLicenseRaw = new DriversLicenseRaw(); + driversLicenseRaw.setCarPlate(carPlate); + String jsonString = jsonObject.toJSONString(); + driversLicenseRaw.setDrivingLicenseDetail(jsonString); + driversLicenseRaw.setCreateOn(LocalDateTime.now()); + driversLicenseRaw.setUpdateOn(LocalDateTime.now()); + driversLicenseRawService.save(driversLicenseRaw); + } + } + } + } + } + + private void saveLastIndex(Long lastIndex, Integer lastCount) { + + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + ACCIDENT_QUERY_INDEX_FILE); + + try { + FileWriter fileWriter = new FileWriter(file); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + bufferedWriter.write(Long.toString(lastIndex)); + bufferedWriter.newLine(); + bufferedWriter.write(Integer.toString(lastCount)); + bufferedWriter.newLine(); + + bufferedWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void readLastIndex() { + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "irs"; + File file = new File(filePath + File.separator + ACCIDENT_QUERY_INDEX_FILE); + try { + List dataList = FileUtil.readLines(file, StandardCharsets.UTF_8); + if (CollUtil.isNotEmpty(dataList) && dataList.size() == 2) { + lastIndex = Long.valueOf(dataList.get(0)); + lastCount = Integer.valueOf(dataList.get(1)); + } + } catch (Exception e) { + log.info("读取下标和车牌号失败!"); + e.printStackTrace(); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/HttpUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/HttpUtil.java new file mode 100644 index 0000000..8a929a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/HttpUtil.java @@ -0,0 +1,215 @@ +package com.ningdatech.carapi.irs.utils; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.util.PublicSuffixMatcher; +import org.apache.http.conn.util.PublicSuffixMatcherLoader; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +public class HttpUtil { + private Logger logger = LoggerFactory.getLogger(getClass()); + private RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(15000) + .setConnectTimeout(15000) + .setConnectionRequestTimeout(15000) + .build(); + private static HttpUtil instance = null; + private HttpUtil(){} + + public static HttpUtil getInstance(){ + if (instance == null) { + instance = new HttpUtil(); + } + return instance; + } + + /** + * 发送 post 请求 + * @param httpUrl 地址 + */ + public String sendHttpPost(String httpUrl) { + HttpPost httpPost= new HttpPost(httpUrl);// 创建 httpPost + return sendHttpPost(httpPost); + } + + /** + * 发送 post 请求 + * @param httpUrl 地址 + * @param params 参数(格式:key1=value1&key2=value2) + */ + public String sendHttpPost(String httpUrl, String params) { + HttpPost httpPost= new HttpPost(httpUrl);// 创建 httpPost + try { + //设置参数 + StringEntity stringEntity = new StringEntity(params, "UTF-8"); + stringEntity.setContentType("application/x-www-form-urlencoded"); + httpPost.setEntity(stringEntity); + } catch (Exception e) { + logger.error(e.getMessage(),e); + } + return sendHttpPost(httpPost); + } + + /** + * 发送 post 请求 + * @param httpUrl 地址 + * @param maps 参数 + */ + public String sendHttpPost(String httpUrl, Map maps) { + HttpPost httpPost= new HttpPost(httpUrl);// 创建 httpPost + // 创建参数队列 + List nameValuePairs = new ArrayList(); + for (String key : maps.keySet()) { + nameValuePairs.add(new BasicNameValuePair(key, maps.get(key))); + } + try { + httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8")); + } catch (Exception e) { + logger.error(e.getMessage(),e); + } + return sendHttpPost(httpPost); + } + + /** + * 发送 Post请求 + * @param httpPost + *@return + */ + private String sendHttpPost(HttpPost httpPost) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse response = null; + HttpEntity entity = null; + String responseContent = null; + try { + // 创建默认的 httpClient 实例. + httpClient = HttpClients.createDefault(); + httpPost.setConfig(requestConfig); + // 执行请求 + response = httpClient.execute(httpPost); + entity = response.getEntity(); + responseContent = EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + logger.error(e.getMessage(),e); + } finally { + try { + // 关闭连接,释放资源 + if (response != null) { + response.close(); + } + if (httpClient != null) { + httpClient.close(); + } + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + } + return responseContent; + } + + /** + * 发送 get 请求 + * @param httpUrl + */ + public String sendHttpGet(String httpUrl) { + HttpGet httpGet = new HttpGet(httpUrl);// 创建 get 请求 + return sendHttpGet(httpGet); + } + + /** + * 发送 get请求 Https + * @param httpUrl + */ + public String sendHttpsGet(String httpUrl) { + HttpGet httpGet = new HttpGet(httpUrl);// 创建 get 请求 + return sendHttpsGet(httpGet); + } + + /** + * 发送 Get请求 + * @param httpGet + *@return + */ + private String sendHttpGet(HttpGet httpGet) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse response = null; + HttpEntity entity = null; + String responseContent = null; + try { + // 创建默认的 httpClient 实例. + httpClient = HttpClients.createDefault(); + httpGet.setConfig(requestConfig); + // 执行请求 + response = httpClient.execute(httpGet); + entity = response.getEntity(); + responseContent = EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + logger.error(e.getMessage(),e); + } finally { + try { + // 关闭连接,释放资源 + if (response != null) { + response.close(); + } + if (httpClient != null) { + httpClient.close(); + } + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + } + return responseContent; + } + + /** + * 发送 Get请求 Https + *@return + */ + private String sendHttpsGet(HttpGet httpGet) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse response = null; + HttpEntity entity = null; + String responseContent = null; + try { + // 创建默认的 httpClient 实例. + PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new + URL(httpGet.getURI().toString())); + DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher); + httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build(); + httpGet.setConfig(requestConfig); + // 执行请求 + response = httpClient.execute(httpGet); + entity = response.getEntity(); + responseContent = EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + logger.error(e.getMessage(),e); + } finally { + try { + // 关闭连接,释放资源 + if (response != null) { + response.close(); + } + if (httpClient != null) { + httpClient.close(); + } + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + } + return responseContent; + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/Md5Utils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/Md5Utils.java new file mode 100644 index 0000000..34e084f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/irs/utils/Md5Utils.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.irs.utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.security.MessageDigest; + +public class Md5Utils { + private static final Logger LOGGER = LoggerFactory.getLogger(Md5Utils.class); + public static byte[] md5(String s) { + MessageDigest algorithm; + try { + algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(s.getBytes("UTF-8")); + byte[] messageDigest = algorithm.digest(); + return messageDigest; + } catch (Exception e) { + LOGGER.error("MD5 Error...", e); + } + return null; + } + private static final String toHex(byte hash[]) { + if (hash == null) { + return null; + } + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + for (i = 0; i < hash.length; i++) { + if ((hash[i] & 0xff) < 0x10) { + buf.append("0"); + } + buf.append(Long.toString(hash[i] & 0xff, 16)); + } + return buf.toString(); + } + + public static String hash(String s) { + try { + return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8"); + } catch (Exception e) { + LOGGER.error("not supported charset...{}", e); + return s; + } + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/constant/LogBackupConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/constant/LogBackupConstant.java new file mode 100644 index 0000000..0e3dc3a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/constant/LogBackupConstant.java @@ -0,0 +1,15 @@ +package com.ningdatech.carapi.log.constant; + +/** + * 短信验证常量 + * @return + * @author CMM + * @since 2023/06/02 11:31 + */ +public interface LogBackupConstant { + + String LOG_FILE_NAME = "logs.tar.gz"; + String LOG_FILE_PATH = "backupLogs"; + + String HOST = "iZbp13nwyvib53j4j1p2xoZ"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/LogBackupController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/LogBackupController.java new file mode 100644 index 0000000..a3acff3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/LogBackupController.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.log.controller; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.log.manage.LogManage; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 用户登录获取验证码 + * + * @author CMM + * @since 2023/01/06 16:38 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/log") +@Api(value = "LogBackupController", tags = "日志备份下载") +@RequiredArgsConstructor +public class LogBackupController { + + private final LogManage logManage; + + @ApiOperation(value = "log backup", notes = "log backup") + @GetMapping("/backup") + public String backupLog() { + return logManage.backupLog(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/OpenApiLogBackupController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/OpenApiLogBackupController.java new file mode 100644 index 0000000..05aec5f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/controller/OpenApiLogBackupController.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.log.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.log.manage.LogBackupManage; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 服务器系统日志备份 + * + * @author CMM + * @since 2023/01/06 16:38 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/log/backup") +@Api(value = "OpenApiLogBackupController", tags = "服务器系统日志备份") +@RequiredArgsConstructor +public class OpenApiLogBackupController { + + private final LogBackupManage logBackupManage; + + @GetMapping( "/download") + @ApiOperation(value = "将服务器定时备份的系统日志通过接口返回") + public ResponseEntity downloadFile(){ + return logBackupManage.downloadFile(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogBackupManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogBackupManage.java new file mode 100644 index 0000000..59d751b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogBackupManage.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.log.manage; + +import java.io.File; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import cn.hutool.core.io.FileUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/01/06 16:40 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class LogBackupManage { + + public ResponseEntity downloadFile() { + // 指定.tar.gz文件的路径 + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "bash/logs.tar.gz"; + File file = new File(filePath); + byte[] fileBytes = FileUtil.readBytes(file); + + + // 设置响应头信息 + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=logs.tar.gz"); + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE); + headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileBytes.length)); + + // 返回ResponseEntity对象 + return ResponseEntity.ok() + .headers(headers) + .body(fileBytes); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogManage.java new file mode 100644 index 0000000..5e407e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/manage/LogManage.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.log.manage; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Objects; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.client.RestTemplate; + +import com.ningdatech.carapi.log.constant.LogBackupConstant; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/01/06 16:40 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class LogManage { + + private final RestTemplate restTemplate; + + @Value("${log.backup.url}") + private String backupUrl; + + public String backupLog() { + + ResponseEntity entity = restTemplate.getForEntity(backupUrl, byte[].class); + if (Boolean.TRUE.equals(saveFile(entity, LogBackupConstant.LOG_FILE_PATH))) { + return "备份成功"; + }else { + return "备份失败"; + } + } + + private Boolean saveFile(ResponseEntity entity, String backupFilePath) { + byte[] body = entity.getBody(); + try { + if (Objects.nonNull(body)) { + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + backupFilePath; + File saveDir = new File(filePath); + if (!saveDir.exists()) { + saveDir.mkdirs(); + } + File saveFile = new File(saveDir, LogBackupConstant.LOG_FILE_NAME); + FileOutputStream fos = new FileOutputStream(saveFile); + FileCopyUtils.copy(body, fos); + fos.flush(); + fos.close(); + return true; + } + } catch (IOException e) { + log.error("文件保存失败:" + e.getMessage()); + return false; + } + return false; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/task/LogBackupTask.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/task/LogBackupTask.java new file mode 100644 index 0000000..3ed763b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/log/task/LogBackupTask.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.log.task; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.ningdatech.carapi.log.constant.LogBackupConstant; +import com.ningdatech.carapi.log.manage.LogManage; + +import cn.hutool.core.date.StopWatch; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 事故责任认定书信息 + * + * @author CMM + * @description + * @since 2022/12/02 16:28 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class LogBackupTask { + @Value("${task.switch.is-open}") + private boolean flag; + + private final LogManage logManage; + + + /** + * 定时备份服务器系统日志 每天23点的55分钟开始执行一次 + * + */ + @Scheduled(cron = "0 55 23 * * ?") + public void doTask() throws UnknownHostException { + if (flag && LogBackupConstant.HOST.equals(InetAddress.getLocalHost().getHostName())) { + log.info("========== 更新服务器备份日志 ==========任务开始"); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + String result = logManage.backupLog(); + log.info(result); + log.info("本机IP为:" + InetAddress.getLocalHost().getHostAddress()); + stopWatch.stop(); + log.info("========== 更新服务器备份日志 ==========任务结束 耗时 {}s", stopWatch.getTotalTimeSeconds()); + } + + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLock.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLock.java new file mode 100644 index 0000000..90223e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLock.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.open.aop; + +import java.lang.annotation.*; + +/** + * @Classname TackLock + * @Description + * @Date 2022/10/31 15:34 + * @Created by PoffyZhang + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TaskLock { + + /** + * 定时任务名称 + * + * @return + */ + String name() default ""; + + /** + * redis缓存key值 + * + * @return + */ + String key(); + + /** + * 过期时间单位s (自动解锁时间,防止死锁) + * + * @return + */ + int expired(); + + /** + * 执行完毕是否解锁 + * + * @return + */ + boolean unLock() default true; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLockAspect.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLockAspect.java new file mode 100644 index 0000000..10fa7c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/aop/TaskLockAspect.java @@ -0,0 +1,88 @@ +package com.ningdatech.carapi.open.aop; + +import com.ningdatech.cache.redis.RedisOps; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import java.time.Duration; +import java.util.UUID; + +/** + * @program: + * @description: 定时任务锁切面 + * @author: PoffyZhang + * @created: 2022/11/1 09:12 + */ +@Aspect +@Component +@Slf4j +@AllArgsConstructor +@Order(10) +public class TaskLockAspect { + + private RedisOps redisOps; + + @Pointcut("@annotation(com.ningdatech.carapi.open.aop.TaskLock)") + public void taskLockAspect() { + + } + + @Around("taskLockAspect() && @annotation(taskLock)") + public Object doAround(ProceedingJoinPoint proceedingJoinPoint, TaskLock taskLock) throws Throwable { + String value = UUID.randomUUID().toString(); + try { + if (lock(taskLock.key(), value, taskLock.expired())) { + return proceedingJoinPoint.proceed(); + } + } catch (Exception e) { + log.error("定时任务执行失败,{}", taskLock.key(), e); + } finally { + // 执行完毕解除锁 + if (taskLock.unLock()) { + String lockValue = getLockValue(taskLock.key()); + if (StringUtils.isNotEmpty(lockValue) && lockValue.equals(value)) { + // 解锁设置为延时1S + unLock(taskLock.key()); + } + } + } + return null; + } + + + + /** + * 加锁 + * @param key + * @param value + * @param time + * @return + */ + public boolean lock(String key , String value , int time){ + return redisOps.setXx(key,value,time,false); + } + + + /** + * 解锁 + * @param key + */ + public void unLock(String key){ + redisOps.expire(key,Duration.ofSeconds(1)); + } + + /** + * 获取锁值 + * @param key + * @return + */ + public String getLockValue(String key){ + return redisOps.get(key); + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/contants/AlarmContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/contants/AlarmContant.java new file mode 100644 index 0000000..532cd2f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/contants/AlarmContant.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.open.contants; + +/** + * @Classname AlarmContant + * @Description + * @Date 2022/10/31 14:07 + * @Created by PoffyZhang + */ +public class AlarmContant { + + private AlarmContant(){ + + } + + public static final String ALARM_DATA_PRICTURE_KEY = "alarm_data:picture"; + + public static final String ALARM_DATA_VIDEO_KEY = "alarm_data:video"; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiAbnormalBehaviorAlarmDataController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiAbnormalBehaviorAlarmDataController.java new file mode 100644 index 0000000..4ed1a75 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiAbnormalBehaviorAlarmDataController.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.carapi.open.manage.AlarmDataManage; +import com.ningdatech.carapi.open.model.dto.AlarmDataPictureDTO; +import com.ningdatech.carapi.open.model.dto.AlarmDataVideoDTO; +import com.ningdatech.openapi.signature.annatation.OpenApiSignature; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * @Classname AbnormalBehaviorAlarmDataController + * @Description + * @Date 2022/10/28 10:05 + * @Created by PoffyZhang + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/alarm-data-save") +@Api(value = "AbnormalBehaviorAlarmData", tags = "保存异常行为数据") +@RequiredArgsConstructor +public class OpenApiAbnormalBehaviorAlarmDataController { + + private final AlarmDataManage alarmDataManage; + + @ApiOperation(value = "图片", notes = "图片") + @PostMapping("/picture") + @OpenApiSignature(expireCheck = false) + public Boolean savePricture(@Valid @RequestBody AlarmDataPictureDTO alarmDataPicture) { + return alarmDataManage.savePicture(alarmDataPicture); + } + + @ApiOperation(value = "短视频", notes = "短视频") + @PostMapping("/video") + @OpenApiSignature(expireCheck = false) + public Boolean saveVideo(@Valid @RequestBody AlarmDataVideoDTO alarmDataVideo) { + return alarmDataManage.saveVideo(alarmDataVideo); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCarPositionController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCarPositionController.java new file mode 100644 index 0000000..8ef1eca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCarPositionController.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.open.controller; + +import java.util.List; + +import javax.validation.Valid; + +import com.ningdatech.basic.model.PageVo; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.car.position.model.po.ReqTrajectoryDataPO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.car.position.model.vo.ResTrajectoryDataVO; +import com.ningdatech.carapi.open.manage.OpenCarPositionManage; +import com.ningdatech.carapi.open.model.po.ReqRealTimeCapPositionPO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/car/position") +@RequiredArgsConstructor +public class OpenApiCarPositionController { + + private final OpenCarPositionManage openCarPositionManage; + + @PostMapping("/trajectory-data-list") + @ApiOperation("获取车辆轨迹数据列表(无分页)") + @WebLog + public List trajectoryDatalist(@Valid @RequestBody ReqTrajectoryDataPO po) { + return openCarPositionManage.trajectoryDatalist(po); + } + + @PostMapping("/real-time-monitor-vehicle-gis-data") + @ApiOperation("实时监控车辆gis数据") + @WebLog + public PageVo realTimeMonitorVehicleGisData(@Valid @RequestBody ReqRealTimeCapPositionPO po) { + return openCarPositionManage.realTimeMonitorAllGisList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCompanyArchivesController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCompanyArchivesController.java new file mode 100644 index 0000000..36c043f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiCompanyArchivesController.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.open.controller; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.carapi.company.entity.dto.ResCompanyArchivesDetailsDTO; +import com.ningdatech.carapi.company.entity.vo.CompanyEmployeesVO; +import com.ningdatech.carapi.company.service.ICompanyArchivesService; +import com.ningdatech.carapi.open.model.vo.CompanySecurityInfoVO; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.CompanySaveDTO; +import com.ningdatech.carapi.sys.entity.vo.CompanyVO; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * @description: 企业档案管理 + * @author: liushuai + * @date: 2022/10/25 17:58 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/open/api/v1/company-archives") +public class OpenApiCompanyArchivesController { + private final ICompanyArchivesService iCompanyArchivesService; + + @GetMapping("/detail") + public ResCompanyArchivesDetailsDTO getCompanyDetail(@RequestParam(value = "companyId", required = false) Long companyId) { + return iCompanyArchivesService.getCompanyDetail(companyId); + } + + @GetMapping("/employees") + public List getCompanyEmployees(@RequestParam(value = "companyId", required = false) Long companyId) { + return iCompanyArchivesService.getCompanyEmployees(companyId); + } + + /** + * 企业安全信息 + * @param companyId + * @return + */ + @GetMapping("/security") + public CompanySecurityInfoVO getCompanySecurityInfo(@RequestParam(value = "companyId", required = false) Long companyId) { + return iCompanyArchivesService.getCompanySecurityInfo(companyId); + } + + @ApiOperation(value = "二维码注册新企业", notes = "二维码注册新企业") + @PostMapping("/register") + public CompanyVO registerCompany(@Valid @RequestBody CompanySaveDTO data) { + Company company = iCompanyArchivesService.saveCompany(data); + return BeanUtil.toBean(company, CompanyVO.class); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiDriverArchivesController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiDriverArchivesController.java new file mode 100644 index 0000000..54fa674 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiDriverArchivesController.java @@ -0,0 +1,104 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.position.model.po.ReqDataPO; +import com.ningdatech.carapi.driver.manage.DriverArchivesManage; +import com.ningdatech.carapi.driver.model.po.ReqArchivalInfoSearchPO; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoDetailVO; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoSearchListVO; +import com.ningdatech.carapi.open.model.OpenApiTestReq; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import com.ningdatech.openapi.signature.annatation.OpenApiSignature; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/31 下午3:09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/v1/driver/archives") +@Api(tags = "外部调用驾驶员详情接口") +@RequiredArgsConstructor +public class OpenApiDriverArchivesController { + + private final DriverArchivesManage driverArchivesManage; + + @PostMapping("/archival-info/search") + @ApiOperation("驾驶员档案管理查询") + public PageVo archivalInfoSearch(@Valid @RequestBody ReqArchivalInfoSearchPO po) { + return driverArchivesManage.archivalInfoSearchOpen(po); + } + + @PostMapping("/archival-info/detail/{driverId}") + @ApiOperation("获取驾驶员档案详情") + public ResArchivalInfoDetailVO getArchivalInfoReviewDetail(@PathVariable("driverId") Long driverId) { + return driverArchivesManage.getDriverArchivalInfo(driverId); + } + + /** + * 查询驾驶员违章记录档案 + * + * @param driverId,violationType + * @return + */ + @ApiOperation(value = "查询驾驶员违章记录档案", notes = "查询驾驶员违章记录档案") + @GetMapping("/violation") + public List getViolation(@Valid @RequestParam Long driverId, @Valid @RequestParam Integer violationType) { + return driverArchivesManage.getViolation(driverId,violationType); + } + + /** + * 查询驾驶员事故记录档案 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询驾驶员事故记录档案", notes = "查询驾驶员事故记录档案") + @GetMapping("/accident-driver/{driverId}") + public List getAccidentVehicle(@Valid @PathVariable Long driverId) { + return driverArchivesManage.getAccidentVehicleOpen(driverId); + } + + /** + * 查询驾驶员死亡事故记录档案 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询驾驶员死亡事故记录档案", notes = "查询驾驶员死亡事故记录档案") + @GetMapping("/accident-dead/{driverId}") + public List getAccidentDead(@Valid @PathVariable Long driverId) { + return driverArchivesManage.getAccidentDeadOpen(driverId); + } + + /** + * 查询驾驶员事故分析记录档案 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询驾驶员事故分析记录档案", notes = "查询驾驶员事故分析记录档案") + @GetMapping("/accident-analysis/{driverId}") + public List getAccidentAnalysis(@Valid @PathVariable Long driverId) { + return driverArchivesManage.getAccidentAnalysisOpen(driverId); + } + + @PostMapping("/archival-info/search-batch") + @ApiOperation("驾驶员档案管理批量查询") + public List archivalInfoSearchBatch(@Valid @RequestBody ReqDataPO po) { + return driverArchivesManage.archivalInfoSearchBatchOpen(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiEquipmentController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiEquipmentController.java new file mode 100644 index 0000000..1d21310 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiEquipmentController.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.carapi.car.equipment.manage.VehicleEquipmentManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/archives/equipment") +@Api(value = "archives", tags = "车辆管理-档案管理") +@RequiredArgsConstructor +public class OpenApiEquipmentController { + private final VehicleEquipmentManage equipmentManage; + + @ApiOperation(value = "测试加一个车辆的设备", notes = "测试加一个车辆的设备") + @GetMapping("/test-add-equipment") + public Boolean testAddEquipment(@RequestParam String car_plate) { + return equipmentManage.initEquipmentFromSip(car_plate); + } + + @ApiOperation(value = "批量添加所有车辆", notes = "批量添加所有车辆") + @GetMapping("/test-add-equipment-all") + public Boolean testAddEquipmentAll() { + return equipmentManage.initEquipmentFromSipAll(); + } + + @GetMapping("/get-equip-no") + public void getEquipNo(){ + equipmentManage.getEquipNo(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiOssController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiOssController.java new file mode 100644 index 0000000..255a9de --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiOssController.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.open.controller; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.common.util.OssUtils; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/oss/") +@RequiredArgsConstructor +public class OpenApiOssController { + + @ApiOperation(value = "查询OSS存储文件大小", notes = "查询OSS存储文件大小") + @GetMapping("/get-oss") + public Long getOss() { + return OssUtils.getOss(null); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRedisController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRedisController.java new file mode 100644 index 0000000..4b349c4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRedisController.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.cache.repository.CachePlusOps; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.Set; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/redis/") +@Api(value = "archives", tags = "对外联调接口") +@RequiredArgsConstructor +public class OpenApiRedisController { + + private final CachePlusOps cachePlusOps; + + @ApiOperation(value = "redis remove", notes = "redis") + @GetMapping("/remove") + public Boolean remove() { + // 模糊匹配所有以keyword:开头的所有key值 + Set keys = cachePlusOps.keys("cm:"+"*"); + + log.info("cm下的key数量:{}",keys.size()); + + for(String key : keys){ + cachePlusOps.del(key); + } + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + Set keysAfter = cachePlusOps.keys("cm:"+"*"); + + log.info("删除后cm下的key数量:{}",keysAfter.size()); + + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRegionController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRegionController.java new file mode 100644 index 0000000..8428419 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiRegionController.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.open.controller; + +import java.util.List; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.sys.entity.vo.RegionTreeVO; +import com.ningdatech.carapi.sys.manage.RegionManage; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/region/") +@Api(value = "archives", tags = "对外联调接口") +@RequiredArgsConstructor +public class OpenApiRegionController { + + private final RegionManage regionManage; + + @PostMapping("/tree") + @ApiOperation("获取区域编码的树状结构") + public List getRegionTree() { + return regionManage.getRegionInfo(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiSecurityAdvisoryController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiSecurityAdvisoryController.java new file mode 100644 index 0000000..9a12c04 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiSecurityAdvisoryController.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.open.controller; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.open.manage.OpenSecurityAdvisoryManage; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/07/04 21:47 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/security/advisory") +@Api(value = "archives", tags = "对外联调接口") +@RequiredArgsConstructor +public class OpenApiSecurityAdvisoryController { + + private final OpenSecurityAdvisoryManage openSecurityAdvisoryManage; + + @ApiOperation("批量上传安全通报") + @GetMapping("/batchUpload") + public String batchUpload(){ + return openSecurityAdvisoryManage.batchUpload(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiTrainingOrganizationController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiTrainingOrganizationController.java new file mode 100644 index 0000000..bdc0eb2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiTrainingOrganizationController.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.manage.TrainingOrganizationManage; +import com.ningdatech.carapi.driver.model.po.ReqDriverTrainingListPO; +import com.ningdatech.carapi.driver.model.vo.ResDriverTrainingListVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * @author liuxinxin + * @date 2022/11/11 上午11:19 + */ + +@RequestMapping("/open/api/v1/driver/training-organization") +@RestController +@Api(tags = "驾驶员管理-培训管理-培训组织") +@Validated +@RequiredArgsConstructor +public class OpenApiTrainingOrganizationController { + + private final TrainingOrganizationManage trainingOrganizationManage; + + @PostMapping("/driver-training/list") + @ApiOperation("驾驶员培训记录列表") + public PageVo driverTrainingList(@Valid @RequestBody ReqDriverTrainingListPO request) { + return trainingOrganizationManage.driverTrainingList(request); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiUserLoginVerificationCodeController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiUserLoginVerificationCodeController.java new file mode 100644 index 0000000..92b10e5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiUserLoginVerificationCodeController.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.open.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.carapi.open.manage.UserLoginManage; +import com.ningdatech.carapi.open.model.dto.UserLoginDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 用户登录获取验证码 + * + * @author CMM + * @since 2023/01/06 16:38 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/user/login") +@Api(value = "OpenApiUserLoginVerificationCodeController", tags = "验证码登录") +@RequiredArgsConstructor +public class OpenApiUserLoginVerificationCodeController { + + private final UserLoginManage userLoginManage; + + @PostMapping( "/get/verificationCode") + @ApiOperation(value = "触发发短信接口,获取短信验证码") + public String getVerificationCode(@RequestBody @Valid UserLoginDTO param){ + return userLoginManage.getVerificationCode(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleArchivesController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleArchivesController.java new file mode 100644 index 0000000..7f857d9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleArchivesController.java @@ -0,0 +1,126 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.archives.aop.AuditVehicle; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesPageQuery; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesQueryDTO; +import com.ningdatech.carapi.archives.manage.ArchivesManage; +import com.ningdatech.carapi.car.vehicle.manage.VehicleManage; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleBaseVO; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.qrcode.model.vo.GetOnVehicleVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/archives/vehicle") +@Api(value = "archives", tags = "车辆管理-档案管理") +@RequiredArgsConstructor +public class OpenApiVehicleArchivesController { + + private final VehicleManage vehicleManage; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final ArchivesManage archivesManage; + + @ApiOperation(value = "车辆档案列表查询", notes = "车辆档案列表查询") + @GetMapping("/archivesList") + public PageVo queryArchivesList(@Valid @ModelAttribute VehicleArchivesPageQuery vehicleArchivesPageQuery) { + return vehicleManage.queryArchivesListOpen(vehicleArchivesPageQuery); + } + + /** + * 查询车辆基本信息 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询车辆基本信息", notes = "查询车辆基本信息") + @GetMapping("/baseInfo") + public VehicleArchivesQueryDTO getDetails(@Valid @RequestParam Long id) { + return vehicleManage.getDetails(id); + } + + /** + * 查询车辆违章记录档案 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆违章记录档案", notes = "查询车辆违章记录档案") + @GetMapping("/violation") + @AuditVehicle + public List getViolation(@Valid @RequestParam String carPlate, @Valid @RequestParam Integer violationType) { + return archivesManage.getViolation(carPlate,violationType); + } + + /** + * 查询车辆事故记录档案 + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆事故记录档案", notes = "查询车辆事故记录档案") + @GetMapping("/accident-vehicle") + @AuditVehicle + public List getAccidentVehicle(@Valid @RequestParam String carPlate) { + return archivesManage.getAccidentVehicleOpen(carPlate); + } + + /** + * 查询车辆死亡事故记录档案 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆死亡事故记录档案", notes = "查询车辆死亡事故记录档案") + @GetMapping("/accident-dead") + @AuditVehicle + public List getAccidentDead(@Valid @RequestParam String carPlate) { + return archivesManage.getAccidentDeadOpen(carPlate); + } + + /** + * 查询车辆事故分析记录档案 + * + * @param carPlate,violationType + * @return + */ + @ApiOperation(value = "查询车辆事故分析记录档案", notes = "查询车辆事故分析记录档案") + @GetMapping("/accident-analysis") + @AuditVehicle + public List getAccidentAnalysis(@Valid @RequestParam String carPlate) { + return archivesManage.getAccidentAnalysisOpen(carPlate); + } + + /** + * 查询车辆上车记录 + * + * @param driverId + * @return + */ + @ApiOperation(value = "查询车辆上车记录-驾驶员ID", notes = "查询车辆上车记录") + @GetMapping("/get-driver-on-car-list") + public List getOnCarDriver(@Valid @RequestParam String driverId) { + return archivesManage.getOnCarDriver(driverId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleController.java new file mode 100644 index 0000000..a82a9cb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleController.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.carapi.car.position.model.po.ReqDataPO; +import com.ningdatech.carapi.car.vehicle.manage.VehicleManage; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleBaseVO; +import com.ningdatech.carapi.car.vehicle.model.vo.VehicleCarPlateVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/vehicle/") +@Api(value = "archives", tags = "对外联调接口") +@RequiredArgsConstructor +public class OpenApiVehicleController { + + private final VehicleManage vehicleManage; + + @ApiOperation(value = "用公司ID去查车牌号", notes = "用公司ID去查车牌号") + @GetMapping("/list-by-companyIds") + public List listByCompanyIds(@Valid @RequestParam("companyIds") List companyIds) { + return vehicleManage.listByCompanyIds(companyIds); + } + + @ApiOperation(value = "用批量车牌号去查车辆信息", notes = "用批量车牌号去查车辆信息") + @PostMapping("/list-by-carplate") + public List listByCarplate(@Valid @RequestBody ReqDataPO po) { + return vehicleManage.listByCarplate(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleEquipmentController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleEquipmentController.java new file mode 100644 index 0000000..e98f037 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/controller/OpenApiVehicleEquipmentController.java @@ -0,0 +1,54 @@ +package com.ningdatech.carapi.open.controller; + +import com.ningdatech.carapi.car.equipment.manage.VehicleEquipmentManage; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentQueryDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/open/api/archives/equipment") +@Api(value = "archives", tags = "车辆管理-档案管理") +@RequiredArgsConstructor +public class OpenApiVehicleEquipmentController { + private final VehicleEquipmentManage equipmentManage; + private final INdVehicleEquipmentInfoService vehicleEquipmentInfoService; + + /** + * 查询车辆设备信息 + * @param id 设备ID + * @return 查询结果 + */ + @ApiOperation(value = "查询车辆设备信息-以设备ID查询", notes = "查询车辆设备信息-以设备ID查询") + @GetMapping("/detailsbyId/{id}") + public VehicleEquipmentQueryDTO getEquipmentById(@PathVariable("id") Long id) { + return equipmentManage.getEquipmentById(id); + } + + /** + * 查询车辆设备信息 + * @param vehicleId 车辆ID + * @return 查询结果 + */ + @ApiOperation(value = "查询车辆设备信息-以车辆ID查询", notes = "查询车辆设备信息-以车辆ID查询") + @GetMapping("/detailsbyVehicleId/{vehicleId}") + public List getEquipment(@PathVariable("vehicleId") Long vehicleId) { + return equipmentManage.getEquipment(vehicleId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/contants/SmsContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/contants/SmsContant.java new file mode 100644 index 0000000..e52515a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/contants/SmsContant.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.open.irs.contants; + +/** + * @author PoffyZhang + * @Classname smsContant + * @Description + * @Date 2022/12/14 18:46 + */ +public interface SmsContant { + + class Url { + + public static final String SMS_SEND_URL = "https://interface.zjzwfw.gov.cn/gateway/component/routing/agent.htm"; + + } + + class Param { + + public static final String TRSACTION_ID = ""; + + public static final String streaming_NO = ""; + + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/SmsService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/SmsService.java new file mode 100644 index 0000000..da152cc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/SmsService.java @@ -0,0 +1,13 @@ +package com.ningdatech.carapi.open.irs.service; + +/** + * @author PoffyZhang + * @Classname smsService + * @Description + * @Date 2022/12/14 18:55 + */ +public interface SmsService { + + public String send(String mobile,String content); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/impl/SmsServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/impl/SmsServiceImpl.java new file mode 100644 index 0000000..2b6b059 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/irs/service/impl/SmsServiceImpl.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.open.irs.service.impl; + +import com.ningdatech.carapi.open.irs.service.SmsService; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; + +/** + * @author PoffyZhang + * @Classname smsServiceImpl + * @Description + * @Date 2022/12/14 18:56 + */ +public class SmsServiceImpl implements SmsService { + + @Resource + private RestTemplate restTemplate; + + @Override + public String send(String mobile, String content) { +// restTemplate.postForObject(SmsContant.Url.SMS_SEND_URL,); + + return null; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/AlarmDataManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/AlarmDataManage.java new file mode 100644 index 0000000..9020dd8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/AlarmDataManage.java @@ -0,0 +1,122 @@ +package com.ningdatech.carapi.open.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.cache.redis.RedisOps; +import com.ningdatech.carapi.open.aop.TaskLock; +import com.ningdatech.carapi.open.contants.AlarmContant; +import com.ningdatech.carapi.open.model.dto.AlarmDataPictureDTO; +import com.ningdatech.carapi.open.model.dto.AlarmDataVideoDTO; +import com.ningdatech.carapi.safe.entity.AlarmDataPicture; +import com.ningdatech.carapi.safe.entity.AlarmDataVideo; +import com.ningdatech.carapi.safe.service.IAlarmDataPictureService; +import com.ningdatech.carapi.safe.service.IAlarmDataVideoService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @Classname AlarmDataManage + * @Description + * @Date 2022/10/28 11:05 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class AlarmDataManage { + private final IAlarmDataPictureService alarmDataPictureService; + private final IAlarmDataVideoService alarmDataVideoService; + + private static final Long MAX_CACHE = 1000L; + + private final RedisOps redisOps; + + public Boolean savePicture(AlarmDataPictureDTO alarmDataPicture) { + if(Objects.isNull(alarmDataPicture)){ + throw new BizException(ExceptionCode.PARAM_EX.getCode(),"推送数据为空"); + } + + AlarmDataPicture entity = BeanUtil.copyProperties(alarmDataPicture, AlarmDataPicture.class); + + //当前如果大于1000 则先去批量插入 + if(MAX_CACHE <= redisOps.lLen(AlarmContant.ALARM_DATA_PRICTURE_KEY)){ + AlarmDataManage clazz = (AlarmDataManage) AopContext.currentProxy(); + clazz.savePicturesOver(); + } + + redisOps.rPush(AlarmContant.ALARM_DATA_PRICTURE_KEY,entity); + + return Boolean.TRUE; + } + + public Boolean saveVideo(AlarmDataVideoDTO alarmDataVideo) { + if(Objects.isNull(alarmDataVideo)){ + throw new BizException(ExceptionCode.PARAM_EX.getCode(),"推送数据为空"); + } + + AlarmDataVideo entity= BeanUtil.copyProperties(alarmDataVideo, AlarmDataVideo.class); + + //当前如果大于1000 则先去批量插入 + if(MAX_CACHE <= redisOps.lLen(AlarmContant.ALARM_DATA_VIDEO_KEY)){ + AlarmDataManage clazz = (AlarmDataManage) AopContext.currentProxy(); + clazz.saveVideoOver(); + } + + redisOps.rPush(AlarmContant.ALARM_DATA_VIDEO_KEY,entity); + + return Boolean.TRUE; + } + + @TaskLock(name = "批量插入图片锁", key = "alarm-data:picture_lock",expired = 5) + public void savePicturesOver() { + Long len = redisOps.lLen(AlarmContant.ALARM_DATA_PRICTURE_KEY); + List objects = redisOps.lRange(AlarmContant.ALARM_DATA_PRICTURE_KEY, 0, len); + List addList = Objects.nonNull(objects) ? objects.stream().filter(Objects::nonNull) + .map(AlarmDataPicture.class::cast) + .collect(Collectors.toList()) : Collections.emptyList(); + + if (CollUtil.isEmpty(addList)) { + log.info("暂无 告警数据 需要插入!"); + return; + } + + if(alarmDataPictureService.saveBatchForSql(addList)){ + //清理掉这部分缓存 不直接删除 怕有并发问题 + redisOps.lTrim( AlarmContant.ALARM_DATA_PRICTURE_KEY,len,-1); + } + } + + @TaskLock(name = "批量插入短视频锁", key = "alarm-data:video_lock",expired = 5) + public void saveVideoOver() { + //当缓存不为空 + if(0 >= redisOps.lLen(AlarmContant.ALARM_DATA_VIDEO_KEY)){ + return; + } + + Long len = redisOps.lLen(AlarmContant.ALARM_DATA_VIDEO_KEY); + List objects = redisOps.lRange(AlarmContant.ALARM_DATA_VIDEO_KEY, 0, len); + List addList = Objects.nonNull(objects) ? objects.stream().filter(Objects::nonNull) + .map(AlarmDataVideo.class::cast) + .collect(Collectors.toList()) : Collections.emptyList(); + + if (CollUtil.isEmpty(addList)) { + log.info("暂无 告警数据 需要插入!"); + return; + } + + if(alarmDataVideoService.saveBatchForSql(addList)){ + //清理掉这部分缓存 不直接删除 怕有并发问题 + redisOps.lTrim( AlarmContant.ALARM_DATA_PRICTURE_KEY,len,-1); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenCarPositionManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenCarPositionManage.java new file mode 100644 index 0000000..833ae41 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenCarPositionManage.java @@ -0,0 +1,343 @@ +package com.ningdatech.carapi.open.manage; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.car.position.model.po.ReqRealTimeMonitorPO; +import com.ningdatech.carapi.car.vehicle.model.po.VehicleCompanyPO; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Maps; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.position.contants.PositionContant; +import com.ningdatech.carapi.car.position.entity.VehiclePositionInfo; +import com.ningdatech.carapi.car.position.model.po.ReqTrajectoryDataPO; +import com.ningdatech.carapi.car.position.model.vo.ResRealTimeMonitorVehicleGisListVO; +import com.ningdatech.carapi.car.position.model.vo.ResTrajectoryDataVO; +import com.ningdatech.carapi.car.position.service.IVehiclePositionInfoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.common.constant.VehicleLimitSpeedEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.SignUtil; +import com.ningdatech.carapi.open.model.po.ReqRealTimeCapPositionPO; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 车辆位置信息 + * + * @author CMM + * @since 2023/11/17 09:35 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class OpenCarPositionManage { + + private final CompaniesCacheHelper companiesCacheHelper; + private final VehiclesCacheHelper vehiclesCacheHelper; + private final IVehiclePositionInfoService iVehiclePositionInfoService; + private final RedisTemplate redisTemplate; + private final RestTemplate restTemplate; + @Value("${car.interfaceKey}") + private String carPositionKey; + @Value("${gps.host}") + private String HOST; + + public List trajectoryDatalist(ReqTrajectoryDataPO po) { + + // 校验签名 + Map paramMap = new HashMap<>(16); + paramMap.put("carPlate", po.getCarPlate()); + // 根据传入的秘钥生成签名 + String appKey = po.getKey(); + String sign = SignUtil.generateSign(paramMap, appKey); + String interfaceKey = SignUtil.generateSign(paramMap, carPositionKey); + if (!sign.equals(interfaceKey)){ + log.error("无权访问轨迹回放接口!"); + throw new BizException("签名错误!"); + } + String carPlate = po.getCarPlate(); + LocalDateTime startTime = po.getStartTime(); + LocalDateTime endTime = po.getEndTime(); + if (Objects.isNull(startTime)) { + startTime = LocalDateTime.now().minusHours(2); + } + // 默认时间区间为2小时前到现在 + if (Objects.isNull(endTime)) { + endTime = LocalDateTime.now(); + } + + // 获取车辆基本信息 + NdVehicleBaseInfo car = vehiclesCacheHelper.getByCarPlate(carPlate); + VUtils.isTrue(Objects.isNull(car)).throwMessage("该车辆不在系统中!"); + + //判断日期有没有跨天 + checkDateExtendIntoNextDay(startTime, endTime); + + //动态表名 + List vehiclePositionInfoList = iVehiclePositionInfoService + .dynamicGpsTableHistorySearch(carPlate, startTime, endTime, NdDateUtils.format(startTime, "yyyy_MM_dd")); + + List resTrajectoryDataVOList = vehiclePositionInfoList.stream().map( + r -> { + ResTrajectoryDataVO vo = BeanUtil.copyProperties(r, ResTrajectoryDataVO.class); + vo.setIsOverSpeed(checkIsOverSpeed(r,car)); + return vo; + }).collect(Collectors.toList()); + //连续6次超速 才算超速 + checkContinuousOverspeed(resTrajectoryDataVOList); + return resTrajectoryDataVOList; + } + + public PageVo realTimeMonitorAllGisList(ReqRealTimeCapPositionPO po) { + // 根据传入的秘钥生成签名 + String appKey = po.getKey(); + String sign = appKey; + Integer pageNumber = po.getPageNumber(); + Integer pageSize = po.getPageSize(); + + // 校验签名 + String interfaceKey = carPositionKey; + if (!sign.equals(interfaceKey)){ + log.error("无权访问车辆实时位置接口!"); + throw new BizException("签名错误!"); + } + int total = vehiclesCacheHelper.all().size(); + List carPlates = vehiclesCacheHelper.all().stream() + .skip((pageNumber - 1) * pageSize) //跳过前面的元素 + .limit(pageSize) + .map(vehicles -> BeanUtil.copyProperties(vehicles,VehicleCompanyPO.class)) + .collect(Collectors.toList()); + log.info("request real carPlates 【{}】:", JSON.toJSONString(carPlates)); + if (CollUtil.isEmpty(carPlates)) { + return PageVo.empty(); + } + Map map = Maps.newConcurrentMap(); + map.put(PositionContant.FIELD_CAR_PLATE, carPlates.stream().map(VehicleCompanyPO::getCarPlate).collect(Collectors.joining(","))); + map.put(PositionContant.HOST_FEILD, HOST); + JSONObject response = restTemplate.getForObject(PositionContant.REAL_GPS_URL, JSONObject.class, map); + log.info("request real gps 【{}】:", JSON.toJSONString(response)); + if (Objects.isNull(response)) { + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), "实时数据请求失败 网络异常"); + } + Integer statusCode = response.getInteger("status_code"); + if (0 != statusCode) { + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), response.getString("message")); + } + JSONArray resultJsonArray = response.getJSONArray("result"); + if (Objects.isNull(resultJsonArray) || resultJsonArray.size() == 0) { + return PageVo.empty(); + } + Map carMap = carPlates.stream() + .filter(w -> Objects.nonNull(w) && Objects.nonNull(w.getCarPlate())) + .filter(CodeUtil.distinctByKey(VehicleCompanyPO::getCarPlate)).collect(Collectors.toMap(VehicleCompanyPO::getCarPlate, v -> v)); + List res = resultJsonArray.stream().map(o -> { + JSONObject j = JSON.parseObject(JSON.toJSONString(o)); + String carPlate = j.getString(PositionContant.FIELD_CAR_PLATE); + VehicleCompanyPO vehicleCompany = carMap.get(carPlate); + ResRealTimeMonitorVehicleGisListVO vo = new ResRealTimeMonitorVehicleGisListVO(); + vo.setCarLongitude(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.LONGITUDE,BigDecimal.valueOf(0L))))); + vo.setCarLatitude(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.LATITUDE,BigDecimal.valueOf(0L))))); + vo.setCarAltitude(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.ALTITUDE,BigDecimal.valueOf(0L))))); + vo.setCarDirection(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.DIRECTION,BigDecimal.valueOf(0L))))); + vo.setCarPlate(carPlate); + vo.setPlateColor(j.getString(PositionContant.PLATE_COLOR)); + vo.setCompanyId(vehicleCompany.getCompanyId()); + vo.setCompanyName(vehicleCompany.getCompanyName()); + vo.setCarVelocity(new BigDecimal(String.valueOf(j.getOrDefault(PositionContant.CAR_VELOCITY,BigDecimal.valueOf(0L))))); + vo.setUpdateTime((j.getString(PositionContant.UPDATE_TIME))); + vo.setSelfNo(vehicleCompany.getSelfNo()); + vo.setStatus(j.getInteger(PositionContant.ONLINE_STATUS)); + vo.setMoving(vehicleCompany.getMoving()); + vo.setVehicleType(vehicleCompany.getVehicleType()); + vo.setVehicleTypeName(vehicleCompany.getVechileTypeName()); + vo.setLimitSpeed(VehicleLimitSpeedEnum.getLimitSpeedByCode(vehicleCompany.getVehicleType())); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(res,total); + } + + public List realTimeMonitorVehicleGisData(ReqRealTimeCapPositionPO po) { + + Map paramMap = new HashMap<>(16); + paramMap.put("carPlate", po.getCarPlate()); + // 根据传入的秘钥生成签名 + String appKey = po.getKey(); + String sign = SignUtil.generateSign(paramMap, appKey); + // 校验签名 + String interfaceKey = SignUtil.generateSign(paramMap, carPositionKey); + if (!sign.equals(interfaceKey)){ + log.error("无权访问车辆实时位置接口!"); + throw new BizException("签名错误!"); + } + + String carNo = po.getCarPlate(); + // 获取车辆基本信息 + NdVehicleBaseInfo car = vehiclesCacheHelper.getByCarPlate(carNo); + VUtils.isTrue(Objects.isNull(car)).throwMessage("该车辆不在系统中!"); + + Map map = Maps.newConcurrentMap(); + map.put(PositionContant.FIELD_CAR_PLATE, carNo); + map.put(PositionContant.HOST_FEILD, HOST); + JSONObject response = restTemplate.getForObject(PositionContant.REAL_GPS_URL, JSONObject.class, map); + if (Objects.isNull(response)) { + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), "实时数据请求失败 网络异常"); + } + Integer statusCode = response.getInteger("status_code"); + if (0 != statusCode) { + throw new BizException(ExceptionCode.BAD_REQUEST.getCode(), response.getString("message")); + } + JSONArray resultJsonArray = response.getJSONArray("result"); + if (Objects.isNull(resultJsonArray) || resultJsonArray.size() == 0) { + return Collections.emptyList(); + } + return resultJsonArray.stream().map(o -> { + LinkedHashMap j = (LinkedHashMap) o; + String carPlate = String.valueOf(j.get(PositionContant.FIELD_CAR_PLATE)); + ResRealTimeMonitorVehicleGisListVO vo = new ResRealTimeMonitorVehicleGisListVO(); + vo.setCarLongitude(BigDecimal.valueOf(Double.parseDouble(String.valueOf(j.getOrDefault(PositionContant.LONGITUDE, BigDecimal.valueOf(0L)))))); + vo.setCarLatitude(BigDecimal.valueOf(Double.parseDouble(String.valueOf(j.getOrDefault(PositionContant.LATITUDE, BigDecimal.valueOf(0L)))))); + vo.setCarAltitude(BigDecimal.valueOf(Double.parseDouble(String.valueOf(j.getOrDefault(PositionContant.ALTITUDE, BigDecimal.valueOf(0L)))))); + vo.setCarDirection(BigDecimal.valueOf(Double.parseDouble(String.valueOf(j.getOrDefault(PositionContant.DIRECTION, BigDecimal.valueOf(0L)))))); + vo.setCarPlate(carPlate); + vo.setPlateColor(String.valueOf(j.get(PositionContant.PLATE_COLOR))); + vo.setCompanyId(car.getCompanyId()); + vo.setCarVelocity(BigDecimal.valueOf(Double.parseDouble(String.valueOf(j.getOrDefault(PositionContant.CAR_VELOCITY, BigDecimal.valueOf(0L)))))); + vo.setUpdateTime(String.valueOf(j.get(PositionContant.UPDATE_TIME))); + vo.setSelfNo(car.getSelfNo()); + vo.setStatus(Integer.valueOf(String.valueOf(j.getOrDefault(PositionContant.ONLINE_STATUS, car.getStatus())))); + vo.setMoving(car.getMoving()); + vo.setVehicleType(car.getVehicleType()); + if (Objects.nonNull(car.getVehicleType())) { + String vehicleTypeName = VehicleTypeEnum.getDescByCode(car.getVehicleType()); + vo.setVehicleTypeName(vehicleTypeName); + } + vo.setLimitSpeed(VehicleLimitSpeedEnum.getLimitSpeedByCode(car.getVehicleType())); + if (Objects.nonNull(car.getCompanyId())) { + CompanyDTO vehicleCompany = companiesCacheHelper.getById(car.getCompanyId()); + vo.setCompanyName(vehicleCompany.getName()); + } + return vo; + }).collect(Collectors.toList()); + } + + /** + * 判断日期有没有跨月 + */ + private void checkDateExtendIntoNextDay(LocalDateTime startTime, LocalDateTime endTime) { + if (!NdDateUtils.format(startTime, DatePattern.NORM_DATE_PATTERN) + .equals(NdDateUtils.format(endTime, DatePattern.NORM_DATE_PATTERN))) { + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "由于GPS数据量大 不支持跨日查询!"); + } + } + + private Boolean checkIsOverSpeed(VehiclePositionInfo positionInfo, NdVehicleBaseInfo car) { + //混凝土和移动泵车 是50 + Integer vehicleType = car.getVehicleType(); + VehicleTypeEnum enumByValue = VehicleTypeEnum.getEnumByValue(vehicleType); + assert enumByValue != null; + if(enumByValue.equals(VehicleTypeEnum.OTHER)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(80)) >= 0){ + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.KRHP)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(50)) >= 0) { + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.MIXER)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(50)) >= 0) { + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.BULK_CEMENT_TRUCK)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(80)) >= 0) { + return Boolean.TRUE; + } + }else if(enumByValue.equals(VehicleTypeEnum.READY_MIXED_MORTAR_TRUC)){ + if(Objects.nonNull(positionInfo.getDashboardSpeed()) && + positionInfo.getCarVelocity().compareTo(BigDecimal.valueOf(80)) >= 0) { + return Boolean.TRUE; + } + } + + return Boolean.FALSE; + } + + private void checkContinuousOverspeed(List resTrajectoryDataVOList) { + if(CollUtil.isNotEmpty(resTrajectoryDataVOList)){ + for(int i = 0;i < resTrajectoryDataVOList.size();i++){ + ResTrajectoryDataVO vo = resTrajectoryDataVOList.get(i); + String carPlate = vo.getCarPlate(); + String REDIS_CAR_FILED = "car-gps:"; + if(vo.getIsOverSpeed()){ + Object num = redisTemplate.opsForValue().get(carPlate); + //如果之前已经有连续6个了 那就相安无事 + if(Objects.isNull(num)){ + redisTemplate.opsForValue().set(REDIS_CAR_FILED + carPlate,1,500, TimeUnit.SECONDS); + }else{ + redisTemplate.opsForValue().increment(REDIS_CAR_FILED + carPlate); + } + }else{ + Object num = redisTemplate.opsForValue().get(REDIS_CAR_FILED + carPlate); + if(Objects.isNull(num)){ + redisTemplate.opsForValue().set(REDIS_CAR_FILED + carPlate,0,500,TimeUnit.SECONDS); + continue; + } + //如果之前已经有连续6个了 那就相安无事 + int overNum = Integer.parseInt(String.valueOf(num)); + if(overNum >= 6){ + redisTemplate.opsForValue().set(REDIS_CAR_FILED + carPlate,0,500,TimeUnit.SECONDS); + }else{ + //如果不是的话 要把之前的 置为不超速 + changeOverspeedFalse(resTrajectoryDataVOList,i,vo,overNum); + } + } + } + } + } + + private void changeOverspeedFalse(List resTrajectoryDataVOList,int index, ResTrajectoryDataVO vo, Integer overNum) { + int flagNum = overNum; + for(int i = index;i >= 0;i--){ + if(flagNum <= 0){ + break; + } + ResTrajectoryDataVO innerVo = resTrajectoryDataVOList.get(i); + if(innerVo.getCarPlate().equals(vo.getCarPlate())){ + innerVo.setIsOverSpeed(Boolean.FALSE); + flagNum--; + } + } + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenSecurityAdvisoryManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenSecurityAdvisoryManage.java new file mode 100644 index 0000000..d199bf8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/OpenSecurityAdvisoryManage.java @@ -0,0 +1,162 @@ +package com.ningdatech.carapi.open.manage; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.TemporalAdjusters; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.safe.entity.NdSecurityAdvisory; +import com.ningdatech.carapi.safe.service.INdSecurityAdvisoryService; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.IRegionService; +import com.ningdatech.file.entity.vo.result.FileResultVO; +import com.ningdatech.file.service.FileService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/01/06 16:40 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class OpenSecurityAdvisoryManage { + + private final INdSecurityAdvisoryService ndSecurityAdvisoryService; + private final RegionsCacheHelper regionsCacheHelper; + private final FileService fileService; + private final IRegionService regionService; + + public String batchUpload() { + List folderList = Lists.newArrayList(); + folderList.add("3301_杭州市"); + folderList.add("3302_宁波市"); + folderList.add("3303_温州市"); + folderList.add("3304_嘉兴市"); + folderList.add("3305_湖州市"); + folderList.add("3306_绍兴市"); + folderList.add("3307_金华市"); + folderList.add("3308_衢州市"); + folderList.add("3309_舟山市"); + folderList.add("3310_台州市"); + folderList.add("3311_丽水市"); + for (String folderName : folderList) { + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "advisory" + File.separator + folderName; + log.info(filePath); + File folder = new File(filePath); + if (folder.isDirectory()) { + readFiles(folder); + } else { + log.info("指定路径不是一个文件夹!"); + } + } + return "上传成功"; + } + + private void readFiles(File folder) { + File[] files = folder.listFiles(); + if (files != null) { + HashSet countySet = new HashSet<>(); + // 根据区县名称获取区域ID + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + for (File file : files) { + if (file.isDirectory()) { + // 递归调用,读取子文件夹中的文件 + readFiles(file); + } else { + // 输出文件名 + log.info(file.getName()); + // 上传文件到OSS + MultipartFile multipartFile; + try { + InputStream inputStream = new FileInputStream(file); + String fileName = file.getName(); + multipartFile = new MockMultipartFile("file", fileName, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + inputStream); + FileResultVO fileResultVo = fileService.upload(multipartFile, "default"); + // 保存到安全通报表中 + NdSecurityAdvisory ndSecurityAdvisory = new NdSecurityAdvisory(); + ndSecurityAdvisory.setCreateBy(2L); + ndSecurityAdvisory.setCreateOn(LocalDateTime.now()); + int startIndex = fileName.indexOf("月"); + String regionName = fileName.substring(startIndex + 1, startIndex + 4); + if ("景宁县".equals(regionName)){ + regionName = "景宁畲族自治县"; + } + Region region = regionMap.get(regionName); + Long regionId; + if (Objects.isNull(region)){ + String folderName = folder.getName(); + int start = folderName.indexOf(StrPool.UNDERSCORE); + String cityName = folderName.substring(start + 1, start + 4); + Region cityRegion = regionMap.get(cityName); + regionId = cityRegion.getId(); + + }else { + regionId = region.getId(); + } + ndSecurityAdvisory.setRegionId(regionId); + ndSecurityAdvisory.setRegionName(regionsCacheHelper.getDisplayName(regionId)); + // 获取当前日期 + LocalDate currentDate = LocalDate.now(); + // 获取当前日期所在月份的第一天 + LocalDate firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth()); + // 获取第一天的开始时间 + LocalTime startTime = LocalTime.of(0, 0,0); + // 将日期和时间合并为完整的日期时间对象 + LocalDateTime time = LocalDateTime.of(firstDayOfMonth, startTime); + //String dateString = "2023-06-01 00:00:00"; + //DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + //LocalDateTime time = LocalDateTime.parse(dateString, formatter); + ndSecurityAdvisory.setAdvisoryDate(time); + ndSecurityAdvisory.setFileId(fileResultVo.getId()); + ndSecurityAdvisory.setAdvisoryFileName(fileName); + ndSecurityAdvisory.setCompanyId(32104L); + ndSecurityAdvisoryService.save(ndSecurityAdvisory); + } catch (IOException e) { + throw new BizException("上传文件失败:" + e.getMessage()); + } + } + } + } + } + + public static void main(String[] args) { + // 获取当前日期 + LocalDate currentDate = LocalDate.now(); + // 获取当前日期所在月份的第一天 + LocalDate firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth()); + // 获取第一天的开始时间 + LocalTime startTime = LocalTime.of(0, 0,0); + // 将日期和时间合并为完整的日期时间对象 + LocalDateTime firstDayOfMonthWithStartTime = LocalDateTime.of(firstDayOfMonth, startTime); + + System.out.println(firstDayOfMonthWithStartTime); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/UserLoginManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/UserLoginManage.java new file mode 100644 index 0000000..26a994f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/manage/UserLoginManage.java @@ -0,0 +1,127 @@ +package com.ningdatech.carapi.open.manage; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.SignUtil; +import com.ningdatech.carapi.open.model.dto.UserLoginDTO; +import com.ningdatech.carapi.sys.contants.UserLoginConstant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.sms.send.GyytzMarketSmsHelper; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/01/06 16:40 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class UserLoginManage { + + private final INdUserInfoService ndUserInfoService; + private final INdUserAuthService ndUserAuthService; + private final UserRoleService userRoleService; + private final CachePlusOps cachePlusOps; + private final GyytzMarketSmsHelper gyytzMarketSmsHelper; + private final RestTemplate restTemplate; + private final CompanyService companyService; + @Value("${sms.interfaceKey}") + private String smsKey; + + @Value("${sms.transmitUrl}") + private String transmitUrl; + + + public String getVerificationCode(UserLoginDTO param) { + // 获取用户名入参信息 + String userName = param.getUsername(); + // 根据用户名获取用户账号信息 + NdUserAuth userAuth = ndUserAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getIdentifier, userName)); + VUtils.isTrue(Objects.isNull(userAuth)).throwMessage("该用户不存在!"); + // 根据用户ID获取用户信息 + NdUserInfo ndUserInfo = ndUserInfoService.getOne(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getId, userAuth.getUserId())); + VUtils.isTrue(Objects.isNull(ndUserInfo)).throwMessage("该用户不存在!"); + // 根据用户信息获取用户角色 + Long userId = ndUserInfo.getId(); + Long companyId = ndUserInfo.getCompanyId(); + UserRole userRole = userRoleService.getOne(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getUserId, userId)); + String mobile = null; + if (Objects.nonNull(userRole)){ + Long roleId = userRole.getRoleId(); + // 如果是企业用户,优先获取企业联系人电话 + if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)){ + // 获取企业联系人电话 + Company company = companyService.getById(companyId); + String contactPhone = company.getContactPhone(); + if (Objects.nonNull(contactPhone)) { + mobile = contactPhone; + }else { + // 如果没有联系人,则向企业关联的法人手机号发送短信 + mobile = ndUserInfo.getMobile(); + } + }else { + mobile = ndUserInfo.getMobile(); + } + } + VUtils.isTrue(StringUtils.isBlank(mobile)).throwMessage("该用户没有设置手机号!"); + + // 生成验证码,保存到用户信息表中 + String verificationCode = CodeUtil.codeFen(6); + ndUserInfo.setVerificationCode(verificationCode); + ndUserInfoService.updateById(ndUserInfo); + + // 将验证码保存到redis中,并设置过期时间 + CacheKey key = new CacheKey(UserLoginConstant.RedisKey.USER_LOGIN + userName); + key.setExpire(Duration.ofMinutes(10)); + cachePlusOps.set(key,verificationCode,false); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + Map requestBody = new HashMap<>(); + requestBody.put("mobile", mobile); + requestBody.put("verificationCode", verificationCode); + // 生成签名 + String sign = SignUtil.generateSign(requestBody, smsKey); + requestBody.put("sign",sign); + + HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); + try { + ResponseEntity responseEntity = restTemplate.postForEntity(transmitUrl, requestEntity, String.class); + return responseEntity.getBody(); + } catch (RestClientException e) { + throw new BizException("调用短信转发服务失败!"); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/OpenApiTestReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/OpenApiTestReq.java new file mode 100644 index 0000000..c4d83f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/OpenApiTestReq.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.open.model; + +import com.ningdatech.openapi.signature.model.AbstractOpenApiSignatureReq; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; + +/** + *

ø + * OpenApiTestReq + *

+ * + * @author WendyYang + * @since 18:32 2022/11/2 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class OpenApiTestReq extends AbstractOpenApiSignatureReq { + + private String name; + + @NotBlank(message = "name is required") + private String code; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataPictureDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataPictureDTO.java new file mode 100644 index 0000000..421ce37 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataPictureDTO.java @@ -0,0 +1,144 @@ +package com.ningdatech.carapi.open.model.dto; + +import com.ningdatech.openapi.signature.model.AbstractOpenApiSignatureReq; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @Classname AlarmDataPicture + * @Description + * @Date 2022/10/28 10:47 + * @Created by PoffyZhang + */ +@Data +@ApiModel(value = "AlarmDataPicture", description = "告警数据 图片保存") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class AlarmDataPictureDTO extends AbstractOpenApiSignatureReq{ + + private static final long serialVersionUID = 1L; + + /** + *设备上报图片ID + */ + @ApiModelProperty("设备上报图片ID") + @NotBlank(message = "设备上报图片ID不能为空") + private String originPicId; + + /** + *车辆编号 + */ + @ApiModelProperty("车辆编号") + private String vehicleIndexCode; + + /** + *车辆自编号 + */ + @ApiModelProperty("车辆自编号") + private String vehicleSelfNo; + + /** + *监控点编号 + */ + @ApiModelProperty("监控点编号") + private String cameraIndexCode; + + /** + *监控点名称 + */ + @ApiModelProperty("监控点名称") + private String cameraName; + + /** + *上传类型 + */ + @ApiModelProperty("上传类型 2:报警") + private Integer uploadType; + + /** + * 告警ID + */ + @ApiModelProperty("告警ID") + @NotBlank(message = "告警ID不能为空") + private String alarmId; + + /** + * 事件类型 + */ + @ApiModelProperty("事件类型") + private String alarmType; + + /** + * 事件类型名 + */ + @ApiModelProperty("事件类型名 如:接打电话") + private String alarmTypeName; + + /** + * 抓拍时间 + */ + @ApiModelProperty("抓拍时间") + @NotNull(message = "抓拍时间不能为空") + private String captureTime; + + /** + * 图片地址 + */ + @ApiModelProperty("图片地址") + @NotBlank(message = "图片地址不能为空") + private String url; + + /** + * 缩略图地址 + */ + @ApiModelProperty("缩略图地址") + private String thumbUrl; + + /** + * 本图片所关联的抓拍图片的唯一标识 + */ + @ApiModelProperty("本图片所关联的抓拍图片的唯一标识") + private String parentPicId; + + /** + * 人脸小图在关联的抓拍图片上的坐标 + */ + @ApiModelProperty("人脸小图在关联的抓拍图片上的坐标") + private String faceRect; + + /** + * 图片类型 + */ + @ApiModelProperty("图片类型 可选项,0x01标识可见光,0x02标识热成像,若没有,则默认为可见光") + private String picType; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String plateNo; + + /** + * 区域编码 + */ + @ApiModelProperty("区域编码") + private String regionIndexCode; + + /** + * 区域名称 + */ + @ApiModelProperty("区域名称") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataVideoDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataVideoDTO.java new file mode 100644 index 0000000..71ea452 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/AlarmDataVideoDTO.java @@ -0,0 +1,169 @@ +package com.ningdatech.carapi.open.model.dto; + +import com.ningdatech.openapi.signature.model.AbstractOpenApiSignatureReq; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @Classname AlarmDataVideo + * @Description + * @Date 2022/10/28 10:47 + * @Created by PoffyZhang + */ +@Data +@ApiModel(value = "AlarmDataVideo", description = "告警数据 短视频保存") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class AlarmDataVideoDTO extends AbstractOpenApiSignatureReq { + + private static final long serialVersionUID = 1L; + + /** + *设备上报短视频唯一标识 + */ + @ApiModelProperty("设备上报短视频唯一标识") + @NotBlank(message = "设备上报短视频唯一标识不能为空") + private String orginVideoId; + + /** + *车辆编号 + */ + @ApiModelProperty("车辆编号") + private String vehicleIndexCode; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String plateNo; + + /** + *车辆自编号 + */ + @ApiModelProperty("车辆自编号") + private String vehicleSelfNo; + + /** + * 区域编码 + */ + @ApiModelProperty("区域编码") + private String regionIndexCode; + + /** + * 区域名称 + */ + @ApiModelProperty("区域名称") + private String regionName; + + /** + *监控点编号 + */ + @ApiModelProperty("监控点编号") + private String cameraIndexCode; + + /** + *监控点名称 + */ + @ApiModelProperty("监控点名称") + private String cameraName; + + /** + *服务编号 + */ + @ApiModelProperty("服务编号") + @NotBlank(message = "服务编号不能为空") + private String serviceIndexCode; + + /** + *开始时间 + */ + @ApiModelProperty("开始时间") + @NotBlank(message = "开始时间不能为空") + private String beginTime; + + /** + *结束时间 + */ + @ApiModelProperty("结束时间") + @NotBlank(message = "结束时间不能为空") + private String endTime; + + /** + *流码开始时间 + */ + @ApiModelProperty("流码开始时间") + @NotBlank(message = "流码开始时间不能为空") + private String streamBeginTime; + + /** + *流码结束时间 + */ + @ApiModelProperty("流码结束时间") + @NotBlank(message = "流码结束时间不能为空") + private String streamEndTime; + + /** + *片段时长 + */ + @ApiModelProperty("片段时长 秒") + @NotNull(message = "片段时长不能为空") + private Integer videoLength; + + /** + * 告警ID + */ + @ApiModelProperty("告警ID") + @NotBlank(message = "告警ID不能为空") + private String alarmId; + + /** + * 告警时间 + */ + @ApiModelProperty("告警时间") + @NotBlank(message = "告警时间不能为空") + private String alarmTime; + + /** + * 事件类型 + */ + @ApiModelProperty("事件类型") + private String alarmType; + + /** + * 事件类型名 + */ + @ApiModelProperty("事件类型名 如:接打电话") + private String alarmTypeName; + + /** + * 片段编号 + */ + @ApiModelProperty("片段编号") + @NotBlank(message = "片段编号不能为空") + private String recordIndexCode; + + /** + * 短视频地址 + */ + @ApiModelProperty("短视频地址") + @NotBlank(message = "短视频地址不能为空") + private String url; + + /** + * 封面url + */ + @ApiModelProperty("封面url") + private String coverUrl; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/UserLoginDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/UserLoginDTO.java new file mode 100644 index 0000000..5995325 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/dto/UserLoginDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.open.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 用户登录实体类 + * + * @author CMM + * @since 2023/01/05 17:41 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserLoginDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户名") + private String username; + + @ApiModelProperty("密码") + private String password; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("手机号") + private String mobile; + + @ApiModelProperty("验证码") + private String verificationCode; + + @ApiModelProperty("签名") + private String sign; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/po/ReqRealTimeCapPositionPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/po/ReqRealTimeCapPositionPO.java new file mode 100644 index 0000000..ee455d5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/po/ReqRealTimeCapPositionPO.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.open.model.po; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * @author CMM + * @since 2023/11/17 10:47 + */ +@ApiModel(description = "车辆实时位置请求入参") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ReqRealTimeCapPositionPO extends PagePo { + @ApiModelProperty("车牌号") + String carPlate; + + @ApiModelProperty("校验公钥") + @NotBlank(message = "秘钥不能为空") + private String key; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/vo/CompanySecurityInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/vo/CompanySecurityInfoVO.java new file mode 100644 index 0000000..d330006 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/open/model/vo/CompanySecurityInfoVO.java @@ -0,0 +1,63 @@ +package com.ningdatech.carapi.open.model.vo; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 企业安全信息 + * + * @author CMM + * @since 2023/05/26 12:18 + */ +@Data +public class CompanySecurityInfoVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("公共信用评价分值") + private Integer commonCreditScore; + + @ApiModelProperty("基本管理信用分值") + private Integer basicCreditScore; + + @ApiModelProperty("安全生产管理信用分值") + private Integer safeProductCreditScore; + + @ApiModelProperty("行业监管信用分值") + private Integer industryRegulateCreditScore; + + @ApiModelProperty("行业荣誉加分") + private Integer industryHonorBonus; + + @ApiModelProperty("企业信用评价总分") + private Integer companyCreditEvaluateTotalScore; + + @ApiModelProperty("信用等级") + private String creditLevel; + + @ApiModelProperty("信用等级含义") + private String creditLevelName; + + @ApiModelProperty("企业风险等级") + private Integer dangerLevel; + + @ApiModelProperty("企业风险名称") + private String dangerLevelName; + + @ApiModelProperty("企业安全风险分值") + private Integer companySafeRiskScore; + + @ApiModelProperty("累计违章次数") + private Integer violationCnt; + + @ApiModelProperty("累计出险次数") + private Integer outDangerCnt; + + @ApiModelProperty("累计受伤人数") + private Integer injuryCnt; + + @ApiModelProperty("累计死亡人数") + private Integer deadCnt; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/controller/QrcodeController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/controller/QrcodeController.java new file mode 100644 index 0000000..f0b8a8c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/controller/QrcodeController.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.qrcode.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoSearchListVO; +import com.ningdatech.carapi.qrcode.manage.QrcodeManage; +import com.ningdatech.carapi.qrcode.model.dto.GetOnVehicleDTO; +import com.ningdatech.carapi.qrcode.model.dto.VehicleGetOnPageQuery; +import com.ningdatech.carapi.qrcode.model.vo.GetOnVehicleVO; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + * 二维码相关 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/qrcode") +@Api(value = "Qrcode", tags = "二维码") +@RequiredArgsConstructor +public class QrcodeController { + + private final QrcodeManage qrcodeManage; + + @ApiOperation(value = "获取当前登录驾驶员信息", notes = "获取当前登录驾驶员信息") + @GetMapping("/driver-logined") + @WebLog + public ResArchivalInfoSearchListVO queryLoginedDriver() { + return qrcodeManage.queryLoginedDriver(); + } + + @ApiOperation(value = "扫码上车", notes = "扫码上车") + @PostMapping("/get-on-vehicle") + @WebLog + public GetOnVehicleVO getOnVehicle(@Valid @RequestBody GetOnVehicleDTO getOnVehicleDTO) { + return qrcodeManage.getOnVehicle(getOnVehicleDTO, LoginUserUtil.getUserId()); + } + + @ApiOperation(value = "上车记录列表查询", notes = "上车记录列表查询") + @GetMapping("/get-on-list") + public PageVo getOnList(@Valid @ModelAttribute VehicleGetOnPageQuery vehicleArchivesPageQuery) { + return qrcodeManage.getOnList(vehicleArchivesPageQuery); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/entity/NdVehicleGetOn.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/entity/NdVehicleGetOn.java new file mode 100644 index 0000000..e31dc64 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/entity/NdVehicleGetOn.java @@ -0,0 +1,90 @@ +package com.ningdatech.carapi.qrcode.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-25 + */ +@Data +@TableName("nd_vehicle_get_on") +@ApiModel(value = "NdVehicleGetOn", description = "车辆档案-上车记录") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleGetOn extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("车辆ID") + @TableField(value = "vehicle_id") + private Long vehicleId; + + @ApiModelProperty("驾驶员ID") + @TableField(value = "driver_id") + private Long driverId; + + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + @ApiModelProperty("驾驶员名字") + @TableField(value = "driver_name") + private String driverName; + + @ApiModelProperty("车辆颜色") + @TableField(value = "plate_color") + private String plateColor; + + @ApiModelProperty("车辆类型") + @TableField(value = "vehicle_type") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + @TableField(value = "vehicle_type_name") + private String vehicleTypeName; + + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + @ApiModelProperty("运营商名") + @TableField(value = "operator_name") + private String operatorName; + + @ApiModelProperty("公司id") + @TableField(value = "company_id") + private Long companyId; + + @ApiModelProperty("公司名") + @TableField(value = "company_name") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/manage/QrcodeManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/manage/QrcodeManage.java new file mode 100644 index 0000000..5adb837 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/manage/QrcodeManage.java @@ -0,0 +1,144 @@ +package com.ningdatech.carapi.qrcode.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesQueryDTO; +import com.ningdatech.carapi.car.vehicle.manage.VehicleManage; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.helper.DriverInfoHelper; +import com.ningdatech.carapi.driver.manage.DriverArchivesManage; +import com.ningdatech.carapi.driver.model.po.ReqGetArchivalInfoReviewDetailPO; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoDetailVO; +import com.ningdatech.carapi.driver.model.vo.ResArchivalInfoSearchListVO; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn; +import com.ningdatech.carapi.qrcode.model.dto.GetOnVehicleDTO; +import com.ningdatech.carapi.qrcode.model.dto.VehicleGetOnPageQuery; +import com.ningdatech.carapi.qrcode.model.vo.GetOnVehicleVO; +import com.ningdatech.carapi.qrcode.service.VehicleGetOnService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; + +/** + * @Classname OrcodeManage + * @Description + * @Date 2022/10/18 14:39 + * @Created by PoffyZhang + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class QrcodeManage { + + private final IDriverInfoService driverInfoService; + private final VehicleGetOnService vehicleGetOnService; + private final VehicleManage vehicleManage; + private final DriverArchivesManage driverArchivesManage; + private final RegionsCacheHelper regionsCacheHelper; + private final DriverInfoHelper driverInfoHelper; + + /** + * 获取当前登录驾驶员信息 + * + * @return + */ + public ResArchivalInfoSearchListVO queryLoginedDriver() { + Long userId = LoginUserUtil.getUserId(); + if (Objects.isNull(userId)) { + throw new BizException(ExceptionCode.JWT_NOT_LOGIN.getCode(), "请确认当前驾驶员已登录"); + } + + LambdaQueryWrapper driverInfoLambdaQueryWrappery = Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getUserId, userId) + .orderByDesc(DriverInfo::getUpdateOn); + DriverInfo driveInfo = driverInfoService.getOne(driverInfoLambdaQueryWrappery); + if (Objects.isNull(driveInfo)) { + throw new BizException("驾驶员信息不存在!"); + } + ResArchivalInfoSearchListVO res = BeanUtil.copyProperties(driveInfo, ResArchivalInfoSearchListVO.class); + res.setDriverId(driveInfo.getId()); + return res; + } + + public PageVo getOnList(VehicleGetOnPageQuery vehicleArchivesPageQuery) { + Page page = vehicleArchivesPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class); + buildWrapper(wrapper, vehicleArchivesPageQuery); + vehicleGetOnService.page(page, wrapper); + List data = CollUtils.convert(page.getRecords(), e -> BeanUtil.copyProperties(e, GetOnVehicleVO.class)); + return PageVo.of(data, page.getTotal()); + } + + private void buildWrapper(LambdaQueryWrapper wrapper, VehicleGetOnPageQuery vehicleArchivesPageQuery) { + if (Objects.nonNull(vehicleArchivesPageQuery.getRegionId())) { + List regionIds = regionsCacheHelper.listChildRegionId(vehicleArchivesPageQuery.getRegionId()); + wrapper.in(CollUtil.isNotEmpty(regionIds), NdVehicleGetOn::getRegionId, regionIds); + } + wrapper.like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleGetOn::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCompanyName()), NdVehicleGetOn::getCompanyName, vehicleArchivesPageQuery.getCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleGetOn::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getDriverName()), NdVehicleGetOn::getDriverName, vehicleArchivesPageQuery.getDriverName()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getOperatorName()), NdVehicleGetOn::getOperatorName, vehicleArchivesPageQuery.getOperatorName()) + .ge(Objects.nonNull(vehicleArchivesPageQuery.getStartTime()), NdVehicleGetOn::getCreateOn, vehicleArchivesPageQuery.getStartTime()) + .le(Objects.nonNull(vehicleArchivesPageQuery.getEndTime()), NdVehicleGetOn::getCreateOn, vehicleArchivesPageQuery.getEndTime()) + .orderBy(Boolean.TRUE, Boolean.FALSE, NdVehicleGetOn::getCreateOn); + } + + /** + * 扫码上车 + * + * @param data + * @return + */ + public GetOnVehicleVO getOnVehicle(GetOnVehicleDTO data, Long userId) { + driverInfoHelper.driverCertificateValidCheck(userId); + + NdVehicleGetOn vehicleGetOn = BeanUtil.toBean(data, NdVehicleGetOn.class); + //进行业务处理 + //1.查询车辆信息 + VehicleArchivesQueryDTO vehicleDetails = vehicleManage.getDetails(data.getVehicleId()); + if (Objects.isNull(vehicleDetails)) { + throw new BizException(ExceptionCode.NOT_FOUND.getCode(), "找不到目标车辆 {}", data.getVehicleId()); + } + //2.查询驾驶员信息 + ReqGetArchivalInfoReviewDetailPO po = new ReqGetArchivalInfoReviewDetailPO(); + po.setDriverId(data.getDriverId()); + ResArchivalInfoDetailVO archivalInfoDetail = driverArchivesManage.getDriverDetail(po); + if (Objects.isNull(archivalInfoDetail)) { + throw new BizException(ExceptionCode.NOT_FOUND.getCode(), "找不到目标驾驶员 {}", data.getVehicleId()); + } + //3.拼接信息存入上车表 + vehicleGetOn.setCarPlate(vehicleDetails.getCarPlate()); + vehicleGetOn.setPlateColor(vehicleDetails.getPlateColor()); + vehicleGetOn.setCompanyId(vehicleDetails.getCompanyId()); + vehicleGetOn.setCompanyName(vehicleDetails.getCompanyName()); + vehicleGetOn.setDriverName(archivalInfoDetail.getDriverName()); + vehicleGetOn.setOperatorName(vehicleDetails.getOperatorName()); + vehicleGetOn.setRegionId(vehicleDetails.getRegionId()); + vehicleGetOn.setRegionName(vehicleDetails.getRegionName()); + if (Objects.nonNull(vehicleDetails.getVehicleType())) { + vehicleGetOn.setVehicleType(vehicleDetails.getVehicleType()); + vehicleGetOn.setVehicleTypeName(VehicleTypeEnum.getDescByCode(vehicleDetails.getVehicleType())); + } + //创建人 最后修改人 + vehicleGetOn.setCreateBy(userId); + vehicleGetOn.setUpdateBy(userId); + vehicleGetOnService.save(vehicleGetOn); + return BeanUtil.toBean(vehicleGetOn, GetOnVehicleVO.class); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.java new file mode 100644 index 0000000..e68c3d9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.qrcode.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-18 + */ +public interface VehicleGetOnMapper extends BaseMapper { + + List selectVehicleGetOnList(@Param("carPlateList") List carPlateList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.xml new file mode 100644 index 0000000..306c2c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/mapper/VehicleGetOnMapper.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/GetOnVehicleDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/GetOnVehicleDTO.java new file mode 100644 index 0000000..e2862cb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/GetOnVehicleDTO.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.qrcode.model.dto; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleGetOn", description = "二维码-上车 值对象") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class GetOnVehicleDTO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + @NotNull(message = "驾驶员ID必填") + private Long driverId; + + /** + * 车辆ID + */ + @ApiModelProperty("车辆ID") + @NotNull(message = "车辆ID必填") + private Long vehicleId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/VehicleGetOnPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/VehicleGetOnPageQuery.java new file mode 100644 index 0000000..d224c39 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/dto/VehicleGetOnPageQuery.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.qrcode.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 车辆档案 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleGetOnPageQuery", description = "上车信息") +public class VehicleGetOnPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 上车开始时间 + */ + @ApiModelProperty(value = "上车开始时间") + private LocalDateTime startTime; + + /** + * 上车结束时间 + */ + @ApiModelProperty(value = "上车结束时间") + private LocalDateTime endTime; + + /** + * 驾驶员名 + */ + @ApiModelProperty(value = "驾驶员名") + private String driverName; + + /** + * 车牌号 + */ + @ApiModelProperty(value = "车牌号") + private String carPlate; + + /** + * 所属企业名 + */ + @ApiModelProperty(value = "所属企业名") + private String companyName; + + /** + * 车辆类型 + */ + @ApiModelProperty(value = "车辆类型") + private Integer vehicleType; + + /** + * 所属区域id + */ + @ApiModelProperty(value = "所属区域id") + private Long regionId; + + + /** + * 运营商名 + */ + @ApiModelProperty(value = "运营商名") + private String operatorName; + + @ApiModelProperty("审核类型 1.待审核 2.已审核") + private Integer auditType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/vo/GetOnVehicleVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/vo/GetOnVehicleVO.java new file mode 100644 index 0000000..e3d2447 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/model/vo/GetOnVehicleVO.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.qrcode.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "GetOnVehicleVO", description = "二维码-上车 视图对象") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class GetOnVehicleVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("车辆ID") + private Long vehicleId; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("驾驶员名字") + private String driverName; + + @ApiModelProperty("车辆颜色") + private String plateColor; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名") + private String regionName; + + @ApiModelProperty("运营商名") + private String operatorName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名") + private String companyName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/VehicleGetOnService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/VehicleGetOnService.java new file mode 100644 index 0000000..7612db9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/VehicleGetOnService.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.qrcode.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn; + +import java.util.List; + +/** + * @Classname VehicleGetOnService + * @Description + * @Date 2022/10/18 15:11 + * @Created by PoffyZhang + */ +public interface VehicleGetOnService extends IService { + + List selectVehicleGetOnList(List carPlateList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/impl/VehicleGetOnServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/impl/VehicleGetOnServiceImpl.java new file mode 100644 index 0000000..506e2fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/qrcode/service/impl/VehicleGetOnServiceImpl.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.qrcode.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn; +import com.ningdatech.carapi.qrcode.mapper.VehicleGetOnMapper; +import com.ningdatech.carapi.qrcode.service.VehicleGetOnService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-18 + */ +@Service +@RequiredArgsConstructor +public class VehicleGetOnServiceImpl extends ServiceImpl implements VehicleGetOnService { + + private final VehicleGetOnMapper vehicleGetOnMapper; + @Override + public List selectVehicleGetOnList(List carPlateList) { + return vehicleGetOnMapper.selectVehicleGetOnList(carPlateList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditStatusEnum.java new file mode 100644 index 0000000..ffd0a63 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditStatusEnum.java @@ -0,0 +1,72 @@ +package com.ningdatech.carapi.report.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 直报系统数据审核状态 + * @return + * @author CMM + * @since 2023/02/07 13:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DataUploadAuditStatusEnum", description = "直报系统数据审核状态-枚举") +public enum DataUploadAuditStatusEnum { + + /** + * 审核中 + */ + UNDER_AUDIT(1,"审核中"), + + /** + * 审核通过 + */ + AUDIT_PASS(2, "审核通过"), + + /** + * 被退回 + */ + AUDIT_BACK(3,"被退回"), + + /** + * 未上报 + */ + NOT_REPORT(4,"未上报"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (DataUploadAuditStatusEnum t : DataUploadAuditStatusEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditTypeEnum.java new file mode 100644 index 0000000..ee94a82 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/DataUploadAuditTypeEnum.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.report.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 直报系统数据审核状态 + * @return + * @author CMM + * @since 2023/02/07 13:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "DataUploadAuditTypeEnum", description = "直报系统数据审核类型-枚举") +public enum DataUploadAuditTypeEnum { + + /** + * 市级散办审核 + */ + CITY_AUDIT(1,"市级散办审核"), + + /** + * 审核通过 + */ + PROVINCE_AUDIT(2, "省散办审核"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (DataUploadAuditTypeEnum t : DataUploadAuditTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/QueryTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/QueryTypeEnum.java new file mode 100644 index 0000000..9693bba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/QueryTypeEnum.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.report.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 直报系统上报数据类型 + * @return + * @author CMM + * @since 2023/02/07 13:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "QueryTypeEnum", description = "直报系统上报查询类型-枚举") +public enum QueryTypeEnum { + + /** + * 审核列表查询 + */ + AUDIT_LIST(1,"审核列表查询"), + + /** + * 查询列表查询 + */ + QUERY_LIST(2, "查询列表查询"),; + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(int code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (QueryTypeEnum t : QueryTypeEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/UploadDataTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/UploadDataTypeEnum.java new file mode 100644 index 0000000..3e2311f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constant/UploadDataTypeEnum.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.report.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 直报系统上报数据类型 + * @return + * @author CMM + * @since 2023/02/07 13:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "UploadDataTypeEnum", description = "直报系统上报数据类型-枚举") +public enum UploadDataTypeEnum { + + /** + * 散装水泥供应量快报 + */ + BULK_CEMENT_SUPPLY_BULLETIN(1,"散装水泥供应量快报"), + + /** + * 中转库进出量快报 + */ + BULK_CEMENT_TRANSFER_BULLETIN(2, "中转库进出量快报"), + + /** + * 温台舟使用量快报 + */ + BULK_CEMENT_THREE_CITY_USAGE_BULLETIN(3,"温台舟使用量快报"), + + /** + * 混凝土供应量快报 + */ + CONCRETE_SUPPLY_BULLETIN(4,"混凝土供应量快报"), + + /** + * 砂浆供应量快报 + */ + MORTAR_SUPPLY_BULLETIN(5,"砂浆供应量快报"), + + /** + * 非禁现区域散装水泥销售使用情况统计年报表 + */ + NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE(6,"非禁现区域散装水泥销售使用情况统计年报表"), + + /** + * 散装水泥物流设施统计年报表 + */ + BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT(7,"散装水泥物流设施统计年报表"), + + /** + * 生产材料物流装备统计年报表 + */ + MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT(8,"生产材料物流装备统计年报表"); + + private Integer code; + private String desc; + + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(int code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (UploadDataTypeEnum t : UploadDataTypeEnum.values()) { + if (code == t.getCode()) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constants/ReportConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constants/ReportConstant.java new file mode 100644 index 0000000..36f4402 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/constants/ReportConstant.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.report.constants; + +/** + * @return + * @author CMM + * @since 2023/06/07 10:27 + */ +public interface ReportConstant { + + String TOTAL = "合计"; + String YEAR = "年"; + + String ISSUE_LIBRARY = "发放库"; + String TRANSFER_LIBRARY = "中转库"; + String FIX_RECEIVE_LIBRARY = "固定接收库"; + + String SPECIAL_VEHICLE = "专用汽车"; + String SPECIAL_VESSEL = "专用船"; + String BULK_CEMENT_TANK = "散装水泥罐"; + String CONCRETE_MIXER_TRUCK = "混凝土搅拌车"; + String CONCRETE_PUMP_TRUCK = "混凝土泵车"; + String DRY_MIX_MORTAR_TRUCK = "干混砂浆运输车"; + String DRY_MIX_MORTAR_MOVING_STORAGE = "干混砂浆移动简仓"; + String DRY_MIX_MORTAR_BACK_TANK_CAR = "干混砂浆背罐车"; + + String BULK_CEMENT_SUPPLY_TEMPLATE = "散装水泥供应量统计月报表"; + String BULK_CEMENT_TRANSFER_TEMPLATE = "浙江省散装水泥中转库进出量快报"; + String BULK_CEMENT_THREE_CITY_USAGE_TEMPLATE = "温州、台州、舟山市散装水泥使用量快报"; + String CONCRETE_SUPPLY_TEMPLATE = "预拌混凝土生产及废弃物综合利用情况统计月报表"; + String MORTAR_SUPPLY_TEMPLATE = "预拌砂浆生产及废弃物综合利用情况统计月报表"; + String NON_PRO_AREAS_TEMPLATE = "非禁现区域散装水泥销售使用情况统计年报表"; + String BULK_CEMENT_LOG_FAC_STA_TEMPLATE = "散装水泥物流设施统计年报表"; + String MATERIAL_LOG_EQUIP_STA_TEMPLATE = "散装水泥、预拌混凝土、干混砂浆物流装备统计年报表"; + String BULK_CEMENT_SUPPLY_EMPTY_TEMPLATE = "散装水泥供应量统计月报表(空)"; + String BULK_CEMENT_TRANSFER_EMPTY_TEMPLATE = "浙江省散装水泥中转库进出量快报(空)"; + String BULK_CEMENT_THREE_CITY_USAGE_EMPTY_TEMPLATE = "温州、台州、舟山市散装水泥使用量快报(空)"; + String CONCRETE_SUPPLY_EMPTY_TEMPLATE = "预拌混凝土生产及废弃物综合利用情况统计月报表(空)"; + String MORTAR_SUPPLY_EMPTY_TEMPLATE = "预拌混凝土生产及废弃物综合利用情况统计月报表(空)"; + String NON_PRO_AREAS_EMPTY_TEMPLATE = "非禁现区域散装水泥销售使用情况统计年报表(空)"; + String BULK_CEMENT_LOG_FAC_STA_EMPTY_TEMPLATE = "散装水泥物流设施统计年报表(空)"; + String MATERIAL_LOG_EQUIP_STA_EMPTY_TEMPLATE = "散装水泥、预拌混凝土、干混砂浆物流装备统计年报表(空)"; + + int TWELVE = 12; + + String VEHICLE_ACCIDENT_DATA_TEMPLATE = "车辆事故数据"; + String VEHICLE_ACCIDENT_DATA_TEMPLATE_EMPTY = "车辆事故数据(空)"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementDirectSystemController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementDirectSystemController.java new file mode 100644 index 0000000..5458d76 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementDirectSystemController.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.report.controller; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.BulkCementDirectSystemManage; +import com.ningdatech.carapi.report.model.po.ReqDataAuditPO; +import com.ningdatech.carapi.report.model.po.ReqDataQueryModifyPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadDetailPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResDataQueryDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataQueryListVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-公用接口") +@Validated +@RequiredArgsConstructor +public class BulkCementDirectSystemController { + + private final BulkCementDirectSystemManage bulkCementDirectSystemManage; + + @PostMapping("/upload/data/detail") + @ApiOperation("散装水泥直报系统上报数据详情") + public ResDataUploadDetailVO uploadDataDetail(@Valid @RequestBody ReqDataUploadDetailPO po) { + return bulkCementDirectSystemManage.uploadDataDetail(po); + } + + @PostMapping("/data/query/list") + @ApiOperation("散装水泥直报系统数据查询列表") + public PageVo dataQueryList(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementDirectSystemManage.dataQueryList(po); + } + + @PostMapping("/data/query/detail") + @ApiOperation("散装水泥直报系统数据查询详情") + public ResDataQueryDetailVO uploadDataQueryDetail(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementDirectSystemManage.uploadDataQueryDetail(po); + } + + @PostMapping("/data/query/modify") + @ApiOperation("12月份数据查询编辑") + @WebLog(value = "12月份数据查询编辑", modular = "数据上报-12月份数据查询编辑") + public String uploadDataQueryModify(@Valid @RequestBody ReqDataQueryModifyPO po) { + return bulkCementDirectSystemManage.uploadDataQueryModify(po); + } + + @PostMapping("/data/audit/list") + @ApiOperation("散装水泥直报系统数据审核列表") + public PageVo dataAuditList(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementDirectSystemManage.dataAuditList(po); + } + + @PostMapping("/data/audit") + @ApiOperation("散装水泥直报系统数据审核") + @WebLog(value = "散装水泥直报系统数据审核", modular = "数据上报-散装水泥直报系统数据审核") + public String dataAudit(@Valid @RequestBody ReqDataAuditPO po) { + return bulkCementDirectSystemManage.dataAudit(po); + } + + @PostMapping("/upload/data/query/export") + @ApiOperation("散装水泥直报系统数据查询导出") + @WebLog(value = "散装水泥供应量上报数据查询导出", modular = "数据上报-散装水泥供应量上报数据查询导出") + public void uploadDataQueryExport(@Valid @RequestBody ReqDataUploadListPO po, HttpServletResponse response) { + bulkCementDirectSystemManage.exportQueryData(po,response); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementLogFacStaAnnualReportController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementLogFacStaAnnualReportController.java new file mode 100644 index 0000000..97d5b88 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementLogFacStaAnnualReportController.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.report.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.BulkCementLogFacStaManage; +import com.ningdatech.carapi.report.model.dto.ReqBulkCementLogFacStaDataUploadDTO; +import com.ningdatech.carapi.report.model.po.ReqBulkCementLogFacStaDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementLogFacStaDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementLogFacStaRelatedDataVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-散装水泥物流设施统计年报") +@Validated +@RequiredArgsConstructor +public class BulkCementLogFacStaAnnualReportController { + + private final BulkCementLogFacStaManage bulkCementLogFacStaManage; + + @PostMapping("/get/bulk-cement-log-fac-sta/related/data") + @ApiOperation("获取散装水泥物流设施统计年报相关数据") + public ResBulkCementLogFacStaRelatedDataVO getConcreteSupplyRelatedData(@Valid @RequestBody ReqBulkCementLogFacStaDataUploadDTO dto) { + return bulkCementLogFacStaManage.getBulkCementLogFacStaRelatedData(dto); + } + + @PostMapping("/get/bulk-cement-log-fac-sta/upload/data") + @ApiOperation("获取散装水泥物流设施统计年报计算数据") + public ResBulkCementLogFacStaDataUploadDetailVO getBulkCementLogFacStaUploadData(@Valid @RequestBody ReqBulkCementLogFacStaDataUploadDTO dto) { + return bulkCementLogFacStaManage.getBulkCementLogFacStaUploadData(dto); + } + @PostMapping("/bulk-cement-log-fac-sta/data/upload") + @ApiOperation("散装水泥物流设施统计年报数据上报") + @WebLog(value = "散装水泥物流设施统计年报数据上报", modular = "数据上报-散装水泥物流设施统计年报数据上报") + public String bulkCementSupplyDataUpload(@Valid @RequestBody ReqBulkCementLogFacStaDataUploadPO po) { + return bulkCementLogFacStaManage.bulkCementLogFacStaDataUpload(po); + } + @PostMapping("/bulk-cement-log-fac-sta/data/upload/list") + @ApiOperation("散装水泥物流设施统计年报年报数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementLogFacStaManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementSupplyBulletinController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementSupplyBulletinController.java new file mode 100644 index 0000000..0c362f5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementSupplyBulletinController.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.report.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.BulkCementSupplyBulletinManage; +import com.ningdatech.carapi.report.model.po.ReqBulkCementSupplyDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementSupplyDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-散装水泥供应量快报") +@Validated +@RequiredArgsConstructor +public class BulkCementSupplyBulletinController { + + private final BulkCementSupplyBulletinManage bulkCementSupplyBulletinManage; + @PostMapping("/get/bulk-cement-supply/upload/data") + @ApiOperation("获取散装水泥供应量快报计算数据") + public ResBulkCementSupplyDataUploadDetailVO getBulkCementSupplyUploadData(@Valid @RequestBody ReqBulkCementSupplyDataUploadPO po) { + return bulkCementSupplyBulletinManage.getBulkCementSupplyUploadData(po); + } + @PostMapping("/bulk-cement-supply/data/upload") + @ApiOperation("散装水泥供应量快报数据上报") + @WebLog(value = "散装水泥供应量快报数据上报", modular = "数据上报-散装水泥供应量快报数据上报") + public String bulkCementSupplyDataUpload(@Valid @RequestBody ReqBulkCementSupplyDataUploadPO po) { + return bulkCementSupplyBulletinManage.bulkCementSupplyDataUpload(po); + } + @PostMapping("/bulk-cement-supply/data/upload/list") + @ApiOperation("散装水泥供应量数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementSupplyBulletinManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementThreeCityUsageBulletinController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementThreeCityUsageBulletinController.java new file mode 100644 index 0000000..971715b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementThreeCityUsageBulletinController.java @@ -0,0 +1,63 @@ +package com.ningdatech.carapi.report.controller; + +import java.math.BigDecimal; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.BulkCementThreeCityUsageBulletinManage; +import com.ningdatech.carapi.report.model.po.ReqBulkCementThreeCityUsageDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementThreeCityUsageDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-温台舟使用量快报") +@Validated +@RequiredArgsConstructor +public class BulkCementThreeCityUsageBulletinController { + + private final BulkCementThreeCityUsageBulletinManage bulkCementThreeCityUsageBulletinManage; + + @PostMapping("/get/bulk-cement-three-city-usage/yearTarget") + @ApiOperation("获取温台舟使用量年目标数据") + public BigDecimal getBulkCementThreeCityUsageYearTarget(@Valid @RequestBody ReqBulkCementThreeCityUsageDataUploadPO po) { + return bulkCementThreeCityUsageBulletinManage.getBulkCementThreeCityUsageYearTarget(po); + } + @PostMapping("/get/bulk-cement-three-city-usage/upload/data") + @ApiOperation("获取温台舟使用量快报计算数据") + public ResBulkCementThreeCityUsageDataUploadDetailVO getBulkCementThreeCityUsageUploadData(@Valid @RequestBody ReqBulkCementThreeCityUsageDataUploadPO po) { + return bulkCementThreeCityUsageBulletinManage.getBulkCementThreeCityUsageUploadData(po); + } + @PostMapping("/bulk-cement-three-city-usage/data/upload") + @ApiOperation("温台舟使用量数据上报") + @WebLog(value = "温台舟使用量数据上报", modular = "数据上报-温台舟使用量数据上报") + public String bulkCementThreeCityUsageDataUpload(@Valid @RequestBody ReqBulkCementThreeCityUsageDataUploadPO po) { + return bulkCementThreeCityUsageBulletinManage.bulkCementThreeCityUsageDataUpload(po); + } + @PostMapping("/bulk-cement-three-city-usage/data/upload/list") + @ApiOperation("温台舟使用量数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementThreeCityUsageBulletinManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementTransferBulletinController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementTransferBulletinController.java new file mode 100644 index 0000000..8add44f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/BulkCementTransferBulletinController.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.report.controller; + +import java.math.BigDecimal; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.BulkCementTransferBulletinManage; +import com.ningdatech.carapi.report.model.po.ReqBulkCementTransferDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementTransferDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-中转库进出量统计") +@Validated +@RequiredArgsConstructor +public class BulkCementTransferBulletinController { + + private final BulkCementTransferBulletinManage bulkCementTransferBulletinManage; + + @PostMapping("/get/bulk-cement-transfer/last-month/data") + @ApiOperation("获取中转库进出量上月数据") + public BigDecimal getBulkCementTransferLastMonthData(@Valid @RequestBody ReqBulkCementTransferDataUploadPO po) { + return bulkCementTransferBulletinManage.getBulkCementTransferLastMonthData(po); + } + + @PostMapping("/get/bulk-cement-transfer/upload/data") + @ApiOperation("获取中转库进出量计算数据") + public ResBulkCementTransferDataUploadDetailVO getBulkCementSupplyUploadData(@Valid @RequestBody ReqBulkCementTransferDataUploadPO po) { + return bulkCementTransferBulletinManage.getBulkCementTransferUploadData(po); + } + @PostMapping("/bulk-cement-transfer/data/upload") + @ApiOperation("中转库进出量数据上报") + @WebLog(value = "中转库进出量数据上报", modular = "数据上报-中转库进出量数据上报") + public String bulkCementSupplyDataUpload(@Valid @RequestBody ReqBulkCementTransferDataUploadPO po) { + return bulkCementTransferBulletinManage.bulkCementTransferDataUpload(po); + } + @PostMapping("/bulk-cement-transfer/data/upload/list") + @ApiOperation("中转库进出量数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return bulkCementTransferBulletinManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/ConcreteSupplyBulletinController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/ConcreteSupplyBulletinController.java new file mode 100644 index 0000000..e1cadbb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/ConcreteSupplyBulletinController.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.report.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.ConcreteSupplyBulletinManage; +import com.ningdatech.carapi.report.model.po.ReqConcreteSupplyDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResConcreteSupplyDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResConcreteSupplyRelatedDataVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-混凝土供应量快报") +@Validated +@RequiredArgsConstructor +public class ConcreteSupplyBulletinController { + + private final ConcreteSupplyBulletinManage concreteSupplyBulletinManage; + + @PostMapping("/get/concrete-supply/related/data") + @ApiOperation("获取混凝土供应量相关数据") + public ResConcreteSupplyRelatedDataVO getConcreteSupplyRelatedData(@Valid @RequestBody ReqConcreteSupplyDataUploadPO po) { + return concreteSupplyBulletinManage.getConcreteSupplyRelatedData(po); + } + @PostMapping("/get/concrete-supply/upload/data") + @ApiOperation("获取混凝土供应量快报计算数据") + public ResConcreteSupplyDataUploadDetailVO getConcreteSupplyUploadData(@Valid @RequestBody ReqConcreteSupplyDataUploadPO po) { + return concreteSupplyBulletinManage.getConcreteSupplyUploadData(po); + } + @PostMapping("/concrete-supply/data/upload") + @ApiOperation("混凝土供应量快报数据上报") + @WebLog(value = "混凝土供应量快报数据上报", modular = "数据上报-混凝土供应量快报数据上报") + public String concreteSupplyDataUpload(@Valid @RequestBody ReqConcreteSupplyDataUploadPO po) { + return concreteSupplyBulletinManage.concreteSupplyDataUpload(po); + } + @PostMapping("/concrete-supply/data/upload/list") + @ApiOperation("混凝土供应量数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return concreteSupplyBulletinManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MaterialLogEquipStaAnnualReportController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MaterialLogEquipStaAnnualReportController.java new file mode 100644 index 0000000..18fbb64 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MaterialLogEquipStaAnnualReportController.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.report.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.MaterialLogEquipStaManage; +import com.ningdatech.carapi.report.model.dto.ReqMaterialLogEquipStaDataUploadDTO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.po.ReqMaterialLogEquipStaDataUploadPO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.model.vo.ResMaterialLogEquipStaDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResMaterialLogEquipStaRelatedDataVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-散装水泥、预拌混凝土、干混砂浆物流装备统计年报") +@Validated +@RequiredArgsConstructor +public class MaterialLogEquipStaAnnualReportController { + + private final MaterialLogEquipStaManage materialLogEquipStaManage; + + @PostMapping("/get/material-log-equip-sta/related/data") + @ApiOperation("获取散装水泥、预拌混凝土、干混砂浆物流装备统计年报相关数据") + public ResMaterialLogEquipStaRelatedDataVO getConcreteSupplyRelatedData(@Valid @RequestBody ReqMaterialLogEquipStaDataUploadDTO dto) { + return materialLogEquipStaManage.getMaterialLogEquipStaRelatedData(dto); + } + + @PostMapping("/get/material-log-equip-sta/upload/data") + @ApiOperation("获取散装水泥、预拌混凝土、干混砂浆物流装备统计年报计算数据") + public ResMaterialLogEquipStaDataUploadDetailVO getBulkCementLogFacStaUploadData(@Valid @RequestBody ReqMaterialLogEquipStaDataUploadDTO dto) { + return materialLogEquipStaManage.getMaterialLogEquipStaUploadData(dto); + } + @PostMapping("/material-log-equip-sta/data/upload") + @ApiOperation("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据上报") + @WebLog(value = "非禁现区散装水泥销售使用情况年报数据上报", modular = "数据上报-非禁现区散装水泥销售使用情况年报数据上报") + public String bulkCementSupplyDataUpload(@Valid @RequestBody ReqMaterialLogEquipStaDataUploadPO po) { + return materialLogEquipStaManage.materialLogEquipStaDataUpload(po); + } + @PostMapping("/material-log-equip-sta/data/upload/list") + @ApiOperation("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return materialLogEquipStaManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MortarSupplyBulletinController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MortarSupplyBulletinController.java new file mode 100644 index 0000000..bd1ad6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/MortarSupplyBulletinController.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.report.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.MortarSupplyBulletinManage; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.po.ReqMortarSupplyDataUploadPO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.model.vo.ResMortarSupplyDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResMortarSupplyRelatedDataVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-砂浆供应量快报") +@Validated +@RequiredArgsConstructor +public class MortarSupplyBulletinController { + + private final MortarSupplyBulletinManage mortarSupplyBulletinManage; + + @PostMapping("/get/mortar-supply/related/data") + @ApiOperation("获取砂浆供应量相关数据") + public ResMortarSupplyRelatedDataVO getMortarSupplyRelatedData(@Valid @RequestBody ReqMortarSupplyDataUploadPO po) { + return mortarSupplyBulletinManage.getMortarSupplyRelatedData(po); + } + @PostMapping("/get/mortar-supply/upload/data") + @ApiOperation("获取砂浆供应量快报计算数据") + public ResMortarSupplyDataUploadDetailVO getMortarSupplyUploadData(@Valid @RequestBody ReqMortarSupplyDataUploadPO po) { + return mortarSupplyBulletinManage.getMortarSupplyUploadData(po); + } + @PostMapping("/mortar-supply/data/upload") + @ApiOperation("砂浆供应量快报数据上报") + @WebLog(value = "砂浆供应量快报数据上报", modular = "数据上报-砂浆供应量快报数据上报") + public String mortarSupplyDataUpload(@Valid @RequestBody ReqMortarSupplyDataUploadPO po) { + return mortarSupplyBulletinManage.mortarSupplyDataUpload(po); + } + @PostMapping("/mortar-supply/data/upload/list") + @ApiOperation("散装水泥供应量数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return mortarSupplyBulletinManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/NonProhibitedAreasBulkCementSalesUseController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/NonProhibitedAreasBulkCementSalesUseController.java new file mode 100644 index 0000000..86955dd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/controller/NonProhibitedAreasBulkCementSalesUseController.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.report.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.report.manage.NonProhibitedAreasBulkCementSalesUseManage; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.po.ReqNonProhibitedAreasDataUploadPO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.model.vo.ResNonProhibitedAreasDataUploadDetailVO; +import com.ningdatech.log.annotation.WebLog; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 散装水泥直报系统 前端控制器 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@RequestMapping("/api/v1/direct/report/system") +@RestController +@Api(tags = "数据上报-非禁现区域散装水泥销售使用情况") +@Validated +@RequiredArgsConstructor +public class NonProhibitedAreasBulkCementSalesUseController { + + private final NonProhibitedAreasBulkCementSalesUseManage nonProhibitedAreasBulkCementSalesUseManage; + + @PostMapping("/get/non-prohibited-areas/upload/data") + @ApiOperation("获取非禁现区散装水泥销售使用情况年报计算数据") + public ResNonProhibitedAreasDataUploadDetailVO getBulkCementSupplyUploadData(@Valid @RequestBody ReqNonProhibitedAreasDataUploadPO po) { + return nonProhibitedAreasBulkCementSalesUseManage.getNonProhibitedAreasUploadData(po); + } + @PostMapping("/non-prohibited-areas/data/upload") + @ApiOperation("非禁现区散装水泥销售使用情况年报数据上报") + @WebLog(value = "非禁现区散装水泥销售使用情况年报数据上报", modular = "数据上报-非禁现区散装水泥销售使用情况年报数据上报") + public String bulkCementSupplyDataUpload(@Valid @RequestBody ReqNonProhibitedAreasDataUploadPO po) { + return nonProhibitedAreasBulkCementSalesUseManage.nonProhibitedAreasDataUpload(po); + } + @PostMapping("/non-prohibited-areas/data/upload/list") + @ApiOperation("非禁现区散装水泥销售使用情况年报数据上报列表") + public PageVo dataUploadList(@Valid @RequestBody ReqDataUploadListPO po) { + return nonProhibitedAreasBulkCementSalesUseManage.dataUploadList(po); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementDirectSystemManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementDirectSystemManage.java new file mode 100644 index 0000000..468b13a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementDirectSystemManage.java @@ -0,0 +1,3585 @@ +package com.ningdatech.carapi.report.manage; + +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.QueryTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.constants.ReportConstant; +import com.ningdatech.carapi.report.model.dto.*; +import com.ningdatech.carapi.report.model.entity.*; +import com.ningdatech.carapi.report.model.po.ReqDataAuditPO; +import com.ningdatech.carapi.report.model.po.ReqDataQueryModifyPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadDetailPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.*; +import com.ningdatech.carapi.report.service.*; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.TemplateExportParams; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.poi.excel.ExcelUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BulkCementDirectSystemManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final IBulkCementSupplyBulletinService bulkCementSupplyBulletinService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final IBulkCementDirectReportSystemUniversalIndexService universalIndexService; + private final CompaniesCacheHelper companiesCacheHelper; + private final IBulkCementTransferBulletinService bulkCementTransferBulletinService; + private final IBulkCementThreeCityUsageBulletinService bulkCementThreeCityUsageBulletinService; + private final IConcreteSupplyBulletinService concreteSupplyBulletinService; + private final IMortarSupplyBulletinService mortarSupplyBulletinService; + private final INonProhibitedAreasBulkCementSalesUseService nonProhibitedAreasBulkCementSalesUseService; + private final IBulkCementLogisticFacilityStatisticAnnualReportService bulkCementLogFacStaAnnualReportService; + private final IMaterialLogisticEquipmentStatisticAnnualReportService materialLogEquipStaAnnualReportService; + private final UserInfoHelper userInfoHelper; + + public PageVo dataAuditList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + + Page page = req.page(); + // 根据所属区域和登录用户角色查出对应的散装水泥供应量数据审核记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditRecord.class); + BulkCementDirectSystemManage context = (BulkCementDirectSystemManage) AopContext.currentProxy(); + context.buildDataAuditListQuery(wrapper, req); + auditRecordService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(BulkCementDirectReportSystemAuditRecord::getAuditInfoId).collect(Collectors.toList()); + VUtils.isTrue(CollUtil.isEmpty(auditInfoIdList)).throwMessage("审核信息不存在!"); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class) + .in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + Map dataRelevanceMap = dataRelevanceService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemDataRelevance::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + LocalDateTime month = r.getReportMonth(); + if (Objects.nonNull(month)) { + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN)); + vo.setReportMonth(reportMonth); + } + vo.setReportYear(r.getReportYear()); + vo.setRegionId(r.getRegionId()); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(r.getRegionId()); + vo.setRegionName(regionDto.getRegionName()); + vo.setAuditDataId(r.getAuditDataId()); + + // 如果登录用户是市散办 + if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())){ + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(r.getAuditDataId()); + vo.setAuditDataIdList(auditDataIdList); + } + // 如果登录用户是省散办 + else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())) { + Long relevanceId = r.getAuditDataId(); + Map> auditDataIdListMap = MapUtil.newHashMap(); + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceMap.get(relevanceId); + if (Objects.nonNull(dataRelevance) && StringUtils.isNotBlank(dataRelevance.getAuditDataIdList())){ + String auditDataIdList = dataRelevance.getAuditDataIdList(); + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + auditDataIdListMap.put(relevanceId,idList); + vo.setAuditDataIdListMap(auditDataIdListMap); + } + } + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditInfoId(auditInfo.getId()); + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + vo.setAuditTime(auditInfo.getAuditTime()); + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + } + vo.setSubmitTime(r.getCreateOn()); + vo.setAuditRecordId(r.getId()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void buildDataAuditListQuery(LambdaQueryWrapper wrapper, ReqDataUploadListPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + Integer reportStartYear = req.getReportStartYear(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer reportEndYear = req.getReportEndYear(); + List auditStatusList = req.getAuditStatusList(); + Integer auditStatus = req.getAuditStatus(); + Integer auditDataType = req.getAuditDataType(); + VUtils.isTrue(Objects.isNull(auditDataType)).throwMessage("请传入审核数据类型!"); + Long regionId = req.getRegionId(); + VUtils.isTrue(CollUtil.isEmpty(auditStatusList)).throwMessage("请传入审核列表审核状态筛选条件!"); + wrapper.ge(Objects.nonNull(reportStartMonth), BulkCementDirectReportSystemAuditRecord::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), BulkCementDirectReportSystemAuditRecord::getReportMonth, reportEndMonth) + .ge(Objects.nonNull(reportStartYear), BulkCementDirectReportSystemAuditRecord::getReportYear, reportStartYear) + .le(Objects.nonNull(reportEndYear), BulkCementDirectReportSystemAuditRecord::getReportYear, reportEndYear) + .in(BulkCementDirectReportSystemAuditRecord::getAuditStatus,auditStatusList) + .eq(BulkCementDirectReportSystemAuditRecord::getAuditDataType,auditDataType) + .eq(Objects.nonNull(auditStatus),BulkCementDirectReportSystemAuditRecord::getAuditStatus,auditStatus) + .eq(Objects.nonNull(regionId),BulkCementDirectReportSystemAuditRecord::getRegionId,regionId) + .orderByDesc(BulkCementDirectReportSystemAuditRecord::getUpdateOn) + .isNotNull(BulkCementDirectReportSystemAuditRecord::getAuditInfoId); + // 如果是市级散办,筛选出审核类型为市级散办审核的数据 + if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)){ + wrapper.eq(BulkCementDirectReportSystemAuditRecord::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + } + // 如果是省级散办,筛选出审核类型为省散办审核的数据 + else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId) || UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(roleId)) { + wrapper.eq(BulkCementDirectReportSystemAuditRecord::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + } + } + + @Transactional(rollbackFor = Exception.class) + public String dataAudit(ReqDataAuditPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + + // 获取入参 + Long auditDataId = req.getAuditDataId(); + Long auditIndoId = req.getAuditInfoId(); + Long auditRecordId = req.getAuditRecordId(); + String auditOpinion = req.getAuditOpinion(); + Integer auditStatus = req.getAuditStatus(); + LocalDateTime reportMonth = req.getReportMonth(); + Integer reportYear = req.getReportYear(); + Integer auditDataType = req.getAuditDataType(); + + // 更新审核信息 + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoService.getById(auditIndoId); + VUtils.isTrue(Objects.isNull(auditInfo)).throwMessage("审核信息不存在!"); + auditInfo.setAuditOpinion(auditOpinion); + auditInfo.setAuditTime(LocalDateTime.now()); + auditInfo.setAuditStatus(auditStatus); + auditInfo.setAuditBy(userDetail.getUserId()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfoService.updateById(auditInfo); + // 更新审核记录信息 + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditRecord.class); + BulkCementDirectSystemManage context = (BulkCementDirectSystemManage) AopContext.currentProxy(); + context.buildAuditRecordQuery(wrapper, auditRecordId); + BulkCementDirectReportSystemAuditRecord auditRecord = auditRecordService.getOne(wrapper); + VUtils.isTrue(Objects.isNull(auditRecord)).throwMessage("审核记录不存在!"); + auditRecord.setAuditStatus(auditStatus); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + auditRecordService.updateById(auditRecord); + + // 更新对应类型的审核数据 + // 如果登录审核用户是市级散办 更新对应数据信息 + if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + switch (auditDataType) { + // 散装水泥供应量数据 + case 1: + BulkCementSupplyBulletin cementSupplyBulletin = bulkCementSupplyBulletinService.getById(auditDataId); + cementSupplyBulletin.setAuditStatus(auditStatus); + cementSupplyBulletin.setUpdateOn(LocalDateTime.now()); + cementSupplyBulletin.setUpdateBy(userDetail.getUserId()); + bulkCementSupplyBulletinService.updateById(cementSupplyBulletin); + break; + // 中转库进出量统计数据 + case 2: + BulkCementTransferBulletin bulkCementTransferBulletin = bulkCementTransferBulletinService.getById(auditDataId); + bulkCementTransferBulletin.setAuditStatus(auditStatus); + bulkCementTransferBulletin.setUpdateOn(LocalDateTime.now()); + bulkCementTransferBulletin.setUpdateBy(userDetail.getUserId()); + bulkCementTransferBulletinService.updateById(bulkCementTransferBulletin); + break; + // 温台舟使用量快报数据 + case 3: + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getById(auditDataId); + bulkCementThreeCityUsageBulletin.setAuditStatus(auditStatus); + bulkCementThreeCityUsageBulletin.setUpdateOn(LocalDateTime.now()); + bulkCementThreeCityUsageBulletin.setUpdateBy(userDetail.getUserId()); + bulkCementThreeCityUsageBulletinService.updateById(bulkCementThreeCityUsageBulletin); + break; + // 混凝土供应量快报数据 + case 4: + ConcreteSupplyBulletin concreteSupplyBulletin = concreteSupplyBulletinService.getById(auditDataId); + concreteSupplyBulletin.setAuditStatus(auditStatus); + concreteSupplyBulletin.setUpdateOn(LocalDateTime.now()); + concreteSupplyBulletin.setUpdateBy(userDetail.getUserId()); + concreteSupplyBulletinService.updateById(concreteSupplyBulletin); + break; + // 砂浆供应量快报数据 + case 5: + MortarSupplyBulletin mortarSupplyBulletin = mortarSupplyBulletinService.getById(auditDataId); + mortarSupplyBulletin.setAuditStatus(auditStatus); + mortarSupplyBulletin.setUpdateOn(LocalDateTime.now()); + mortarSupplyBulletin.setUpdateBy(userDetail.getUserId()); + mortarSupplyBulletinService.updateById(mortarSupplyBulletin); + break; + // 非禁现区域散装水泥销售使用情况数据 + case 6: + NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse = nonProhibitedAreasBulkCementSalesUseService.getById(auditDataId); + nonProhibitedAreasBulkCementSalesUse.setAuditStatus(auditStatus); + nonProhibitedAreasBulkCementSalesUse.setUpdateOn(LocalDateTime.now()); + nonProhibitedAreasBulkCementSalesUse.setUpdateBy(userDetail.getUserId()); + nonProhibitedAreasBulkCementSalesUseService.updateById(nonProhibitedAreasBulkCementSalesUse); + break; + // 散装水泥物流设施统计年报表数据 + case 7: + // 获取填报的各设备名称的数据更新审核状态 + BulkCementDirectReportSystemDataRelevance dataRelevance1 = dataRelevanceService.getById(auditDataId); + String auditDataIdList1 = dataRelevance1.getAuditDataIdList(); + VUtils.isTrue(StringUtils.isBlank(auditDataIdList1)).throwMessage("审核数据不存在!"); + List idList1 = Arrays.stream(auditDataIdList1.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + for (Long id : idList1) { + BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogFacStaAnnualReport = bulkCementLogFacStaAnnualReportService.getById(id); + bulkCementLogFacStaAnnualReport.setAuditStatus(auditStatus); + bulkCementLogFacStaAnnualReport.setUpdateOn(LocalDateTime.now()); + bulkCementLogFacStaAnnualReport.setUpdateBy(userDetail.getUserId()); + bulkCementLogFacStaAnnualReportService.updateById(bulkCementLogFacStaAnnualReport); + } + // 更新区县关联数据 + dataRelevance1.setAuditStatus(auditStatus); + dataRelevance1.setUpdateOn(LocalDateTime.now()); + dataRelevance1.setUpdateBy(userDetail.getUserId()); + dataRelevanceService.updateById(dataRelevance1); + break; + // 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据 + case 8: + // 获取填报的各设备名称的数据更新审核状态 + BulkCementDirectReportSystemDataRelevance dataRelevance2 = dataRelevanceService.getById(auditDataId); + String auditDataIdList2 = dataRelevance2.getAuditDataIdList(); + VUtils.isTrue(StringUtils.isBlank(auditDataIdList2)).throwMessage("审核数据不存在!"); + List idList2 = Arrays.stream(auditDataIdList2.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + for (Long id : idList2) { + MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport = materialLogEquipStaAnnualReportService.getById(id); + materialLogEquipStaAnnualReport.setAuditStatus(auditStatus); + materialLogEquipStaAnnualReport.setUpdateOn(LocalDateTime.now()); + materialLogEquipStaAnnualReport.setUpdateBy(userDetail.getUserId()); + materialLogEquipStaAnnualReportService.updateById(materialLogEquipStaAnnualReport); + } + // 更新区县关联数据 + dataRelevance2.setAuditStatus(auditStatus); + dataRelevance2.setUpdateOn(LocalDateTime.now()); + dataRelevance2.setUpdateBy(userDetail.getUserId()); + dataRelevanceService.updateById(dataRelevance2); + break; + default: + throw new IllegalStateException("Unexpected value: " + auditDataType); + } + } + + // 登录用户是市级散办更新对应的市级关联数据 + // 登录用户是省散办更新对应的省关联数 + Long regionId; + if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType,auditDataType) + // 非年报关联数据,通过传入的上报月份查询 + .eq(Objects.nonNull(reportMonth), BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + // 年报数据,通过传入的上报年份查询 + .eq(Objects.nonNull(reportYear),BulkCementDirectReportSystemDataRelevance::getReportYear,reportYear)); + VUtils.isTrue(Objects.isNull(dataRelevance)).throwMessage("关联数据不存在!"); + + // 如果审核通过,更新关联数据ID列表 + // 注意:审核数据类型如果为散装水泥物流设施统计年报或者散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据 + // 实际上auditDataIdList中存放的是各区县关联数据ID + if (DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(auditStatus)){ + String auditDataIdList = dataRelevance.getAuditDataIdList(); + // 如果是审核的第一个数据,更新关联数据中上报数据列表 + if (StringUtils.isBlank(auditDataIdList)){ + List auditIdList = Lists.newArrayList(); + auditIdList.add(auditDataId); + String idListStr = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + dataRelevance.setAuditDataIdList(idListStr); + } + // 如果审核的不是第一个数据,更新关联数据中上报数据列表 + else { + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!idList.contains(auditDataId)){ + idList.add(auditDataId); + String idListStr = idList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + dataRelevance.setAuditDataIdList(idListStr); + } + } + } + // 如果登录用户是市级散办,更新关联数据审核状态为未上报,更新关联表中数据的最近一次更新时间和关联数据ID列表 + if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())){ + dataRelevance.setLastUpdateTime(LocalDateTime.now()); + dataRelevance.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + } + // 如果登录用户是省散办,审核状态设置为审核通过 + else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())) { + dataRelevance.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + // 市级关联数据也要更新状态为审核通过 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(auditDataId); + cityRelevanceData.setAuditStatus(auditStatus); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setLastUpdateTime(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + dataRelevanceService.updateById(cityRelevanceData); + } + dataRelevance.setUpdateOn(LocalDateTime.now()); + dataRelevance.setUpdateBy(userDetail.getUserId()); + dataRelevanceService.updateById(dataRelevance); + return "审核成功!"; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildAuditRecordQuery(LambdaQueryWrapper wrapper, Long auditRecordId) { + wrapper.eq(BulkCementDirectReportSystemAuditRecord::getId,auditRecordId); + } + + public PageVo dataQueryList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Integer pageNumber = req.getPageNumber(); + Integer pageSize = req.getPageSize(); + + Long regionId; + if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + + // 市级散办和省散办账号有该列表权限 + // 根据所属区域查出对应数据类型的上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + Integer reportStartYear = req.getReportStartYear(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer reportEndYear = req.getReportEndYear(); + Integer auditStatus = req.getAuditStatus(); + Integer auditDataType = req.getAuditDataType(); + VUtils.isTrue(Objects.isNull(auditDataType)).throwMessage("请传入审核数据类型!"); + wrapper.ge(Objects.nonNull(reportStartMonth), BulkCementDirectReportSystemDataRelevance::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), BulkCementDirectReportSystemDataRelevance::getReportMonth, reportEndMonth) + .ge(Objects.nonNull(reportStartYear), BulkCementDirectReportSystemDataRelevance::getReportYear, reportStartYear) + .le(Objects.nonNull(reportEndYear), BulkCementDirectReportSystemDataRelevance::getReportYear, reportEndYear) + .eq(Objects.nonNull(auditStatus),BulkCementDirectReportSystemDataRelevance::getAuditStatus,auditStatus) + // 其中市级关联数据对应的数据ID列表为对应上报数据的ID + // 省级关联数据对应的数据ID列表为各市级关联数据的ID + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType,auditDataType) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId,regionId) + .orderByDesc(BulkCementDirectReportSystemDataRelevance::getReportMonth); + List list = dataRelevanceService.list(wrapper); + if (CollUtil.isEmpty(list)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = list.stream().map(BulkCementDirectReportSystemDataRelevance::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + // 获取关联数据信息 + Map dataRelevanceMap = dataRelevanceService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .select(BulkCementDirectReportSystemDataRelevance::getId,BulkCementDirectReportSystemDataRelevance::getAuditStatus, BulkCementDirectReportSystemDataRelevance::getAuditDataIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemDataRelevance::getId, v -> v)); + List resVos = list.stream().map(r -> { + ResDataQueryListVO vo = new ResDataQueryListVO(); + LocalDateTime month = r.getReportMonth(); + if (Objects.nonNull(month)) { + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT_EN); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(NdDateUtils.DEFAULT_MONTH_FORMAT_EN)); + vo.setReportMonth(reportMonth); + } + vo.setReportYear(r.getReportYear()); + vo.setRegionId(r.getRegionId()); + vo.setRelevanceDataId(r.getId()); + + String auditDataIdList = r.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)) { + List idList = Lists.newArrayList(); + Map> dataIdListMap = MapUtil.newHashMap(); + // 如果登录用户为市级散办或者查询列表为温台舟使用量列表,直接得到所属各区县(三 市)上报数据的ID列表 + // 注意:此处审核数据类型如果为散装水泥物流设施统计年报或者散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据 + // 实际上auditDataIdList中存放的是各区县关联数据ID + if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + } + // 如果登录用户为省级散办,先得到各所属市关联的数据ID列表,再得出各市所属各区县上报数据的ID列表 + else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())) { + List relevanceIdList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + for (Long relevanceId : relevanceIdList) { + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceMap.get(relevanceId); + if (Objects.nonNull(dataRelevance) && StringUtils.isNotBlank(dataRelevance.getAuditDataIdList())) { + String dataIdList = dataRelevance.getAuditDataIdList(); + List ids = Arrays.stream(dataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 筛选出所有已经审核通过的关联上报数据 + if (DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(dataRelevance.getAuditStatus())){ + // 一对多的关系 + dataIdListMap.put(relevanceId, ids); + } + } + } + } + vo.setAuditDataIdList(idList); + vo.setAuditDataIdListMap(dataIdListMap); + } + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + vo.setAuditInfoId(auditInfo.getId()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + vo.setUpdateTime(r.getUpdateOn()); + return vo; + }).collect(Collectors.toList()); + List result; + List dataList = Lists.newArrayList(); + // 省级账号 过滤掉没有数据的记录 + if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())){ + dataList = resVos.stream().filter(r -> CollUtil.isNotEmpty(r.getAuditDataIdListMap())).collect(Collectors.toList()); + result = dataList.stream().skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize).collect(Collectors.toList()); + }else { + result = resVos; + } + + return PageVo.of(result, dataList.size()); + } + + public ResDataQueryDetailVO uploadDataQueryDetail(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + + List auditDataIdList = req.getAuditDataIdList(); + Map> auditDataIdListMap = req.getAuditDataIdListMap(); + Integer auditDataType = req.getAuditDataType(); + LocalDateTime reportMonth = req.getReportMonth(); + Integer reportYear = req.getReportYear(); + Long regionId = req.getRegionId(); + + // 判断传入的区域ID是否在登录用户所属的区域权限内 + Long userDetailRegionId = userDetail.getRegionId(); + List listChildRegionId = regionsCacheHelper.listChildRegionId(userDetailRegionId, true, false); + if (!listChildRegionId.contains(userDetailRegionId)){ + throw new BizException("您无权查看该地区数据!"); + } + + Integer queryType = req.getQueryType(); + if (Objects.isNull(regionId)){ + if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + } + ResDataQueryDetailVO vo = new ResDataQueryDetailVO(); + vo.setReportMonth(reportMonth); + vo.setReportYear(reportYear); + // 根据登录用户角色判断应当返回的数据 + // 如果登录用户是市级散办,返回所属各区县上报的对应类型的数据 + if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())){ + if (CollUtil.isEmpty(auditDataIdList)){ + return vo; + } + Map dataMap = MapUtil.newHashMap(); + // 获取所属区县上报已审核通过的对应类型的数据 + Long companyId = userDetail.getCompanyId(); + getDataMap(auditDataIdList, auditDataType, companyId, dataMap, Boolean.FALSE, reportMonth,regionId,queryType); + assemblyDetailVO(auditDataType, vo, dataMap, Boolean.FALSE, reportMonth,regionId,reportYear,queryType,userDetail); + } + // 如果登录用户是省散办,返回所属各市上报的对应类型的数据 + else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId()) || + UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(userDetail.getRoleId())) { + if (CollUtil.isNotEmpty(auditDataIdListMap)) { + Map dataMap = MapUtil.newHashMap(); + Set relevanceIds = auditDataIdListMap.keySet(); + Map dataRelevanceMap = dataRelevanceService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .in(BulkCementDirectReportSystemDataRelevance::getId, relevanceIds)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemDataRelevance::getId, v -> v)); + for (Long relevanceId : relevanceIds) { + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceMap.get(relevanceId); + if (Objects.nonNull(dataRelevance)){ + List idList = auditDataIdListMap.get(relevanceId); + Long companyId = dataRelevance.getCompanyId(); + Long relevanceRegionId = dataRelevance.getRegionId(); + Map tempDataMap = MapUtil.newHashMap(); + if (UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode().equals(auditDataType) || + UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode().equals(auditDataType)){ + getDataMap(idList, auditDataType, companyId, tempDataMap, Boolean.TRUE, reportMonth, relevanceRegionId, queryType); + for (Map.Entry entry : tempDataMap.entrySet()) { + // key为发放库、中转库、固定接收库 + String key = entry.getKey(); + Map mapValue = (Map) entry.getValue(); + Map value = (Map) dataMap.get(key); + if (Objects.nonNull(value)){ + for (Map.Entry objectEntry : mapValue.entrySet()) { + // key为各市散装中心名称 + String entryKey = objectEntry.getKey(); + Object valueList = objectEntry.getValue(); + value.put(entryKey, valueList); + } + }else { + dataMap.put(key,mapValue); + } + } + }else { + getDataMap(idList, auditDataType, companyId, dataMap, Boolean.TRUE, reportMonth, relevanceRegionId, queryType); + } + } + } + assemblyDetailVO(auditDataType,vo,dataMap,Boolean.TRUE, reportMonth, regionId, reportYear, queryType, userDetail); + } + } + return vo; + } + + private void assemblyDetailVO(Integer auditDataType, ResDataQueryDetailVO vo, Map dataMap, Boolean flag, LocalDateTime reportMonth, Long regionId, Integer reportYear, Integer queryType, UserInfoDetails userDetail) { + + switch (auditDataType) { + // 散装水泥供应量数据 + case 1: + ResBulkCementSupplyDataQueryDetailVO bulkCementSupplyDataQueryDetailVo = new ResBulkCementSupplyDataQueryDetailVO(); + getBulkCementSupplyDataQueryDetailVo(dataMap, flag, reportMonth, bulkCementSupplyDataQueryDetailVo,regionId); + // 返回单位信息 + // 如果是审核列表查询,登录用户是市散办,查询的是具体区县的详情,如果是12月的数据,要返回单位信息 + if (QueryTypeEnum.AUDIT_LIST.getCode().equals(queryType) && + userDetail.getRoleId().equals(UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId()) && + reportMonth.getMonthValue() == ReportConstant.TWELVE){ + BulkCementSupplyBulletin bulkCementSupplyBulletin = bulkCementSupplyBulletinService.getOne(Wrappers.lambdaQuery(BulkCementSupplyBulletin.class) + .eq(BulkCementSupplyBulletin::getReportMonth, reportMonth) + .eq(BulkCementSupplyBulletin::getRegionId, regionId)); + if (Objects.nonNull(bulkCementSupplyBulletin)){ + bulkCementSupplyDataQueryDetailVo.setUnitResponsiblePerson(bulkCementSupplyBulletin.getUnitResponsiblePerson()); + bulkCementSupplyDataQueryDetailVo.setPreparer(bulkCementSupplyBulletin.getPreparer()); + bulkCementSupplyDataQueryDetailVo.setReviewer(bulkCementSupplyBulletin.getReviewer()); + LocalDateTime submissionDate = bulkCementSupplyBulletin.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementSupplyDataQueryDetailVo.setSubmissionDate(submitDate); + } + } + // 否则省审核、市/省查询列表查询,返回登录用户所在市/省关联数据的单位信息 + else { + BulkCementDirectReportSystemDataRelevance dataRelevance1 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance1)) { + bulkCementSupplyDataQueryDetailVo.setUnitResponsiblePerson(dataRelevance1.getUnitResponsiblePerson()); + bulkCementSupplyDataQueryDetailVo.setPreparer(dataRelevance1.getPreparer()); + bulkCementSupplyDataQueryDetailVo.setReviewer(dataRelevance1.getReviewer()); + LocalDateTime submissionDate = dataRelevance1.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementSupplyDataQueryDetailVo.setSubmissionDate(submitDate); + } + } + vo.setBulkCementSupplyDataVo(bulkCementSupplyDataQueryDetailVo); + break; + // 中转库进出量统计数据 + case 2: + ResBulkCementTransferDataQueryDetailVO bulkCementTransferDataQueryDetailVo = new ResBulkCementTransferDataQueryDetailVO(); + getBulkCementTransferDataQueryDetailVo(dataMap, flag,reportMonth,bulkCementTransferDataQueryDetailVo,regionId); + // 返回单位信息 + // 如果是审核列表查询,查询的是具体区县的详情,如果是12月的数据,要返回单位信息 + if (QueryTypeEnum.AUDIT_LIST.getCode().equals(queryType) && + userDetail.getRoleId().equals(UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId()) && reportMonth.getMonthValue() == ReportConstant.TWELVE){ + BulkCementTransferBulletin bulkCementTransferBulletin = bulkCementTransferBulletinService.getOne(Wrappers.lambdaQuery(BulkCementTransferBulletin.class) + .eq(BulkCementTransferBulletin::getReportMonth, reportMonth) + .eq(BulkCementTransferBulletin::getRegionId, regionId)); + if (Objects.nonNull(bulkCementTransferBulletin)){ + bulkCementTransferDataQueryDetailVo.setUnitResponsiblePerson(bulkCementTransferBulletin.getUnitResponsiblePerson()); + bulkCementTransferDataQueryDetailVo.setPreparer(bulkCementTransferBulletin.getPreparer()); + bulkCementTransferDataQueryDetailVo.setReviewer(bulkCementTransferBulletin.getReviewer()); + LocalDateTime submissionDate = bulkCementTransferBulletin.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementTransferDataQueryDetailVo.setSubmissionDate(submitDate); + } + } + // 否则省审核、市/省查询列表查询,返回登录用户所在市/省关联数据的单位信息 + else { + BulkCementDirectReportSystemDataRelevance dataRelevance2 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance2)) { + bulkCementTransferDataQueryDetailVo.setUnitResponsiblePerson(dataRelevance2.getUnitResponsiblePerson()); + bulkCementTransferDataQueryDetailVo.setPreparer(dataRelevance2.getPreparer()); + bulkCementTransferDataQueryDetailVo.setReviewer(dataRelevance2.getReviewer()); + LocalDateTime submissionDate = dataRelevance2.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementTransferDataQueryDetailVo.setSubmissionDate(submitDate); + } + } + vo.setBulkCementTransferDataVo(bulkCementTransferDataQueryDetailVo); + break; + // 温台舟使用量快报数据 + case 3: + ResBulkCementThreeCityUsageDataQueryDetailVO bulkCementThreeCityUsageDataQueryDetailVO = new ResBulkCementThreeCityUsageDataQueryDetailVO(); + getBulkCementThreeCityUsageDataQueryDetailVo(dataMap,reportMonth, bulkCementThreeCityUsageDataQueryDetailVO,regionId); + // 返回单位信息 + // 如果是审核列表查询,查询的是具体区县的详情,如果是12月的数据,要返回单位信息 + if (QueryTypeEnum.AUDIT_LIST.getCode().equals(queryType) && + userDetail.getRoleId().equals(UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId()) && reportMonth.getMonthValue() == ReportConstant.TWELVE){ + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class) + .eq(BulkCementThreeCityUsageBulletin::getReportMonth, reportMonth) + .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId)); + if (Objects.nonNull(bulkCementThreeCityUsageBulletin)){ + bulkCementThreeCityUsageDataQueryDetailVO.setUnitResponsiblePerson(bulkCementThreeCityUsageBulletin.getUnitResponsiblePerson()); + bulkCementThreeCityUsageDataQueryDetailVO.setPreparer(bulkCementThreeCityUsageBulletin.getPreparer()); + bulkCementThreeCityUsageDataQueryDetailVO.setReviewer(bulkCementThreeCityUsageBulletin.getReviewer()); + LocalDateTime submissionDate = bulkCementThreeCityUsageBulletin.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementThreeCityUsageDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + // 否则省审核、市/省查询列表查询,返回登录用户所在市/省关联数据的单位信息 + else { + BulkCementDirectReportSystemDataRelevance dataRelevance3 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance3)) { + bulkCementThreeCityUsageDataQueryDetailVO.setUnitResponsiblePerson(dataRelevance3.getUnitResponsiblePerson()); + bulkCementThreeCityUsageDataQueryDetailVO.setPreparer(dataRelevance3.getPreparer()); + bulkCementThreeCityUsageDataQueryDetailVO.setReviewer(dataRelevance3.getReviewer()); + LocalDateTime submissionDate = dataRelevance3.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementThreeCityUsageDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + vo.setBulkCementThreeCityUsageDataVo(bulkCementThreeCityUsageDataQueryDetailVO); + break; + // 混凝土供应量快报数据 + case 4: + ResConcreteSupplyDataQueryDetailVO concreteSupplyDataQueryDetailVO = new ResConcreteSupplyDataQueryDetailVO(); + getConcreteSupplyDataQueryDetailVo(dataMap, flag, reportMonth, concreteSupplyDataQueryDetailVO, regionId); + // 返回单位信息 + // 如果是审核列表查询,查询的是具体区县的详情,如果是12月的数据,要返回单位信息 + if (QueryTypeEnum.AUDIT_LIST.getCode().equals(queryType) && + userDetail.getRoleId().equals(UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId()) && reportMonth.getMonthValue() == ReportConstant.TWELVE){ + ConcreteSupplyBulletin concreteSupplyBulletin = concreteSupplyBulletinService.getOne(Wrappers.lambdaQuery(ConcreteSupplyBulletin.class) + .eq(ConcreteSupplyBulletin::getReportMonth, reportMonth) + .eq(ConcreteSupplyBulletin::getRegionId, regionId)); + if (Objects.nonNull(concreteSupplyBulletin)){ + concreteSupplyDataQueryDetailVO.setUnitResponsiblePerson(concreteSupplyBulletin.getUnitResponsiblePerson()); + concreteSupplyDataQueryDetailVO.setPreparer(concreteSupplyBulletin.getPreparer()); + concreteSupplyDataQueryDetailVO.setReviewer(concreteSupplyBulletin.getReviewer()); + LocalDateTime submissionDate = concreteSupplyBulletin.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + concreteSupplyDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + // 否则省审核、市/省查询列表查询,返回登录用户所在市/省关联数据的单位信息 + else { + BulkCementDirectReportSystemDataRelevance dataRelevance4 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance4)) { + concreteSupplyDataQueryDetailVO.setUnitResponsiblePerson(dataRelevance4.getUnitResponsiblePerson()); + concreteSupplyDataQueryDetailVO.setPreparer(dataRelevance4.getPreparer()); + concreteSupplyDataQueryDetailVO.setReviewer(dataRelevance4.getReviewer()); + LocalDateTime submissionDate = dataRelevance4.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + concreteSupplyDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + vo.setConcreteSupplyDataVo(concreteSupplyDataQueryDetailVO); + break; + // 砂浆供应量快报数据 + case 5: + ResMortarSupplyDataQueryDetailVO mortarSupplyDataQueryDetailVO = new ResMortarSupplyDataQueryDetailVO(); + getMortarSupplyDataQueryDetailVo(dataMap, flag, reportMonth, mortarSupplyDataQueryDetailVO,regionId); + // 返回单位信息 + // 如果是审核列表查询,查询的是具体区县的详情,如果是12月的数据,要返回单位信息 + if (QueryTypeEnum.AUDIT_LIST.getCode().equals(queryType) && + userDetail.getRoleId().equals(UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId()) && reportMonth.getMonthValue() == ReportConstant.TWELVE){ + MortarSupplyBulletin mortarSupplyBulletin = mortarSupplyBulletinService.getOne(Wrappers.lambdaQuery(MortarSupplyBulletin.class) + .eq(MortarSupplyBulletin::getReportMonth, reportMonth) + .eq(MortarSupplyBulletin::getRegionId, regionId)); + if (Objects.nonNull(mortarSupplyBulletin)){ + mortarSupplyDataQueryDetailVO.setUnitResponsiblePerson(mortarSupplyBulletin.getUnitResponsiblePerson()); + mortarSupplyDataQueryDetailVO.setPreparer(mortarSupplyBulletin.getPreparer()); + mortarSupplyDataQueryDetailVO.setReviewer(mortarSupplyBulletin.getReviewer()); + LocalDateTime submissionDate = mortarSupplyBulletin.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + mortarSupplyDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + // 否则省审核、市/省查询列表查询,返回登录用户所在市/省关联数据的单位信息 + else { + BulkCementDirectReportSystemDataRelevance dataRelevance5 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance5)) { + mortarSupplyDataQueryDetailVO.setUnitResponsiblePerson(dataRelevance5.getUnitResponsiblePerson()); + mortarSupplyDataQueryDetailVO.setPreparer(dataRelevance5.getPreparer()); + mortarSupplyDataQueryDetailVO.setReviewer(dataRelevance5.getReviewer()); + LocalDateTime submissionDate = dataRelevance5.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + mortarSupplyDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + vo.setMortarSupplyDataVo(mortarSupplyDataQueryDetailVO); + break; + // 非禁现区域散装水泥销售使用情况数据 + case 6: + ResNonProhibitedAreasDataQueryDetailVO nonProhibitedAreasDataQueryDetailVO = new ResNonProhibitedAreasDataQueryDetailVO(); + getNonProAreasDataQueryDetailVo(dataMap,reportYear, nonProhibitedAreasDataQueryDetailVO,regionId); + // 返回单位信息 + // 如果是审核列表查询,查询的是具体区县的详情 + if (QueryTypeEnum.AUDIT_LIST.getCode().equals(queryType) && + userDetail.getRoleId().equals(UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId())){ + NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse = nonProhibitedAreasBulkCementSalesUseService.getOne(Wrappers.lambdaQuery(NonProhibitedAreasBulkCementSalesUse.class) + .eq(NonProhibitedAreasBulkCementSalesUse::getReportYear, reportYear) + .eq(NonProhibitedAreasBulkCementSalesUse::getRegionId, regionId)); + if (Objects.nonNull(nonProhibitedAreasBulkCementSalesUse)){ + nonProhibitedAreasDataQueryDetailVO.setUnitResponsiblePerson(nonProhibitedAreasBulkCementSalesUse.getUnitResponsiblePerson()); + nonProhibitedAreasDataQueryDetailVO.setPreparer(nonProhibitedAreasBulkCementSalesUse.getPreparer()); + nonProhibitedAreasDataQueryDetailVO.setReviewer(nonProhibitedAreasBulkCementSalesUse.getReviewer()); + LocalDateTime submissionDate = nonProhibitedAreasBulkCementSalesUse.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + nonProhibitedAreasDataQueryDetailVO.setSubmissionDate(submitDate); + nonProhibitedAreasDataQueryDetailVO.setRemark(nonProhibitedAreasBulkCementSalesUse.getRemark()); + } + } + // 否则省审核、市/省查询列表查询,返回登录用户所在市/省关联数据的单位信息 + else { + BulkCementDirectReportSystemDataRelevance dataRelevance6 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance6)) { + nonProhibitedAreasDataQueryDetailVO.setUnitResponsiblePerson(dataRelevance6.getUnitResponsiblePerson()); + nonProhibitedAreasDataQueryDetailVO.setPreparer(dataRelevance6.getPreparer()); + nonProhibitedAreasDataQueryDetailVO.setReviewer(dataRelevance6.getReviewer()); + LocalDateTime submissionDate = dataRelevance6.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + nonProhibitedAreasDataQueryDetailVO.setSubmissionDate(submitDate); + } + } + vo.setNonProAreasDataVo(nonProhibitedAreasDataQueryDetailVO); + break; + // 散装水泥物流设施统计年报表数据 + case 7: + ResBulkCementLogFacStaDataQueryVO bulkCementLogFacStaDataQueryVo = new ResBulkCementLogFacStaDataQueryVO(); + Map resMap1 = MapUtil.newHashMap(); + // map中是三种设备名称对应的数据集合 + for (Map.Entry entry : dataMap.entrySet()) { + Map map = (Map) entry.getValue(); + String key = entry.getKey(); + ResBulkCementLogFacStaDataQueryDetailVO bulkCementLogFacStaDataQueryDetailVO = new ResBulkCementLogFacStaDataQueryDetailVO(); + getBulkCementLogFacStaDataQueryDetailVo(key, map,reportYear, bulkCementLogFacStaDataQueryDetailVO,regionId); + resMap1.put(key,bulkCementLogFacStaDataQueryDetailVO); + } + bulkCementLogFacStaDataQueryVo.setBulkCementLogFacStaDataMap(resMap1); + // 返回单位信息 + BulkCementDirectReportSystemDataRelevance dataRelevance7 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance7)) { + bulkCementLogFacStaDataQueryVo.setUnitResponsiblePerson(dataRelevance7.getUnitResponsiblePerson()); + bulkCementLogFacStaDataQueryVo.setPreparer(dataRelevance7.getPreparer()); + bulkCementLogFacStaDataQueryVo.setReviewer(dataRelevance7.getReviewer()); + LocalDateTime submissionDate = dataRelevance7.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + bulkCementLogFacStaDataQueryVo.setSubmissionDate(submitDate); + } + vo.setBulkCementLogFacStaDataVo(bulkCementLogFacStaDataQueryVo); + break; + // 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据 + case 8: + ResMaterialLogEquipStaDataQueryVO materialLogEquipStaDataQueryVo = new ResMaterialLogEquipStaDataQueryVO(); + Map resMap2 = MapUtil.newHashMap(); + // map中是八种设备名称对应的数据集合 + for (Map.Entry entry : dataMap.entrySet()) { + Map map = (Map) entry.getValue(); + String key = entry.getKey(); + ResMaterialLogEquipStaDataQueryDetailVO materialLogEquipStaDataQueryDetailVO = new ResMaterialLogEquipStaDataQueryDetailVO(); + getMaterialLogEquipStaDataQueryDetailVo(key, map,reportYear, materialLogEquipStaDataQueryDetailVO,regionId); + resMap2.put(key,materialLogEquipStaDataQueryDetailVO); + } + // 返回单位信息 + BulkCementDirectReportSystemDataRelevance dataRelevance8 = + dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, + UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId)); + if (Objects.nonNull(dataRelevance8)) { + materialLogEquipStaDataQueryVo.setUnitResponsiblePerson(dataRelevance8.getUnitResponsiblePerson()); + materialLogEquipStaDataQueryVo.setPreparer(dataRelevance8.getPreparer()); + materialLogEquipStaDataQueryVo.setReviewer(dataRelevance8.getReviewer()); + LocalDateTime submissionDate = dataRelevance8.getSubmissionDate(); + String submissionDateStr = NdDateUtils.format(submissionDate, DatePattern.CHINESE_DATE_PATTERN); + LocalDateTime submitDate = LocalDateTimeUtil.parse(submissionDateStr, + DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)); + materialLogEquipStaDataQueryVo.setSubmissionDate(submitDate); + } + materialLogEquipStaDataQueryVo.setMaterialLogEquipStaDataMap(resMap2); + vo.setMaterialLogEquipStaDataVo(materialLogEquipStaDataQueryVo); + break; + default: + throw new IllegalStateException("Unexpected value: " + auditDataType); + } + } + + private void getBulkCementSupplyDataQueryDetailVo(Map dataMap, Boolean flag, LocalDateTime reportMonth, ResBulkCementSupplyDataQueryDetailVO bulkCementSupplyDataQueryDetailVo, Long regionId) { + // 统计各字段合计值 + // 合计散装水泥总量 + List bulkCementAmountTotalList = Lists.newArrayList(); + // 合计水泥产量 + List cementOutputTotalList = Lists.newArrayList(); + // 合计完成量 + List completedAmountTotalList = Lists.newArrayList(); + // 合计水泥产量 + List cumulativeCementProductionTotalList = Lists.newArrayList(); + // 合计增加量 + List incrementTotalList = Lists.newArrayList(); + // 去年这个月的合计完成量 + List preYearCompletedAmountTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 散装水泥总量 + List data1List = totalDataList.stream().map(ResBulkCementSupplyDataUploadDetailVO::getBulkCementAmountTotal).collect(Collectors.toList()); + bulkCementAmountTotalList.addAll(data1List); + // 水泥产量 + List data2List = totalDataList.stream().map(ResBulkCementSupplyDataUploadDetailVO::getCementOutputTotal).collect(Collectors.toList()); + cementOutputTotalList.addAll(data2List); + // 完成量 + List data3List = totalDataList.stream().map(ResBulkCementSupplyDataUploadDetailVO::getCompletedTotalAmountTotal).collect(Collectors.toList()); + completedAmountTotalList.addAll(data3List); + // 水泥产量 + List data4List = totalDataList.stream().map(ResBulkCementSupplyDataUploadDetailVO::getCumulativeCementProductionTotal).collect(Collectors.toList()); + cumulativeCementProductionTotalList.addAll(data4List); + // 增加量 + List data5List = totalDataList.stream().map(ResBulkCementSupplyDataUploadDetailVO::getIncrementTotal).collect(Collectors.toList()); + incrementTotalList.addAll(data5List); + // 去年这个月的合计完成量 + List data6List = totalDataList.stream().map(v -> { + BigDecimal increaseRate = v.getIncreaseRateTotal(); + BigDecimal increment = v.getIncrementTotal(); + if (Objects.nonNull(increaseRate) && Objects.nonNull(increment)) { + if (BigDecimal.ZERO.compareTo(increaseRate) != 0) { + return increment.divide(increaseRate, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + } + } + return BigDecimal.ZERO; + }).collect(Collectors.toList()); + preYearCompletedAmountTotalList.addAll(data6List); + } + List totalValues = Lists.newArrayList(); + ResBulkCementSupplyDataUploadDetailVO totalVo = new ResBulkCementSupplyDataUploadDetailVO(); + // 合计散装水泥总量 + BigDecimal bulkCementAmountTotal = bulkCementAmountTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setBulkCementAmount(bulkCementAmountTotal); + // 合计水泥产量 + BigDecimal cementOutputTotal = cementOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCementOutput(cementOutputTotal); + // 合计完成量 + BigDecimal completedAmountTotal = completedAmountTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCompletedTotalAmount(completedAmountTotal); + // 合计水泥产量 + BigDecimal cumulativeCementProductionTotal = cumulativeCementProductionTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCumulativeCementProduction(cumulativeCementProductionTotal); + // 合计增加量 + BigDecimal incrementTotal = incrementTotalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setIncrement(incrementTotal); + // 合计散装率: 合计完成量 / 合计水泥产量 * 100 + BigDecimal bulkRateTotal; + if (BigDecimal.ZERO.compareTo(cumulativeCementProductionTotal) != 0) { + bulkRateTotal = completedAmountTotal.divide(cumulativeCementProductionTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + bulkRateTotal = BigDecimal.ZERO; + } + totalVo.setBulkRate(bulkRateTotal); + // 合计增长率:合计增长量 / 去年这个月的合计完成量 * 100 + BigDecimal increaseRateTotal; + BigDecimal preYearCompletedAmountTotal = preYearCompletedAmountTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + if (BigDecimal.ZERO.compareTo(preYearCompletedAmountTotal) != 0) { + increaseRateTotal = incrementTotal.divide(preYearCompletedAmountTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + increaseRateTotal = incrementTotal.multiply(BigDecimal.valueOf(100L)); + } + totalVo.setIncreaseRate(increaseRateTotal); + // 合计散装率目标 + // 如果是省散办查询详情 + if (Boolean.TRUE.equals(flag)) { + int year = reportMonth.getYear(); + BulkCementDirectReportSystemUniversalIndex universalIndex = universalIndexService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemUniversalIndex.class) + .eq(BulkCementDirectReportSystemUniversalIndex::getYear, year) + .eq(BulkCementDirectReportSystemUniversalIndex::getRegionId, DefValConstants.ZJREGION_ID)); + if (Objects.nonNull(universalIndex)){ + totalVo.setBulkRateTarget(universalIndex.getBulkRateTarget()); + } + } + totalVo.setUnitName(ReportConstant.TOTAL); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + bulkCementSupplyDataQueryDetailVo.setBulkCementSupplyDataMap(dataMap); + } + + private void getBulkCementTransferDataQueryDetailVo(Map dataMap, Boolean flag, LocalDateTime reportMonth, ResBulkCementTransferDataQueryDetailVO bulkCementTransferDataQueryDetailVo, Long regionId) { + // 统计各字段合计值 + // 合计上月末库存 + List lastMonthEndInventoryTotalList = Lists.newArrayList(); + // 合计本月进库量 + List thisMonthIncomingStorageTotalList = Lists.newArrayList(); + // 合计累计进库量 + List cumulativeIncomingStorageTotalList = Lists.newArrayList(); + // 合计本月出库量 + List thisMonthOutgoingStorageTotalList = Lists.newArrayList(); + // 合计累计出库量 + List cumulativeOutgoingStorageTotalList = Lists.newArrayList(); + // 合计月末库存量 + List monthEndInventoryTotalList = Lists.newArrayList(); + + // 去年这个月的合计库存量 + List preYearMonthEndInventoryTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 上月末库存 + List data1List = totalDataList.stream().map(ResBulkCementTransferDataUploadDetailVO::getLastMonthEndInventoryTotal).collect(Collectors.toList()); + lastMonthEndInventoryTotalList.addAll(data1List); + // 本月进库量 + List data2List = totalDataList.stream().map(ResBulkCementTransferDataUploadDetailVO::getThisMonthIncomingStorageTotal).collect(Collectors.toList()); + thisMonthIncomingStorageTotalList.addAll(data2List); + // 累计进库量 + List data3List = totalDataList.stream().map(ResBulkCementTransferDataUploadDetailVO::getCumulativeIncomingStorageTotal).collect(Collectors.toList()); + cumulativeIncomingStorageTotalList.addAll(data3List); + // 本月出库量 + List data4List = totalDataList.stream().map(ResBulkCementTransferDataUploadDetailVO::getThisMonthOutgoingStorageTotal).collect(Collectors.toList()); + thisMonthOutgoingStorageTotalList.addAll(data4List); + // 累计出库量 + List data5List = totalDataList.stream().map(ResBulkCementTransferDataUploadDetailVO::getCumulativeOutgoingStorageTotal).collect(Collectors.toList()); + cumulativeOutgoingStorageTotalList.addAll(data5List); + // 月末库存量 + List data6List = totalDataList.stream().map(ResBulkCementTransferDataUploadDetailVO::getMonthEndInventoryTotal).collect(Collectors.toList()); + monthEndInventoryTotalList.addAll(data6List); + + // 去年这个月的合计月末库存量 + List data7List = totalDataList.stream().map(v -> { + BigDecimal monthEndInventory = v.getMonthEndInventoryTotal(); + BigDecimal monthEndInventoryGrowthRate = v.getMonthEndInventoryGrowthRateTotal(); + return monthEndInventory.divide(monthEndInventoryGrowthRate.add(BigDecimal.valueOf(100L)),RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + }).collect(Collectors.toList()); + preYearMonthEndInventoryTotalList.addAll(data7List); + } + List totalValues = Lists.newArrayList(); + ResBulkCementTransferDataUploadDetailVO totalVo = new ResBulkCementTransferDataUploadDetailVO(); + // 合计上月末库存 + BigDecimal lastMonthEndInventoryTotal = lastMonthEndInventoryTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setLastMonthEndInventory(lastMonthEndInventoryTotal); + // 合计本月进库量 + BigDecimal thisMonthIncomingStorageTotal = thisMonthIncomingStorageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthIncomingStorage(thisMonthIncomingStorageTotal); + // 合计累计进库量 + BigDecimal cumulativeIncomingStorageTotal = cumulativeIncomingStorageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCumulativeIncomingStorage(cumulativeIncomingStorageTotal); + // 合计本月出库量 + BigDecimal thisMonthOutgoingStorageTotal = thisMonthOutgoingStorageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthOutgoingStorage(thisMonthOutgoingStorageTotal); + // 合计累计出库量 + BigDecimal cumulativeOutgoingStorageTotal = cumulativeOutgoingStorageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCumulativeOutgoingStorage(cumulativeOutgoingStorageTotal); + // 合计月末库存量 + BigDecimal monthEndInventoryTotal = monthEndInventoryTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setMonthEndInventory( monthEndInventoryTotal); + // 合计月末库存同比增长率: (合计月末库存量 - 去年合计月末库存量) / 去年合计月末库存量 * 100 + BigDecimal monthEndInventoryGrowthRateTotal; + BigDecimal preYearMonthEndInventoryTotal = preYearMonthEndInventoryTotalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + if (BigDecimal.ZERO.compareTo(preYearMonthEndInventoryTotal) != 0) { + monthEndInventoryGrowthRateTotal = (monthEndInventoryTotal.subtract(preYearMonthEndInventoryTotal)).divide(preYearMonthEndInventoryTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + monthEndInventoryGrowthRateTotal = monthEndInventoryTotal.multiply(BigDecimal.valueOf(100L)); + } + totalVo.setMonthEndInventoryGrowthRate(monthEndInventoryGrowthRateTotal); + totalValues.add(totalVo); + totalVo.setUnitName(ReportConstant.TOTAL); + dataMap.put(ReportConstant.TOTAL,totalValues); + bulkCementTransferDataQueryDetailVo.setBulkCementTransferDataMap(dataMap); + } + + private void getBulkCementThreeCityUsageDataQueryDetailVo(Map dataMap, LocalDateTime reportMonth, ResBulkCementThreeCityUsageDataQueryDetailVO bulkCementThreeCityUsageDataQueryDetailVO, Long regionId) { + + // 统计各字段合计值 + // 合计年目标 + List yearTargetTotalList = Lists.newArrayList(); + // 合计本月使用量 + List thisMonthUsageTotalList = Lists.newArrayList(); + // 合计累计使用量 + List accumulativeUsageTotalList = Lists.newArrayList(); + // 合计本省本月使用量 + List thisProvinceThisMonthUsageTotalList = Lists.newArrayList(); + // 合计本省累计使用量 + List thisProvinceAccumulativeUsageTotalList = Lists.newArrayList(); + // 合计外省本月使用量 + List otherProvinceThisMonthUsageTotalList = Lists.newArrayList(); + // 合计外省累计使用量 + List otherProvinceAccumulativeUsageTotalList = Lists.newArrayList(); + + // 合计去年这个月的累计使用量 + List preYearAccumulativeUsageTotalList = Lists.newArrayList(); + // 合计上个月的累计使用量 + List preAccumulativeUsageTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 年目标 + List data1List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getYearTargetTotal).collect(Collectors.toList()); + yearTargetTotalList.addAll(data1List); + // 本月使用量 + List data2List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getThisMonthUsageTotal).collect(Collectors.toList()); + thisMonthUsageTotalList.addAll(data2List); + // 累计使用量 + List data3List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getAccumulativeUsageTotal).collect(Collectors.toList()); + accumulativeUsageTotalList.addAll(data3List); + // 本省本月使用量 + List data4List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getThisProvinceThisMonthUsageTotal).collect(Collectors.toList()); + thisProvinceThisMonthUsageTotalList.addAll(data4List); + // 本省累计使用量 + List data5List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getThisProvinceAccumulativeUsageTotal).collect(Collectors.toList()); + thisProvinceAccumulativeUsageTotalList.addAll(data5List); + // 外省本月使用量 + List data6List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getOtherProvinceThisMonthUsageTotal).collect(Collectors.toList()); + otherProvinceThisMonthUsageTotalList.addAll(data6List); + // 外省累计使用量 + List data7List = totalDataList.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getOtherProvinceThisMonthUsageTotal).collect(Collectors.toList()); + otherProvinceAccumulativeUsageTotalList.addAll(data7List); + + // 去年这个月的累计使用量 + List data8List = totalDataList.stream().map(v -> { + BigDecimal accumulativeUsageTotal = v.getAccumulativeUsageTotal(); + BigDecimal growthRateTotal = v.getGrowthRateTotal(); + if (Objects.nonNull(accumulativeUsageTotal) && Objects.nonNull(growthRateTotal)){ + if (BigDecimal.ZERO.compareTo(growthRateTotal) != 0) { + return accumulativeUsageTotal.divide(growthRateTotal.add(BigDecimal.valueOf(100L)), RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + } + } + return BigDecimal.ZERO; + }).collect(Collectors.toList()); + preYearAccumulativeUsageTotalList.addAll(data8List); + + // 上个月的累计使用量 + List data9List = totalDataList.stream().map(v -> { + BigDecimal thisMonthUsageTotal = v.getThisMonthUsageTotal(); + BigDecimal thisMonthUsage = v.getThisMonthUsage(); + if (Objects.nonNull(thisMonthUsage)) { + return thisMonthUsageTotal.subtract(thisMonthUsage); + }else { + return thisMonthUsageTotal; + } + }).collect(Collectors.toList()); + preAccumulativeUsageTotalList.addAll(data9List); + } + + List totalValues = Lists.newArrayList(); + ResBulkCementThreeCityUsageDataUploadDetailVO totalVo = new ResBulkCementThreeCityUsageDataUploadDetailVO(); + + // 合计年目标 + BigDecimal yearTargetTotal = yearTargetTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setYearTarget(yearTargetTotal); + // 合计累计使用量 + BigDecimal accumulativeUsageTotal = accumulativeUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setAccumulativeUsage(accumulativeUsageTotal); + // 合计占全年目标百分比:合计累计使用量 / 合计年目标 * 100 + BigDecimal percentageOfAnnualTargetTotal = BigDecimal.ZERO; + + if (BigDecimal.ZERO.compareTo(yearTargetTotal) != 0) { + percentageOfAnnualTargetTotal = accumulativeUsageTotal.divide(yearTargetTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + } + totalVo.setPercentageOfAnnualTarget(percentageOfAnnualTargetTotal); + + // 合计同比增长率: (合计累计使用量 - 去年合计累计使用量) / 去年合计累计使用量 * 100 + BigDecimal growthRateTotal; + BigDecimal preYearAccumulativeUsageTotal = preYearAccumulativeUsageTotalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + if (BigDecimal.ZERO.compareTo(preYearAccumulativeUsageTotal) != 0) { + growthRateTotal = (accumulativeUsageTotal.subtract(preYearAccumulativeUsageTotal)).divide(preYearAccumulativeUsageTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + growthRateTotal = accumulativeUsageTotal.multiply(BigDecimal.valueOf(100L)); + } + totalVo.setGrowthRate(growthRateTotal); + + // 合计本月使用量 + BigDecimal thisMonthUsageTotal = thisMonthUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthUsage(thisMonthUsageTotal); + // 合计本省本月使用量 + BigDecimal thisProvinceThisMonthUsageTotal = thisProvinceThisMonthUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisProvinceThisMonthUsage(thisProvinceThisMonthUsageTotal); + // 合计本省累计使用量 + BigDecimal thisProvinceAccumulativeUsageTotal = thisProvinceAccumulativeUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisProvinceAccumulativeUsage(thisProvinceAccumulativeUsageTotal); + // 合计外省本月使用量 + BigDecimal otherProvinceThisMonthUsageTotal = otherProvinceThisMonthUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setOtherProvinceThisMonthUsage(otherProvinceThisMonthUsageTotal); + // 合计外省累计使用量 + BigDecimal otherProvinceAccumulativeUsageTotal = otherProvinceAccumulativeUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setOtherProvinceAccumulativeUsage(otherProvinceAccumulativeUsageTotal); + totalVo.setUnitName(ReportConstant.TOTAL); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + bulkCementThreeCityUsageDataQueryDetailVO.setBulkCementThreeCityUsageDataMap(dataMap); + } + + private void getConcreteSupplyDataQueryDetailVo(Map dataMap, Boolean flag, LocalDateTime reportMonth, ResConcreteSupplyDataQueryDetailVO concreteSupplyDataQueryDetailVo, Long regionId) { + + // 统计各字段合计值 + // 合计三类指导目标 + List threeCategoryGuidGoalTotalList = Lists.newArrayList(); + // 合计生产企业数量 + List productionCompanyNumsTotalList = Lists.newArrayList(); + // 合计年设计生产能力 + List annualDesignProductionCapacityTotalList = Lists.newArrayList(); + // 合计本月实际产量 + List thisMonthOutputTotalList = Lists.newArrayList(); + // 合计累计实际产量 + List accumulativeOutputTotalList = Lists.newArrayList(); + // 合计本月使用散装水泥量 + List thisMonthCementUsageTotalList = Lists.newArrayList(); + // 合计累计使用散装水泥量 + List cementAccumulativeUsageTotalList = Lists.newArrayList(); + // 合计本月废弃物综合利用量 + List thisMonthWasteUtilizationTotalList = Lists.newArrayList(); + // 合计累计废弃物综合利用量 + List accumulativeWasteUtilizationTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 三类指导目标 + List data1List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getThreeCategoryGuidGoalTotal).collect(Collectors.toList()); + threeCategoryGuidGoalTotalList.addAll(data1List); + // 生产企业数量 + List data2List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getProductionCompanyNumsTotal).collect(Collectors.toList()); + productionCompanyNumsTotalList.addAll(data2List); + // 年设计生产能力 + List data3List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getAnnualDesignProductionCapacityTotal).collect(Collectors.toList()); + annualDesignProductionCapacityTotalList.addAll(data3List); + // 本月实际产量 + List data4List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getThisMonthOutputTotal).collect(Collectors.toList()); + thisMonthOutputTotalList.addAll(data4List); + // 累计实际产量 + List data5List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getAccumulativeOutputTotal).collect(Collectors.toList()); + accumulativeOutputTotalList.addAll(data5List); + + // 本月使用散装水泥量 + List data6List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getThisMonthCementUsageTotal).collect(Collectors.toList()); + thisMonthCementUsageTotalList.addAll(data6List); + // 累计使用散装水泥量 + List data7List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getCementAccumulativeUsageTotal).collect(Collectors.toList()); + cementAccumulativeUsageTotalList.addAll(data7List); + // 本月废弃物综合利用量 + List data8List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getThisMonthWasteUtilizationTotal).collect(Collectors.toList()); + thisMonthWasteUtilizationTotalList.addAll(data8List); + // 累计废弃物综合利用量 + List data9List = totalDataList.stream().map(ResConcreteSupplyDataUploadDetailVO::getAccumulativeWasteUtilizationTotal).collect(Collectors.toList()); + accumulativeWasteUtilizationTotalList.addAll(data9List); + + } + List totalValues = Lists.newArrayList(); + ResConcreteSupplyDataUploadDetailVO totalVo = new ResConcreteSupplyDataUploadDetailVO(); + + // 合计三类指导目标 + BigDecimal threeCategoryGuidGoalTotal = threeCategoryGuidGoalTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThreeCategoryGuidGoal(threeCategoryGuidGoalTotal); + // 合计生产企业数量 + int productionCompanyNumsTotal = productionCompanyNumsTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setProductionCompanyNums(productionCompanyNumsTotal); + // 合计年设计生产能力 + BigDecimal annualDesignProductionCapacityTotal = annualDesignProductionCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setAnnualDesignProductionCapacity(annualDesignProductionCapacityTotal); + // 合计本月实际产量 + BigDecimal thisMonthOutputTotal = thisMonthOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthOutput(thisMonthOutputTotal); + // 合计累计实际产量 + BigDecimal accumulativeOutputTotal = accumulativeOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setAccumulativeOutput(accumulativeOutputTotal); + + // 合计本月使用散装水泥量 + BigDecimal thisMonthCementUsageTotal = thisMonthCementUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthCementUsage(thisMonthCementUsageTotal); + // 合计累计使用散装水泥量 + BigDecimal cementAccumulativeUsageTotal = cementAccumulativeUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCementAccumulativeUsage(cementAccumulativeUsageTotal); + // 合计本月废弃物综合利用量 + BigDecimal thisMonthWasteUtilizationTotal = thisMonthWasteUtilizationTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthWasteUtilization(thisMonthWasteUtilizationTotal); + // 合计累计废弃物综合利用量 + BigDecimal accumulativeWasteUtilizationTotal = accumulativeWasteUtilizationTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setAccumulativeWasteUtilization(accumulativeWasteUtilizationTotal); + totalVo.setUnitName(ReportConstant.TOTAL); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + concreteSupplyDataQueryDetailVo.setConcreteSupplyDataMap(dataMap); + } + private void getMortarSupplyDataQueryDetailVo(Map dataMap, Boolean flag, LocalDateTime reportMonth, ResMortarSupplyDataQueryDetailVO mortarSupplyDataQueryDetailVo, Long regionId) { + + // 统计各字段合计值 + // 合计二类指导目标 + List twoCategoryGuidGoalTotalList = Lists.newArrayList(); + // 合计普通干混砂浆生产企业数量 + List dryMixedMortarProductionCompanyNumTotalList = Lists.newArrayList(); + // 合计普通干混砂浆生产总能力 + List dryMixedMortarProductiveCapacityTotalList = Lists.newArrayList(); + // 合计普通干混砂浆散装能力 + List dryMixedMortarBulkCapacityTotalList = Lists.newArrayList(); + // 合计本月总产量 + List thisMonthTotalOutputTotalList = Lists.newArrayList(); + // 合计本月累计总产量 + List thisMonthAccumulativeOutputTotalList = Lists.newArrayList(); + // 合计普通干混砂浆本月产量 + List dryMixedMortarThisMonthOutputTotalList = Lists.newArrayList(); + // 合计普通干混砂浆累计产量 + List dryMixedMortarThisMonthAccumulativeOutputTotalList = Lists.newArrayList(); + // 合计普通干混砂浆同比增长量 + List dryMixedMortarIncrementTotalList = Lists.newArrayList(); + + // 合计去年这个月普通干混砂浆累计产量 + List preYearDryMixedMortarThisMonthAccumulativeOutputTotalList = Lists.newArrayList(); + + // 合计普通干混砂浆本月散装量 + List dryMixedMortarThisMonthBulkQuantityTotalList = Lists.newArrayList(); + // 合计普通干混砂浆累计散装量 + List dryMixedMortarAccumulativeBulkQuantityTotalList = Lists.newArrayList(); + // 合计湿拌砂浆本月产量 + List wetMortarThisMonthOutputTotalList = Lists.newArrayList(); + // 合计湿拌砂浆累计产量 + List wetMortarAccumulativeOutputTotalList = Lists.newArrayList(); + // 合计散装水泥本月使用量 + List bulkCementThisMonthUsageTotalList = Lists.newArrayList(); + // 合计散装水泥累计使用量 + List bulkCementAccumulativeUsageTotalList = Lists.newArrayList(); + // 合计废弃物本月综合利用量 + List wasteThisMonthComprehensiveUtilizationTotalList = Lists.newArrayList(); + // 合计废弃物累计综合利用量 + List wasteAccumulativeComprehensiveUtilizationTotalList = Lists.newArrayList(); + + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 二类指导目标 + List data1List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getTwoCategoryGuidGoalTotal).collect(Collectors.toList()); + twoCategoryGuidGoalTotalList.addAll(data1List); + // 普通干混砂浆生产企业数量 + List data2List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarProductionCompanyNumTotal).collect(Collectors.toList()); + dryMixedMortarProductionCompanyNumTotalList.addAll(data2List); + // 普通干混砂浆生产总能力 + List data3List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarProductiveCapacityTotal).collect(Collectors.toList()); + dryMixedMortarProductiveCapacityTotalList.addAll(data3List); + // 普通干混砂浆散装能力 + List data4List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarBulkCapacityTotal).collect(Collectors.toList()); + dryMixedMortarBulkCapacityTotalList.addAll(data4List); + // 本月总产量 + List data5List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getThisMonthTotalOutputTotal).collect(Collectors.toList()); + thisMonthTotalOutputTotalList.addAll(data5List); + + // 本月累计总产量 + List data6List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getThisMonthAccumulativeOutputTotal).collect(Collectors.toList()); + thisMonthAccumulativeOutputTotalList.addAll(data6List); + // 普通干混砂浆本月产量 + List data7List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarThisMonthOutputTotal).collect(Collectors.toList()); + dryMixedMortarThisMonthOutputTotalList.addAll(data7List); + // 普通干混砂浆累计产量 + List data8List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarThisMonthAccumulativeOutputTotal).collect(Collectors.toList()); + dryMixedMortarThisMonthAccumulativeOutputTotalList.addAll(data8List); + // 普通干混砂浆同比增长量 + List data9List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarIncrementTotal).collect(Collectors.toList()); + dryMixedMortarIncrementTotalList.addAll(data9List); + // 去年这个月普通干混砂浆累计产量 + List data10List = totalDataList.stream().map(r -> { + BigDecimal dryMixedMortarIncrementTotal = r.getDryMixedMortarIncrementTotal(); + BigDecimal dryMixedMortarGrowthRateTotal = r.getDryMixedMortarGrowthRateTotal(); + if (Objects.nonNull(dryMixedMortarIncrementTotal) && Objects.nonNull(dryMixedMortarGrowthRateTotal)){ + if (BigDecimal.ZERO.compareTo(dryMixedMortarGrowthRateTotal) != 0){ + return dryMixedMortarIncrementTotal.divide(dryMixedMortarGrowthRateTotal,RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + } + } + return BigDecimal.ZERO; + }).collect(Collectors.toList()); + preYearDryMixedMortarThisMonthAccumulativeOutputTotalList.addAll(data10List); + // 普通干混砂浆本月散装量 + List data11List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarThisMonthBulkQuantityTotal).collect(Collectors.toList()); + dryMixedMortarThisMonthBulkQuantityTotalList.addAll(data11List); + // 普通干混砂浆累计散装量 + List data12List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarAccumulativeBulkQuantityTotal).collect(Collectors.toList()); + dryMixedMortarAccumulativeBulkQuantityTotalList.addAll(data12List); + // 湿拌砂浆本月产量 + List data13List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getWetMortarThisMonthOutputTotal).collect(Collectors.toList()); + wetMortarThisMonthOutputTotalList.addAll(data13List); + // 湿拌砂浆累计产量 + List data14List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getWetMortarAccumulativeOutputTotal).collect(Collectors.toList()); + wetMortarAccumulativeOutputTotalList.addAll(data14List); + // 散装水泥本月使用量 + List data15List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getBulkCementThisMonthUsageTotal).collect(Collectors.toList()); + bulkCementThisMonthUsageTotalList.addAll(data15List); + // 散装水泥累计使用量 + List data16List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getBulkCementAccumulativeUsageTotal).collect(Collectors.toList()); + bulkCementAccumulativeUsageTotalList.addAll(data16List); + // 废弃物本月综合利用量 + List data17List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getWasteThisMonthComprehensiveUtilizationTotal).collect(Collectors.toList()); + wasteThisMonthComprehensiveUtilizationTotalList.addAll(data17List); + // 废弃物累计综合利用量 + List data18List = totalDataList.stream().map(ResMortarSupplyDataUploadDetailVO::getWasteAccumulativeComprehensiveUtilizationTotal).collect(Collectors.toList()); + wasteAccumulativeComprehensiveUtilizationTotalList.addAll(data18List); + } + + List totalValues = Lists.newArrayList(); + ResMortarSupplyDataUploadDetailVO totalVo = new ResMortarSupplyDataUploadDetailVO(); + + // 合计二类指导目标 + BigDecimal twoCategoryGuidGoalTotal = twoCategoryGuidGoalTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setTwoCategoryGuidGoal(twoCategoryGuidGoalTotal); + // 合计普通干混砂浆生产企业数量 + int dryMixedMortarProductionCompanyNumTotal = dryMixedMortarProductionCompanyNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setDryMixedMortarProductionCompanyNum(dryMixedMortarProductionCompanyNumTotal); + // 合计普通干混砂浆生产总能力 + BigDecimal dryMixedMortarProductiveCapacityTotal = dryMixedMortarProductiveCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarProductiveCapacity(dryMixedMortarProductiveCapacityTotal); + // 合计普通干混砂浆散装能力 + BigDecimal dryMixedMortarBulkCapacityTotal = dryMixedMortarBulkCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarBulkCapacity(dryMixedMortarBulkCapacityTotal); + // 合计本月总产量 + BigDecimal thisMonthTotalOutputTotal = thisMonthTotalOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthTotalOutput(thisMonthTotalOutputTotal); + // 合计本月累计总产量 + BigDecimal thisMonthAccumulativeOutputTotal = thisMonthAccumulativeOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisMonthAccumulativeOutput(thisMonthAccumulativeOutputTotal); + // 合计普通干混砂浆本月产量 + BigDecimal dryMixedMortarThisMonthOutputTotal = dryMixedMortarThisMonthOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarThisMonthOutput(dryMixedMortarThisMonthOutputTotal); + // 合计普通干混砂浆累计产量 + BigDecimal dryMixedMortarThisMonthAccumulativeOutputTotal = dryMixedMortarThisMonthAccumulativeOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarThisMonthAccumulativeOutput(dryMixedMortarThisMonthAccumulativeOutputTotal); + // 合计普通干混砂浆同比增长量 + BigDecimal dryMixedMortarIncrementTotal = dryMixedMortarIncrementTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarIncrement(dryMixedMortarIncrementTotal); + // 合计增长率 + BigDecimal preYearDryMixedMortarThisMonthAccumulativeOutputTotal = preYearDryMixedMortarThisMonthAccumulativeOutputTotalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + BigDecimal dryMixedMortarGrowthRateTotal; + if (BigDecimal.ZERO.compareTo(preYearDryMixedMortarThisMonthAccumulativeOutputTotal) != 0){ + dryMixedMortarGrowthRateTotal = dryMixedMortarIncrementTotal.divide(preYearDryMixedMortarThisMonthAccumulativeOutputTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + }else { + dryMixedMortarGrowthRateTotal = dryMixedMortarIncrementTotal.multiply(BigDecimal.valueOf(100L)); + } + totalVo.setDryMixedMortarGrowthRate(dryMixedMortarGrowthRateTotal); + + // 合计普通干混砂浆本月散装量 + BigDecimal dryMixedMortarThisMonthBulkQuantityTotal = dryMixedMortarThisMonthBulkQuantityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarThisMonthBulkQuantity(dryMixedMortarThisMonthBulkQuantityTotal); + // 合计普通干混砂浆累计散装量 + BigDecimal dryMixedMortarAccumulativeBulkQuantityTotal = dryMixedMortarAccumulativeBulkQuantityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setDryMixedMortarAccumulativeBulkQuantity(dryMixedMortarAccumulativeBulkQuantityTotal); + // 合计湿拌砂浆本月产量 + BigDecimal wetMortarThisMonthOutputTotal = wetMortarThisMonthOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setWetMortarThisMonthOutput(wetMortarThisMonthOutputTotal); + // 合计湿拌砂浆累计产量 + BigDecimal wetMortarAccumulativeOutputTotal = wetMortarAccumulativeOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setWetMortarAccumulativeOutput(wetMortarAccumulativeOutputTotal); + // 合计散装水泥本月使用量 + BigDecimal bulkCementThisMonthUsageTotal = bulkCementThisMonthUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setBulkCementThisMonthUsage(bulkCementThisMonthUsageTotal); + // 合计散装水泥累计使用量 + BigDecimal bulkCementAccumulativeUsageTotal = bulkCementAccumulativeUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setBulkCementAccumulativeUsage(bulkCementAccumulativeUsageTotal); + // 合计废弃物本月综合利用量 + BigDecimal wasteThisMonthComprehensiveUtilizationTotal = wasteThisMonthComprehensiveUtilizationTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setWasteThisMonthComprehensiveUtilization(wasteThisMonthComprehensiveUtilizationTotal); + // 合计废弃物累计综合利用量 + BigDecimal wasteAccumulativeComprehensiveUtilizationTotal = wasteAccumulativeComprehensiveUtilizationTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setWasteAccumulativeComprehensiveUtilization(wasteAccumulativeComprehensiveUtilizationTotal); + totalVo.setRegionName(ReportConstant.TOTAL); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + mortarSupplyDataQueryDetailVo.setMortarSupplyDataMap(dataMap); + } + private void getNonProAreasDataQueryDetailVo(Map dataMap, Integer reportYear, ResNonProhibitedAreasDataQueryDetailVO nonProhibitedAreasDataQueryDetailVO, Long regionId) { + + // 统计各字段合计值 + // 合计销售点总数 + List salePointAccumulativeNumTotalList = Lists.newArrayList(); + // 合计水泥企业建点数量 + List cementCompanyBuildPointNumTotalList = Lists.newArrayList(); + // 合计其他投资建点数量 + List otherInvestmentBuildPointNumTotalList = Lists.newArrayList(); + // 合计销售量 + List saleVolumeTotalList = Lists.newArrayList(); + // 合计散装水泥罐数量 + List bulkCementTankNumTotalList = Lists.newArrayList(); + + // 合计散装水泥罐容量 + List bulkCementTankCapacityTotalList = Lists.newArrayList(); + // 合计水泥使用量 + List cementUsageTotalList = Lists.newArrayList(); + // 合计散装水泥使用量 + List bulkCementUsageTotalList = Lists.newArrayList(); + // 合计生产预拌混凝土使用散装水泥量 + List readyMixedConcreteBulkCementUsageTotalList = Lists.newArrayList(); + // 合计生产水泥制品使用散装水泥量 + List cementProductsBulkCementUsageTotalList = Lists.newArrayList(); + + // 合计非禁现区生产预拌混凝土产量 + List readyMixedConcreteOutputTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 销售点总数 + List data1List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getSalePointAccumulativeNumTotal).collect(Collectors.toList()); + salePointAccumulativeNumTotalList.addAll(data1List); + // 水泥企业建点数量 + List data2List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getCementCompanyBuildPointNumTotal).collect(Collectors.toList()); + cementCompanyBuildPointNumTotalList.addAll(data2List); + // 其他投资建点数量 + List data3List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getOtherInvestmentBuildPointNumTotal).collect(Collectors.toList()); + otherInvestmentBuildPointNumTotalList.addAll(data3List); + // 销售量 + List data4List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getSaleVolumeTotal).collect(Collectors.toList()); + saleVolumeTotalList.addAll(data4List); + // 散装水泥罐数量 + List data5List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getBulkCementTankNumTotal).collect(Collectors.toList()); + bulkCementTankNumTotalList.addAll(data5List); + + // 散装水泥罐容量 + List data6List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getBulkCementTankCapacityTotal).collect(Collectors.toList()); + bulkCementTankCapacityTotalList.addAll(data6List); + // 水泥使用量 + List data7List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getCementUsageTotal).collect(Collectors.toList()); + cementUsageTotalList.addAll(data7List); + // 散装水泥使用量 + List data8List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getBulkCementUsageTotal).collect(Collectors.toList()); + bulkCementUsageTotalList.addAll(data8List); + // 生产预拌混凝土使用散装水泥量 + List data9List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getReadyMixedConcreteBulkCementUsageTotal).collect(Collectors.toList()); + readyMixedConcreteBulkCementUsageTotalList.addAll(data9List); + // 生产水泥制品使用散装水泥量 + List data10List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getCementProductsBulkCementUsageTotal).collect(Collectors.toList()); + cementProductsBulkCementUsageTotalList.addAll(data10List); + // 非禁现区生产预拌混凝土产量 + List data11List = totalDataList.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getReadyMixedConcreteOutputTotal).collect(Collectors.toList()); + readyMixedConcreteOutputTotalList.addAll(data11List); + } + + List totalValues = Lists.newArrayList(); + ResNonProhibitedAreasDataUploadDetailVO totalVo = new ResNonProhibitedAreasDataUploadDetailVO(); + + int salePointAccumulativeNumTotal = salePointAccumulativeNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setSalePointAccumulativeNum(salePointAccumulativeNumTotal); + int cementCompanyBuildPointNumTotal = cementCompanyBuildPointNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setCementCompanyBuildPointNum(cementCompanyBuildPointNumTotal); + int otherInvestmentBuildPointNumTotal = otherInvestmentBuildPointNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setOtherInvestmentBuildPointNum(otherInvestmentBuildPointNumTotal); + BigDecimal saleVolumeTotal = saleVolumeTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setSaleVolume(saleVolumeTotal); + int bulkCementTankNumTotal = bulkCementTankNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setBulkCementTankNum(bulkCementTankNumTotal); + + BigDecimal bulkCementTankCapacityTotal = bulkCementTankCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setBulkCementTankCapacity(bulkCementTankCapacityTotal); + BigDecimal cementUsageTotal = cementUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCementUsage(cementUsageTotal); + BigDecimal bulkCementUsageTotal = bulkCementUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setBulkCementUsage(bulkCementUsageTotal); + BigDecimal readyMixedConcreteBulkCementUsageTotal = readyMixedConcreteBulkCementUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setReadyMixedConcreteBulkCementUsage(readyMixedConcreteBulkCementUsageTotal); + BigDecimal cementProductsBulkCementUsageTotal = cementProductsBulkCementUsageTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setCementProductsBulkCementUsage(cementProductsBulkCementUsageTotal); + + // 合计散装水泥使用率: 合计散装水泥使用量 / 合计水泥使用量 * 100 + BigDecimal bulkCementUsageRateTotal = bulkCementUsageTotal.divide(cementUsageTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + totalVo.setBulkCementUsageRate(bulkCementUsageRateTotal); + + BigDecimal readyMixedConcreteOutputTotal = readyMixedConcreteOutputTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setReadyMixedConcreteOutput(readyMixedConcreteOutputTotal); + totalVo.setRegionName(ReportConstant.TOTAL); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + nonProhibitedAreasDataQueryDetailVO.setNonProAreasDataMap(dataMap); + } + + private void getBulkCementLogFacStaDataQueryDetailVo(String key, Map dataMap, Integer reportYear, ResBulkCementLogFacStaDataQueryDetailVO bulkCementLogFacStaDataQueryDetailVo, Long regionId) { + + // 统计各字段合计值 + // 合计年初数量 + List yearBeginNumTotalList = Lists.newArrayList(); + // 合计年初容量 + List yearBeginCapacityTotalList = Lists.newArrayList(); + // 合计本年新增容量 + List thisYearNewAddCapacityTotalList = Lists.newArrayList(); + // 合计本年新增数量 + List thisYearNewAddNumTotalList = Lists.newArrayList(); + // 合计本年报废数量 + List thisYearScrapNumTotalList = Lists.newArrayList(); + + // 合计本年报废容量 + List thisYearScrapCapacityTotalList = Lists.newArrayList(); + // 合计年末数量 + List yearEndNumTotalList = Lists.newArrayList(); + // 合计年末容量 + List yearEndCapacityTotalList = Lists.newArrayList(); + // 合计本年实际作业量 + List thisYearWorkAmountTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 年初数量 + List data1List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearBeginNumTotal).collect(Collectors.toList()); + yearBeginNumTotalList.addAll(data1List); + // 年初容量 + List data2List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearBeginCapacityTotal).collect(Collectors.toList()); + yearBeginCapacityTotalList.addAll(data2List); + // 本年新增容量 + List data3List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearNewAddCapacityTotal).collect(Collectors.toList()); + thisYearNewAddCapacityTotalList.addAll(data3List); + // 本年新增数量 + List data4List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearNewAddNumTotal).collect(Collectors.toList()); + thisYearNewAddNumTotalList.addAll(data4List); + // 本年报废数量 + List data5List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearScrapNumTotal).collect(Collectors.toList()); + thisYearScrapNumTotalList.addAll(data5List); + + // 本年报废容量 + List data6List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearScrapCapacityTotal).collect(Collectors.toList()); + thisYearScrapCapacityTotalList.addAll(data6List); + // 年末数量 + List data7List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearEndNumTotal).collect(Collectors.toList()); + yearEndNumTotalList.addAll(data7List); + // 年末容量 + List data8List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearEndCapacityTotal).collect(Collectors.toList()); + yearEndCapacityTotalList.addAll(data8List); + // 本年实际作业量 + List data9List = totalDataList.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearWorkAmountTotal).collect(Collectors.toList()); + thisYearWorkAmountTotalList.addAll(data9List); + } + + List totalValues = Lists.newArrayList(); + ResBulkCementLogFacStaDataUploadDetailVO totalVo = new ResBulkCementLogFacStaDataUploadDetailVO(); + int yearBeginNumTotal = yearBeginNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setYearBeginNum(yearBeginNumTotal); + BigDecimal yearBeginCapacityTotal = yearBeginCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setYearBeginCapacity(yearBeginCapacityTotal); + BigDecimal thisYearNewAddCapacityTotal = thisYearNewAddCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisYearNewAddCapacity(thisYearNewAddCapacityTotal); + int thisYearNewAddNumTotal = thisYearNewAddNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setThisYearNewAddNum(thisYearNewAddNumTotal); + int thisYearScrapNumTotal = thisYearScrapNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setThisYearScrapNum(thisYearScrapNumTotal); + + BigDecimal thisYearScrapCapacityTotal = thisYearScrapCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisYearScrapCapacity(thisYearScrapCapacityTotal); + int yearEndNumTotal = yearEndNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setYearEndNum(yearEndNumTotal); + BigDecimal yearEndCapacityTotal = yearEndCapacityTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setYearEndCapacity(yearEndCapacityTotal); + BigDecimal thisYearWorkAmountTotal = thisYearWorkAmountTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisYearWorkAmount(thisYearWorkAmountTotal); + // 将最终的合计数据也加入dataMap中 + totalVo.setRegionName(ReportConstant.TOTAL); + totalVo.setFacilityName(key); + totalVo.setReportYear(reportYear); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + bulkCementLogFacStaDataQueryDetailVo.setBulkCementLogFacDataMap(dataMap); + } + + private void getMaterialLogEquipStaDataQueryDetailVo(String key, Map dataMap, Integer reportYear, ResMaterialLogEquipStaDataQueryDetailVO materialLogEquipStaDataQueryDetailVo, Long regionId) { + + // 统计各字段合计值 + // 合计年初数量 + List yearBeginNumTotalList = Lists.newArrayList(); + // 合计年初额定量 + List yearBeginNominalRateTotalList = Lists.newArrayList(); + // 合计本年新增额定量 + List thisYearNewAddNominalRateTotalList = Lists.newArrayList(); + // 合计本年新增数量 + List thisYearNewAddNumTotalList = Lists.newArrayList(); + // 合计本年减少数量 + List thisYearDecreaseNumTotalList = Lists.newArrayList(); + + // 合计本年减少额定量 + List thisYearDecreaseNominalRateTotalList = Lists.newArrayList(); + // 合计年末数量 + List yearEndNumTotalList = Lists.newArrayList(); + // 合计年末额定量 + List yearEndNominalTotalList = Lists.newArrayList(); + + // 对于市级散办,map中只有一个键值对,统计的是该市各区县对应字段的集合 + // 对于省散办,map中对应各市键值对,统计的是各个市下各区县对应字段的集合 + for (Map.Entry entry : dataMap.entrySet()) { + List value = (List)entry.getValue(); + // 筛选出为市合计数据的那条记录(市散办有一条、省散办中有多个) + List totalDataList = value.stream().filter(v -> Boolean.TRUE.equals(v.getIsCityTotalData())).collect(Collectors.toList()); + // 年初数量 + List data1List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearBeginNumTotal).collect(Collectors.toList()); + yearBeginNumTotalList.addAll(data1List); + // 年初额定量 + List data2List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearBeginNominalRateTotal).collect(Collectors.toList()); + yearBeginNominalRateTotalList.addAll(data2List); + // 本年新增额定量 + List data3List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearNewAddNominalRateTotal).collect(Collectors.toList()); + thisYearNewAddNominalRateTotalList.addAll(data3List); + // 本年新增数量 + List data4List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearNewAddNumTotal).collect(Collectors.toList()); + thisYearNewAddNumTotalList.addAll(data4List); + // 本年减少数量 + List data5List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearDecreaseNumTotal).collect(Collectors.toList()); + thisYearDecreaseNumTotalList.addAll(data5List); + + // 本年减少额定量 + List data6List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearDecreaseNominalRateTotal).collect(Collectors.toList()); + thisYearDecreaseNominalRateTotalList.addAll(data6List); + // 年末数量 + List data7List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearEndNumTotal).collect(Collectors.toList()); + yearEndNumTotalList.addAll(data7List); + // 年末额定量 + List data8List = totalDataList.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearEndNominalTotal).collect(Collectors.toList()); + yearEndNominalTotalList.addAll(data8List); + } + + List totalValues = Lists.newArrayList(); + ResMaterialLogEquipStaDataUploadDetailVO totalVo = new ResMaterialLogEquipStaDataUploadDetailVO(); + int yearBeginNumTotal = yearBeginNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setYearBeginNum(yearBeginNumTotal); + BigDecimal yearBeginCapacityTotal = yearBeginNominalRateTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setYearBeginNominalRate(yearBeginCapacityTotal); + BigDecimal thisYearNewAddCapacityTotal = thisYearNewAddNominalRateTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisYearNewAddNominalRate(thisYearNewAddCapacityTotal); + int thisYearNewAddNumTotal = thisYearNewAddNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setThisYearNewAddNum(thisYearNewAddNumTotal); + int thisYearScrapNumTotal = thisYearDecreaseNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setThisYearDecreaseNum(thisYearScrapNumTotal); + + BigDecimal thisYearScrapCapacityTotal = thisYearDecreaseNominalRateTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setThisYearDecreaseNominalRate(thisYearScrapCapacityTotal); + int yearEndNumTotal = yearEndNumTotalList.stream().mapToInt(Integer::intValue).sum(); + totalVo.setYearEndNum(yearEndNumTotal); + BigDecimal yearEndCapacityTotal = yearEndNominalTotalList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + totalVo.setYearEndNominal(yearEndCapacityTotal); + // 将最终的合计数据也加入dataMap中 + totalVo.setRegionName(ReportConstant.TOTAL); + totalVo.setEquipmentName(key); + totalVo.setReportYear(reportYear); + totalValues.add(totalVo); + dataMap.put(ReportConstant.TOTAL,totalValues); + materialLogEquipStaDataQueryDetailVo.setMaterialLogEquipDataMap(dataMap); + } + + private void getDataMap(List auditDataIdList, Integer auditDataType, Long companyId, Map dataMap, Boolean flag, LocalDateTime reportMonth, Long regionId, Integer queryType) { + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + BulkCementDirectSystemManage context = (BulkCementDirectSystemManage) AopContext.currentProxy(); + switch (auditDataType) { + // 散装水泥供应量数据 + case 1: + assemblyBulkCementSupplyDataMap(context, auditDataIdList, dataMap, flag, reportMonth, regionDto,queryType); + break; + // 中转库进出量统计数据 + case 2: + assemblyBulkCementTransferDataMap(context, auditDataIdList, dataMap, flag, reportMonth,regionDto,queryType); + break; + // 温台舟使用量快报数据 + case 3: + assemblyBulkCementThreeCityUsageDataMap(context,auditDataIdList, dataMap, reportMonth, regionDto,queryType); + break; + // 混凝土供应量快报数据 + case 4: + assemblyConcreteSupplyDataMap(context,auditDataIdList, dataMap, flag, regionDto); + break; + // 砂浆供应量快报数据 + case 5: + assemblyMortarSupplyDataMap(context,auditDataIdList, dataMap, flag,reportMonth, regionDto,queryType); + break; + // 非禁现区域散装水泥销售使用情况数据 + case 6: + assemblyNonProAreasDataMap(context,auditDataIdList, dataMap, flag, regionDto, companyDto); + break; + // 散装水泥物流设施统计年报表数据 + case 7: + assemblyBulkCementLogFacStaDataMap(context,auditDataIdList, dataMap, flag, regionDto); + break; + // 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据 + case 8: + assemblyMaterialLogEquipStaDataMap(context,auditDataIdList, dataMap, flag, regionDto); + break; + default: + throw new IllegalStateException("Unexpected value: " + auditDataType); + } + } + + private void assemblyMaterialLogEquipStaDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, RegionDTO regionDto) { + // 根据传入的关联数据ID列表,获取相关联的上报数据信息 + // 获取关联数据信息 + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + context.buildRelevanceDataMapQuery(wrapper, auditDataIdList); + List dataList = dataRelevanceService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + + Map dataRelevanceMap = dataList.stream().collect(Collectors.toMap(BulkCementDirectReportSystemDataRelevance::getId, v -> v)); + List dataIdList = Lists.newArrayList(); + for (Long relevanceId : auditDataIdList) { + BulkCementDirectReportSystemDataRelevance relevance = dataRelevanceMap.get(relevanceId); + if (Objects.nonNull(relevance) && StringUtils.isNotBlank(relevance.getAuditDataIdList())) { + String auditDataIdListStr = relevance.getAuditDataIdList(); + List idList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + dataIdList.addAll(idList); + } + } + Map materialLogEquipStaAnnualReportMap = materialLogEquipStaAnnualReportService.list(Wrappers.lambdaQuery(MaterialLogisticEquipmentStatisticAnnualReport.class) + .in(MaterialLogisticEquipmentStatisticAnnualReport::getId, dataIdList)) + .stream().collect(Collectors.toMap(MaterialLogisticEquipmentStatisticAnnualReport::getId, v -> v)); + List vos8 = dataIdList.stream().map(a -> { + ResMaterialLogEquipStaDataUploadDetailVO resVo = new ResMaterialLogEquipStaDataUploadDetailVO(); + MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport = materialLogEquipStaAnnualReportMap.get(a); + if (Objects.nonNull(materialLogEquipStaAnnualReport)) { + BeanUtils.copyProperties(materialLogEquipStaAnnualReport, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 先按装备名称分组 + // 专用汽车 + List specialVehicleDetailVos = vos8.stream() + .filter(v -> ReportConstant.SPECIAL_VEHICLE.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 专用船 + List specialVesselDetailVos = vos8.stream() + .filter(v -> ReportConstant.SPECIAL_VESSEL.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 散装水泥罐 + List bulkCementTankDetailVos = vos8.stream() + .filter(v -> ReportConstant.BULK_CEMENT_TANK.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 混凝土搅拌车 + List concreteMixerTruckDetailVos = vos8.stream() + .filter(v -> ReportConstant.CONCRETE_MIXER_TRUCK.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 混凝土泵车 + List concretePumpTruckDetailVos = vos8.stream() + .filter(v -> ReportConstant.CONCRETE_PUMP_TRUCK.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 干混砂浆运输车 + List dryMixMortarTruckDetailVos = vos8.stream() + .filter(v -> ReportConstant.DRY_MIX_MORTAR_TRUCK.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 干混砂浆移动简仓 + List dryMixMortarMovingStorageDetailVos = vos8.stream() + .filter(v -> ReportConstant.DRY_MIX_MORTAR_MOVING_STORAGE.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + // 干混砂浆背罐车 + List dryMixMortarBackTankCarDetailVos = vos8.stream() + .filter(v -> ReportConstant.DRY_MIX_MORTAR_BACK_TANK_CAR.equals(v.getEquipmentName())) + .collect(Collectors.toList()); + + // 计算当前市各设备名称的合计数据,并加入到dataMap对应键值对中的vos中 + ResMaterialLogEquipStaDataUploadDetailVO vo1 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo2 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo3 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo4 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo5 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo6 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo7 = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo8 = new ResMaterialLogEquipStaDataUploadDetailVO(); + + vo1.setIsCityTotalData(Boolean.TRUE); + vo2.setIsCityTotalData(Boolean.TRUE); + vo3.setIsCityTotalData(Boolean.TRUE); + vo4.setIsCityTotalData(Boolean.TRUE); + vo5.setIsCityTotalData(Boolean.TRUE); + vo6.setIsCityTotalData(Boolean.TRUE); + vo7.setIsCityTotalData(Boolean.TRUE); + vo8.setIsCityTotalData(Boolean.TRUE); + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + vo1.setRegionName(ReportConstant.TOTAL); + vo2.setRegionName(ReportConstant.TOTAL); + vo3.setRegionName(ReportConstant.TOTAL); + vo4.setRegionName(ReportConstant.TOTAL); + vo5.setRegionName(ReportConstant.TOTAL); + vo6.setRegionName(ReportConstant.TOTAL); + vo7.setRegionName(ReportConstant.TOTAL); + vo8.setRegionName(ReportConstant.TOTAL); + + // 统计专用汽车各字段合计值 + Map dataMap1 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(specialVehicleDetailVos, vo1); + specialVehicleDetailVos.add(vo1); + // 单位名称改成了地区 + dataMap1.put(regionDto.getRegionName(),specialVehicleDetailVos); + dataMap.put(ReportConstant.SPECIAL_VEHICLE,dataMap1); + // 统计专用船各字段合计值 + Map dataMap2 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(specialVesselDetailVos, vo2); + specialVesselDetailVos.add(vo2); + // 单位名称改成了地区 + dataMap2.put(regionDto.getRegionName(),specialVesselDetailVos); + dataMap.put(ReportConstant.SPECIAL_VESSEL,dataMap2); + // 统计散装水泥罐各字段合计值 + Map dataMap3 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(bulkCementTankDetailVos, vo3); + bulkCementTankDetailVos.add(vo3); + // 单位名称改成了地区 + dataMap3.put(regionDto.getRegionName(),bulkCementTankDetailVos); + dataMap.put(ReportConstant.BULK_CEMENT_TANK,dataMap3); + + // 统计混凝土搅拌车各字段合计值 + Map dataMap4 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(concreteMixerTruckDetailVos, vo4); + concreteMixerTruckDetailVos.add(vo4); + // 单位名称改成了地区 + dataMap4.put(regionDto.getRegionName(),concreteMixerTruckDetailVos); + dataMap.put(ReportConstant.CONCRETE_MIXER_TRUCK,dataMap4); + // 统计混凝土泵车各字段合计值 + Map dataMap5 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(concretePumpTruckDetailVos, vo5); + concretePumpTruckDetailVos.add(vo5); + // 单位名称改成了地区 + dataMap5.put(regionDto.getRegionName(),concretePumpTruckDetailVos); + dataMap.put(ReportConstant.CONCRETE_PUMP_TRUCK,dataMap5); + // 统计干混砂浆运输车各字段合计值 + Map dataMap6 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(dryMixMortarTruckDetailVos, vo6); + dryMixMortarTruckDetailVos.add(vo6); + // 单位名称改成了地区 + dataMap6.put(regionDto.getRegionName(),dryMixMortarTruckDetailVos); + dataMap.put(ReportConstant.DRY_MIX_MORTAR_TRUCK,dataMap6); + + // 统计干混砂浆移动简仓各字段合计值 + Map dataMap7 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(dryMixMortarMovingStorageDetailVos, vo7); + dryMixMortarMovingStorageDetailVos.add(vo7); + // 单位名称改成了地区 + dataMap7.put(regionDto.getRegionName(),concretePumpTruckDetailVos); + dataMap.put(ReportConstant.DRY_MIX_MORTAR_MOVING_STORAGE,dataMap7); + // 统计干混砂浆背罐车各字段合计值 + Map dataMap8 = MapUtil.newHashMap(); + getCityMaterialLogEquipStaTotalData(dryMixMortarBackTankCarDetailVos, vo8); + dryMixMortarBackTankCarDetailVos.add(vo8); + // 单位名称改成了地区 + dataMap8.put(regionDto.getRegionName(),dryMixMortarBackTankCarDetailVos); + dataMap.put(ReportConstant.DRY_MIX_MORTAR_BACK_TANK_CAR,dataMap8); + } + private void assemblyBulkCementLogFacStaDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, RegionDTO regionDto) { + // 根据传入的关联数据ID列表,获取相关联的上报数据信息 + // 获取关联数据信息 + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + context.buildRelevanceDataMapQuery(wrapper, auditDataIdList); + List dataList = dataRelevanceService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + + Map dataRelevanceMap = dataList.stream().collect(Collectors.toMap(BulkCementDirectReportSystemDataRelevance::getId, v -> v)); + List dataIdList = Lists.newArrayList(); + for (Long relevanceId : auditDataIdList) { + BulkCementDirectReportSystemDataRelevance relevance = dataRelevanceMap.get(relevanceId); + if (Objects.nonNull(relevance) && StringUtils.isNotBlank(relevance.getAuditDataIdList())) { + String auditDataIdListStr = relevance.getAuditDataIdList(); + List idList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + dataIdList.addAll(idList); + } + } + Map bulkCementLogFacStaAnnualReportMap = bulkCementLogFacStaAnnualReportService.list(Wrappers.lambdaQuery(BulkCementLogisticFacilityStatisticAnnualReport.class) + .in(BulkCementLogisticFacilityStatisticAnnualReport::getId, dataIdList)) + .stream().collect(Collectors.toMap(BulkCementLogisticFacilityStatisticAnnualReport::getId, v -> v)); + List vos7 = dataIdList.stream().map(a -> { + ResBulkCementLogFacStaDataUploadDetailVO resVo = new ResBulkCementLogFacStaDataUploadDetailVO(); + BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogFacStaAnnualReport = bulkCementLogFacStaAnnualReportMap.get(a); + if (Objects.nonNull(bulkCementLogFacStaAnnualReport)) { + BeanUtils.copyProperties(bulkCementLogFacStaAnnualReport, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 先按设备名称分组 + // 发放库 + List issueLibDetailVos = vos7.stream() + .filter(v -> ReportConstant.ISSUE_LIBRARY.equals(v.getFacilityName())) + .collect(Collectors.toList()); + // 中转库 + List transferLibDetailVos = vos7.stream() + .filter(v -> ReportConstant.TRANSFER_LIBRARY.equals(v.getFacilityName())) + .collect(Collectors.toList()); + // 固定接收库 + List fixRecLibDetailVos = vos7.stream() + .filter(v -> ReportConstant.FIX_RECEIVE_LIBRARY.equals(v.getFacilityName())) + .collect(Collectors.toList()); + + // 计算当前市各设备名称的合计数据,并加入到dataMap对应键值对中的vos中 + ResBulkCementLogFacStaDataUploadDetailVO vo7 = new ResBulkCementLogFacStaDataUploadDetailVO(); + ResBulkCementLogFacStaDataUploadDetailVO vo8 = new ResBulkCementLogFacStaDataUploadDetailVO(); + ResBulkCementLogFacStaDataUploadDetailVO vo9 = new ResBulkCementLogFacStaDataUploadDetailVO(); + vo7.setIsCityTotalData(Boolean.TRUE); + vo8.setIsCityTotalData(Boolean.TRUE); + vo9.setIsCityTotalData(Boolean.TRUE); + + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + vo7.setRegionName(ReportConstant.TOTAL); + vo8.setRegionName(ReportConstant.TOTAL); + vo9.setRegionName(ReportConstant.TOTAL); + + // 统计发放库各字段合计值 + Map dataMap1 = MapUtil.newHashMap(); + getCityBulkCementLogFacStaTotalData(issueLibDetailVos, vo7); + issueLibDetailVos.add(vo7); + // 单位名称改成了地区 + dataMap1.put(regionDto.getRegionName(),issueLibDetailVos); + dataMap.put(ReportConstant.ISSUE_LIBRARY,dataMap1); + // 统计中转库各字段合计值 + Map dataMap2 = MapUtil.newHashMap(); + getCityBulkCementLogFacStaTotalData(transferLibDetailVos, vo8); + transferLibDetailVos.add(vo8); + // 单位名称改成了地区 + dataMap2.put(regionDto.getRegionName(),transferLibDetailVos); + dataMap.put(ReportConstant.TRANSFER_LIBRARY,dataMap2); + // 统计固定接收库各字段合计值 + Map dataMap3 = MapUtil.newHashMap(); + getCityBulkCementLogFacStaTotalData(fixRecLibDetailVos, vo9); + fixRecLibDetailVos.add(vo9); + // 单位名称改成了地区 + dataMap3.put(regionDto.getRegionName(),fixRecLibDetailVos); + dataMap.put(ReportConstant.FIX_RECEIVE_LIBRARY,dataMap3); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildRelevanceDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(BulkCementDirectReportSystemDataRelevance::getId,auditDataIdList) + .select(BulkCementDirectReportSystemDataRelevance::getId, BulkCementDirectReportSystemDataRelevance::getAuditDataIdList); + } + + private void assemblyNonProAreasDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, RegionDTO regionDto, CompanyDTO companyDto) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NonProhibitedAreasBulkCementSalesUse.class); + context.buildNonProAreasDataMapQuery(wrapper, auditDataIdList); + List dataList = nonProhibitedAreasBulkCementSalesUseService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + + Map nonProhibitedAreasBulkCementSalesUseMap = dataList.stream().collect(Collectors.toMap(NonProhibitedAreasBulkCementSalesUse::getId, v -> v)); + List vos6 = auditDataIdList.stream().map(a -> { + ResNonProhibitedAreasDataUploadDetailVO resVo = new ResNonProhibitedAreasDataUploadDetailVO(); + NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse = nonProhibitedAreasBulkCementSalesUseMap.get(a); + if (Objects.nonNull(nonProhibitedAreasBulkCementSalesUse)) { + BeanUtils.copyProperties(nonProhibitedAreasBulkCementSalesUse, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 计算当前市的合计数据,并加入到dataMap对应键值对中的vos中 + ResNonProhibitedAreasDataUploadDetailVO vo6 = new ResNonProhibitedAreasDataUploadDetailVO(); + vo6.setIsCityTotalData(Boolean.TRUE); + vo6.setRegionName(ReportConstant.TOTAL); + // 统计各字段合计值 + getCityNonProAreasTotalData(vos6, vo6); + vos6.add(vo6); + // 单位名称改成了地区 + dataMap.put(regionDto.getRegionName(),vos6); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildNonProAreasDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(NonProhibitedAreasBulkCementSalesUse::getId,auditDataIdList); + } + + private void assemblyMortarSupplyDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, LocalDateTime reportMonth, RegionDTO regionDto, Integer queryType) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(MortarSupplyBulletin.class); + context.buildMortarSupplyDataMapQuery(wrapper, auditDataIdList); + List dataList = mortarSupplyBulletinService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + Map bulkCementSupplyBulletinMap = dataList.stream().collect(Collectors.toMap(MortarSupplyBulletin::getId, v -> v)); + List vos5 = auditDataIdList.stream().map(a -> { + ResMortarSupplyDataUploadDetailVO resVo = new ResMortarSupplyDataUploadDetailVO(); + MortarSupplyBulletin mortarSupplyBulletin = bulkCementSupplyBulletinMap.get(a); + if (Objects.nonNull(mortarSupplyBulletin)) { + BeanUtils.copyProperties(mortarSupplyBulletin, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 计算当前市的合计数据,并加入到dataMap对应键值对中的vos中 + ResMortarSupplyDataUploadDetailVO vo5 = new ResMortarSupplyDataUploadDetailVO(); + vo5.setIsCityTotalData(Boolean.TRUE); + // 如果登录用户是市级散办 + vo5.setRegionName(ReportConstant.TOTAL); + // 统计各字段合计值 + getCityMortarSupplyTotalData(vos5, vo5,reportMonth,regionDto,queryType); + vos5.add(vo5); + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + // 单位名称改成了地区 + dataMap.put(regionDto.getRegionName(),vos5); + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildMortarSupplyDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(MortarSupplyBulletin::getId,auditDataIdList); + } + + private void assemblyConcreteSupplyDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, RegionDTO regionDto) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ConcreteSupplyBulletin.class); + context.buildConcreteSupplyDataMapQuery(wrapper, auditDataIdList); + List dataList = concreteSupplyBulletinService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + Map concreteSupplyBulletinMap = dataList.stream().collect(Collectors.toMap(ConcreteSupplyBulletin::getId, v -> v)); + List vos4 = auditDataIdList.stream().map(a -> { + ResConcreteSupplyDataUploadDetailVO resVo = new ResConcreteSupplyDataUploadDetailVO(); + ConcreteSupplyBulletin concreteSupplyBulletin = concreteSupplyBulletinMap.get(a); + if (Objects.nonNull(concreteSupplyBulletin)) { + BeanUtils.copyProperties(concreteSupplyBulletin, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 计算当前市的合计数据,并加入到dataMap对应键值对中的vos中 + ResConcreteSupplyDataUploadDetailVO vo4 = new ResConcreteSupplyDataUploadDetailVO(); + vo4.setIsCityTotalData(Boolean.TRUE); + vo4.setUnitName(ReportConstant.TOTAL); + // 统计各字段合计值 + getCityConcreteSupplyTotalData(vos4, vo4); + vos4.add(vo4); + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + // 单位名称改成了地区 + dataMap.put(regionDto.getRegionName(),vos4); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildConcreteSupplyDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(ConcreteSupplyBulletin::getId,auditDataIdList); + } + + private void assemblyBulkCementThreeCityUsageDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, LocalDateTime reportMonth, RegionDTO regionDto, Integer queryType) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class); + context.buildBulkCementThreeCityUsageDataMapQuery(wrapper, auditDataIdList); + List dataList = bulkCementThreeCityUsageBulletinService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + Map bulkCementThreeCityUsageBulletinMap = dataList.stream().collect(Collectors.toMap(BulkCementThreeCityUsageBulletin::getId, v -> v)); + List vos3 = auditDataIdList.stream().map(a -> { + ResBulkCementThreeCityUsageDataUploadDetailVO resVo = new ResBulkCementThreeCityUsageDataUploadDetailVO(); + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinMap.get(a); + if (Objects.nonNull(bulkCementThreeCityUsageBulletin)) { + BeanUtils.copyProperties(bulkCementThreeCityUsageBulletin, resVo); + // 本省本月、外省本月数据需取整返回(其余在数据填报时已经做过处理,数据库中存的就是取整后的值) + BigDecimal thisProvinceThisMonthUsage = Objects.isNull(resVo.getThisProvinceThisMonthUsage()) ? BigDecimal.ZERO : resVo.getThisProvinceThisMonthUsage(); + resVo.setThisProvinceThisMonthUsage(thisProvinceThisMonthUsage.setScale(0, RoundingMode.HALF_UP)); + BigDecimal otherProvinceThisMonthUsage = Objects.isNull(resVo.getOtherProvinceThisMonthUsage()) ? BigDecimal.ZERO : resVo.getOtherProvinceThisMonthUsage(); + resVo.setThisMonthUsageTotal(otherProvinceThisMonthUsage.setScale(0, RoundingMode.HALF_UP)); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 计算当前市的合计数据,并加入到dataMap对应键值对中的vos中 + ResBulkCementThreeCityUsageDataUploadDetailVO vo3 = new ResBulkCementThreeCityUsageDataUploadDetailVO(); + vo3.setIsCityTotalData(Boolean.TRUE); + // 如果登录用户是市级散办,单位名称一列为合计 + // 登录用户是省散办不需要单独再加一条合计数据,dataMap中即为三个市各自上报的数据 + vo3.setUnitName(ReportConstant.TOTAL); + // 统计各字段合计值(与原数据一致,因为市登录用户只有一条数据) + getCityBulkCementThreeCityUsageTotalData(vos3, vo3,reportMonth,regionDto,queryType); + vos3.add(vo3); + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + // 单位名称改成了地区 + dataMap.put(regionDto.getRegionName(),vos3); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementThreeCityUsageDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(BulkCementThreeCityUsageBulletin::getId,auditDataIdList); + } + + private void assemblyBulkCementTransferDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, LocalDateTime reportMonth, RegionDTO regionDTO, Integer queryType) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementTransferBulletin.class); + context.buildBulkCementTransferDataMapQuery(wrapper, auditDataIdList); + List dataList = bulkCementTransferBulletinService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + Map bulkCementTransferBulletinMap = dataList.stream().collect(Collectors.toMap(BulkCementTransferBulletin::getId, v -> v)); + List vos2 = auditDataIdList.stream().map(a -> { + ResBulkCementTransferDataUploadDetailVO resVo = new ResBulkCementTransferDataUploadDetailVO(); + BulkCementTransferBulletin bulkCementTransferBulletin = bulkCementTransferBulletinMap.get(a); + if (Objects.nonNull(bulkCementTransferBulletin)) { + BeanUtils.copyProperties(bulkCementTransferBulletin, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 计算当前市的合计数据,并加入到dataMap对应键值对中的vos中 + ResBulkCementTransferDataUploadDetailVO vo2 = new ResBulkCementTransferDataUploadDetailVO(); + vo2.setIsCityTotalData(Boolean.TRUE); + vo2.setUnitName(ReportConstant.TOTAL); + // 统计各字段合计值 + getCityBulkCementTransferTotalData(vos2, vo2,reportMonth,regionDTO,queryType); + vos2.add(vo2); + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDTO.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + // 单位名称改成了地区 + dataMap.put(regionDTO.getRegionName(),vos2); + } + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementTransferDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(BulkCementTransferBulletin::getId,auditDataIdList); + } + + private void assemblyBulkCementSupplyDataMap(BulkCementDirectSystemManage context, List auditDataIdList, Map dataMap, Boolean flag, LocalDateTime reportMonth, RegionDTO regionDTO, Integer queryType) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementSupplyBulletin.class); + context.buildBulkCementSupplyDataMapQuery(wrapper, auditDataIdList); + List dataList = bulkCementSupplyBulletinService.list(wrapper); + if (CollUtil.isEmpty(dataList)){ + return; + } + Map bulkCementSupplyBulletinMap = dataList.stream().collect(Collectors.toMap(BulkCementSupplyBulletin::getId, v -> v)); + List vos1 = auditDataIdList.stream().map(a -> { + ResBulkCementSupplyDataUploadDetailVO resVo = new ResBulkCementSupplyDataUploadDetailVO(); + BulkCementSupplyBulletin bulkCementSupplyBulletin = bulkCementSupplyBulletinMap.get(a); + if (Objects.nonNull(bulkCementSupplyBulletin)) { + BeanUtils.copyProperties(bulkCementSupplyBulletin, resVo); + // 不为市合计数据 + resVo.setIsCityTotalData(Boolean.FALSE); + } + return resVo; + }).collect(Collectors.toList()); + // 计算当前市的合计数据,并加入到dataMap对应键值对中的vos中 + ResBulkCementSupplyDataUploadDetailVO vo1 = new ResBulkCementSupplyDataUploadDetailVO(); + vo1.setIsCityTotalData(Boolean.TRUE); + // 如果登录用户是市级散办 + vo1.setUnitName(ReportConstant.TOTAL); + // 如果是省散办查询页面,需要返回查询上报月份所在年份各市设定的散装率目标 + if (Boolean.TRUE.equals(flag)) { + int year = reportMonth.getYear(); + BulkCementDirectReportSystemUniversalIndex universalIndex = universalIndexService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemUniversalIndex.class) + .eq(BulkCementDirectReportSystemUniversalIndex::getYear, year) + .eq(BulkCementDirectReportSystemUniversalIndex::getRegionId, regionDTO.getId())); + if (Objects.nonNull(universalIndex)){ + vo1.setBulkRateTarget(universalIndex.getBulkRateTarget()); + } + } + // 统计各字段合计值 + getCityBulkCementSupplyTotalData(vos1, vo1,reportMonth,regionDTO,queryType); + vos1.add(vo1); + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDTO.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + // 单位名称改成了地区 + dataMap.put(regionDTO.getRegionName(),vos1); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementSupplyDataMapQuery(LambdaQueryWrapper wrapper, List auditDataIdList) { + wrapper.in(BulkCementSupplyBulletin::getId, auditDataIdList); + } + + private void getCityBulkCementSupplyTotalData(List vos, ResBulkCementSupplyDataUploadDetailVO vo, LocalDateTime reportMonth, RegionDTO regionDTO, Integer queryType) { + // 合计散装水泥总量 + List bulkCementAmountList = vos.stream().map(ResBulkCementSupplyDataUploadDetailVO::getBulkCementAmount).collect(Collectors.toList()); + // 合计水泥产量 + List cementOutputList = vos.stream().map(ResBulkCementSupplyDataUploadDetailVO::getCementOutput).collect(Collectors.toList()); + // 合计完成量 + List completedAmountList = vos.stream().map(ResBulkCementSupplyDataUploadDetailVO::getCompletedTotalAmount).collect(Collectors.toList()); + // 合计水泥产量 + List cumulativeCementProductionList = vos.stream().map(ResBulkCementSupplyDataUploadDetailVO::getCumulativeCementProduction).collect(Collectors.toList()); + // 合计增加量 + List incrementList = vos.stream().map(ResBulkCementSupplyDataUploadDetailVO::getIncrement).collect(Collectors.toList()); + // 去年这个月的合计完成量 + List childRegionIdList; + if (QueryTypeEnum.QUERY_LIST.getCode().equals(queryType)) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId; + if (userDetail.getRegionId().equals(DefValConstants.SYSTEM_ID)){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + childRegionIdList = regionsCacheHelper.listChildRegionId(regionId, false, true); + }else { + childRegionIdList = regionsCacheHelper.listChildRegionId(regionDTO.getId(), true, true); + } + LocalDateTime preYearReportMonth = reportMonth.minusYears(1L); + List preYearDataList = bulkCementSupplyBulletinService.list(Wrappers.lambdaQuery(BulkCementSupplyBulletin.class) + .eq(BulkCementSupplyBulletin::getReportMonth, preYearReportMonth) + .in(BulkCementSupplyBulletin::getRegionId, childRegionIdList)); + List preYearCompletedAmountList = preYearDataList.stream().map(BulkCementSupplyBulletin::getCompletedTotalAmount).collect(Collectors.toList()); + + BigDecimal bulkCementAmountTotal = bulkCementAmountList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setBulkCementAmountTotal(bulkCementAmountTotal); + BigDecimal cementOutputTotal = cementOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCementOutputTotal(cementOutputTotal); + BigDecimal completedAmountTotal = completedAmountList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCompletedTotalAmountTotal(completedAmountTotal); + BigDecimal cumulativeCementProductionTotal = cumulativeCementProductionList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCumulativeCementProductionTotal(cumulativeCementProductionTotal); + BigDecimal incrementTotal = incrementList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setIncrementTotal(incrementTotal); + // 合计散装率: 合计完成量 / 合计水泥产量 * 100 + BigDecimal bulkRateTotal; + if (BigDecimal.ZERO.compareTo(cumulativeCementProductionTotal) != 0) { + bulkRateTotal = completedAmountTotal.divide(cumulativeCementProductionTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + bulkRateTotal = completedAmountTotal.multiply(BigDecimal.valueOf(100L)); + } + vo.setBulkRateTotal(bulkRateTotal); + // 合计增长率:合计增长量 / 去年这个月的合计完成量 * 100 + BigDecimal preYearCompletedAmountTotal = preYearCompletedAmountList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + BigDecimal increaseRateTotal; + if (BigDecimal.ZERO.compareTo(preYearCompletedAmountTotal) != 0) { + increaseRateTotal = incrementTotal.divide(preYearCompletedAmountTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + increaseRateTotal = incrementTotal.multiply(BigDecimal.valueOf(100L)); + } + vo.setIncreaseRateTotal(increaseRateTotal); + } + + private void getCityBulkCementTransferTotalData(List vos, ResBulkCementTransferDataUploadDetailVO vo, LocalDateTime reportMonth, RegionDTO regionDTO, Integer queryType) { + // 合计上月末库存 + List lastMonthEndInventoryList = vos.stream().map(ResBulkCementTransferDataUploadDetailVO::getLastMonthEndInventory).collect(Collectors.toList()); + // 合计本月进库量 + List thisMonthIncomingStorageList = vos.stream().map(ResBulkCementTransferDataUploadDetailVO::getThisMonthIncomingStorage).collect(Collectors.toList()); + // 合计累计进库量 + List cumulativeIncomingStorageList = vos.stream().map(ResBulkCementTransferDataUploadDetailVO::getCumulativeIncomingStorage).collect(Collectors.toList()); + // 合计本月出库量 + List thisMonthOutgoingStorageList = vos.stream().map(ResBulkCementTransferDataUploadDetailVO::getThisMonthOutgoingStorage).collect(Collectors.toList()); + // 合计累计出库量 + List cumulativeOutgoingStorageList = vos.stream().map(ResBulkCementTransferDataUploadDetailVO::getCumulativeOutgoingStorage).collect(Collectors.toList()); + // 合计库存量 + List monthEndInventoryList = vos.stream().map(ResBulkCementTransferDataUploadDetailVO::getMonthEndInventory).collect(Collectors.toList()); + + // 去年这个月的合计库存量 + LocalDateTime preYearReportMonth = reportMonth.minusYears(1L); + List childRegionIdList = Lists.newArrayList(); + if (QueryTypeEnum.QUERY_LIST.getCode().equals(queryType)) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId; + if (userDetail.getRegionId().equals(DefValConstants.SYSTEM_ID)){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + childRegionIdList = regionsCacheHelper.listChildRegionId(regionId, false, true); + }else { + childRegionIdList = regionsCacheHelper.listChildRegionId(regionDTO.getId(), true, true); + } + List preYearDataList = bulkCementTransferBulletinService.list(Wrappers.lambdaQuery(BulkCementTransferBulletin.class) + .eq(BulkCementTransferBulletin::getReportMonth, preYearReportMonth) + .in(BulkCementTransferBulletin::getRegionId, childRegionIdList)); + List preYearMonthEndInventoryList = preYearDataList.stream().map(BulkCementTransferBulletin::getMonthEndInventory).collect(Collectors.toList()); + BigDecimal lastMonthEndInventoryTotal = lastMonthEndInventoryList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setLastMonthEndInventoryTotal(lastMonthEndInventoryTotal); + BigDecimal thisMonthIncomingStorageTotal = thisMonthIncomingStorageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthIncomingStorageTotal(thisMonthIncomingStorageTotal); + BigDecimal cumulativeIncomingStorageTotal = cumulativeIncomingStorageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCumulativeIncomingStorageTotal(cumulativeIncomingStorageTotal); + BigDecimal thisMonthOutgoingStorageTotal = thisMonthOutgoingStorageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthOutgoingStorageTotal(thisMonthOutgoingStorageTotal); + BigDecimal cumulativeOutgoingStorageTotal = cumulativeOutgoingStorageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCumulativeOutgoingStorageTotal(cumulativeOutgoingStorageTotal); + BigDecimal monthEndInventoryTotal = monthEndInventoryList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setMonthEndInventoryTotal(monthEndInventoryTotal); + // 合计同比增长率:(合计月末库存量 - 去年合计月末库存量) / 去年合计月末库存量 * 100 + BigDecimal preYearMonthEndInventoryTotal = preYearMonthEndInventoryList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + BigDecimal monthEndInventoryGrowthRateTotal = BigDecimal.ZERO; + if (BigDecimal.ZERO.compareTo(monthEndInventoryTotal) != 0){ + if (BigDecimal.ZERO.compareTo(preYearMonthEndInventoryTotal) != 0) { + BigDecimal subtract = monthEndInventoryTotal.subtract(preYearMonthEndInventoryTotal); + monthEndInventoryGrowthRateTotal = subtract.divide(preYearMonthEndInventoryTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + }else { + monthEndInventoryGrowthRateTotal = monthEndInventoryTotal.multiply(BigDecimal.valueOf(100L)); + } + } + vo.setMonthEndInventoryGrowthRateTotal(monthEndInventoryGrowthRateTotal); + } + + private void getCityBulkCementThreeCityUsageTotalData(List vos, ResBulkCementThreeCityUsageDataUploadDetailVO vo, LocalDateTime reportMonth, RegionDTO regionDto, Integer queryType) { + // 合计年目标 + List yearTargetList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getYearTarget).collect(Collectors.toList()); + // 合计占全年目标百分比 + List percentageOfAnnualTargetList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getPercentageOfAnnualTarget).collect(Collectors.toList()); + // 合计本月使用量 + List thisMonthUsageList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getThisMonthUsage).collect(Collectors.toList()); + // 合计累计使用量 + List accumulativeUsageList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getAccumulativeUsage).collect(Collectors.toList()); + + // 去年这个月的合计累计使用量 + List childRegionIdList = Lists.newArrayList(); + if (QueryTypeEnum.QUERY_LIST.getCode().equals(queryType)) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId; + if (userDetail.getRegionId().equals(DefValConstants.SYSTEM_ID)){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + childRegionIdList = regionsCacheHelper.listChildRegionId(regionId, false, true); + }else { + childRegionIdList = regionsCacheHelper.listChildRegionId(regionDto.getId(), true, true);; + } + LocalDateTime preYearReportMonth = reportMonth.minusYears(1L); + List preYearReportMonthDataList = bulkCementThreeCityUsageBulletinService.list(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class) + .eq(BulkCementThreeCityUsageBulletin::getReportMonth, preYearReportMonth) + .in(BulkCementThreeCityUsageBulletin::getRegionId,childRegionIdList)); + List preYearAccumulativeUsage = preYearReportMonthDataList.stream().map(BulkCementThreeCityUsageBulletin::getAccumulativeUsage).collect(Collectors.toList()); + // 合计本省本月使用量 + List thisProvinceThisMonthUsageList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getThisProvinceThisMonthUsage).collect(Collectors.toList()); + // 合计本省累计使用量 + List thisProvinceAccumulativeUsageList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getThisProvinceAccumulativeUsage).collect(Collectors.toList()); + // 合计外省本月使用量 + List otherProvinceThisMonthUsageList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getOtherProvinceThisMonthUsage).collect(Collectors.toList()); + // 合计外省累计使用量 + List otherProvinceAccumulativeUsageList = vos.stream().map(ResBulkCementThreeCityUsageDataUploadDetailVO::getOtherProvinceAccumulativeUsage).collect(Collectors.toList()); + + BigDecimal yearTargetTotal = yearTargetList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setYearTargetTotal(yearTargetTotal); + BigDecimal percentageOfAnnualTargetTotal = percentageOfAnnualTargetList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setPercentageOfAnnualTargetTotal(percentageOfAnnualTargetTotal); + BigDecimal thisMonthUsageTotal = thisMonthUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthUsageTotal(thisMonthUsageTotal); + BigDecimal accumulativeUsageTotal = accumulativeUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setAccumulativeUsageTotal(accumulativeUsageTotal); + // 合计同比增长率 = (今年合计累计使用量 - 去年合计累计使用量) / 去年合计累计使用量 * 100 + BigDecimal growthRateTotal = BigDecimal.ZERO; + BigDecimal preYearAccumulativeUsageTotal = preYearAccumulativeUsage.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + if (BigDecimal.ZERO.compareTo(accumulativeUsageTotal) != 0) { + if (BigDecimal.ZERO.compareTo(preYearAccumulativeUsageTotal) != 0) { + BigDecimal subtract = accumulativeUsageTotal.subtract(preYearAccumulativeUsageTotal); + growthRateTotal = subtract.divide(preYearAccumulativeUsageTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + }else { + growthRateTotal = accumulativeUsageTotal.multiply(BigDecimal.valueOf(100L)); + } + } + vo.setGrowthRateTotal(growthRateTotal); + BigDecimal thisProvinceThisMonthUsageTotal = thisProvinceThisMonthUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisProvinceThisMonthUsageTotal(thisProvinceThisMonthUsageTotal); + BigDecimal thisProvinceAccumulativeUsageTotal = thisProvinceAccumulativeUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisProvinceAccumulativeUsageTotal(thisProvinceAccumulativeUsageTotal); + BigDecimal otherProvinceThisMonthUsageTotal = otherProvinceThisMonthUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setOtherProvinceThisMonthUsageTotal(otherProvinceThisMonthUsageTotal); + BigDecimal otherProvinceAccumulativeUsageTotal = otherProvinceAccumulativeUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setOtherProvinceAccumulativeUsageTotal(otherProvinceAccumulativeUsageTotal); + } + private void getCityConcreteSupplyTotalData(List vos, ResConcreteSupplyDataUploadDetailVO vo) { + // 合计三类指导目标 + List threeCategoryGuidGoalList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getThreeCategoryGuidGoal).collect(Collectors.toList()); + // 合计生产企业数量 + List productionCompanyNumsList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getProductionCompanyNums).collect(Collectors.toList()); + // 合计年设计生产能力 + List annualDesignProductionCapacityList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getAnnualDesignProductionCapacity).collect(Collectors.toList()); + // 合计本月实际产量 + List thisMonthOutputList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getThisMonthOutput).collect(Collectors.toList()); + // 合计累计实际产量 + List accumulativeOutputList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getAccumulativeOutput).collect(Collectors.toList()); + // 合计本月使用散装水泥量 + List thisMonthCementUsageList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getThisMonthCementUsage).collect(Collectors.toList()); + // 合计累计使用散装水泥量 + List cementAccumulativeUsageList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getCementAccumulativeUsage).collect(Collectors.toList()); + // 合计本月废弃物综合利用量 + List thisMonthWasteUtilizationList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getThisMonthWasteUtilization).collect(Collectors.toList()); + // 合计累计废弃物综合利用量 + List accumulativeWasteUtilizationList = vos.stream().map(ResConcreteSupplyDataUploadDetailVO::getAccumulativeWasteUtilization).collect(Collectors.toList()); + + BigDecimal threeCategoryGuidGoalTotal = threeCategoryGuidGoalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThreeCategoryGuidGoalTotal(threeCategoryGuidGoalTotal); + int productionCompanyNumsTotal = productionCompanyNumsList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setProductionCompanyNumsTotal(productionCompanyNumsTotal); + BigDecimal annualDesignProductionCapacityTotal = annualDesignProductionCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setAnnualDesignProductionCapacityTotal(annualDesignProductionCapacityTotal); + BigDecimal thisMonthOutputTotal = thisMonthOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthOutputTotal(thisMonthOutputTotal); + BigDecimal accumulativeOutputTotal = accumulativeOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setAccumulativeOutputTotal(accumulativeOutputTotal); + BigDecimal thisMonthCementUsageTotal = thisMonthCementUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthCementUsageTotal(thisMonthCementUsageTotal); + BigDecimal cementAccumulativeUsageTotal = cementAccumulativeUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCementAccumulativeUsageTotal(cementAccumulativeUsageTotal); + BigDecimal thisMonthWasteUtilizationTotal = thisMonthWasteUtilizationList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthWasteUtilizationTotal(thisMonthWasteUtilizationTotal); + BigDecimal accumulativeWasteUtilizationTotal = accumulativeWasteUtilizationList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setAccumulativeWasteUtilizationTotal(accumulativeWasteUtilizationTotal); + } + + private void getCityMortarSupplyTotalData(List vos, ResMortarSupplyDataUploadDetailVO vo, LocalDateTime reportMonth, RegionDTO regionDto, Integer queryType) { + // 合计二类指导目标 + List twoCategoryGuidGoalList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getTwoCategoryGuidGoal).collect(Collectors.toList()); + // 合计普通干混砂浆生产企业数量 + List dryMixedMortarProductionCompanyNumList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarProductionCompanyNum).collect(Collectors.toList()); + // 合计普通干混砂浆生产总能力 + List dryMixedMortarProductiveCapacityList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarProductiveCapacity).collect(Collectors.toList()); + // 合计普通干混砂浆散装能力 + List dryMixedMortarBulkCapacityList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarBulkCapacity).collect(Collectors.toList()); + // 合计本月总产量 + List thisMonthTotalOutputList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getThisMonthTotalOutput).collect(Collectors.toList()); + // 合计本月累计总产量 + List thisMonthAccumulativeOutputList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getThisMonthAccumulativeOutput).collect(Collectors.toList()); + // 合计普通干混砂浆本月产量 + List dryMixedMortarThisMonthOutputList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarThisMonthOutput).collect(Collectors.toList()); + // 合计普通干混砂浆累计产量 + List dryMixedMortarThisMonthAccumulativeOutputList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarThisMonthAccumulativeOutput).collect(Collectors.toList()); + // 合计普通干混砂浆同比增长量 + List dryMixedMortarIncrementList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarIncrement).collect(Collectors.toList()); + + // 合计去年这个月普通干混砂浆累计产量 + LocalDateTime preYearReportMonth = reportMonth.minusYears(1L); + List childRegionIdList = Lists.newArrayList(); + if (QueryTypeEnum.QUERY_LIST.getCode().equals(queryType)) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId; + if (userDetail.getRegionId().equals(DefValConstants.SYSTEM_ID)){ + regionId = DefValConstants.ZJREGION_ID; + }else { + regionId = userDetail.getRegionId(); + } + childRegionIdList = regionsCacheHelper.listChildRegionId(regionId, false, true); + }else { + childRegionIdList = regionsCacheHelper.listChildRegionId(regionDto.getId(), true, true); + } + List preYearDataList = mortarSupplyBulletinService.list(Wrappers.lambdaQuery(MortarSupplyBulletin.class) + .eq(MortarSupplyBulletin::getReportMonth, preYearReportMonth) + .in(MortarSupplyBulletin::getRegionId, childRegionIdList)); + List preYearDryMixedMortarThisMonthAccumulativeOutputList = preYearDataList.stream().map(MortarSupplyBulletin::getDryMixedMortarThisMonthAccumulativeOutput).collect(Collectors.toList()); + + // 合计普通干混砂浆本月散装量 + List dryMixedMortarThisMonthBulkQuantityList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarThisMonthBulkQuantity).collect(Collectors.toList()); + // 合计普通干混砂浆累计散装量 + List dryMixedMortarAccumulativeBulkQuantityList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getDryMixedMortarAccumulativeBulkQuantity).collect(Collectors.toList()); + // 合计湿拌砂浆本月产量 + List wetMortarThisMonthOutputList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getWetMortarThisMonthOutput).collect(Collectors.toList()); + // 合计湿拌砂浆累计产量 + List wetMortarAccumulativeOutputList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getWetMortarAccumulativeOutput).collect(Collectors.toList()); + // 合计散装水泥本月使用量 + List bulkCementThisMonthUsageList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getBulkCementThisMonthUsage).collect(Collectors.toList()); + // 合计散装水泥累计使用量 + List bulkCementAccumulativeUsageList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getBulkCementAccumulativeUsage).collect(Collectors.toList()); + // 合计废弃物本月综合利用量 + List wasteThisMonthComprehensiveUtilizationList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getWasteThisMonthComprehensiveUtilization).collect(Collectors.toList()); + // 合计废弃物累计综合利用量 + List wasteAccumulativeComprehensiveUtilizationList = vos.stream().map(ResMortarSupplyDataUploadDetailVO::getWasteAccumulativeComprehensiveUtilization).collect(Collectors.toList()); + + BigDecimal twoCategoryGuidGoalTotal = twoCategoryGuidGoalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setTwoCategoryGuidGoalTotal(twoCategoryGuidGoalTotal); + int dryMixedMortarProductionCompanyNumTotal = dryMixedMortarProductionCompanyNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setDryMixedMortarProductionCompanyNumTotal(dryMixedMortarProductionCompanyNumTotal); + BigDecimal dryMixedMortarProductiveCapacityTotal = dryMixedMortarProductiveCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarProductiveCapacityTotal(dryMixedMortarProductiveCapacityTotal); + BigDecimal dryMixedMortarBulkCapacityTotal = dryMixedMortarBulkCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarBulkCapacityTotal(dryMixedMortarBulkCapacityTotal); + + BigDecimal thisMonthTotalOutputTotal = thisMonthTotalOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthTotalOutputTotal(thisMonthTotalOutputTotal); + BigDecimal thisMonthAccumulativeOutputTotal = thisMonthAccumulativeOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisMonthAccumulativeOutputTotal(thisMonthAccumulativeOutputTotal); + BigDecimal dryMixedMortarThisMonthOutputTotal = dryMixedMortarThisMonthOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarThisMonthOutputTotal(dryMixedMortarThisMonthOutputTotal); + BigDecimal dryMixedMortarThisMonthAccumulativeOutputTotal = dryMixedMortarThisMonthAccumulativeOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarThisMonthAccumulativeOutputTotal(dryMixedMortarThisMonthAccumulativeOutputTotal); + BigDecimal dryMixedMortarIncrementTotal = dryMixedMortarIncrementList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarIncrementTotal(dryMixedMortarIncrementTotal); + BigDecimal preYearDryMixedMortarThisMonthAccumulativeOutputTotal = preYearDryMixedMortarThisMonthAccumulativeOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + // 合计普通干混砂浆增长率: 合计普通干混砂浆同比增长量 / 合计去年这个月普通干混砂浆累计产量 * 100 + BigDecimal dryMixedMortarGrowthRateTotal = BigDecimal.ZERO; + if (BigDecimal.ZERO.compareTo(preYearDryMixedMortarThisMonthAccumulativeOutputTotal) != 0){ + dryMixedMortarGrowthRateTotal = dryMixedMortarIncrementTotal.divide(preYearDryMixedMortarThisMonthAccumulativeOutputTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + } + vo.setDryMixedMortarGrowthRateTotal(dryMixedMortarGrowthRateTotal); + BigDecimal dryMixedMortarThisMonthBulkQuantityTotal = dryMixedMortarThisMonthBulkQuantityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarThisMonthBulkQuantityTotal(dryMixedMortarThisMonthBulkQuantityTotal); + BigDecimal dryMixedMortarAccumulativeBulkQuantityTotal = dryMixedMortarAccumulativeBulkQuantityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setDryMixedMortarAccumulativeBulkQuantityTotal(dryMixedMortarAccumulativeBulkQuantityTotal); + BigDecimal wetMortarThisMonthOutputTotal = wetMortarThisMonthOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setWetMortarThisMonthOutputTotal(wetMortarThisMonthOutputTotal); + BigDecimal wetMortarAccumulativeOutputTotal = wetMortarAccumulativeOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setWetMortarAccumulativeOutputTotal(wetMortarAccumulativeOutputTotal); + BigDecimal bulkCementThisMonthUsageTotal = bulkCementThisMonthUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setBulkCementThisMonthUsageTotal(bulkCementThisMonthUsageTotal); + BigDecimal bulkCementAccumulativeUsageTotal = bulkCementAccumulativeUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setBulkCementAccumulativeUsageTotal(bulkCementAccumulativeUsageTotal); + BigDecimal wasteThisMonthComprehensiveUtilizationTotal = wasteThisMonthComprehensiveUtilizationList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setWasteThisMonthComprehensiveUtilizationTotal(wasteThisMonthComprehensiveUtilizationTotal); + BigDecimal wasteAccumulativeComprehensiveUtilizationTotal = wasteAccumulativeComprehensiveUtilizationList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setWasteAccumulativeComprehensiveUtilizationTotal(wasteAccumulativeComprehensiveUtilizationTotal); + } + + private void getCityNonProAreasTotalData(List vos, ResNonProhibitedAreasDataUploadDetailVO vo) { + // 合计销售点总数 + List salePointAccumulativeNumList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getSalePointAccumulativeNum).collect(Collectors.toList()); + // 合计水泥企业建点数量 + List cementCompanyBuildPointNumList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getCementCompanyBuildPointNum).collect(Collectors.toList()); + // 合计其他投资建点数量 + List otherInvestmentBuildPointNumList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getOtherInvestmentBuildPointNum).collect(Collectors.toList()); + // 合计销售量 + List saleVolumeList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getSaleVolume).collect(Collectors.toList()); + // 合计散装水泥罐数量 + List bulkCementTankNumList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getBulkCementTankNum).collect(Collectors.toList()); + + // 合计散装水泥罐容量 + List bulkCementTankCapacityList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getBulkCementTankCapacity).collect(Collectors.toList()); + // 合计水泥使用量 + List cementUsageList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getCementUsage).collect(Collectors.toList()); + // 合计散装水泥使用量 + List bulkCementUsageList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getBulkCementUsage).collect(Collectors.toList()); + // 合计生产预拌混凝土使用散装水泥量 + List readyMixedConcreteBulkCementUsageList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getReadyMixedConcreteBulkCementUsage).collect(Collectors.toList()); + // 合计生产水泥制品使用散装水泥量 + List cementProductsBulkCementUsageList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getCementProductsBulkCementUsage).collect(Collectors.toList()); + + // 合计非禁现区生产预拌混凝土产量 + List readyMixedConcreteOutputList = vos.stream().map(ResNonProhibitedAreasDataUploadDetailVO::getReadyMixedConcreteOutput).collect(Collectors.toList()); + + int salePointAccumulativeNumTotal = salePointAccumulativeNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setSalePointAccumulativeNumTotal(salePointAccumulativeNumTotal); + int cementCompanyBuildPointNumTotal = cementCompanyBuildPointNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setCementCompanyBuildPointNumTotal(cementCompanyBuildPointNumTotal); + int otherInvestmentBuildPointNumTotal = otherInvestmentBuildPointNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setOtherInvestmentBuildPointNumTotal(otherInvestmentBuildPointNumTotal); + BigDecimal saleVolumeTotal = saleVolumeList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setSaleVolumeTotal(saleVolumeTotal); + int bulkCementTankNumTotal = bulkCementTankNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setBulkCementTankNumTotal(bulkCementTankNumTotal); + + BigDecimal bulkCementTankCapacityTotal = bulkCementTankCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setBulkCementTankCapacityTotal(bulkCementTankCapacityTotal); + BigDecimal cementUsageTotal = cementUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCementUsageTotal(cementUsageTotal); + BigDecimal bulkCementUsageTotal = bulkCementUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setBulkCementUsageTotal(bulkCementUsageTotal); + BigDecimal readyMixedConcreteBulkCementUsageTotal = readyMixedConcreteBulkCementUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setReadyMixedConcreteBulkCementUsageTotal(readyMixedConcreteBulkCementUsageTotal); + BigDecimal cementProductsBulkCementUsageTotal = cementProductsBulkCementUsageList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setCementProductsBulkCementUsageTotal(cementProductsBulkCementUsageTotal); + + // 合计散装水泥使用率: 合计散装水泥使用量 / 合计水泥使用量 * 100 + BigDecimal bulkCementUsageRateTotal = bulkCementUsageTotal.divide(cementUsageTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + vo.setBulkCementUsageRateTotal(bulkCementUsageRateTotal); + + BigDecimal readyMixedConcreteOutputTotal = readyMixedConcreteOutputList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setReadyMixedConcreteOutputTotal(readyMixedConcreteOutputTotal); + + } + private void getCityBulkCementLogFacStaTotalData(List vos, ResBulkCementLogFacStaDataUploadDetailVO vo) { + // 合计年初数量 + List yearBeginNumList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearBeginNum).collect(Collectors.toList()); + // 合计年初容量 + List yearBeginCapacityList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearBeginCapacity).collect(Collectors.toList()); + // 合计本年新增容量 + List thisYearNewAddCapacityList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearNewAddCapacity).collect(Collectors.toList()); + // 合计本年新增数量 + List thisYearNewAddNumList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearNewAddNum).collect(Collectors.toList()); + // 合计本年报废数量 + List thisYearScrapNumList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearScrapNum).collect(Collectors.toList()); + + // 合计本年报废容量 + List thisYearScrapCapacityList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearScrapCapacity).collect(Collectors.toList()); + // 合计年末数量 + List yearEndNumList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearEndNum).collect(Collectors.toList()); + // 合计年末容量 + List yearEndCapacityList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getYearEndCapacity).collect(Collectors.toList()); + // 合计本年实际作业量 + List thisYearWorkAmountList = vos.stream().map(ResBulkCementLogFacStaDataUploadDetailVO::getThisYearWorkAmount).collect(Collectors.toList()); + + int yearBeginNumTotal = yearBeginNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setYearBeginNumTotal(yearBeginNumTotal); + BigDecimal yearBeginCapacityTotal = yearBeginCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setYearBeginCapacityTotal(yearBeginCapacityTotal); + BigDecimal thisYearNewAddCapacityTotal = thisYearNewAddCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisYearNewAddCapacityTotal(thisYearNewAddCapacityTotal); + int thisYearNewAddNumTotal = thisYearNewAddNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setThisYearNewAddNumTotal(thisYearNewAddNumTotal); + int thisYearScrapNumTotal = thisYearScrapNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setThisYearScrapNumTotal(thisYearScrapNumTotal); + + BigDecimal thisYearScrapCapacityTotal = thisYearScrapCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisYearScrapCapacityTotal(thisYearScrapCapacityTotal); + int yearEndNumTotal = yearEndNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setYearEndNumTotal(yearEndNumTotal); + BigDecimal yearEndCapacityTotal = yearEndCapacityList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setYearEndCapacityTotal(yearEndCapacityTotal); + BigDecimal thisYearWorkAmountTotal = thisYearWorkAmountList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisYearWorkAmountTotal(thisYearWorkAmountTotal); + } + private void getCityMaterialLogEquipStaTotalData(List vos, ResMaterialLogEquipStaDataUploadDetailVO vo) { + // 合计年初数量 + List yearBeginNumList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearBeginNum).collect(Collectors.toList()); + // 合计年初额定量 + List yearBeginNominalRateList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearBeginNominalRate).collect(Collectors.toList()); + // 合计本年新增额定量 + List thisYearNewAddNominalRateList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearNewAddNominalRate).collect(Collectors.toList()); + // 合计本年新增数量 + List thisYearNewAddNumList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearNewAddNum).collect(Collectors.toList()); + // 合计本年减少数量 + List thisYearDecreaseNumList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearDecreaseNum).collect(Collectors.toList()); + + // 合计本年减少额定量 + List thisYearDecreaseNominalRateList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getThisYearDecreaseNominalRate).collect(Collectors.toList()); + // 合计年末数量 + List yearEndNumList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearEndNum).collect(Collectors.toList()); + // 合计年末额定量 + List yearEndNominalList = vos.stream().map(ResMaterialLogEquipStaDataUploadDetailVO::getYearEndNominal).collect(Collectors.toList()); + + int yearBeginNumTotal = yearBeginNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setYearBeginNumTotal(yearBeginNumTotal); + BigDecimal yearBeginNominalRateTotal = yearBeginNominalRateList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setYearBeginNominalRateTotal(yearBeginNominalRateTotal); + BigDecimal thisYearNewAddNominalRateTotal = thisYearNewAddNominalRateList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisYearNewAddNominalRateTotal(thisYearNewAddNominalRateTotal); + int thisYearNewAddNumTotal = thisYearNewAddNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setThisYearNewAddNumTotal(thisYearNewAddNumTotal); + int thisYearDecreaseNumTotal = thisYearDecreaseNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setThisYearDecreaseNumTotal(thisYearDecreaseNumTotal); + + BigDecimal thisYearDecreaseNominalRateTotal = thisYearDecreaseNominalRateList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setThisYearDecreaseNominalRateTotal(thisYearDecreaseNominalRateTotal); + int yearEndNumTotal = yearEndNumList.stream().filter(Objects::nonNull).mapToInt(Integer::intValue).sum(); + vo.setYearEndNumTotal(yearEndNumTotal); + BigDecimal yearEndNominalTotal = yearEndNominalList.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + vo.setYearEndNominalTotal(yearEndNominalTotal); + } + + public String uploadDataQueryModify(ReqDataQueryModifyPO req) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long relevanceId = req.getRelevanceId(); + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceService.getById(relevanceId); + VUtils.isTrue(Objects.isNull(dataRelevance)).throwMessage("关联数据不存在!"); + dataRelevance.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + dataRelevance.setPreparer(req.getPreparer()); + dataRelevance.setReviewer(req.getReviewer()); + dataRelevance.setSubmissionDate(req.getSubmissionDate()); + dataRelevance.setUpdateOn(LocalDateTime.now()); + dataRelevance.setUpdateBy(userDetail.getUserId()); + dataRelevanceService.updateById(dataRelevance); + return "编辑成功"; + } + + public void exportQueryData(ReqDataUploadListPO req, HttpServletResponse response) { + + ResDataQueryDetailVO resDataQueryDetailVo = uploadDataQueryDetail(req); + + Integer auditDataType = req.getAuditDataType(); + String templateName; + String templatePath; + List dtoList = Lists.newArrayList(); + List bulkCementLogFacStaDto1List = Lists.newArrayList(); + List bulkCementLogFacStaDto2List = Lists.newArrayList(); + List bulkCementLogFacStaDto3List = Lists.newArrayList(); + List materialLogEquipStaDto1List = Lists.newArrayList(); + List materialLogEquipStaDto2List = Lists.newArrayList(); + List materialLogEquipStaDto3List = Lists.newArrayList(); + List materialLogEquipStaDto4List = Lists.newArrayList(); + List materialLogEquipStaDto5List = Lists.newArrayList(); + List materialLogEquipStaDto6List = Lists.newArrayList(); + List materialLogEquipStaDto7List = Lists.newArrayList(); + List materialLogEquipStaDto8List = Lists.newArrayList(); + + File directory = new File(""); + LocalDateTime reportMonth = req.getReportMonth(); + Integer reportYear = req.getReportYear(); + //设置日期格式 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日"); + String date; + String unitResponsiblePerson = StrPool.EMPTY; + String preparer = StrPool.EMPTY; + String reviewer = StrPool.EMPTY; + String submissionDate = StrPool.EMPTY; + switch (auditDataType) { + // 散装水泥供应量数据 + case 1: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getBulkCementSupplyDataVo())) { + templateName = ReportConstant.BULK_CEMENT_SUPPLY_TEMPLATE; + dtoList = getBulkCementSupplyDtoList(resDataQueryDetailVo); + }else { + templateName = ReportConstant.BULK_CEMENT_SUPPLY_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份"); + date = sdf.format(NdDateUtils.localDateTime2Date(reportMonth)); + break; + // 中转库进出量统计数据 + case 2: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getBulkCementTransferDataVo())) { + templateName = ReportConstant.BULK_CEMENT_TRANSFER_TEMPLATE; + dtoList = getBulkCementTransferDtoList(resDataQueryDetailVo); + }else { + templateName = ReportConstant.BULK_CEMENT_TRANSFER_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份"); + date = sdf.format(NdDateUtils.localDateTime2Date(reportMonth)); + break; + // 温台舟使用量快报数据 + case 3: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getBulkCementThreeCityUsageDataVo())) { + templateName = ReportConstant.BULK_CEMENT_THREE_CITY_USAGE_TEMPLATE; + dtoList = getBulkCementThreeCityUsageDtoList(resDataQueryDetailVo); + }else { + templateName = ReportConstant.BULK_CEMENT_THREE_CITY_USAGE_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份"); + date = sdf.format(NdDateUtils.localDateTime2Date(reportMonth)); + break; + // 混凝土供应量快报数据 + case 4: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getConcreteSupplyDataVo())) { + templateName = ReportConstant.CONCRETE_SUPPLY_TEMPLATE; + dtoList = getConcreteSupplyDtoList(resDataQueryDetailVo); + }else { + templateName = ReportConstant.CONCRETE_SUPPLY_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份"); + date = sdf.format(NdDateUtils.localDateTime2Date(reportMonth)); + break; + // 砂浆供应量快报数据 + case 5: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getMortarSupplyDataVo())) { + templateName = ReportConstant.MORTAR_SUPPLY_TEMPLATE; + List dataList = new ArrayList<>(); + List mortarSupplyDtoList = getMortarSupplyDtoList(resDataQueryDetailVo); + mortarSupplyDtoList.forEach(m -> { + LinkedHashMap dataMap = new LinkedHashMap<>(); + dataMap.put("regionName",m.getRegionName()); + dataMap.put("twoCategoryGuidGoal",m.getTwoCategoryGuidGoal()); + dataMap.put("dryMixedMortarProductionCompanyNum",m.getDryMixedMortarProductionCompanyNum()); + dataMap.put("dryMixedMortarProductiveCapacity",m.getDryMixedMortarProductiveCapacity()); + dataMap.put("dryMixedMortarBulkCapacity",m.getDryMixedMortarBulkCapacity()); + dataMap.put("thisMonthTotalOutput",m.getThisMonthTotalOutput()); + dataMap.put("thisMonthAccumulativeOutput",m.getThisMonthAccumulativeOutput()); + dataMap.put("dryMixedMortarThisMonthOutput",m.getDryMixedMortarThisMonthOutput()); + dataMap.put("dryMixedMortarThisMonthAccumulativeOutput",m.getDryMixedMortarThisMonthAccumulativeOutput()); + dataMap.put("dryMixedMortarIncrement",m.getDryMixedMortarIncrement()); + dataMap.put("dryMixedMortarGrowthRate",m.getDryMixedMortarGrowthRate()); + dataMap.put("dryMixedMortarThisMonthBulkQuantity",m.getDryMixedMortarThisMonthBulkQuantity()); + dataMap.put("dryMixedMortarAccumulativeBulkQuantity",m.getDryMixedMortarAccumulativeBulkQuantity()); + dataMap.put("wetMortarThisMonthOutput",m.getWetMortarThisMonthOutput()); + dataMap.put("wetMortarAccumulativeOutput",m.getWetMortarAccumulativeOutput()); + dataMap.put("bulkCementThisMonthUsage",m.getBulkCementThisMonthUsage()); + dataMap.put("bulkCementAccumulativeUsage",m.getBulkCementAccumulativeUsage()); + dataMap.put("wasteAccumulativeComprehensiveUtilization",m.getWasteAccumulativeComprehensiveUtilization()); + dataList.add(dataMap); + }); + dtoList = dataList; + }else { + templateName = ReportConstant.MORTAR_SUPPLY_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份"); + date = sdf.format(NdDateUtils.localDateTime2Date(reportMonth)); + break; + // 非禁现区域散装水泥销售使用情况数据 + case 6: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getNonProAreasDataVo())) { + templateName = ReportConstant.NON_PRO_AREAS_TEMPLATE; + dtoList = getNonProAreasDtoList(resDataQueryDetailVo); + }else { + templateName = ReportConstant.NON_PRO_AREAS_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请传入上报年份!"); + date = reportYear + ReportConstant.YEAR; + ResNonProhibitedAreasDataQueryDetailVO nonProAreasDataVo = resDataQueryDetailVo.getNonProAreasDataVo(); + unitResponsiblePerson = nonProAreasDataVo.getUnitResponsiblePerson(); + preparer = nonProAreasDataVo.getPreparer(); + reviewer = nonProAreasDataVo.getReviewer(); + if (Objects.nonNull(nonProAreasDataVo.getSubmissionDate())) { + submissionDate = sdf2.format(NdDateUtils.localDateTime2Date(nonProAreasDataVo.getSubmissionDate())); + } + break; + // 散装水泥物流设施统计年报表数据 + case 7: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getBulkCementLogFacStaDataVo())) { + templateName = ReportConstant.BULK_CEMENT_LOG_FAC_STA_TEMPLATE; + // 发放库 + bulkCementLogFacStaDto1List = getBulkCementLogFacStaDtoList(resDataQueryDetailVo,ReportConstant.ISSUE_LIBRARY); + // 中转库 + bulkCementLogFacStaDto2List = getBulkCementLogFacStaDtoList(resDataQueryDetailVo,ReportConstant.TRANSFER_LIBRARY); + // 固定接收库 + bulkCementLogFacStaDto3List = getBulkCementLogFacStaDtoList(resDataQueryDetailVo,ReportConstant.FIX_RECEIVE_LIBRARY); + }else { + templateName = ReportConstant.BULK_CEMENT_LOG_FAC_STA_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请传入上报年份!"); + date = reportYear + ReportConstant.YEAR; + ResBulkCementLogFacStaDataQueryVO bulkCementLogFacStaDataVo = resDataQueryDetailVo.getBulkCementLogFacStaDataVo(); + unitResponsiblePerson = bulkCementLogFacStaDataVo.getUnitResponsiblePerson(); + preparer = bulkCementLogFacStaDataVo.getPreparer(); + reviewer = bulkCementLogFacStaDataVo.getReviewer(); + if (Objects.nonNull(bulkCementLogFacStaDataVo.getSubmissionDate())) { + submissionDate = sdf2.format(NdDateUtils.localDateTime2Date(bulkCementLogFacStaDataVo.getSubmissionDate())); + } + break; + // 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据 + case 8: + if (Objects.nonNull(resDataQueryDetailVo) && Objects.nonNull(resDataQueryDetailVo.getMaterialLogEquipStaDataVo())) { + templateName = ReportConstant.MATERIAL_LOG_EQUIP_STA_TEMPLATE; + // 专用汽车 + materialLogEquipStaDto1List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.SPECIAL_VEHICLE); + // 专用船 + materialLogEquipStaDto2List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.SPECIAL_VESSEL); + // 散装水泥罐 + materialLogEquipStaDto3List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.BULK_CEMENT_TANK); + // 混凝土搅拌车 + materialLogEquipStaDto4List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.CONCRETE_MIXER_TRUCK); + // 混凝土泵车 + materialLogEquipStaDto5List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.CONCRETE_PUMP_TRUCK); + // 干混砂浆运输车 + materialLogEquipStaDto6List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.DRY_MIX_MORTAR_TRUCK); + // 干混砂浆移动简仓 + materialLogEquipStaDto7List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.DRY_MIX_MORTAR_MOVING_STORAGE); + // 干混砂浆背罐车 + materialLogEquipStaDto8List = getMaterialLogEquipStaDtoList(resDataQueryDetailVo,ReportConstant.DRY_MIX_MORTAR_BACK_TANK_CAR); + }else { + templateName = ReportConstant.MATERIAL_LOG_EQUIP_STA_EMPTY_TEMPLATE; + } + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请传入上报年份!"); + date = reportYear + ReportConstant.YEAR; + ResMaterialLogEquipStaDataQueryVO materialLogEquipStaDataVo = resDataQueryDetailVo.getMaterialLogEquipStaDataVo(); + unitResponsiblePerson = materialLogEquipStaDataVo.getUnitResponsiblePerson(); + preparer = materialLogEquipStaDataVo.getPreparer(); + reviewer = materialLogEquipStaDataVo.getReviewer(); + if (Objects.nonNull(materialLogEquipStaDataVo.getSubmissionDate())) { + submissionDate = sdf2.format(NdDateUtils.localDateTime2Date(materialLogEquipStaDataVo.getSubmissionDate())); + } + break; + default: + throw new IllegalStateException("Unexpected value: " + auditDataType); + } + templatePath = directory.getAbsolutePath() + File.separator + "template" + File.separator + templateName + ".xls"; + // 获取本地目录的Excel模板 + TemplateExportParams temp = new TemplateExportParams(templatePath); + temp.setSheetNum(new Integer[] {0}); + temp.setSheetName(new String[] {templateName}); + Map map = new HashMap<>(4); + map.put("date", date); + map.put("unitResponsiblePerson", unitResponsiblePerson); + map.put("preparer", preparer); + map.put("reviewer", reviewer); + map.put("submissionDate", submissionDate); + if (UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode().equals(auditDataType)){ + map.put("map1List", bulkCementLogFacStaDto1List); + map.put("map2List", bulkCementLogFacStaDto2List); + map.put("map3List", bulkCementLogFacStaDto3List); + } else if (UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode().equals(auditDataType)) { + map.put("map1List", materialLogEquipStaDto1List); + map.put("map2List", materialLogEquipStaDto2List); + map.put("map3List", materialLogEquipStaDto3List); + map.put("map4List", materialLogEquipStaDto4List); + map.put("map5List", materialLogEquipStaDto5List); + map.put("map6List", materialLogEquipStaDto6List); + map.put("map7List", materialLogEquipStaDto7List); + map.put("map8List", materialLogEquipStaDto8List); + } else { + map.put("mapList", dtoList); + } + Workbook workbook = ExcelExportUtil.exportExcel(temp, map); + if (!UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode().equals(auditDataType) && + !UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode().equals(auditDataType) && + CollUtil.isEmpty(dtoList)) { + // 输出空模板 + // 获取本地目录的空Excel模板 + try { + InputStream templateInputStream = this.getClass().getClassLoader().getResourceAsStream("template" + File.separator + templateName + ".xlsx"); + OutputStream outputStream = response.getOutputStream(); + // 设置要下载的文件的名称 + ExcelDownUtil.setFileName(templateName, response); + // 设置文件的MIME类型 + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + + byte[] b = new byte[2048]; + int len; + while ((len = templateInputStream.read(b)) != -1) { + outputStream.write(b, 0, len); + } + templateInputStream.close(); + outputStream.flush(); + outputStream.close(); + } catch (IOException e) { + throw new BizException("读取模板失败!"); + } + return; + } + if (workbook == null){ + throw new BizException("读取编辑表模板失败!"); + } + // 重置响应对象 + response.reset(); + try { + response.setHeader("Content-disposition", + "attachment;filename*=utf-8''" + URLEncoder.encode(Objects.requireNonNull(templateName), "UTF-8") + ".xlsx"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setContentType(ExcelUtil.XLS_CONTENT_TYPE); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + // 写出数据输出流到页面 + try { + OutputStream output = response.getOutputStream(); + BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output); + workbook.write(bufferedOutPut); + bufferedOutPut.flush(); + bufferedOutPut.close(); + output.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private List getMaterialLogEquipStaDtoList(ResDataQueryDetailVO resDataQueryDetailVo,String key) { + List dtoList; + ResMaterialLogEquipStaDataQueryVO materialLogEquipStaDataQueryVo = resDataQueryDetailVo.getMaterialLogEquipStaDataVo(); + Map materialLogEquipStaDataMap = materialLogEquipStaDataQueryVo.getMaterialLogEquipStaDataMap(); + + List dataList = Lists.newArrayList(); + // materialLogEquipStaDataMap为以装备名称为key的8组map值 + ResMaterialLogEquipStaDataQueryDetailVO detailVo = (ResMaterialLogEquipStaDataQueryDetailVO) materialLogEquipStaDataMap.get(key); + Map dataMap = detailVo.getMaterialLogEquipDataMap(); + Set> entries = dataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) dataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream().filter(v -> !ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()); + String cityNameKey = entry.getKey(); + ResMaterialLogEquipStaDataUploadDetailVO totalVo = new ResMaterialLogEquipStaDataUploadDetailVO(); + ResMaterialLogEquipStaDataUploadDetailVO vo = value.stream().filter(v -> ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()).get(0); + totalVo.setRegionName(cityNameKey); + totalVo.setYearBeginNum(vo.getYearBeginNumTotal()); + totalVo.setYearBeginNominalRate(vo.getYearBeginNominalRateTotal()); + totalVo.setThisYearNewAddNum(vo.getThisYearNewAddNumTotal()); + totalVo.setThisYearNewAddNominalRate(vo.getThisYearNewAddNominalRateTotal()); + totalVo.setThisYearDecreaseNum(vo.getThisYearDecreaseNumTotal()); + totalVo.setThisYearDecreaseNominalRate(vo.getThisYearDecreaseNominalRateTotal()); + totalVo.setYearEndNum(vo.getYearEndNumTotal()); + totalVo.setYearEndNominal(vo.getYearEndNominalTotal()); + totalVo.setRemark(vo.getRemark()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + MaterialLogEquipStaQueryDataExportDTO exportDto = new MaterialLogEquipStaQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + private List getBulkCementLogFacStaDtoList(ResDataQueryDetailVO resDataQueryDetailVo, String key) { + List dtoList = Lists.newArrayList(); + ResBulkCementLogFacStaDataQueryVO bulkCementLogFacStaDataQueryVo = resDataQueryDetailVo.getBulkCementLogFacStaDataVo(); + Map bulkCementLogFacStaDataMap = bulkCementLogFacStaDataQueryVo.getBulkCementLogFacStaDataMap(); + + List dataList = Lists.newArrayList(); + // bulkCementLogFacStaDataMap为以设备名称为key的三组map值 + ResBulkCementLogFacStaDataQueryDetailVO detailVo = (ResBulkCementLogFacStaDataQueryDetailVO) bulkCementLogFacStaDataMap.get(key); + Map dataMap = detailVo.getBulkCementLogFacDataMap(); + Set> entries = dataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) dataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream().filter(v -> !ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()); + String cityNameKey = entry.getKey(); + ResBulkCementLogFacStaDataUploadDetailVO totalVo = new ResBulkCementLogFacStaDataUploadDetailVO(); + ResBulkCementLogFacStaDataUploadDetailVO vo = value.stream().filter(v -> ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()).get(0); + totalVo.setRegionName(cityNameKey); + totalVo.setYearBeginNum(vo.getYearBeginNumTotal()); + totalVo.setYearBeginCapacity(vo.getYearBeginCapacityTotal()); + totalVo.setThisYearNewAddNum(vo.getThisYearNewAddNumTotal()); + totalVo.setThisYearNewAddCapacity(vo.getThisYearNewAddCapacityTotal()); + totalVo.setThisYearScrapNum(vo.getThisYearScrapNumTotal()); + totalVo.setThisYearScrapCapacity(vo.getThisYearScrapCapacityTotal()); + totalVo.setYearEndNum(vo.getYearEndNumTotal()); + totalVo.setYearEndCapacity(vo.getYearEndCapacityTotal()); + totalVo.setThisYearWorkAmount(vo.getThisYearWorkAmountTotal()); + totalVo.setRemark(vo.getRemark()); + dataList.add(totalVo); + dataList.addAll(vos); + } + List exportDtoList = dataList.stream().map(d -> { + BulkCementLogFacStaQueryDataExportDTO exportDto = new BulkCementLogFacStaQueryDataExportDTO(); + BeanUtils.copyProperties(d,exportDto); + return exportDto; + }).collect(Collectors.toList()); + dtoList.addAll(exportDtoList); + return dtoList; + } + private List getNonProAreasDtoList(ResDataQueryDetailVO resDataQueryDetailVo) { + List dtoList; + ResNonProhibitedAreasDataQueryDetailVO nonProAreasDataVo = resDataQueryDetailVo.getNonProAreasDataVo(); + Map nonProAreasDataMap = nonProAreasDataVo.getNonProAreasDataMap(); + List dataList = Lists.newArrayList(); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + Set> entries = nonProAreasDataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) nonProAreasDataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream().filter(v -> !ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()); + String key = entry.getKey(); + ResNonProhibitedAreasDataUploadDetailVO totalVo = new ResNonProhibitedAreasDataUploadDetailVO(); + ResNonProhibitedAreasDataUploadDetailVO vo = value.stream().filter(v -> ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()).get(0); + totalVo.setRegionName(key); + totalVo.setSalePointAccumulativeNum(vo.getSalePointAccumulativeNumTotal()); + totalVo.setCementCompanyBuildPointNum(vo.getCementCompanyBuildPointNumTotal()); + totalVo.setOtherInvestmentBuildPointNum(vo.getOtherInvestmentBuildPointNumTotal()); + totalVo.setSaleVolume(vo.getSaleVolumeTotal()); + totalVo.setBulkCementTankNum(vo.getBulkCementTankNumTotal()); + totalVo.setBulkCementTankCapacity(vo.getBulkCementTankCapacityTotal()); + totalVo.setCementUsage(vo.getCementUsageTotal()); + totalVo.setBulkCementUsage(vo.getBulkCementUsageTotal()); + totalVo.setReadyMixedConcreteBulkCementUsage(vo.getReadyMixedConcreteBulkCementUsageTotal()); + totalVo.setBulkCementUsageRate(vo.getBulkCementUsageRateTotal()); + totalVo.setReadyMixedConcreteOutput(vo.getReadyMixedConcreteOutputTotal()); + totalVo.setRemark(vo.getRemark()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + NonProAreasQueryDataExportDTO exportDto = new NonProAreasQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + private List getMortarSupplyDtoList(ResDataQueryDetailVO resDataQueryDetailVo) { + List dtoList; + ResMortarSupplyDataQueryDetailVO mortarSupplyDataVo = resDataQueryDetailVo.getMortarSupplyDataVo(); + Map mortarSupplyDataMap = mortarSupplyDataVo.getMortarSupplyDataMap(); + List dataList = Lists.newArrayList(); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + Set> entries = mortarSupplyDataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) mortarSupplyDataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream().filter(v -> !ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()); + String key = entry.getKey(); + ResMortarSupplyDataUploadDetailVO totalVo = new ResMortarSupplyDataUploadDetailVO(); + ResMortarSupplyDataUploadDetailVO vo = value.stream().filter(v -> ReportConstant.TOTAL.equals(v.getRegionName())).collect(Collectors.toList()).get(0); + totalVo.setRegionName(key); + totalVo.setTwoCategoryGuidGoal(vo.getTwoCategoryGuidGoalTotal()); + totalVo.setDryMixedMortarProductionCompanyNum(vo.getDryMixedMortarProductionCompanyNumTotal()); + totalVo.setDryMixedMortarProductiveCapacity(vo.getDryMixedMortarProductiveCapacityTotal()); + totalVo.setDryMixedMortarBulkCapacity(vo.getDryMixedMortarBulkCapacityTotal()); + totalVo.setThisMonthTotalOutput(vo.getThisMonthTotalOutputTotal()); + totalVo.setThisMonthAccumulativeOutput(vo.getThisMonthAccumulativeOutputTotal()); + totalVo.setDryMixedMortarThisMonthOutput(vo.getDryMixedMortarThisMonthOutputTotal()); + totalVo.setDryMixedMortarThisMonthAccumulativeOutput(vo.getDryMixedMortarThisMonthAccumulativeOutputTotal()); + totalVo.setDryMixedMortarIncrement(vo.getDryMixedMortarIncrementTotal()); + totalVo.setDryMixedMortarGrowthRate(vo.getDryMixedMortarGrowthRateTotal()); + totalVo.setDryMixedMortarThisMonthBulkQuantity(vo.getDryMixedMortarThisMonthBulkQuantityTotal()); + totalVo.setDryMixedMortarAccumulativeBulkQuantity(vo.getDryMixedMortarAccumulativeBulkQuantityTotal()); + totalVo.setWetMortarThisMonthOutput(vo.getWetMortarThisMonthOutputTotal()); + totalVo.setWetMortarAccumulativeOutput(vo.getWetMortarAccumulativeOutputTotal()); + totalVo.setBulkCementThisMonthUsage(vo.getBulkCementThisMonthUsageTotal()); + totalVo.setBulkCementAccumulativeUsage(vo.getBulkCementAccumulativeUsageTotal()); + totalVo.setWasteAccumulativeComprehensiveUtilization(vo.getWasteAccumulativeComprehensiveUtilizationTotal()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + MortarSupplyQueryDataExportDTO exportDto = new MortarSupplyQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + private List getConcreteSupplyDtoList(ResDataQueryDetailVO resDataQueryDetailVo) { + List dtoList; + ResConcreteSupplyDataQueryDetailVO concreteSupplyDataVo = resDataQueryDetailVo.getConcreteSupplyDataVo(); + Map concreteSupplyDataMap = concreteSupplyDataVo.getConcreteSupplyDataMap(); + List dataList = Lists.newArrayList(); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + Set> entries = concreteSupplyDataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) concreteSupplyDataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream() + .filter(v -> !ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()); + String key = entry.getKey(); + ResConcreteSupplyDataUploadDetailVO totalVo = new ResConcreteSupplyDataUploadDetailVO(); + ResConcreteSupplyDataUploadDetailVO vo = value.stream() + .filter(v -> ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()).get(0); + totalVo.setUnitName(key); + totalVo.setThreeCategoryGuidGoal(vo.getThreeCategoryGuidGoalTotal()); + totalVo.setProductionCompanyNums(vo.getProductionCompanyNumsTotal()); + totalVo.setAnnualDesignProductionCapacity(vo.getAnnualDesignProductionCapacityTotal()); + totalVo.setThisMonthOutput(vo.getThisMonthOutputTotal()); + totalVo.setAccumulativeOutput(vo.getAccumulativeOutputTotal()); + totalVo.setThisMonthCementUsage(vo.getThisMonthCementUsageTotal()); + totalVo.setCementAccumulativeUsage(vo.getCementAccumulativeUsageTotal()); + totalVo.setThisMonthWasteUtilization(vo.getThisMonthWasteUtilizationTotal()); + totalVo.setAccumulativeWasteUtilization(vo.getAccumulativeWasteUtilizationTotal()); + totalVo.setRemark(vo.getRemark()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + ConcreteSupplyQueryDataExportDTO exportDto = new ConcreteSupplyQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + private List getBulkCementThreeCityUsageDtoList(ResDataQueryDetailVO resDataQueryDetailVo) { + List dtoList; + ResBulkCementThreeCityUsageDataQueryDetailVO bulkCementThreeCityUsageDataVo = resDataQueryDetailVo.getBulkCementThreeCityUsageDataVo(); + Map bulkCementThreeCityUsageDataMap = bulkCementThreeCityUsageDataVo.getBulkCementThreeCityUsageDataMap(); + List dataList = Lists.newArrayList(); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + Set> entries = bulkCementThreeCityUsageDataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) bulkCementThreeCityUsageDataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream() + .filter(v -> !ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()); + String key = entry.getKey(); + ResBulkCementThreeCityUsageDataUploadDetailVO totalVo = new ResBulkCementThreeCityUsageDataUploadDetailVO(); + ResBulkCementThreeCityUsageDataUploadDetailVO vo = value.stream() + .filter(v -> ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()).get(0); + totalVo.setUnitName(key); + totalVo.setYearTarget(vo.getYearTargetTotal()); + totalVo.setPercentageOfAnnualTarget(vo.getPercentageOfAnnualTargetTotal()); + totalVo.setThisMonthUsage(vo.getThisMonthUsageTotal()); + totalVo.setAccumulativeUsage(vo.getAccumulativeUsageTotal()); + totalVo.setGrowthRate(vo.getGrowthRateTotal()); + totalVo.setThisProvinceThisMonthUsage(vo.getThisProvinceThisMonthUsageTotal()); + totalVo.setThisProvinceAccumulativeUsage(vo.getThisProvinceAccumulativeUsageTotal()); + totalVo.setOtherProvinceAccumulativeUsage(vo.getOtherProvinceAccumulativeUsageTotal()); + totalVo.setOtherProvinceAccumulativeUsage(vo.getOtherProvinceAccumulativeUsageTotal()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + BulkCementThreeCityUsageQueryDataExportDTO exportDto = new BulkCementThreeCityUsageQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + private List getBulkCementTransferDtoList(ResDataQueryDetailVO resDataQueryDetailVo) { + List dtoList; + ResBulkCementTransferDataQueryDetailVO bulkCementTransferDataVo = resDataQueryDetailVo.getBulkCementTransferDataVo(); + Map bulkCementTransferDataMap = bulkCementTransferDataVo.getBulkCementTransferDataMap(); + List dataList = Lists.newArrayList(); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + Set> entries = bulkCementTransferDataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) bulkCementTransferDataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream().filter(v -> !ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()); + String key = entry.getKey(); + ResBulkCementTransferDataUploadDetailVO totalVo = new ResBulkCementTransferDataUploadDetailVO(); + ResBulkCementTransferDataUploadDetailVO vo = value.stream().filter(v -> ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()).get(0); + totalVo.setUnitName(key); + totalVo.setLastMonthEndInventory(vo.getLastMonthEndInventoryTotal()); + totalVo.setThisMonthIncomingStorage(vo.getThisMonthIncomingStorageTotal()); + totalVo.setCumulativeIncomingStorage(vo.getCumulativeIncomingStorageTotal()); + totalVo.setThisMonthOutgoingStorage(vo.getThisMonthOutgoingStorageTotal()); + totalVo.setCumulativeOutgoingStorage(vo.getCumulativeOutgoingStorageTotal()); + totalVo.setMonthEndInventory(vo.getMonthEndInventoryTotal()); + totalVo.setMonthEndInventoryGrowthRate(vo.getMonthEndInventoryGrowthRateTotal()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + BulkCementTransferQueryDataExportDTO exportDto = new BulkCementTransferQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + + private List getBulkCementSupplyDtoList(ResDataQueryDetailVO resDataQueryDetailVo) { + List dtoList; + ResBulkCementSupplyDataQueryDetailVO bulkCementSupplyDataVo = resDataQueryDetailVo.getBulkCementSupplyDataVo(); + Map bulkCementSupplyDataMap = bulkCementSupplyDataVo.getBulkCementSupplyDataMap(); + List dataList = Lists.newArrayList(); + // 如果是市级散办,map中只有一个键值对,且包含合计的数据 + // 如果是省散办,entries中有多个键值对,且包含合计的数据 + Set> entries = bulkCementSupplyDataMap.entrySet().stream() + .filter(e -> !ReportConstant.TOTAL.equals(e.getKey())).collect(Collectors.toSet()); + List values = (List) bulkCementSupplyDataMap.get(ReportConstant.TOTAL); + dataList.add(values.get(0)); + for (Map.Entry entry : entries) { + List value = (List) entry.getValue(); + List vos = value.stream().filter(v -> !ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()); + String key = entry.getKey(); + ResBulkCementSupplyDataUploadDetailVO totalVo = new ResBulkCementSupplyDataUploadDetailVO(); + ResBulkCementSupplyDataUploadDetailVO vo = value.stream().filter(v -> ReportConstant.TOTAL.equals(v.getUnitName())).collect(Collectors.toList()).get(0); + totalVo.setUnitName(key); + totalVo.setBulkRateTarget(vo.getBulkRateTarget()); + totalVo.setBulkCementAmount(vo.getBulkCementAmountTotal()); + totalVo.setCementOutput(vo.getCementOutputTotal()); + totalVo.setCompletedTotalAmount(vo.getCompletedTotalAmountTotal()); + totalVo.setBulkRate(vo.getBulkRateTotal()); + totalVo.setIncrement(vo.getIncrementTotal()); + totalVo.setIncreaseRate(vo.getIncreaseRateTotal()); + totalVo.setCumulativeCementProduction(vo.getCumulativeCementProductionTotal()); + dataList.add(totalVo); + dataList.addAll(vos); + } + dtoList = dataList.stream().map(d -> { + BulkCementSupplyQueryDataExportDTO exportDto = new BulkCementSupplyQueryDataExportDTO(); + BeanUtils.copyProperties(d, exportDto); + return exportDto; + }).collect(Collectors.toList()); + return dtoList; + } + + public ResDataUploadDetailVO uploadDataDetail(ReqDataUploadDetailPO req) { + Long auditDataId = req.getAuditDataId(); + Integer auditDataType = req.getAuditDataType(); + ResDataUploadDetailVO resVo = new ResDataUploadDetailVO(); + BulkCementDirectSystemManage context = (BulkCementDirectSystemManage) AopContext.currentProxy(); + switch (auditDataType) { + // 散装水泥供应量数据 + case 1: + LambdaQueryWrapper wrapper1 = Wrappers.lambdaQuery(BulkCementSupplyBulletin.class); + context.buildBulkCementSupplyBulletinQuery(wrapper1, auditDataId); + BulkCementSupplyBulletin bulkCementSupplyBulletin = bulkCementSupplyBulletinService.getOne(wrapper1); + VUtils.isTrue(Objects.isNull(bulkCementSupplyBulletin)).throwMessage("数据不存在!"); + ResBulkCementSupplyDataUploadDetailVO vo1 = new ResBulkCementSupplyDataUploadDetailVO(); + BeanUtils.copyProperties(bulkCementSupplyBulletin, vo1); + resVo.setBulkCementSupplyDataUploadDetailVo(vo1); + resVo.setReportMonth(bulkCementSupplyBulletin.getReportMonth()); + resVo.setUnitResponsiblePerson(bulkCementSupplyBulletin.getUnitResponsiblePerson()); + resVo.setPreparer(bulkCementSupplyBulletin.getPreparer()); + resVo.setReviewer(bulkCementSupplyBulletin.getReviewer()); + resVo.setSubmissionDate(bulkCementSupplyBulletin.getSubmissionDate()); + break; + // 中转库进出量统计数据 + case 2: + LambdaQueryWrapper wrapper2 = Wrappers.lambdaQuery(BulkCementTransferBulletin.class); + context.buildBulkCementTransferBulletinQuery(wrapper2, auditDataId); + BulkCementTransferBulletin bulkCementTransferBulletin = bulkCementTransferBulletinService.getOne(wrapper2); + VUtils.isTrue(Objects.isNull(bulkCementTransferBulletin)).throwMessage("数据不存在!"); + ResBulkCementTransferDataUploadDetailVO vo2 = new ResBulkCementTransferDataUploadDetailVO(); + BeanUtils.copyProperties(bulkCementTransferBulletin, vo2); + resVo.setBulkCementTransferDataUploadDetailVo(vo2); + resVo.setReportMonth(bulkCementTransferBulletin.getReportMonth()); + resVo.setUnitResponsiblePerson(bulkCementTransferBulletin.getUnitResponsiblePerson()); + resVo.setPreparer(bulkCementTransferBulletin.getPreparer()); + resVo.setReviewer(bulkCementTransferBulletin.getReviewer()); + resVo.setSubmissionDate(bulkCementTransferBulletin.getSubmissionDate()); + break; + // 温台舟使用量快报数据 + case 3: + LambdaQueryWrapper wrapper3 = Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class); + context.buildBulkCementThreeCityUsageBulletinQuery(wrapper3, auditDataId); + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(wrapper3); + VUtils.isTrue(Objects.isNull(bulkCementThreeCityUsageBulletin)).throwMessage("数据不存在!"); + ResBulkCementThreeCityUsageDataUploadDetailVO vo3 = new ResBulkCementThreeCityUsageDataUploadDetailVO(); + BeanUtils.copyProperties(bulkCementThreeCityUsageBulletin, vo3); + resVo.setBulkCementThreeCityUsageDataUploadDetailVo(vo3); + resVo.setReportMonth(bulkCementThreeCityUsageBulletin.getReportMonth()); + resVo.setUnitResponsiblePerson(bulkCementThreeCityUsageBulletin.getUnitResponsiblePerson()); + resVo.setPreparer(bulkCementThreeCityUsageBulletin.getPreparer()); + resVo.setReviewer(bulkCementThreeCityUsageBulletin.getReviewer()); + resVo.setSubmissionDate(bulkCementThreeCityUsageBulletin.getSubmissionDate()); + break; + // 混凝土供应量快报数据 + case 4: + LambdaQueryWrapper wrapper4 = Wrappers.lambdaQuery(ConcreteSupplyBulletin.class); + context.buildConcreteSupplyBulletinQuery(wrapper4, auditDataId); + ConcreteSupplyBulletin concreteSupplyBulletin = concreteSupplyBulletinService.getOne(wrapper4); + VUtils.isTrue(Objects.isNull(concreteSupplyBulletin)).throwMessage("数据不存在!"); + ResConcreteSupplyDataUploadDetailVO vo4 = new ResConcreteSupplyDataUploadDetailVO(); + BeanUtils.copyProperties(concreteSupplyBulletin, vo4); + resVo.setConcreteSupplyDataUploadDetailVO(vo4); + resVo.setRemark(concreteSupplyBulletin.getRemark()); + resVo.setReportMonth(concreteSupplyBulletin.getReportMonth()); + resVo.setUnitResponsiblePerson(concreteSupplyBulletin.getUnitResponsiblePerson()); + resVo.setPreparer(concreteSupplyBulletin.getPreparer()); + resVo.setReviewer(concreteSupplyBulletin.getReviewer()); + resVo.setSubmissionDate(concreteSupplyBulletin.getSubmissionDate()); + break; + // 砂浆供应量快报数据 + case 5: + LambdaQueryWrapper wrapper5 = Wrappers.lambdaQuery(MortarSupplyBulletin.class); + context.buildMortarSupplyBulletinQuery(wrapper5, auditDataId); + MortarSupplyBulletin mortarSupplyBulletin = mortarSupplyBulletinService.getOne(wrapper5); + VUtils.isTrue(Objects.isNull(mortarSupplyBulletin)).throwMessage("数据不存在!"); + ResMortarSupplyDataUploadDetailVO vo5 = new ResMortarSupplyDataUploadDetailVO(); + BeanUtils.copyProperties(mortarSupplyBulletin, vo5); + resVo.setMortarSupplyDataUploadDetailVO(vo5); + resVo.setReportMonth(mortarSupplyBulletin.getReportMonth()); + resVo.setUnitResponsiblePerson(mortarSupplyBulletin.getUnitResponsiblePerson()); + resVo.setPreparer(mortarSupplyBulletin.getPreparer()); + resVo.setReviewer(mortarSupplyBulletin.getReviewer()); + resVo.setSubmissionDate(mortarSupplyBulletin.getSubmissionDate()); + break; + // 非禁现区域散装水泥销售使用情况数据 + case 6: + LambdaQueryWrapper wrapper6 = Wrappers.lambdaQuery(NonProhibitedAreasBulkCementSalesUse.class); + context.buildNonProhibitedAreasBulkCementSalesUseQuery(wrapper6, auditDataId); + NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse = nonProhibitedAreasBulkCementSalesUseService.getOne(wrapper6); + VUtils.isTrue(Objects.isNull(nonProhibitedAreasBulkCementSalesUse)).throwMessage("数据不存在!"); + ResNonProhibitedAreasDataUploadDetailVO vo6 = new ResNonProhibitedAreasDataUploadDetailVO(); + BeanUtils.copyProperties(nonProhibitedAreasBulkCementSalesUse, vo6); + resVo.setNonProhibitedAreasDataUploadDetailVO(vo6); + resVo.setReportYear(nonProhibitedAreasBulkCementSalesUse.getReportYear()); + resVo.setUnitResponsiblePerson(nonProhibitedAreasBulkCementSalesUse.getUnitResponsiblePerson()); + resVo.setPreparer(nonProhibitedAreasBulkCementSalesUse.getPreparer()); + resVo.setReviewer(nonProhibitedAreasBulkCementSalesUse.getReviewer()); + resVo.setSubmissionDate(nonProhibitedAreasBulkCementSalesUse.getSubmissionDate()); + break; + // 散装水泥物流设施统计年报表数据 + case 7: + // 获取关联表数据 + LambdaQueryWrapper wrapper7 = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + context.buildBulkCementDirectReportSystemDataRelevanceQuery(wrapper7, auditDataId); + BulkCementDirectReportSystemDataRelevance dataRelevance1 = dataRelevanceService.getOne(wrapper7); + VUtils.isTrue(Objects.isNull(dataRelevance1)).throwMessage("数据不存在!"); + String auditDataIdList1 = dataRelevance1.getAuditDataIdList(); + if (StringUtils.isBlank(auditDataIdList1)){ + return null; + } + // 按设备名称分组返回 + Map dataMap1 = MapUtil.newHashMap(); + List idList1 = Arrays.stream(auditDataIdList1.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + for (Long id : idList1) { + BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogFacStaAnnualReport = bulkCementLogFacStaAnnualReportService.getById(id); + ResBulkCementLogFacStaDataUploadDetailVO vo = new ResBulkCementLogFacStaDataUploadDetailVO(); + BeanUtils.copyProperties(bulkCementLogFacStaAnnualReport, vo); + dataMap1.put(bulkCementLogFacStaAnnualReport.getFacilityName(), vo); + } + resVo.setBulkCementLogFacStaDataUploadDetailVO(dataMap1); + resVo.setReportYear(dataRelevance1.getReportYear()); + resVo.setUnitResponsiblePerson(dataRelevance1.getUnitResponsiblePerson()); + resVo.setPreparer(dataRelevance1.getPreparer()); + resVo.setReviewer(dataRelevance1.getReviewer()); + resVo.setSubmissionDate(dataRelevance1.getSubmissionDate()); + break; + // 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据 + case 8: + // 获取关联表数据 + LambdaQueryWrapper wrapper8 = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + context.buildBulkCementDirectReportSystemDataRelevanceQuery(wrapper8, auditDataId); + BulkCementDirectReportSystemDataRelevance dataRelevance2 = dataRelevanceService.getOne(wrapper8); + VUtils.isTrue(Objects.isNull(dataRelevance2)).throwMessage("数据不存在!"); + String auditDataIdList2 = dataRelevance2.getAuditDataIdList(); + if (StringUtils.isBlank(auditDataIdList2)){ + return null; + } + // 按装备名称分组返回 + Map dataMap2 = MapUtil.newHashMap(); + List idList2 = Arrays.stream(auditDataIdList2.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + for (Long id : idList2) { + MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport = materialLogEquipStaAnnualReportService.getById(id); + ResMaterialLogEquipStaDataUploadDetailVO vo = new ResMaterialLogEquipStaDataUploadDetailVO(); + BeanUtils.copyProperties(materialLogEquipStaAnnualReport, vo); + dataMap2.put(materialLogEquipStaAnnualReport.getEquipmentName(), vo); + } + resVo.setMaterialLogEquipStaDataUploadDetailVO(dataMap2); + resVo.setReportYear(dataRelevance2.getReportYear()); + resVo.setUnitResponsiblePerson(dataRelevance2.getUnitResponsiblePerson()); + resVo.setPreparer(dataRelevance2.getPreparer()); + resVo.setReviewer(dataRelevance2.getReviewer()); + resVo.setSubmissionDate(dataRelevance2.getSubmissionDate()); + break; + default: + throw new IllegalStateException("Unexpected value: " + auditDataType); + } + return resVo; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementDirectReportSystemDataRelevanceQuery(LambdaQueryWrapper wrapper7, Long auditDataId) { + wrapper7.eq(BulkCementDirectReportSystemDataRelevance::getId,auditDataId); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildNonProhibitedAreasBulkCementSalesUseQuery(LambdaQueryWrapper wrapper6, Long auditDataId) { + wrapper6.eq(NonProhibitedAreasBulkCementSalesUse::getId,auditDataId); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildMortarSupplyBulletinQuery(LambdaQueryWrapper wrapper5, Long auditDataId) { + wrapper5.eq(MortarSupplyBulletin::getId,auditDataId); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildConcreteSupplyBulletinQuery(LambdaQueryWrapper wrapper4, Long auditDataId) { + wrapper4.eq(ConcreteSupplyBulletin::getId,auditDataId); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementThreeCityUsageBulletinQuery(LambdaQueryWrapper wrapper3, Long auditDataId) { + wrapper3.eq(BulkCementThreeCityUsageBulletin::getId,auditDataId); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementTransferBulletinQuery(LambdaQueryWrapper wrapper2, Long auditDataId) { + wrapper2.eq(BulkCementTransferBulletin::getId,auditDataId); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL) + public void buildBulkCementSupplyBulletinQuery(LambdaQueryWrapper wrapper1, Long auditDataId) { + wrapper1.eq(BulkCementSupplyBulletin::getId,auditDataId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementLogFacStaManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementLogFacStaManage.java new file mode 100644 index 0000000..31c846d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementLogFacStaManage.java @@ -0,0 +1,461 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.dto.ReqBulkCementLogFacStaDataUploadDTO; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.ningdatech.carapi.report.model.entity.BulkCementLogisticFacilityStatisticAnnualReport; +import com.ningdatech.carapi.report.model.po.ReqBulkCementLogFacStaDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementLogFacStaDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementLogFacStaRelatedDataVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditInfoService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditRecordService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemDataRelevanceService; +import com.ningdatech.carapi.report.service.IBulkCementLogisticFacilityStatisticAnnualReportService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BulkCementLogFacStaManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final IBulkCementLogisticFacilityStatisticAnnualReportService bulkCementLogFacStaService; + private final CompaniesCacheHelper companiesCacheHelper; + + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + Page page = req.page(); + // 根据所属区域查出对应的散装水泥物流设施统计年报数据上报记录 + // (每个上报年份对应多个设备名称的数据,需要从数据关联表中查询) + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + // 获取入参 + Integer reportStartYear = req.getReportStartYear(); + Integer reportEndYear = req.getReportEndYear(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartYear), BulkCementDirectReportSystemDataRelevance::getReportYear, reportStartYear) + .le(Objects.nonNull(reportEndYear), BulkCementDirectReportSystemDataRelevance::getReportYear, reportEndYear) + .eq(Objects.nonNull(auditStatus),BulkCementDirectReportSystemDataRelevance::getAuditStatus,auditStatus) + // 市级/省级散办单位可根据区域分别查出对应的关联数据 + // 其中市级关联数据对应的数据ID列表为对应上报数据关联数据的ID + // 省级关联数据对应的数据ID列表为各市级关联数据的ID(温台舟使用量关联数据对应的数据ID列表 + // 仍为对应上报数据的ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType,UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId,regionId) + .orderByDesc(BulkCementDirectReportSystemDataRelevance::getReportYear); + //.isNotNull(BulkCementDirectReportSystemDataRelevance::getAuditInfoId); + dataRelevanceService.page(page,wrapper); + + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(BulkCementDirectReportSystemDataRelevance::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + Integer reportYear = r.getReportYear(); + vo.setRegionId(r.getRegionId()); + vo.setReportYear(reportYear); + vo.setAuditDataId(r.getId()); + + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String bulkCementLogFacStaDataUpload(ReqBulkCementLogFacStaDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Integer reportYear = req.getReportYear(); + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请选择上报年份!"); + Long regionId = userDetail.getRegionId(); + + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + // 先提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 发放库数据 + ReqBulkCementLogFacStaDataUploadDTO issueLibraryData = req.getIssueLibraryData(); + VUtils.isTrue(Objects.isNull(issueLibraryData)).throwMessage("请传入发放库数据!"); + // 中转库数据 + ReqBulkCementLogFacStaDataUploadDTO transferLibraryData = req.getTransferLibraryData(); + VUtils.isTrue(Objects.isNull(transferLibraryData)).throwMessage("请传入中转库数据!"); + // 固定接收库数据 + ReqBulkCementLogFacStaDataUploadDTO fixedReceiveLibraryData = req.getFixedReceiveLibraryData(); + VUtils.isTrue(Objects.isNull(fixedReceiveLibraryData)).throwMessage("请传入固定接收库数据!"); + // 合并保存(虽然每个设备名称的数据单独按一条数据保存,但审核数据仍在一条中) + List dataList = Lists.newArrayList(); + dataList.add(issueLibraryData); + dataList.add(transferLibraryData); + dataList.add(fixedReceiveLibraryData); + + // 创建区县关联数据信息(对应每个设备名称的数据关系为一对多) + BulkCementDirectReportSystemDataRelevance countryData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + + BulkCementDirectReportSystemDataRelevance countryRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + // 区县的区域ID + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + Long parentId = regionDto.getParentId(); + // 判断上报年份所在市的市级关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + // 判断当前地区当前上报年份数据是否已经存在,如果已经存在,更新原数据 + checkUploadData(reportYear, regionId, cityData); + // 说明为重新提交 + if (Objects.nonNull(countryData)){ + // 先删除关联的已经保存的各设备名称的数据 + String auditDataIdList = countryData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idList)){ + bulkCementLogFacStaService.remove(Wrappers.lambdaQuery(BulkCementLogisticFacilityStatisticAnnualReport.class) + .in(BulkCementLogisticFacilityStatisticAnnualReport::getId,idList)); + } + } + // 更新市级关联数据 + updateCityData(cityData,countryData); + // 删除被退回的数据 + dataRelevanceService.removeById(countryData); + } + assemblyRelevanceData(userDetail, reportYear, countryRelevanceData); + countryRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + countryRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + countryRelevanceData.setAuditInfoId(cityAuditInfo.getId()); + countryRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + countryRelevanceData.setPreparer(req.getPreparer()); + countryRelevanceData.setReviewer(req.getReviewer()); + countryRelevanceData.setSubmissionDate(req.getSubmissionDate()); + countryRelevanceData.setRegionId(userDetail.getRegionId()); + countryRelevanceData.setCompanyId(userDetail.getCompanyId()); + List auditDataIdList = Lists.newArrayList(); + // 保存本次上报数据信息 + for (ReqBulkCementLogFacStaDataUploadDTO uploadDto : dataList) { + BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogFacStaAnnualReport = + new BulkCementLogisticFacilityStatisticAnnualReport(); + assemblyData(uploadDto, userDetail, bulkCementLogFacStaAnnualReport); + bulkCementLogFacStaAnnualReport.setAuditInfoId(cityAuditInfo.getId()); + bulkCementLogFacStaAnnualReport.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + bulkCementLogFacStaService.save(bulkCementLogFacStaAnnualReport); + auditDataIdList.add(bulkCementLogFacStaAnnualReport.getId()); + } + // 保存关联数据ID集合(一条关联数据对应多条不同设备名称的数据) + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + countryRelevanceData.setAuditDataIdList(idListStr); + dataRelevanceService.saveOrUpdate(countryRelevanceData); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, countryRelevanceData.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportYear(reportYear); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportYear, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + // 补充省散办关联数据信息 + Long cityRelevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(cityRelevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(cityRelevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportYear, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportYear(cityRelevanceData.getReportYear()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail, Integer reportYear, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportYear(reportYear); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + + } + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqBulkCementLogFacStaDataUploadDTO req, UserInfoDetails userDetail, BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogFacStaAnnualReport) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + bulkCementLogFacStaAnnualReport.setRegionName(regionName); + bulkCementLogFacStaAnnualReport.setFacilityName(req.getFacilityName()); + bulkCementLogFacStaAnnualReport.setYearBeginNum(req.getYearBeginNum()); + bulkCementLogFacStaAnnualReport.setYearBeginCapacity(req.getYearBeginCapacity()); + bulkCementLogFacStaAnnualReport.setThisYearNewAddNum(req.getThisYearNewAddNum()); + bulkCementLogFacStaAnnualReport.setThisYearNewAddCapacity(req.getThisYearNewAddCapacity()); + bulkCementLogFacStaAnnualReport.setThisYearScrapNum(req.getThisYearScrapNum()); + bulkCementLogFacStaAnnualReport.setThisYearScrapCapacity(req.getThisYearScrapCapacity()); + bulkCementLogFacStaAnnualReport.setYearEndNum(req.getYearEndNum()); + bulkCementLogFacStaAnnualReport.setYearEndCapacity(req.getYearEndCapacity()); + bulkCementLogFacStaAnnualReport.setThisYearWorkAmount(req.getThisYearWorkAmount()); + bulkCementLogFacStaAnnualReport.setReportYear(req.getReportYear()); + bulkCementLogFacStaAnnualReport.setRemark(req.getRemark()); + bulkCementLogFacStaAnnualReport.setCompanyId(userDetail.getCompanyId()); + bulkCementLogFacStaAnnualReport.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + bulkCementLogFacStaAnnualReport.setPreparer(req.getPreparer()); + bulkCementLogFacStaAnnualReport.setReviewer(req.getReviewer()); + bulkCementLogFacStaAnnualReport.setSubmissionDate(req.getSubmissionDate()); + bulkCementLogFacStaAnnualReport.setRegionId(userDetail.getRegionId()); + bulkCementLogFacStaAnnualReport.setCreateOn(LocalDateTime.now()); + bulkCementLogFacStaAnnualReport.setCreateBy(userDetail.getUserId()); + bulkCementLogFacStaAnnualReport.setUpdateOn(LocalDateTime.now()); + bulkCementLogFacStaAnnualReport.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(Integer reportYear, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + // 查询区县关联数据 + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + if (Objects.nonNull(dataRelevance) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(dataRelevance.getAuditStatus())){ + // 先删除关联的已经保存的各设备名称的数据 + String auditDataIdList = dataRelevance.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idList)){ + bulkCementLogFacStaService.remove(Wrappers.lambdaQuery(BulkCementLogisticFacilityStatisticAnnualReport.class) + .in(BulkCementLogisticFacilityStatisticAnnualReport::getId,idList)); + } + } + updateCityData(cityData,dataRelevance); + dataRelevanceService.removeById(dataRelevance); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, BulkCementDirectReportSystemDataRelevance dataRelevance) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报年份的数据数据从市级关联表中删除 + idList.remove(dataRelevance.getId()); + } + } + } + + public ResBulkCementLogFacStaDataUploadDetailVO getBulkCementLogFacStaUploadData(ReqBulkCementLogFacStaDataUploadDTO req) { + // 获取填报的数据 + Integer yearBeginNum = req.getYearBeginNum(); + BigDecimal yearBeginCapacity = req.getYearBeginCapacity(); + Integer thisYearNewAddNum = req.getThisYearNewAddNum(); + BigDecimal thisYearNewAddCapacity = req.getThisYearNewAddCapacity(); + BigDecimal thisYearScrapCapacity = req.getThisYearScrapCapacity(); + Integer thisYearScrapNum = req.getThisYearScrapNum(); + BigDecimal thisYearWorkAmount = req.getThisYearWorkAmount(); + String remark = req.getRemark(); + Integer reportYear = req.getReportYear(); + String facilityName = req.getFacilityName(); + VUtils.isTrue(StringUtils.isBlank(facilityName)).throwMessage("请传入设备名称!"); + + ResBulkCementLogFacStaDataUploadDetailVO vo = new ResBulkCementLogFacStaDataUploadDetailVO(); + vo.setYearBeginNum(yearBeginNum); + vo.setYearBeginCapacity(yearBeginCapacity); + vo.setThisYearNewAddNum(thisYearNewAddNum); + vo.setThisYearNewAddCapacity(thisYearNewAddCapacity); + vo.setThisYearScrapCapacity(thisYearScrapCapacity); + vo.setThisYearScrapNum(thisYearScrapNum); + vo.setThisYearWorkAmount(thisYearWorkAmount); + vo.setReportYear(reportYear); + vo.setRemark(remark); + + // 计算各数据 + // 年末数量: 年初数量 + 本年新增数量 - 本年报废数量 + if (Objects.nonNull(yearBeginNum) && Objects.nonNull(thisYearNewAddNum) && Objects.nonNull(thisYearScrapNum)){ + int yearEndNum = yearBeginNum + thisYearNewAddNum - thisYearScrapNum; + vo.setYearEndNum(yearEndNum); + } + // 年末容量: 年初容量 + 本年新增容量 - 本年报废容量 + if (Objects.nonNull(yearBeginCapacity) && Objects.nonNull(thisYearNewAddCapacity) && Objects.nonNull(thisYearScrapCapacity)){ + BigDecimal yearEndCapacity = yearBeginCapacity.add(thisYearNewAddCapacity).subtract(thisYearScrapCapacity); + vo.setYearEndCapacity(yearEndCapacity); + } + return vo; + } + + public ResBulkCementLogFacStaRelatedDataVO getBulkCementLogFacStaRelatedData(ReqBulkCementLogFacStaDataUploadDTO dto) { + Integer reportYear = dto.getReportYear(); + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请传入上报年份!"); + Long regionId = dto.getRegionId(); + VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!"); + String facilityName = dto.getFacilityName(); + VUtils.isTrue(StringUtils.isBlank(facilityName)).throwMessage("请传入设备名称!"); + Integer preReportYear = reportYear - 1; + BulkCementLogisticFacilityStatisticAnnualReport preYearBulkCementLogFacStaAnnualReport = bulkCementLogFacStaService.getOne(Wrappers.lambdaQuery(BulkCementLogisticFacilityStatisticAnnualReport.class) + .eq(BulkCementLogisticFacilityStatisticAnnualReport::getReportYear, preReportYear) + .eq(BulkCementLogisticFacilityStatisticAnnualReport::getFacilityName,facilityName) + .eq(BulkCementLogisticFacilityStatisticAnnualReport::getRegionId, regionId)); + ResBulkCementLogFacStaRelatedDataVO vo = new ResBulkCementLogFacStaRelatedDataVO(); + if (Objects.nonNull(preYearBulkCementLogFacStaAnnualReport)) { + // 去年的年末数量 + vo.setYearBeginNum(preYearBulkCementLogFacStaAnnualReport.getYearEndNum()); + // 去年的年末容量 + vo.setYearBeginCapacity(preYearBulkCementLogFacStaAnnualReport.getYearEndCapacity()); + } + return vo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementSupplyBulletinManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementSupplyBulletinManage.java new file mode 100644 index 0000000..76071e1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementSupplyBulletinManage.java @@ -0,0 +1,402 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.ningdatech.carapi.report.model.entity.BulkCementSupplyBulletin; +import com.ningdatech.carapi.report.model.po.ReqBulkCementSupplyDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementSupplyDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditInfoService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditRecordService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemDataRelevanceService; +import com.ningdatech.carapi.report.service.IBulkCementSupplyBulletinService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BulkCementSupplyBulletinManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final IBulkCementSupplyBulletinService bulkCementSupplyBulletinService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final CompaniesCacheHelper companiesCacheHelper; + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + + Page page = req.page(); + // 根据所属区域查出对应的散装水泥供应量数据上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementSupplyBulletin.class); + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartMonth), BulkCementSupplyBulletin::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), BulkCementSupplyBulletin::getReportMonth, reportEndMonth) + .eq(Objects.nonNull(auditStatus),BulkCementSupplyBulletin::getAuditStatus,auditStatus) + .eq(BulkCementSupplyBulletin::getRegionId,regionId) + .orderByDesc(BulkCementSupplyBulletin::getReportMonth); + //.isNotNull(BulkCementSupplyBulletin::getAuditInfoId); + bulkCementSupplyBulletinService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(BulkCementSupplyBulletin::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + LocalDateTime month = r.getReportMonth(); + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN)); + vo.setRegionId(r.getRegionId()); + vo.setReportMonth(reportMonth); + vo.setAuditDataId(r.getId()); + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String bulkCementSupplyDataUpload(ReqBulkCementSupplyDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请选择上报月份!"); + + // 提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + BulkCementSupplyBulletin cementSupplyBulletin = new BulkCementSupplyBulletin(); + // 区县的区域ID + Long countryRegionId = userDetail.getRegionId(); + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId); + Long parentId = regionDto.getParentId(); + // 判断上报月份所在市的关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode())); + // 判断当前地区当前上报月份数据是否已经存在,如果已经存在,删除原数据并更新市、省关联数据列表 + checkUploadData(reportMonth, regionId, cityData); + Long dataId = req.getId(); + // 上报数据Id不为空,说明为重新提交 + if (Objects.nonNull(dataId)) { + BulkCementSupplyBulletin oldData = bulkCementSupplyBulletinService.getById(dataId); + VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!"); + // 更新市级关联数据 + updateCityData(cityData,oldData); + // 删除被退回的数据 + bulkCementSupplyBulletinService.removeById(oldData); + } + assemblyData(req, userDetail, cementSupplyBulletin); + cementSupplyBulletin.setAuditInfoId(cityAuditInfo.getId()); + cementSupplyBulletin.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + bulkCementSupplyBulletinService.save(cementSupplyBulletin); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cementSupplyBulletin.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportMonth(reportMonth); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + // 如果市级关联数据不存在,创建市级关联数据,但不更新上报数据,等审核通过再更新 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + // 有新上报的数据,关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + Long relevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode())); + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportMonth(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail,LocalDateTime reportMonth, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportMonth(reportMonth); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqBulkCementSupplyDataUploadPO req, UserInfoDetails userDetail, BulkCementSupplyBulletin cementSupplyBulletin) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + cementSupplyBulletin.setUnitName(regionName); + cementSupplyBulletin.setBulkCementAmount(req.getBulkCementAmount()); + cementSupplyBulletin.setCementOutput(req.getCementOutput()); + cementSupplyBulletin.setCompletedTotalAmount(req.getCompletedTotalAmount()); + cementSupplyBulletin.setBulkRate(req.getBulkRate()); + cementSupplyBulletin.setIncrement(req.getIncrement()); + cementSupplyBulletin.setIncreaseRate(req.getIncreaseRate()); + cementSupplyBulletin.setCumulativeCementProduction(req.getCumulativeCementProduction()); + cementSupplyBulletin.setReportMonth(req.getReportMonth()); + cementSupplyBulletin.setCompanyId(userDetail.getCompanyId()); + cementSupplyBulletin.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cementSupplyBulletin.setPreparer(req.getPreparer()); + cementSupplyBulletin.setReviewer(req.getReviewer()); + cementSupplyBulletin.setSubmissionDate(req.getSubmissionDate()); + cementSupplyBulletin.setRegionId(userDetail.getRegionId()); + cementSupplyBulletin.setCreateOn(LocalDateTime.now()); + cementSupplyBulletin.setCreateBy(userDetail.getUserId()); + cementSupplyBulletin.setUpdateOn(LocalDateTime.now()); + cementSupplyBulletin.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(LocalDateTime reportMonth, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + BulkCementSupplyBulletin bulkCementSupplyBulletin = bulkCementSupplyBulletinService.getOne(Wrappers.lambdaQuery(BulkCementSupplyBulletin.class) + .eq(BulkCementSupplyBulletin::getRegionId, regionId) + .eq(BulkCementSupplyBulletin::getReportMonth, reportMonth)); + // 判断审核状态,如果审核通过,更新审核通过的数据 + if (Objects.nonNull(bulkCementSupplyBulletin) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(bulkCementSupplyBulletin.getAuditStatus())){ + updateCityData(cityData, bulkCementSupplyBulletin); + bulkCementSupplyBulletinService.removeById(bulkCementSupplyBulletin); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, BulkCementSupplyBulletin bulkCementSupplyBulletin) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报月份的数据数据从关联表中删除 + idList.remove(bulkCementSupplyBulletin.getId()); + } + } + } + + public ResBulkCementSupplyDataUploadDetailVO getBulkCementSupplyUploadData(ReqBulkCementSupplyDataUploadPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + // 获取填报的数据 + BigDecimal bulkCementAmount = req.getBulkCementAmount(); + BigDecimal cementOutput = req.getCementOutput(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 计算年初至本月累计各数据 + // 获取上个月该地区的散装水泥供应量数据 + LocalDateTime preReportMonth = reportMonth.minusMonths(1L); + BulkCementSupplyBulletin preBulkCementSupplyBulletin = bulkCementSupplyBulletinService.getOne(Wrappers.lambdaQuery(BulkCementSupplyBulletin.class) + .eq(BulkCementSupplyBulletin::getRegionId, regionId) + .eq(BulkCementSupplyBulletin::getReportMonth, preReportMonth)); + VUtils.isTrue(Objects.isNull(preBulkCementSupplyBulletin)).throwMessage("系统上个月数据不存在!"); + // 获取去年当前上报月份该地区的散装水泥供应量数据 + LocalDateTime preYearReportMonth = preReportMonth.minusYears(1L).plusMonths(1L); + BulkCementSupplyBulletin preYearBulkCementSupplyBulletin = bulkCementSupplyBulletinService.getOne(Wrappers.lambdaQuery(BulkCementSupplyBulletin.class) + .eq(BulkCementSupplyBulletin::getRegionId, regionId) + .eq(BulkCementSupplyBulletin::getReportMonth, preYearReportMonth)); + VUtils.isTrue(Objects.isNull(preYearBulkCementSupplyBulletin)).throwMessage("系统去年该月数据不存在!"); + + ResBulkCementSupplyDataUploadDetailVO vo = new ResBulkCementSupplyDataUploadDetailVO(); + vo.setBulkCementAmount(bulkCementAmount); + vo.setCementOutput(cementOutput); + + + BigDecimal completeAmount = null; + if (Objects.nonNull(bulkCementAmount)) { + // 完成量:散装水泥总量 + 上个月完成量 + BigDecimal preMonthCompletedTotalAmount = preBulkCementSupplyBulletin.getCompletedTotalAmount(); + BigDecimal preMonthCompletedAmount = Objects.isNull(preMonthCompletedTotalAmount) ? BigDecimal.ZERO : preMonthCompletedTotalAmount; + completeAmount = bulkCementAmount.add(preMonthCompletedAmount); + vo.setCompletedTotalAmount(completeAmount); + + // 比去年同期增加量: 完成量 - 去年这个月的完成量 + BigDecimal preYearCompletedTotalAmount = preYearBulkCementSupplyBulletin.getCompletedTotalAmount(); + BigDecimal preYearCompletedAmount = Objects.isNull(preYearCompletedTotalAmount) ? BigDecimal.ZERO : preYearCompletedTotalAmount; + BigDecimal increment = completeAmount.subtract(preYearCompletedAmount).setScale(2, RoundingMode.HALF_UP); + vo.setIncrement(increment); + + // 比去年同期增长率:增长量 / 去年这个月的完成量 + BigDecimal increaseRate; + if (BigDecimal.ZERO.compareTo(preYearCompletedAmount) != 0) { + increaseRate = increment.divide(preYearCompletedAmount, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + }else { + increaseRate = increment.divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + } + vo.setIncreaseRate(increaseRate); + } + + if (Objects.nonNull(cementOutput)) { + // 本月止累计水泥产量:水泥产量 + 上个月的本月止累计水泥产量 + BigDecimal preMonthCumulativeCementProduction = preBulkCementSupplyBulletin.getCumulativeCementProduction(); + BigDecimal preMonthCumulativeOutput = Objects.isNull(preMonthCumulativeCementProduction) ? BigDecimal.ZERO : preMonthCumulativeCementProduction; + BigDecimal cumulativeOutput = cementOutput.add(preMonthCumulativeOutput).setScale(2, RoundingMode.HALF_UP); + vo.setCumulativeCementProduction(cumulativeOutput); + + // 散装率:完成量 / 水泥产量 * 100% + if (Objects.nonNull(completeAmount)) { + BigDecimal bulkRate = completeAmount.divide(cumulativeOutput, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + vo.setBulkRate(bulkRate); + } + } + return vo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementThreeCityUsageBulletinManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementThreeCityUsageBulletinManage.java new file mode 100644 index 0000000..c863c52 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementThreeCityUsageBulletinManage.java @@ -0,0 +1,414 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.entity.*; +import com.ningdatech.carapi.report.model.po.ReqBulkCementThreeCityUsageDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementThreeCityUsageDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.service.*; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BulkCementThreeCityUsageBulletinManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementThreeCityUsageBulletinService bulkCementThreeCityUsageBulletinService; + private final IBulkCementDirectReportSystemUniversalIndexService universalIndexService; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final CompaniesCacheHelper companiesCacheHelper; + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + + Page page = req.page(); + // 根据所属区域查出对应的散装水泥供应量数据上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class); + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartMonth), BulkCementThreeCityUsageBulletin::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), BulkCementThreeCityUsageBulletin::getReportMonth, reportEndMonth) + .eq(Objects.nonNull(auditStatus),BulkCementThreeCityUsageBulletin::getAuditStatus,auditStatus) + .eq(BulkCementThreeCityUsageBulletin::getRegionId,regionId) + .orderByDesc(BulkCementThreeCityUsageBulletin::getReportMonth); + //.isNotNull(BulkCementThreeCityUsageBulletin::getAuditInfoId); + bulkCementThreeCityUsageBulletinService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(BulkCementThreeCityUsageBulletin::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + LocalDateTime month = r.getReportMonth(); + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN)); + vo.setRegionId(r.getRegionId()); + vo.setReportMonth(reportMonth); + vo.setAuditDataId(r.getId()); + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String bulkCementThreeCityUsageDataUpload(ReqBulkCementThreeCityUsageDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请选择上报月份!"); + + // 提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = new BulkCementThreeCityUsageBulletin(); + // 区县的区域ID + Long countryRegionId = userDetail.getRegionId(); + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId); + Long parentId = regionDto.getParentId(); + // 判断上报月份所在市的关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode())); + + // 判断当前地区当前上报月份数据是否已经存在,如果已经存在,删除原数据并更新市、省关联数据列表 + checkUploadData(reportMonth, regionId, cityData); + Long dataId = req.getId(); + // 上报数据不为空,说明为重新提交 + if (Objects.nonNull(dataId)) { + BulkCementThreeCityUsageBulletin oldData = bulkCementThreeCityUsageBulletinService.getById(dataId); + VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!"); + // 更新市级关联数据 + updateCityData(cityData,oldData); + // 删除被退回的数据 + bulkCementThreeCityUsageBulletinService.removeById(oldData); + + } + + assemblyData(req, userDetail, bulkCementThreeCityUsageBulletin); + bulkCementThreeCityUsageBulletin.setAuditInfoId(cityAuditInfo.getId()); + bulkCementThreeCityUsageBulletin.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + bulkCementThreeCityUsageBulletinService.saveOrUpdate(bulkCementThreeCityUsageBulletin); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, bulkCementThreeCityUsageBulletin.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportMonth(reportMonth); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + Long relevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode())); + + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportMonth(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + return "上报成功!"; + } + private void assemblyRelevanceData(UserInfoDetails userDetail, LocalDateTime reportMonth, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportMonth(reportMonth); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqBulkCementThreeCityUsageDataUploadPO req, UserInfoDetails userDetail, BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + bulkCementThreeCityUsageBulletin.setUnitName(regionName); + bulkCementThreeCityUsageBulletin.setYearTarget(req.getYearTarget()); + bulkCementThreeCityUsageBulletin.setPercentageOfAnnualTarget(req.getPercentageOfAnnualTarget()); + bulkCementThreeCityUsageBulletin.setThisMonthUsage(req.getThisMonthUsage()); + bulkCementThreeCityUsageBulletin.setAccumulativeUsage(req.getAccumulativeUsage()); + bulkCementThreeCityUsageBulletin.setGrowthRate(req.getGrowthRate()); + bulkCementThreeCityUsageBulletin.setThisProvinceThisMonthUsage(req.getThisProvinceThisMonthUsage()); + bulkCementThreeCityUsageBulletin.setThisProvinceAccumulativeUsage(req.getThisProvinceAccumulativeUsage()); + bulkCementThreeCityUsageBulletin.setOtherProvinceThisMonthUsage(req.getOtherProvinceThisMonthUsage()); + bulkCementThreeCityUsageBulletin.setOtherProvinceAccumulativeUsage(req.getOtherProvinceAccumulativeUsage()); + bulkCementThreeCityUsageBulletin.setReportMonth(req.getReportMonth()); + bulkCementThreeCityUsageBulletin.setCompanyId(userDetail.getCompanyId()); + bulkCementThreeCityUsageBulletin.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + bulkCementThreeCityUsageBulletin.setPreparer(req.getPreparer()); + bulkCementThreeCityUsageBulletin.setReviewer(req.getReviewer()); + bulkCementThreeCityUsageBulletin.setSubmissionDate(req.getSubmissionDate()); + bulkCementThreeCityUsageBulletin.setRegionId(userDetail.getRegionId()); + bulkCementThreeCityUsageBulletin.setCreateOn(LocalDateTime.now()); + bulkCementThreeCityUsageBulletin.setCreateBy(userDetail.getUserId()); + bulkCementThreeCityUsageBulletin.setUpdateOn(LocalDateTime.now()); + bulkCementThreeCityUsageBulletin.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(LocalDateTime reportMonth, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class) + .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId) + .eq(BulkCementThreeCityUsageBulletin::getReportMonth, reportMonth)); + // 判断审核状态,如果审核通过,更新审核通过的数据 + if (Objects.nonNull(bulkCementThreeCityUsageBulletin) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(bulkCementThreeCityUsageBulletin.getAuditStatus())){ + updateCityData(cityData,bulkCementThreeCityUsageBulletin); + bulkCementThreeCityUsageBulletinService.removeById(bulkCementThreeCityUsageBulletin); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报月份的数据数据从关联表中删除 + idList.remove(bulkCementThreeCityUsageBulletin.getId()); + } + } + } + + public ResBulkCementThreeCityUsageDataUploadDetailVO getBulkCementThreeCityUsageUploadData(ReqBulkCementThreeCityUsageDataUploadPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + // 获取填报的数据 + BigDecimal thisProvinceThisMonthUsage = req.getThisProvinceThisMonthUsage(); + BigDecimal otherProvinceThisMonthUsage = req.getOtherProvinceThisMonthUsage(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 计算合计、本省、外省各数据 + // 获取上个月该地区的散装水泥使用量数据 + LocalDateTime preReportMonth = reportMonth.minusMonths(1L); + BulkCementThreeCityUsageBulletin preBulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class) + .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId) + .eq(BulkCementThreeCityUsageBulletin::getReportMonth, preReportMonth)); + VUtils.isTrue(Objects.isNull(preBulkCementThreeCityUsageBulletin)).throwMessage("系统上个月数据不存在!"); + // 获取去年当前上报月份该地区的散装水泥使用量数据 + LocalDateTime preYearReportMonth = preReportMonth.minusYears(1L).plusMonths(1L); + BulkCementThreeCityUsageBulletin preYearBulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class) + .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId) + .eq(BulkCementThreeCityUsageBulletin::getReportMonth, preYearReportMonth)); + VUtils.isTrue(Objects.isNull(preYearBulkCementThreeCityUsageBulletin)).throwMessage("系统去年该月数据不存在!"); + + ResBulkCementThreeCityUsageDataUploadDetailVO vo = new ResBulkCementThreeCityUsageDataUploadDetailVO(); + vo.setThisProvinceThisMonthUsage(thisProvinceThisMonthUsage); + vo.setOtherProvinceThisMonthUsage(otherProvinceThisMonthUsage); + if (Objects.nonNull(thisProvinceThisMonthUsage) && Objects.nonNull(otherProvinceThisMonthUsage)){ + // 本月使用量 = 本省本月使用量 + 外省本月使用量 + // 先取整再运算,防止数据相加再取整后值不一致 + BigDecimal thisProvince = thisProvinceThisMonthUsage.setScale(0, RoundingMode.HALF_UP); + BigDecimal otherProvince = otherProvinceThisMonthUsage.setScale(0, RoundingMode.HALF_UP); + BigDecimal thisMonthUsage = thisProvince.add(otherProvince); + vo.setThisMonthUsage(thisMonthUsage); + + // 累计使用量:上个月的累计使用量 + 本月使用量 = 本省累计使用量 + 外省累计使用量 + BigDecimal preMonthAccumulativeUsage = preBulkCementThreeCityUsageBulletin.getAccumulativeUsage(); + BigDecimal preMonthAccUsage = Objects.isNull(preMonthAccumulativeUsage) ? BigDecimal.ZERO : preMonthAccumulativeUsage; + BigDecimal accumulativeUsage = thisMonthUsage.add(preMonthAccUsage).setScale(0, RoundingMode.HALF_UP); + vo.setAccumulativeUsage(accumulativeUsage); + + // 同比增长率: (今年这个月的累计使用量 - 去年这个月的累计使用量) / 去年这个月的累计使用量 * 100 + BigDecimal preYearAccumulativeUsage = preYearBulkCementThreeCityUsageBulletin.getAccumulativeUsage(); + BigDecimal preYearAccUsage = Objects.isNull(preYearAccumulativeUsage) ? BigDecimal.ZERO : preYearAccumulativeUsage; + BigDecimal growthRate = accumulativeUsage.subtract(preYearAccUsage).divide(preYearAccUsage, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + vo.setGrowthRate(growthRate); + } + + if (Objects.nonNull(thisProvinceThisMonthUsage)) { + // 本省累计使用量:上个月本省累计使用量 + 本省本月使用量 + BigDecimal preMonthThisProvinceAccumulativeUsage = preBulkCementThreeCityUsageBulletin.getThisProvinceAccumulativeUsage(); + BigDecimal preMonthThisProvinceAccUsage = Objects.isNull(preMonthThisProvinceAccumulativeUsage) ? BigDecimal.ZERO : preMonthThisProvinceAccumulativeUsage; + BigDecimal thisProvinceAccumulativeUsage = thisProvinceThisMonthUsage.add(preMonthThisProvinceAccUsage).setScale(0, RoundingMode.HALF_UP); + vo.setThisProvinceAccumulativeUsage(thisProvinceAccumulativeUsage); + } + + if (Objects.nonNull(otherProvinceThisMonthUsage)) { + // 外省累计使用量:上个月外省累计使用量 + 外省本月使用量 + BigDecimal preMonthOtherProvinceAccumulativeUsage = preBulkCementThreeCityUsageBulletin.getOtherProvinceAccumulativeUsage(); + BigDecimal preMonthOtherProvinceAccUsage = Objects.isNull(preMonthOtherProvinceAccumulativeUsage) ? BigDecimal.ZERO : preMonthOtherProvinceAccumulativeUsage; + BigDecimal otherProvinceAccumulativeUsage = otherProvinceThisMonthUsage.add(preMonthOtherProvinceAccUsage).setScale(0, RoundingMode.HALF_UP); + vo.setOtherProvinceAccumulativeUsage(otherProvinceAccumulativeUsage); + } + return vo; + } + + public BigDecimal getBulkCementThreeCityUsageYearTarget(ReqBulkCementThreeCityUsageDataUploadPO po) { + LocalDateTime reportMonth = po.getReportMonth(); + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份!"); + Long regionId = po.getRegionId(); + VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!"); + int year = reportMonth.getYear(); + BulkCementDirectReportSystemUniversalIndex universalIndex = universalIndexService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemUniversalIndex.class) + .eq(BulkCementDirectReportSystemUniversalIndex::getRegionId, regionId) + .eq(BulkCementDirectReportSystemUniversalIndex::getYear, year)); + + if (Objects.isNull(universalIndex)){ + return BigDecimal.ZERO; + } + return universalIndex.getBulkCementUsageYearTarget(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementTransferBulletinManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementTransferBulletinManage.java new file mode 100644 index 0000000..8232299 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/BulkCementTransferBulletinManage.java @@ -0,0 +1,405 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.ningdatech.carapi.report.model.entity.BulkCementTransferBulletin; +import com.ningdatech.carapi.report.model.po.ReqBulkCementTransferDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResBulkCementTransferDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditInfoService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditRecordService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemDataRelevanceService; +import com.ningdatech.carapi.report.service.IBulkCementTransferBulletinService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BulkCementTransferBulletinManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final IBulkCementTransferBulletinService bulkCementTransferBulletinService; + private final CompaniesCacheHelper companiesCacheHelper; + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + + Page page = req.page(); + // 根据所属区域查出对应的中转库进出量数据上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementTransferBulletin.class); + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartMonth), BulkCementTransferBulletin::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), BulkCementTransferBulletin::getReportMonth, reportEndMonth) + .eq(Objects.nonNull(auditStatus),BulkCementTransferBulletin::getAuditStatus,auditStatus) + .eq(BulkCementTransferBulletin::getRegionId,regionId) + .orderByDesc(BulkCementTransferBulletin::getReportMonth); + //.isNotNull(BulkCementTransferBulletin::getAuditInfoId); + bulkCementTransferBulletinService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(BulkCementTransferBulletin::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + LocalDateTime month = r.getReportMonth(); + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN)); + vo.setRegionId(r.getRegionId()); + vo.setReportMonth(reportMonth); + vo.setAuditDataId(r.getId()); + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String bulkCementTransferDataUpload(ReqBulkCementTransferDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请选择上报月份!"); + + // 提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + BulkCementTransferBulletin bulkCementTransferBulletin = new BulkCementTransferBulletin(); + // 区县的区域ID + Long countryRegionId = userDetail.getRegionId(); + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId); + Long parentId = regionDto.getParentId(); + // 判断上报月份所在市的关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode())); + // 判断当前地区当前上报月份数据是否已经存在,如果已经存在,删除原数据并更新市、省关联数据列表 + checkUploadData(reportMonth, regionId, cityData); + Long dataId = req.getId(); + // 上报数据不为空,说明为重新提交 + if (Objects.nonNull(dataId)) { + BulkCementTransferBulletin oldData = bulkCementTransferBulletinService.getById(dataId); + VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!"); + // 更新市级关联数据 + updateCityData(cityData,oldData); + // 删除被退回的数据 + bulkCementTransferBulletinService.removeById(oldData); + } + + assemblyData(req, userDetail, bulkCementTransferBulletin); + bulkCementTransferBulletin.setAuditInfoId(cityAuditInfo.getId()); + bulkCementTransferBulletin.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + bulkCementTransferBulletinService.saveOrUpdate(bulkCementTransferBulletin); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, bulkCementTransferBulletin.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportMonth(reportMonth); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + Long relevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode())); + + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportMonth(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail, LocalDateTime reportMonth, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportMonth(reportMonth); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqBulkCementTransferDataUploadPO req, UserInfoDetails userDetail, BulkCementTransferBulletin bulkCementTransferBulletin) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + bulkCementTransferBulletin.setUnitName(regionName); + bulkCementTransferBulletin.setLastMonthEndInventory(req.getLastMonthEndInventory()); + bulkCementTransferBulletin.setThisMonthIncomingStorage(req.getThisMonthIncomingStorage()); + bulkCementTransferBulletin.setCumulativeIncomingStorage(req.getCumulativeIncomingStorage()); + bulkCementTransferBulletin.setThisMonthOutgoingStorage(req.getThisMonthOutgoingStorage()); + bulkCementTransferBulletin.setCumulativeOutgoingStorage(req.getCumulativeOutgoingStorage()); + bulkCementTransferBulletin.setMonthEndInventory(req.getMonthEndInventory()); + bulkCementTransferBulletin.setMonthEndInventoryGrowthRate(req.getMonthEndInventoryGrowthRate()); + bulkCementTransferBulletin.setReportMonth(req.getReportMonth()); + bulkCementTransferBulletin.setCompanyId(userDetail.getCompanyId()); + bulkCementTransferBulletin.setRegionId(userDetail.getRegionId()); + bulkCementTransferBulletin.setCreateOn(LocalDateTime.now()); + bulkCementTransferBulletin.setCreateBy(userDetail.getUserId()); + bulkCementTransferBulletin.setUpdateOn(LocalDateTime.now()); + bulkCementTransferBulletin.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(LocalDateTime reportMonth, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + BulkCementTransferBulletin bulkCementTransferBulletin = bulkCementTransferBulletinService.getOne(Wrappers.lambdaQuery(BulkCementTransferBulletin.class) + .eq(BulkCementTransferBulletin::getRegionId, regionId) + .eq(BulkCementTransferBulletin::getReportMonth, reportMonth)); + if (Objects.nonNull(bulkCementTransferBulletin) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(bulkCementTransferBulletin.getAuditStatus())){ + // 判断审核状态,如果审核通过,更新审核通过的数据 + updateCityData(cityData,bulkCementTransferBulletin); + bulkCementTransferBulletinService.removeById(bulkCementTransferBulletin); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, BulkCementTransferBulletin bulkCementTransferBulletin) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报月份的数据数据从关联表中删除 + idList.remove(bulkCementTransferBulletin.getId()); + } + } + } + + public ResBulkCementTransferDataUploadDetailVO getBulkCementTransferUploadData(ReqBulkCementTransferDataUploadPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + // 上月末库存 + BigDecimal lastMonthEndInventory = req.getLastMonthEndInventory(); + VUtils.isTrue(Objects.isNull(lastMonthEndInventory)).throwMessage("请传入上月末库存!"); + // 获取填报的数据 + // 本月进库量 + BigDecimal thisMonthIncomingStorage = req.getThisMonthIncomingStorage(); + // 本月出库量 + BigDecimal thisMonthOutgoingStorage = req.getThisMonthOutgoingStorage(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 计算累计进库量、累计出库量、月末库存量、同比增长率 + // 获取上个月该地区的累计进库量、累计出库量 + LocalDateTime preReportMonth = reportMonth.minusMonths(1L); + BulkCementTransferBulletin preBulkCementTransferBulletin = bulkCementTransferBulletinService.getOne(Wrappers.lambdaQuery(BulkCementTransferBulletin.class) + .eq(BulkCementTransferBulletin::getRegionId, regionId) + .eq(BulkCementTransferBulletin::getReportMonth, preReportMonth)); + VUtils.isTrue(Objects.isNull(preBulkCementTransferBulletin)).throwMessage("系统上个月数据不存在!"); + // 获取去年当前上报月份该地区的月末库存量 + LocalDateTime preYearReportMonth = preReportMonth.minusYears(1L).plusMonths(1L); + BulkCementTransferBulletin preYearBulkCementTransferBulletin = bulkCementTransferBulletinService.getOne(Wrappers.lambdaQuery(BulkCementTransferBulletin.class) + .eq(BulkCementTransferBulletin::getRegionId, regionId) + .eq(BulkCementTransferBulletin::getReportMonth, preYearReportMonth)); + VUtils.isTrue(Objects.isNull(preYearBulkCementTransferBulletin)).throwMessage("系统去年该月数据不存在!"); + + ResBulkCementTransferDataUploadDetailVO vo = new ResBulkCementTransferDataUploadDetailVO(); + vo.setLastMonthEndInventory(lastMonthEndInventory); + vo.setThisMonthIncomingStorage(thisMonthIncomingStorage); + vo.setThisMonthOutgoingStorage(thisMonthOutgoingStorage); + + if (Objects.nonNull(thisMonthIncomingStorage)) { + // 累计进库量:本月进库量 + 上个月累计进库量 + BigDecimal preMonthCumulativeIncomingStorage = preBulkCementTransferBulletin.getCumulativeIncomingStorage(); + BigDecimal preMonCumInStorage = Objects.isNull(preMonthCumulativeIncomingStorage) ? BigDecimal.ZERO : preMonthCumulativeIncomingStorage; + BigDecimal cumulativeIncomingStorage = thisMonthIncomingStorage.add(preMonCumInStorage); + vo.setCumulativeIncomingStorage(cumulativeIncomingStorage); + } + + if (Objects.nonNull(thisMonthOutgoingStorage)) { + // 累计出库量: 本月出库量 + 上个月的累计出库量 + BigDecimal preMonthCumulativeOutgoingStorage = preBulkCementTransferBulletin.getCumulativeOutgoingStorage(); + BigDecimal preMonCumOutStorage = Objects.isNull(preMonthCumulativeOutgoingStorage) ? BigDecimal.ZERO : preMonthCumulativeOutgoingStorage; + BigDecimal cumulativeOutgoingStorage = thisMonthOutgoingStorage.add(preMonCumOutStorage); + vo.setCumulativeOutgoingStorage(cumulativeOutgoingStorage); + } + + if (Objects.nonNull(thisMonthIncomingStorage) && Objects.nonNull(thisMonthOutgoingStorage)){ + // 月末库存量 = 上月末库存量 + 本月进库量 - 本月出库量 + BigDecimal monthEndInventory = lastMonthEndInventory.add(thisMonthIncomingStorage).subtract(thisMonthOutgoingStorage); + vo.setMonthEndInventory(monthEndInventory); + // 同比增长率 = (月末库存量 - 去年月末库存量)/ 去年月末库存量 * 100 + BigDecimal preYearMonthEndInventory = preYearBulkCementTransferBulletin.getMonthEndInventory(); + BigDecimal monthEndInventoryGrowthRate = monthEndInventory.subtract(preYearMonthEndInventory).divide(preYearMonthEndInventory, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + vo.setMonthEndInventoryGrowthRate(monthEndInventoryGrowthRate); + } + return vo; + } + + public BigDecimal getBulkCementTransferLastMonthData(ReqBulkCementTransferDataUploadPO po) { + LocalDateTime reportMonth = po.getReportMonth(); + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份!"); + Long regionId = po.getRegionId(); + VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!"); + LocalDateTime preReportMonth = reportMonth.minusMonths(1); + BulkCementTransferBulletin transferBulletin = bulkCementTransferBulletinService.getOne(Wrappers.lambdaQuery(BulkCementTransferBulletin.class) + .eq(BulkCementTransferBulletin::getReportMonth, preReportMonth) + .eq(BulkCementTransferBulletin::getRegionId, regionId)); + if (Objects.isNull(transferBulletin)){ + return BigDecimal.ZERO; + } + return transferBulletin.getLastMonthEndInventory(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/ConcreteSupplyBulletinManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/ConcreteSupplyBulletinManage.java new file mode 100644 index 0000000..c904192 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/ConcreteSupplyBulletinManage.java @@ -0,0 +1,417 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.entity.*; +import com.ningdatech.carapi.report.model.po.ReqConcreteSupplyDataUploadPO; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.vo.ResConcreteSupplyDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResConcreteSupplyRelatedDataVO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.service.*; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class ConcreteSupplyBulletinManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final IConcreteSupplyBulletinService concreteSupplyBulletinService; + private final IBulkCementDirectReportSystemUniversalIndexService universalIndexService; + private final CompaniesCacheHelper companiesCacheHelper; + + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + + Page page = req.page(); + // 根据所属区域查出对应的散装水泥供应量数据上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ConcreteSupplyBulletin.class); + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartMonth), ConcreteSupplyBulletin::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), ConcreteSupplyBulletin::getReportMonth, reportEndMonth) + .eq(Objects.nonNull(auditStatus),ConcreteSupplyBulletin::getAuditStatus,auditStatus) + .eq(ConcreteSupplyBulletin::getRegionId,regionId) + .orderByDesc(ConcreteSupplyBulletin::getReportMonth); + //.isNotNull(ConcreteSupplyBulletin::getAuditInfoId); + concreteSupplyBulletinService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(ConcreteSupplyBulletin::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + LocalDateTime month = r.getReportMonth(); + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN)); + vo.setRegionId(r.getRegionId()); + vo.setReportMonth(reportMonth); + vo.setAuditDataId(r.getId()); + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String concreteSupplyDataUpload(ReqConcreteSupplyDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请选择上报月份!"); + + // 提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + ConcreteSupplyBulletin concreteSupplyBulletin = new ConcreteSupplyBulletin(); + // 区县的区域ID + Long countryRegionId = userDetail.getRegionId(); + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId); + Long parentId = regionDto.getParentId(); + // 判断上报月份所在市的关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode())); + // 判断当前地区当前上报月份数据是否已经存在,如果已经存在,删除原数据并更新市、省关联数据列表 + checkUploadData(reportMonth, regionId, cityData); + Long dataId = req.getId(); + // 上报数据不为空,说明为重新提交 + if (Objects.nonNull(dataId)) { + ConcreteSupplyBulletin oldData = concreteSupplyBulletinService.getById(dataId); + VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!"); + // 更新市级关联数据 + updateCityData(cityData,oldData); + // 删除被退回的数据 + concreteSupplyBulletinService.removeById(oldData); + } + + assemblyData(req, userDetail, concreteSupplyBulletin); + concreteSupplyBulletin.setAuditInfoId(cityAuditInfo.getId()); + concreteSupplyBulletin.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + concreteSupplyBulletinService.saveOrUpdate(concreteSupplyBulletin); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, concreteSupplyBulletin.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportMonth(reportMonth); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + Long relevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode())); + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportMonth(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail, LocalDateTime reportMonth, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportMonth(reportMonth); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqConcreteSupplyDataUploadPO req, UserInfoDetails userDetail, ConcreteSupplyBulletin concreteSupplyBulletin) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + concreteSupplyBulletin.setUnitName(regionName); + concreteSupplyBulletin.setThreeCategoryGuidGoal(req.getThreeCategoryGuidGoal()); + concreteSupplyBulletin.setProductionCompanyNums(req.getProductionCompanyNums()); + concreteSupplyBulletin.setAnnualDesignProductionCapacity(req.getAnnualDesignProductionCapacity()); + concreteSupplyBulletin.setThisMonthOutput(req.getThisMonthOutput()); + concreteSupplyBulletin.setAccumulativeOutput(req.getAccumulativeOutput()); + concreteSupplyBulletin.setThisMonthCementUsage(req.getThisMonthCementUsage()); + concreteSupplyBulletin.setCementAccumulativeUsage(req.getCementAccumulativeUsage()); + concreteSupplyBulletin.setThisMonthWasteUtilization(req.getThisMonthWasteUtilization()); + concreteSupplyBulletin.setAccumulativeWasteUtilization(req.getAccumulativeWasteUtilization()); + concreteSupplyBulletin.setReportMonth(req.getReportMonth()); + concreteSupplyBulletin.setCompanyId(userDetail.getCompanyId()); + concreteSupplyBulletin.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + concreteSupplyBulletin.setPreparer(req.getPreparer()); + concreteSupplyBulletin.setReviewer(req.getReviewer()); + concreteSupplyBulletin.setSubmissionDate(req.getSubmissionDate()); + concreteSupplyBulletin.setRegionId(userDetail.getRegionId()); + concreteSupplyBulletin.setCreateOn(LocalDateTime.now()); + concreteSupplyBulletin.setCreateBy(userDetail.getUserId()); + concreteSupplyBulletin.setUpdateOn(LocalDateTime.now()); + concreteSupplyBulletin.setUpdateBy(userDetail.getUserId()); + concreteSupplyBulletin.setRemark(req.getRemark()); + } + + private void checkUploadData(LocalDateTime reportMonth, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + ConcreteSupplyBulletin concreteSupplyBulletin = concreteSupplyBulletinService.getOne(Wrappers.lambdaQuery(ConcreteSupplyBulletin.class) + .eq(ConcreteSupplyBulletin::getRegionId, regionId) + .eq(ConcreteSupplyBulletin::getReportMonth, reportMonth)); + // 判断审核状态,如果审核通过,更新审核通过的数据 + if (Objects.nonNull(concreteSupplyBulletin) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(concreteSupplyBulletin.getAuditStatus())){ + updateCityData(cityData,concreteSupplyBulletin); + concreteSupplyBulletinService.removeById(concreteSupplyBulletin); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, ConcreteSupplyBulletin concreteSupplyBulletin) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报月份的数据数据从关联表中删除 + idList.remove(concreteSupplyBulletin.getId()); + } + } + } + + public ResConcreteSupplyDataUploadDetailVO getConcreteSupplyUploadData(ReqConcreteSupplyDataUploadPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + // 获取填报的数据 + BigDecimal threeCategoryGuidGoal = req.getThreeCategoryGuidGoal(); + Integer productionCompanyNums = req.getProductionCompanyNums(); + BigDecimal annualDesignProductionCapacity = req.getAnnualDesignProductionCapacity(); + + BigDecimal thisMonthOutput = req.getThisMonthOutput(); + BigDecimal thisMonthCementUsage = req.getThisMonthCementUsage(); + BigDecimal thisMonthWasteUtilization = req.getThisMonthWasteUtilization(); + String remark = req.getRemark(); + + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 计算实际产量(立方米)、使用散装水泥量(吨)、废弃物综合利用量(吨) + // 获取上个月该地区的混凝土供应量数据 + LocalDateTime preReportMonth = reportMonth.minusMonths(1L); + ConcreteSupplyBulletin preConcreteSupplyBulletin = concreteSupplyBulletinService.getOne(Wrappers.lambdaQuery(ConcreteSupplyBulletin.class) + .eq(ConcreteSupplyBulletin::getRegionId, regionId) + .eq(ConcreteSupplyBulletin::getReportMonth, preReportMonth)); + VUtils.isTrue(Objects.isNull(preConcreteSupplyBulletin)).throwMessage("系统上个月数据不存在!"); + + ResConcreteSupplyDataUploadDetailVO vo = new ResConcreteSupplyDataUploadDetailVO(); + vo.setThreeCategoryGuidGoal(threeCategoryGuidGoal); + vo.setProductionCompanyNums(productionCompanyNums); + vo.setAnnualDesignProductionCapacity(annualDesignProductionCapacity); + vo.setRemark(remark); + + if (Objects.nonNull(thisMonthOutput)) { + // 累计产量:本月实际产量 + 上个月累计产量 + BigDecimal preMonthAccumulativeOutput = preConcreteSupplyBulletin.getAccumulativeOutput(); + BigDecimal preMonthAccOutput = Objects.isNull(preMonthAccumulativeOutput) ? BigDecimal.ZERO : preMonthAccumulativeOutput; + BigDecimal accumulativeOutput = thisMonthOutput.add(preMonthAccOutput); + vo.setAccumulativeOutput(accumulativeOutput); + } + + if (Objects.nonNull(thisMonthCementUsage)) { + // 累计使用散装水泥量: 本月使用散装水泥量 + 上个月累计使用散装水泥量 + BigDecimal preMonthCementAccumulativeUsage = preConcreteSupplyBulletin.getCementAccumulativeUsage(); + BigDecimal preMonthCementAccUsage = Objects.isNull(preMonthCementAccumulativeUsage) ? BigDecimal.ZERO : preMonthCementAccumulativeUsage; + BigDecimal cementAccumulativeUsage = thisMonthCementUsage.add(preMonthCementAccUsage); + vo.setCementAccumulativeUsage(cementAccumulativeUsage); + } + + if (Objects.nonNull(thisMonthWasteUtilization)) { + // 累计废弃物综合利用量: 本月废弃物综合利用量 + 上个月累计废弃物综合利用量 + BigDecimal preMonthAccumulativeWasteUtilization = preConcreteSupplyBulletin.getAccumulativeWasteUtilization(); + BigDecimal preMonthAccWasteUtilization = Objects.isNull(preMonthAccumulativeWasteUtilization) ? BigDecimal.ZERO : preMonthAccumulativeWasteUtilization; + BigDecimal accumulativeWasteUtilization = thisMonthWasteUtilization.add(preMonthAccWasteUtilization); + vo.setAccumulativeWasteUtilization(accumulativeWasteUtilization); + } + return vo; + } + + public ResConcreteSupplyRelatedDataVO getConcreteSupplyRelatedData(ReqConcreteSupplyDataUploadPO po) { + LocalDateTime reportMonth = po.getReportMonth(); + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份!"); + Long regionId = po.getRegionId(); + VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!"); + LocalDateTime preReportMonth = reportMonth.minusMonths(1); + ConcreteSupplyBulletin preMonthConcreteSupplyBulletin = concreteSupplyBulletinService.getOne(Wrappers.lambdaQuery(ConcreteSupplyBulletin.class) + .eq(ConcreteSupplyBulletin::getReportMonth, preReportMonth) + .eq(ConcreteSupplyBulletin::getRegionId, regionId)); + int year = reportMonth.getYear(); + BulkCementDirectReportSystemUniversalIndex universalIndex = universalIndexService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemUniversalIndex.class) + .eq(BulkCementDirectReportSystemUniversalIndex::getRegionId, regionId) + .eq(BulkCementDirectReportSystemUniversalIndex::getYear, year)); + ResConcreteSupplyRelatedDataVO vo = new ResConcreteSupplyRelatedDataVO(); + if (Objects.nonNull(preMonthConcreteSupplyBulletin)) { + vo.setProductionCompanyNums(preMonthConcreteSupplyBulletin.getProductionCompanyNums()); + vo.setAnnualDesignProductionCapacity(preMonthConcreteSupplyBulletin.getAnnualDesignProductionCapacity()); + } + if (Objects.nonNull(universalIndex)) { + vo.setThreeCategoryGuidGoal(universalIndex.getConcreteSupplyThreeCategoryGuidGoal()); + }else { + vo.setThreeCategoryGuidGoal(BigDecimal.ZERO); + } + return vo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MaterialLogEquipStaManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MaterialLogEquipStaManage.java new file mode 100644 index 0000000..a58bd0b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MaterialLogEquipStaManage.java @@ -0,0 +1,478 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.dto.ReqMaterialLogEquipStaDataUploadDTO; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.ningdatech.carapi.report.model.entity.MaterialLogisticEquipmentStatisticAnnualReport; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.po.ReqMaterialLogEquipStaDataUploadPO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.model.vo.ResMaterialLogEquipStaDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResMaterialLogEquipStaRelatedDataVO; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditInfoService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditRecordService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemDataRelevanceService; +import com.ningdatech.carapi.report.service.IMaterialLogisticEquipmentStatisticAnnualReportService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class MaterialLogEquipStaManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final CompaniesCacheHelper companiesCacheHelper; + private final IMaterialLogisticEquipmentStatisticAnnualReportService materialLogEquipStaAnnualReportService; + + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + Page page = req.page(); + // 根据所属区域查出对应的散装水泥物流设施统计年报数据上报记录 + // (每个上报年份对应多个设备名称的数据,需要从数据关联表中查询) + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class); + // 获取入参 + Integer reportStartYear = req.getReportStartYear(); + Integer reportEndYear = req.getReportEndYear(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartYear), BulkCementDirectReportSystemDataRelevance::getReportYear, reportStartYear) + .le(Objects.nonNull(reportEndYear), BulkCementDirectReportSystemDataRelevance::getReportYear, reportEndYear) + .eq(Objects.nonNull(auditStatus),BulkCementDirectReportSystemDataRelevance::getAuditStatus,auditStatus) + // 市级/省级散办单位可根据区域分别查出对应的关联数据 + // 其中市级关联数据对应的数据ID列表为对应上报数据关联数据的ID + // 省级关联数据对应的数据ID列表为各市级关联数据的ID(温台舟使用量关联数据对应的数据ID列表 + // 仍为对应上报数据的ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType,UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId,regionId) + .orderByDesc(BulkCementDirectReportSystemDataRelevance::getReportYear); + //.isNotNull(BulkCementDirectReportSystemDataRelevance::getAuditInfoId); + dataRelevanceService.page(page,wrapper); + + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(BulkCementDirectReportSystemDataRelevance::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + Integer reportYear = r.getReportYear(); + vo.setRegionId(r.getRegionId()); + vo.setReportYear(reportYear); + vo.setAuditDataId(r.getId()); + + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String materialLogEquipStaDataUpload(ReqMaterialLogEquipStaDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Integer reportYear = req.getReportYear(); + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请选择上报年份!"); + Long regionId = userDetail.getRegionId(); + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + // 先提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 专用汽车数据 + ReqMaterialLogEquipStaDataUploadDTO specialVehicleData = req.getSpecialVehicleData(); + VUtils.isTrue(Objects.isNull(specialVehicleData)).throwMessage("请传入专用汽车数据!"); + // 专用船数据 + ReqMaterialLogEquipStaDataUploadDTO specialVesselData = req.getSpecialVesselData(); + VUtils.isTrue(Objects.isNull(specialVesselData)).throwMessage("请传入专用船数据!"); + // 散装水泥罐数据 + ReqMaterialLogEquipStaDataUploadDTO bulkCementTankData = req.getBulkCementTankData(); + VUtils.isTrue(Objects.isNull(bulkCementTankData)).throwMessage("请传入散装水泥罐数据!"); + // 混凝土搅拌车数据 + ReqMaterialLogEquipStaDataUploadDTO concreteMixerTruckData = req.getConcreteMixerTruckData(); + VUtils.isTrue(Objects.isNull(concreteMixerTruckData)).throwMessage("请传入混凝土搅拌车数据!"); + // 混凝土泵车数据 + ReqMaterialLogEquipStaDataUploadDTO concretePumpTruckData = req.getConcretePumpTruckData(); + VUtils.isTrue(Objects.isNull(concretePumpTruckData)).throwMessage("请传入混凝土泵车数据!"); + // 干混砂浆运输车数据 + ReqMaterialLogEquipStaDataUploadDTO dryMixMortarTruckData = req.getDryMixMortarTruckData(); + VUtils.isTrue(Objects.isNull(dryMixMortarTruckData)).throwMessage("请传入干混砂浆运输车数据!"); + // 干混砂浆移动简仓数据 + ReqMaterialLogEquipStaDataUploadDTO dryMixMortarMovingStorageData = req.getDryMixMortarMovingStorageData(); + VUtils.isTrue(Objects.isNull(dryMixMortarMovingStorageData)).throwMessage("请传入干混砂浆移动简仓数据!"); + // 干混砂浆背罐车数据 + ReqMaterialLogEquipStaDataUploadDTO dryMixMortarBackTankCarData = req.getDryMixMortarBackTankCarData(); + VUtils.isTrue(Objects.isNull(dryMixMortarBackTankCarData)).throwMessage("请传入干混砂浆背罐车数据!"); + + + // 合并保存(虽然每个装备名称的数据单独按一条数据保存,但审核数据仍在一条中) + List dataList = Lists.newArrayList(); + dataList.add(specialVehicleData); + dataList.add(specialVesselData); + dataList.add(bulkCementTankData); + dataList.add(concreteMixerTruckData); + dataList.add(concretePumpTruckData); + dataList.add(dryMixMortarTruckData); + dataList.add(dryMixMortarMovingStorageData); + dataList.add(dryMixMortarBackTankCarData); + + // 创建区县关联数据信息(对应每个设备名称的数据关系为一对多) + BulkCementDirectReportSystemDataRelevance countryData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + + BulkCementDirectReportSystemDataRelevance countryRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + // 区县的区域ID + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + Long parentId = regionDto.getParentId(); + // 判断上报年份所在市的市级关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + // 判断当前地区当前上报年份数据是否已经存在,如果已经存在,更新原数据 + checkUploadData(reportYear, regionId, cityData); + // 说明为重新提交 + if (Objects.nonNull(countryData)){ + // 先删除关联的已经保存的各装备名称的数据 + String auditDataIdList = countryData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idList)){ + materialLogEquipStaAnnualReportService.remove(Wrappers.lambdaQuery(MaterialLogisticEquipmentStatisticAnnualReport.class) + .in(MaterialLogisticEquipmentStatisticAnnualReport::getId,idList)); + } + } + // 更新市级关联数据 + updateCityData(cityData,countryData); + // 删除被退回的数据 + dataRelevanceService.removeById(countryData); + } + assemblyRelevanceData(userDetail, reportYear, countryRelevanceData); + countryRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + countryRelevanceData.setPreparer(req.getPreparer()); + countryRelevanceData.setReviewer(req.getReviewer()); + countryRelevanceData.setSubmissionDate(req.getSubmissionDate()); + countryRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + countryRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + countryRelevanceData.setRegionId(userDetail.getRegionId()); + countryRelevanceData.setCompanyId(userDetail.getCompanyId()); + List auditDataIdList = Lists.newArrayList(); + // 保存本次上报数据信息 + for (ReqMaterialLogEquipStaDataUploadDTO uploadDto : dataList) { + MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport = + new MaterialLogisticEquipmentStatisticAnnualReport(); + assemblyData(uploadDto, userDetail, materialLogEquipStaAnnualReport); + materialLogEquipStaAnnualReport.setAuditInfoId(cityAuditInfo.getId()); + materialLogEquipStaAnnualReport.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + materialLogEquipStaAnnualReportService.save(materialLogEquipStaAnnualReport); + auditDataIdList.add(materialLogEquipStaAnnualReport.getId()); + } + // 保存关联数据ID集合(一条关联数据对应多条不同设备名称的数据) + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + countryRelevanceData.setAuditDataIdList(idListStr); + dataRelevanceService.saveOrUpdate(countryRelevanceData); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, countryRelevanceData.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportYear(reportYear); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportYear, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + // 补充省散办关联数据信息 + Long cityRelevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(cityRelevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(cityRelevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报年份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + // 如果上报年份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportYear, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportYear(cityRelevanceData.getReportYear()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail, Integer reportYear, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportYear(reportYear); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqMaterialLogEquipStaDataUploadDTO req, UserInfoDetails userDetail, MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + materialLogEquipStaAnnualReport.setRegionName(regionName); + materialLogEquipStaAnnualReport.setEquipmentName(req.getEquipmentName()); + materialLogEquipStaAnnualReport.setYearBeginNum(req.getYearBeginNum()); + materialLogEquipStaAnnualReport.setYearBeginNominalRate(req.getYearBeginNominalRate()); + materialLogEquipStaAnnualReport.setThisYearNewAddNum(req.getThisYearNewAddNum()); + materialLogEquipStaAnnualReport.setThisYearNewAddNominalRate(req.getThisYearNewAddNominalRate()); + materialLogEquipStaAnnualReport.setThisYearDecreaseNum(req.getThisYearDecreaseNum()); + materialLogEquipStaAnnualReport.setThisYearDecreaseNominalRate(req.getThisYearDecreaseNominalRate()); + materialLogEquipStaAnnualReport.setYearEndNum(req.getYearEndNum()); + materialLogEquipStaAnnualReport.setYearEndNominal(req.getYearEndNominal()); + + materialLogEquipStaAnnualReport.setReportYear(req.getReportYear()); + materialLogEquipStaAnnualReport.setRemark(req.getRemark()); + materialLogEquipStaAnnualReport.setCompanyId(userDetail.getCompanyId()); + materialLogEquipStaAnnualReport.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + materialLogEquipStaAnnualReport.setPreparer(req.getPreparer()); + materialLogEquipStaAnnualReport.setReviewer(req.getReviewer()); + materialLogEquipStaAnnualReport.setSubmissionDate(req.getSubmissionDate()); + materialLogEquipStaAnnualReport.setRegionId(userDetail.getRegionId()); + materialLogEquipStaAnnualReport.setCreateOn(LocalDateTime.now()); + materialLogEquipStaAnnualReport.setCreateBy(userDetail.getUserId()); + materialLogEquipStaAnnualReport.setUpdateOn(LocalDateTime.now()); + materialLogEquipStaAnnualReport.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(Integer reportYear, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + // 查询区县关联数据 + BulkCementDirectReportSystemDataRelevance dataRelevance = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + if (Objects.nonNull(dataRelevance) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(dataRelevance.getAuditStatus())){ + // 先删除关联的已经保存的各装备名称的数据 + String auditDataIdList = dataRelevance.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idList)){ + materialLogEquipStaAnnualReportService.remove(Wrappers.lambdaQuery(MaterialLogisticEquipmentStatisticAnnualReport.class) + .in(MaterialLogisticEquipmentStatisticAnnualReport::getId,idList)); + } + } + updateCityData(cityData,dataRelevance); + dataRelevanceService.removeById(dataRelevance); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, BulkCementDirectReportSystemDataRelevance dataRelevance) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报年份的数据数据从市级关联表中删除 + idList.remove(dataRelevance.getId()); + } + } + } + + public ResMaterialLogEquipStaDataUploadDetailVO getMaterialLogEquipStaUploadData(ReqMaterialLogEquipStaDataUploadDTO req) { + // 获取填报的数据 + Integer yearBeginNum = req.getYearBeginNum(); + BigDecimal yearBeginNominalRate = req.getYearBeginNominalRate(); + Integer thisYearNewAddNum = req.getThisYearNewAddNum(); + BigDecimal thisYearNewAddNominalRate = req.getThisYearNewAddNominalRate(); + Integer thisYearDecreaseNum = req.getThisYearDecreaseNum(); + BigDecimal thisYearDecreaseNominalRate = req.getThisYearDecreaseNominalRate(); + String remark = req.getRemark(); + Integer reportYear = req.getReportYear(); + String equipmentName = req.getEquipmentName(); + VUtils.isTrue(StringUtils.isBlank(equipmentName)).throwMessage("请传入设备名称!"); + + ResMaterialLogEquipStaDataUploadDetailVO vo = new ResMaterialLogEquipStaDataUploadDetailVO(); + vo.setYearBeginNum(yearBeginNum); + vo.setYearBeginNominalRate(yearBeginNominalRate); + vo.setThisYearNewAddNum(thisYearNewAddNum); + vo.setThisYearNewAddNominalRate(thisYearNewAddNominalRate); + vo.setThisYearDecreaseNum(thisYearDecreaseNum); + vo.setThisYearDecreaseNominalRate(thisYearDecreaseNominalRate); + vo.setReportYear(reportYear); + vo.setRemark(remark); + + // 计算各数据 + // 年末数量: 年初数量 + 本年新增数量 - 本年减少数量 + if (Objects.nonNull(yearBeginNum) && Objects.nonNull(thisYearNewAddNum) && Objects.nonNull(thisYearDecreaseNum)){ + int yearEndNum = yearBeginNum + thisYearNewAddNum - thisYearDecreaseNum; + vo.setYearEndNum(yearEndNum); + } + // 年末额定量: 年初额定量 + 本年新增额定量 - 本年减少额定量 + if (Objects.nonNull(yearBeginNominalRate) && Objects.nonNull(thisYearNewAddNominalRate) && Objects.nonNull(thisYearDecreaseNominalRate)){ + BigDecimal yearEndCapacity = yearBeginNominalRate.add(thisYearNewAddNominalRate).subtract(thisYearDecreaseNominalRate); + vo.setYearEndNominal(yearEndCapacity); + } + return vo; + } + + public ResMaterialLogEquipStaRelatedDataVO getMaterialLogEquipStaRelatedData(ReqMaterialLogEquipStaDataUploadDTO dto) { + Integer reportYear = dto.getReportYear(); + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请传入上报年份!"); + Long regionId = dto.getRegionId(); + VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!"); + String equipmentName = dto.getEquipmentName(); + VUtils.isTrue(StringUtils.isBlank(equipmentName)).throwMessage("请传入装备名称!"); + Integer preReportYear = reportYear - 1; + MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport = materialLogEquipStaAnnualReportService.getOne(Wrappers.lambdaQuery(MaterialLogisticEquipmentStatisticAnnualReport.class) + .eq(MaterialLogisticEquipmentStatisticAnnualReport::getReportYear, preReportYear) + .eq(MaterialLogisticEquipmentStatisticAnnualReport::getEquipmentName,equipmentName) + .eq(MaterialLogisticEquipmentStatisticAnnualReport::getRegionId, regionId)); + ResMaterialLogEquipStaRelatedDataVO vo = new ResMaterialLogEquipStaRelatedDataVO(); + if (Objects.nonNull(materialLogEquipStaAnnualReport)) { + // 去年的年末数量 + vo.setYearBeginNum(materialLogEquipStaAnnualReport.getYearEndNum()); + // 去年的年末额定量 + vo.setYearBeginNominalRate(materialLogEquipStaAnnualReport.getYearEndNominal()); + } + return vo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MortarSupplyBulletinManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MortarSupplyBulletinManage.java new file mode 100644 index 0000000..a4d1916 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/MortarSupplyBulletinManage.java @@ -0,0 +1,473 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.entity.*; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.po.ReqMortarSupplyDataUploadPO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.model.vo.ResMortarSupplyDataUploadDetailVO; +import com.ningdatech.carapi.report.model.vo.ResMortarSupplyRelatedDataVO; +import com.ningdatech.carapi.report.service.*; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class MortarSupplyBulletinManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final IMortarSupplyBulletinService mortarSupplyBulletinService; + private final IBulkCementDirectReportSystemUniversalIndexService universalIndexService; + private final CompaniesCacheHelper companiesCacheHelper; + + public PageVo dataUploadList(ReqDataUploadListPO req) { + + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + Page page = req.page(); + // 根据所属区域查出对应的散装水泥供应量数据上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(MortarSupplyBulletin.class); + // 获取入参 + LocalDateTime reportStartMonth = req.getReportStartMonth(); + LocalDateTime reportEndMonth = req.getReportEndMonth(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartMonth), MortarSupplyBulletin::getReportMonth, reportStartMonth) + .le(Objects.nonNull(reportEndMonth), MortarSupplyBulletin::getReportMonth, reportEndMonth) + .eq(Objects.nonNull(auditStatus),MortarSupplyBulletin::getAuditStatus,auditStatus) + .eq(MortarSupplyBulletin::getRegionId,regionId) + .orderByDesc(MortarSupplyBulletin::getReportMonth); + //.isNotNull(MortarSupplyBulletin::getAuditInfoId); + mortarSupplyBulletinService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(MortarSupplyBulletin::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + LocalDateTime month = r.getReportMonth(); + String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT); + LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN)); + vo.setRegionId(r.getRegionId()); + vo.setReportMonth(reportMonth); + vo.setAuditDataId(r.getId()); + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String mortarSupplyDataUpload(ReqMortarSupplyDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请选择上报月份!"); + + // 提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + MortarSupplyBulletin mortarSupplyBulletin = new MortarSupplyBulletin(); + // 区县的区域ID + Long countryRegionId = userDetail.getRegionId(); + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId); + Long parentId = regionDto.getParentId(); + // 判断上报月份所在市的关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode())); + // 判断当前地区当前上报月份数据是否已经存在,如果已经存在,删除原数据并更新市、省关联数据列表 + checkUploadData(reportMonth, regionId, cityData); + Long dataId = req.getId(); + // 上报数据不为空,说明为重新提交 + if (Objects.nonNull(dataId)) { + MortarSupplyBulletin oldData = mortarSupplyBulletinService.getById(dataId); + VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!"); + // 更新市级关联数据 + updateCityData(cityData,oldData); + // 删除被退回的数据 + mortarSupplyBulletinService.removeById(oldData); + } + + assemblyData(req, userDetail, mortarSupplyBulletin); + mortarSupplyBulletin.setAuditInfoId(cityAuditInfo.getId()); + mortarSupplyBulletin.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + mortarSupplyBulletinService.saveOrUpdate(mortarSupplyBulletin); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, mortarSupplyBulletin.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportMonth(reportMonth); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + Long relevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode())); + + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, reportMonth, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportMonth(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail, LocalDateTime reportMonth, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportMonth(reportMonth); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqMortarSupplyDataUploadPO req, UserInfoDetails userDetail, MortarSupplyBulletin mortarSupplyBulletin) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + mortarSupplyBulletin.setRegionName(regionName); + mortarSupplyBulletin.setTwoCategoryGuidGoal(req.getTwoCategoryGuidGoal()); + mortarSupplyBulletin.setDryMixedMortarProductionCompanyNum(req.getDryMixedMortarProductionCompanyNum()); + mortarSupplyBulletin.setDryMixedMortarProductiveCapacity(req.getDryMixedMortarProductiveCapacity()); + mortarSupplyBulletin.setDryMixedMortarBulkCapacity(req.getDryMixedMortarBulkCapacity()); + + mortarSupplyBulletin.setThisMonthTotalOutput(req.getThisMonthTotalOutput()); + mortarSupplyBulletin.setThisMonthAccumulativeOutput(req.getThisMonthAccumulativeOutput()); + mortarSupplyBulletin.setDryMixedMortarThisMonthOutput(req.getDryMixedMortarThisMonthOutput()); + mortarSupplyBulletin.setDryMixedMortarThisMonthAccumulativeOutput(req.getDryMixedMortarThisMonthAccumulativeOutput()); + mortarSupplyBulletin.setDryMixedMortarIncrement(req.getDryMixedMortarIncrement()); + mortarSupplyBulletin.setDryMixedMortarGrowthRate(req.getDryMixedMortarGrowthRate()); + mortarSupplyBulletin.setDryMixedMortarThisMonthBulkQuantity(req.getDryMixedMortarThisMonthBulkQuantity()); + mortarSupplyBulletin.setDryMixedMortarAccumulativeBulkQuantity(req.getDryMixedMortarAccumulativeBulkQuantity()); + mortarSupplyBulletin.setWetMortarThisMonthOutput(req.getWetMortarThisMonthOutput()); + mortarSupplyBulletin.setWetMortarAccumulativeOutput(req.getWetMortarAccumulativeOutput()); + mortarSupplyBulletin.setBulkCementThisMonthUsage(req.getBulkCementThisMonthUsage()); + mortarSupplyBulletin.setBulkCementAccumulativeUsage(req.getBulkCementAccumulativeUsage()); + mortarSupplyBulletin.setWasteThisMonthComprehensiveUtilization(req.getWasteThisMonthComprehensiveUtilization()); + mortarSupplyBulletin.setWasteAccumulativeComprehensiveUtilization(req.getWasteAccumulativeComprehensiveUtilization()); + mortarSupplyBulletin.setReportMonth(req.getReportMonth()); + mortarSupplyBulletin.setCompanyId(userDetail.getCompanyId()); + mortarSupplyBulletin.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + mortarSupplyBulletin.setPreparer(req.getPreparer()); + mortarSupplyBulletin.setReviewer(req.getReviewer()); + mortarSupplyBulletin.setSubmissionDate(req.getSubmissionDate()); + mortarSupplyBulletin.setRegionId(userDetail.getRegionId()); + mortarSupplyBulletin.setCreateOn(LocalDateTime.now()); + mortarSupplyBulletin.setCreateBy(userDetail.getUserId()); + mortarSupplyBulletin.setUpdateOn(LocalDateTime.now()); + mortarSupplyBulletin.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(LocalDateTime reportMonth, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + MortarSupplyBulletin mortarSupplyBulletin = mortarSupplyBulletinService.getOne(Wrappers.lambdaQuery(MortarSupplyBulletin.class) + .eq(MortarSupplyBulletin::getRegionId, regionId) + .eq(MortarSupplyBulletin::getReportMonth, reportMonth)); + // 判断审核状态,如果审核通过,更新审核通过的数据 + if (Objects.nonNull(mortarSupplyBulletin) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(mortarSupplyBulletin.getAuditStatus())){ + updateCityData(cityData,mortarSupplyBulletin); + mortarSupplyBulletinService.removeById(mortarSupplyBulletin); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, MortarSupplyBulletin mortarSupplyBulletin) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报月份的数据数据从关联表中删除 + idList.remove(mortarSupplyBulletin.getId()); + } + } + } + + public ResMortarSupplyDataUploadDetailVO getMortarSupplyUploadData(ReqMortarSupplyDataUploadPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + // 上月填报的数据 + BigDecimal twoCategoryGuidGoal = req.getTwoCategoryGuidGoal(); + Integer dryMixedMortarProductionCompanyNum = req.getDryMixedMortarProductionCompanyNum(); + BigDecimal dryMixedMortarProductiveCapacity = req.getDryMixedMortarProductiveCapacity(); + BigDecimal dryMixedMortarBulkCapacity = req.getDryMixedMortarBulkCapacity(); + + // 普通干混砂浆本月产量 + BigDecimal dryMixedMortarThisMonthOutput = req.getDryMixedMortarThisMonthOutput(); + // 普通干混砂浆本月散装量 + BigDecimal dryMixedMortarThisMonthBulkQuantity = req.getDryMixedMortarThisMonthBulkQuantity(); + // 湿拌砂浆本月产量 + BigDecimal wetMortarThisMonthOutput = req.getWetMortarThisMonthOutput(); + // 散装水泥本月使用量 + BigDecimal bulkCementThisMonthUsage = req.getBulkCementThisMonthUsage(); + // 废弃物本月综合利用量 + BigDecimal wasteThisMonthComprehensiveUtilization = req.getWasteThisMonthComprehensiveUtilization(); + + LocalDateTime reportMonth = req.getReportMonth(); + Long regionId = userDetail.getRegionId(); + + // 计算实际产量、使用散装水泥量、废弃物综合利用量 + // 获取上个月该地区的砂浆供应量数据 + LocalDateTime preReportMonth = reportMonth.minusMonths(1L); + MortarSupplyBulletin preMortarSupplyBulletin = mortarSupplyBulletinService.getOne(Wrappers.lambdaQuery(MortarSupplyBulletin.class) + .eq(MortarSupplyBulletin::getRegionId, regionId) + .eq(MortarSupplyBulletin::getReportMonth, preReportMonth)); + VUtils.isTrue(Objects.isNull(preMortarSupplyBulletin)).throwMessage("系统上个月数据不存在!"); + // 获取去年当前上报月份该地区的散装水泥供应量数据 + LocalDateTime preYearReportMonth = preReportMonth.minusYears(1L).plusMonths(1L); + MortarSupplyBulletin preYearMortarSupplyBulletin = mortarSupplyBulletinService.getOne(Wrappers.lambdaQuery(MortarSupplyBulletin.class) + .eq(MortarSupplyBulletin::getRegionId, regionId) + .eq(MortarSupplyBulletin::getReportMonth, preYearReportMonth)); + VUtils.isTrue(Objects.isNull(preYearMortarSupplyBulletin)).throwMessage("系统去年该月数据不存在!"); + + ResMortarSupplyDataUploadDetailVO vo = new ResMortarSupplyDataUploadDetailVO(); + vo.setTwoCategoryGuidGoal(twoCategoryGuidGoal); + vo.setDryMixedMortarProductionCompanyNum(dryMixedMortarProductionCompanyNum); + vo.setDryMixedMortarProductiveCapacity(dryMixedMortarProductiveCapacity); + vo.setDryMixedMortarBulkCapacity(dryMixedMortarBulkCapacity); + + if (Objects.nonNull(dryMixedMortarThisMonthOutput) && Objects.nonNull(wetMortarThisMonthOutput)){ + // 本月总产量:本月普通干混砂浆产量 + 本月湿拌砂浆产量 + BigDecimal thisMonthTotalOutput = dryMixedMortarThisMonthOutput.add(wetMortarThisMonthOutput); + vo.setThisMonthTotalOutput(thisMonthTotalOutput); + // 本月累计总产量:本月总产量 + 上个月的累计总产量 + BigDecimal preThisMonthAccumulativeOutput = preMortarSupplyBulletin.getThisMonthAccumulativeOutput(); + BigDecimal thisMonthAccumulativeOutput = thisMonthTotalOutput.add(preThisMonthAccumulativeOutput); + vo.setThisMonthAccumulativeOutput(thisMonthAccumulativeOutput); + } + + if (Objects.nonNull(dryMixedMortarThisMonthOutput)) { + // 普通干混砂浆累计产量:普通干混砂浆本月产量 + 上个月普通干混砂浆累计产量 + BigDecimal preMonthDryMixedMortarThisMonthAccumulativeOutput = preMortarSupplyBulletin.getDryMixedMortarThisMonthAccumulativeOutput(); + BigDecimal preMonthDryMixedMortarThisMonthAccOutput = Objects.isNull(preMonthDryMixedMortarThisMonthAccumulativeOutput) ? BigDecimal.ZERO : preMonthDryMixedMortarThisMonthAccumulativeOutput; + BigDecimal dryMixedMortarThisMonthAccumulativeOutput = dryMixedMortarThisMonthOutput.add(preMonthDryMixedMortarThisMonthAccOutput); + vo.setDryMixedMortarThisMonthAccumulativeOutput(dryMixedMortarThisMonthAccumulativeOutput); + + // 普通干混砂浆同比增加量: 普通干混砂浆累计产量 - 去年普通干混砂浆累计产量 + BigDecimal preYearDryMixedMortarThisMonthAccumulativeOutput = preYearMortarSupplyBulletin.getDryMixedMortarThisMonthAccumulativeOutput(); + BigDecimal preYearDryMixedMortarThisMonthAccOutput = Objects.isNull(preYearDryMixedMortarThisMonthAccumulativeOutput) ? BigDecimal.ZERO : preYearDryMixedMortarThisMonthAccumulativeOutput; + BigDecimal dryMixedMortarIncrement = dryMixedMortarThisMonthAccumulativeOutput.subtract(preYearDryMixedMortarThisMonthAccOutput); + vo.setDryMixedMortarIncrement(dryMixedMortarIncrement); + // 普通干混砂浆增长率:普通干混砂浆同比增加量 / 去年普通干混砂浆累计产量 + BigDecimal dryMixedMortarGrowthRate = dryMixedMortarIncrement.divide(preYearDryMixedMortarThisMonthAccumulativeOutput, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + vo.setDryMixedMortarGrowthRate(dryMixedMortarGrowthRate); + } + + if (Objects.nonNull(dryMixedMortarThisMonthBulkQuantity)) { + // 普通干混砂浆累计散装量:普通干混砂浆本月散装量 + 上个月普通干混砂浆累计散装量 + BigDecimal preDryMixedMortarAccumulativeBulkQuantity = preMortarSupplyBulletin.getDryMixedMortarAccumulativeBulkQuantity(); + BigDecimal dryMixedMortarAccumulativeBulkQuantity = dryMixedMortarThisMonthBulkQuantity.add(preDryMixedMortarAccumulativeBulkQuantity); + vo.setDryMixedMortarAccumulativeBulkQuantity(dryMixedMortarAccumulativeBulkQuantity); + } + + if (Objects.nonNull(wetMortarThisMonthOutput)) { + // 湿拌砂浆累计产量:湿拌砂浆本月产量 + 上个月湿拌砂浆累计产量 + BigDecimal preMonthWetMortarAccumulativeOutput = preMortarSupplyBulletin.getWetMortarAccumulativeOutput(); + BigDecimal preMonthWetMortarAccOutput = Objects.isNull(preMonthWetMortarAccumulativeOutput) ? BigDecimal.ZERO : preMonthWetMortarAccumulativeOutput; + BigDecimal wetMortarAccumulativeOutput = wetMortarThisMonthOutput.add(preMonthWetMortarAccOutput); + vo.setWetMortarAccumulativeOutput(wetMortarAccumulativeOutput); + } + + if (Objects.nonNull(bulkCementThisMonthUsage)) { + // 累计使用散装水泥量:本月使用散装水泥量 + 上个月累计使用散装水泥量 + BigDecimal preMonthBulkCementAccumulativeUsage = preMortarSupplyBulletin.getBulkCementAccumulativeUsage(); + BigDecimal preMonthBulkCementAccUsage = Objects.isNull(preMonthBulkCementAccumulativeUsage) ? BigDecimal.ZERO : preMonthBulkCementAccumulativeUsage; + BigDecimal bulkCementAccumulativeUsage = bulkCementThisMonthUsage.add(preMonthBulkCementAccUsage); + vo.setBulkCementAccumulativeUsage(bulkCementAccumulativeUsage); + } + + if (Objects.nonNull(wasteThisMonthComprehensiveUtilization)) { + // 累计废弃物综合利用量:本月废弃物综合利用量 + 上个月累计废弃物综合利用量 + BigDecimal preMonthWasteAccumulativeComprehensiveUtilization = preMortarSupplyBulletin.getWasteAccumulativeComprehensiveUtilization(); + BigDecimal preMonthWasteAccComprehensiveUtilization = Objects.isNull(preMonthWasteAccumulativeComprehensiveUtilization) ? BigDecimal.ZERO : preMonthWasteAccumulativeComprehensiveUtilization; + BigDecimal wasteAccumulativeComprehensiveUtilization = wasteThisMonthComprehensiveUtilization.add(preMonthWasteAccComprehensiveUtilization); + vo.setWasteAccumulativeComprehensiveUtilization(wasteAccumulativeComprehensiveUtilization); + } + return vo; + } + + public ResMortarSupplyRelatedDataVO getMortarSupplyRelatedData(ReqMortarSupplyDataUploadPO po) { + LocalDateTime reportMonth = po.getReportMonth(); + VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份!"); + Long regionId = po.getRegionId(); + VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!"); + LocalDateTime preReportMonth = reportMonth.minusMonths(1); + MortarSupplyBulletin preMonthMortarSupplyBulletin = mortarSupplyBulletinService.getOne(Wrappers.lambdaQuery(MortarSupplyBulletin.class) + .eq(MortarSupplyBulletin::getReportMonth, preReportMonth) + .eq(MortarSupplyBulletin::getRegionId, regionId)); + int year = reportMonth.getYear(); + BulkCementDirectReportSystemUniversalIndex universalIndex = universalIndexService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemUniversalIndex.class) + .eq(BulkCementDirectReportSystemUniversalIndex::getRegionId, regionId) + .eq(BulkCementDirectReportSystemUniversalIndex::getYear, year)); + ResMortarSupplyRelatedDataVO vo = new ResMortarSupplyRelatedDataVO(); + if (Objects.nonNull(universalIndex)) { + vo.setTwoCategoryGuidGoal(universalIndex.getMortarSupplyTwoCategoryGuidGoal()); + }else { + vo.setTwoCategoryGuidGoal(BigDecimal.ZERO); + } + if (Objects.nonNull(preMonthMortarSupplyBulletin)){ + vo.setDryMixedMortarProductionCompanyNum(preMonthMortarSupplyBulletin.getDryMixedMortarProductionCompanyNum()); + vo.setDryMixedMortarProductiveCapacity(preMonthMortarSupplyBulletin.getDryMixedMortarProductiveCapacity()); + vo.setDryMixedMortarBulkCapacity(preMonthMortarSupplyBulletin.getDryMixedMortarBulkCapacity()); + } + return vo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/NonProhibitedAreasBulkCementSalesUseManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/NonProhibitedAreasBulkCementSalesUseManage.java new file mode 100644 index 0000000..32729fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/manage/NonProhibitedAreasBulkCementSalesUseManage.java @@ -0,0 +1,381 @@ +package com.ningdatech.carapi.report.manage; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.ningdatech.carapi.report.model.entity.NonProhibitedAreasBulkCementSalesUse; +import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO; +import com.ningdatech.carapi.report.model.po.ReqNonProhibitedAreasDataUploadPO; +import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO; +import com.ningdatech.carapi.report.model.vo.ResNonProhibitedAreasDataUploadDetailVO; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditInfoService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditRecordService; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemDataRelevanceService; +import com.ningdatech.carapi.report.service.INonProhibitedAreasBulkCementSalesUseService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/28 11:15 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class NonProhibitedAreasBulkCementSalesUseManage { + + private final IBulkCementDirectReportSystemAuditRecordService auditRecordService; + private final IBulkCementDirectReportSystemAuditInfoService auditInfoService; + private final RegionsCacheHelper regionsCacheHelper; + private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + private final INonProhibitedAreasBulkCementSalesUseService nonProhibitedAreasBulkCementSalesUseService; + private final CompaniesCacheHelper companiesCacheHelper; + + public PageVo dataUploadList(ReqDataUploadListPO req) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + Page page = req.page(); + // 根据所属区域查出对应的散装水泥供应量数据上报记录 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NonProhibitedAreasBulkCementSalesUse.class); + // 获取入参 + Integer reportStartYear = req.getReportStartYear(); + Integer reportEndYear = req.getReportEndYear(); + Integer auditStatus = req.getAuditStatus(); + wrapper.ge(Objects.nonNull(reportStartYear), NonProhibitedAreasBulkCementSalesUse::getReportYear, reportStartYear) + .le(Objects.nonNull(reportEndYear), NonProhibitedAreasBulkCementSalesUse::getReportYear, reportEndYear) + .eq(Objects.nonNull(auditStatus),NonProhibitedAreasBulkCementSalesUse::getAuditStatus,auditStatus) + .eq(NonProhibitedAreasBulkCementSalesUse::getRegionId,regionId) + .orderByDesc(NonProhibitedAreasBulkCementSalesUse::getReportYear); + //.isNotNull(NonProhibitedAreasBulkCementSalesUse::getAuditInfoId); + nonProhibitedAreasBulkCementSalesUseService.page(page,wrapper); + List records = page.getRecords(); + if (CollUtil.isEmpty(records)){ + return PageVo.empty(); + } + // 获取审核信息 + List auditInfoIdList = records.stream().map(NonProhibitedAreasBulkCementSalesUse::getAuditInfoId).collect(Collectors.toList()); + Map auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList)) + .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v)); + List resVos = records.stream().map(r -> { + ResDataUploadListVO vo = new ResDataUploadListVO(); + Integer reportYear = r.getReportYear(); + vo.setRegionId(r.getRegionId()); + vo.setReportYear(reportYear); + vo.setAuditDataId(r.getId()); + BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId()); + if (Objects.nonNull(auditInfo)) { + vo.setAuditOpinion(auditInfo.getAuditOpinion()); + } + vo.setAuditStatus(r.getAuditStatus()); + String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus()); + vo.setAuditStatusName(desc); + vo.setCreateOn(r.getCreateOn()); + return vo; + }).collect(Collectors.toList()); + return PageVo.of(resVos, page.getTotal()); + } + + @Transactional(rollbackFor = Exception.class) + public String nonProhibitedAreasDataUpload(ReqNonProhibitedAreasDataUploadPO req) { + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Integer reportYear = req.getReportYear(); + Long regionId = userDetail.getRegionId(); + + // 如果登录用户为区县散办 + if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + VUtils.isTrue(Objects.isNull(reportYear)).throwMessage("请选择上报年份!"); + + // 提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + NonProhibitedAreasBulkCementSalesUse nonProAreasBulkCementSalesUse = new NonProhibitedAreasBulkCementSalesUse(); + // 区县的区域ID + Long countryRegionId = userDetail.getRegionId(); + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId); + Long parentId = regionDto.getParentId(); + // 判断上报月份所在市的关联数据不存在 + RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode())); + // 判断当前地区当前上报月份数据是否已经存在,如果已经存在,删除原数据并更新市、省关联数据列表 + checkUploadData(reportYear, regionId, cityData); + Long dataId = req.getId(); + // 上报数据不为空,说明为重新提交 + if (Objects.nonNull(dataId)) { + NonProhibitedAreasBulkCementSalesUse oldData = nonProhibitedAreasBulkCementSalesUseService.getById(dataId); + VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!"); + // 更新市级关联数据 + updateCityData(cityData,oldData); + // 删除被退回的数据 + nonProhibitedAreasBulkCementSalesUseService.removeById(oldData); + } + + assemblyData(req, userDetail, nonProAreasBulkCementSalesUse); + nonProAreasBulkCementSalesUse.setAuditInfoId(cityAuditInfo.getId()); + nonProAreasBulkCementSalesUse.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + nonProhibitedAreasBulkCementSalesUseService.saveOrUpdate(nonProAreasBulkCementSalesUse); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, nonProAreasBulkCementSalesUse.getId(), cityAuditInfo.getId(), auditRecord); + auditRecord.setReportYear(reportYear); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 补充所在市的关联数据信息 + if (Objects.isNull(cityData)) { + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, nonProAreasBulkCementSalesUse.getId(), reportYear, cityRelevanceData); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + } + + } + // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中,并提交省级审核信息和审核记录 + else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) { + + Long relevanceDataId = req.getId(); + VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!"); + + // 提交省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据审核状态为审核中 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(userDetail.getUserId()); + cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + cityRelevanceData.setPreparer(req.getPreparer()); + cityRelevanceData.setReviewer(req.getReviewer()); + cityRelevanceData.setSubmissionDate(req.getSubmissionDate()); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, reportYear) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode())); + + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + if (Objects.isNull(provinceData)) { + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + assemblyRelevanceData(userDetail, relevanceDataId, reportYear, provinceRelevanceData); + provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + provinceRelevanceData.setCompanyId(companyDto.getId()); + } + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord); + provinceAuditRecord.setReportYear(cityRelevanceData.getReportYear()); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + + return "上报成功!"; + } + + private void assemblyRelevanceData(UserInfoDetails userDetail, Long auditDataId, Integer reportYear, BulkCementDirectReportSystemDataRelevance relevanceData) { + relevanceData.setReportYear(reportYear); + relevanceData.setCreateOn(LocalDateTime.now()); + relevanceData.setCreateBy(userDetail.getUserId()); + relevanceData.setUpdateOn(LocalDateTime.now()); + relevanceData.setUpdateBy(userDetail.getUserId()); + relevanceData.setLastUpdateTime(LocalDateTime.now()); + } + private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) { + auditRecord.setAuditDataId(auditDataId); + auditRecord.setAuditInfoId(auditInfoId); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode()); + auditRecord.setCompanyId(userDetail.getCompanyId()); + auditRecord.setRegionId(userDetail.getRegionId()); + auditRecord.setCreateOn(LocalDateTime.now()); + auditRecord.setCreateBy(userDetail.getUserId()); + auditRecord.setUpdateOn(LocalDateTime.now()); + auditRecord.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) { + auditInfo.setAuditStatus(underAudit.getCode()); + auditInfo.setAuditDataType(UploadDataTypeEnum.NON_PROHIBITED_AREAS_BULK_CEMENT_SALES_USE.getCode()); + auditInfo.setCreateOn(LocalDateTime.now()); + auditInfo.setCreateBy(userDetail.getUserId()); + auditInfo.setUpdateOn(LocalDateTime.now()); + auditInfo.setUpdateBy(userDetail.getUserId()); + } + + private void assemblyData(ReqNonProhibitedAreasDataUploadPO req, UserInfoDetails userDetail, NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse) { + RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId()); + String regionName = regionDto.getRegionName(); + // 单位名称改成了地区 + nonProhibitedAreasBulkCementSalesUse.setRegionName(regionName); + nonProhibitedAreasBulkCementSalesUse.setSalePointAccumulativeNum(req.getSalePointAccumulativeNum()); + nonProhibitedAreasBulkCementSalesUse.setCementCompanyBuildPointNum(req.getCementCompanyBuildPointNum()); + nonProhibitedAreasBulkCementSalesUse.setOtherInvestmentBuildPointNum(req.getOtherInvestmentBuildPointNum()); + nonProhibitedAreasBulkCementSalesUse.setSaleVolume(req.getSaleVolume()); + nonProhibitedAreasBulkCementSalesUse.setBulkCementTankNum(req.getBulkCementTankNum()); + nonProhibitedAreasBulkCementSalesUse.setBulkCementTankCapacity(req.getBulkCementTankCapacity()); + nonProhibitedAreasBulkCementSalesUse.setCementUsage(req.getCementUsage()); + nonProhibitedAreasBulkCementSalesUse.setBulkCementUsage(req.getBulkCementUsage()); + nonProhibitedAreasBulkCementSalesUse.setReadyMixedConcreteBulkCementUsage(req.getReadyMixedConcreteBulkCementUsage()); + nonProhibitedAreasBulkCementSalesUse.setCementProductsBulkCementUsage(req.getCementProductsBulkCementUsage()); + nonProhibitedAreasBulkCementSalesUse.setBulkCementUsageRate(req.getBulkCementUsageRate()); + nonProhibitedAreasBulkCementSalesUse.setReadyMixedConcreteOutput(req.getReadyMixedConcreteOutput()); + nonProhibitedAreasBulkCementSalesUse.setReportYear(req.getReportYear()); + nonProhibitedAreasBulkCementSalesUse.setRemark(req.getRemark()); + nonProhibitedAreasBulkCementSalesUse.setCompanyId(userDetail.getCompanyId()); + nonProhibitedAreasBulkCementSalesUse.setUnitResponsiblePerson(req.getUnitResponsiblePerson()); + nonProhibitedAreasBulkCementSalesUse.setPreparer(req.getPreparer()); + nonProhibitedAreasBulkCementSalesUse.setReviewer(req.getReviewer()); + nonProhibitedAreasBulkCementSalesUse.setSubmissionDate(req.getSubmissionDate()); + nonProhibitedAreasBulkCementSalesUse.setRegionId(userDetail.getRegionId()); + nonProhibitedAreasBulkCementSalesUse.setCreateOn(LocalDateTime.now()); + nonProhibitedAreasBulkCementSalesUse.setCreateBy(userDetail.getUserId()); + nonProhibitedAreasBulkCementSalesUse.setUpdateOn(LocalDateTime.now()); + nonProhibitedAreasBulkCementSalesUse.setUpdateBy(userDetail.getUserId()); + } + + private void checkUploadData(Integer reportYear, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) { + NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse = nonProhibitedAreasBulkCementSalesUseService.getOne(Wrappers.lambdaQuery(NonProhibitedAreasBulkCementSalesUse.class) + .eq(NonProhibitedAreasBulkCementSalesUse::getRegionId, regionId) + .eq(NonProhibitedAreasBulkCementSalesUse::getReportYear, reportYear)); + // 判断审核状态,如果审核通过,更新审核通过的数据 + if (Objects.nonNull(nonProhibitedAreasBulkCementSalesUse) && + DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(nonProhibitedAreasBulkCementSalesUse.getAuditStatus())){ + updateCityData(cityData,nonProhibitedAreasBulkCementSalesUse); + nonProhibitedAreasBulkCementSalesUseService.removeById(nonProhibitedAreasBulkCementSalesUse); + } + } + + private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse) { + if (Objects.nonNull(cityData)) { + String auditDataIdList = cityData.getAuditDataIdList(); + if (StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + // 将已经存在的该地区该上报月份的数据数据从关联表中删除 + idList.remove(nonProhibitedAreasBulkCementSalesUse.getId()); + } + } + } + + public ResNonProhibitedAreasDataUploadDetailVO getNonProhibitedAreasUploadData(ReqNonProhibitedAreasDataUploadPO req) { + + // 获取登录用户信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + // 获取填报的数据 + Integer cementCompanyBuildPointNum = req.getCementCompanyBuildPointNum(); + Integer otherInvestmentBuildPointNum = req.getOtherInvestmentBuildPointNum(); + BigDecimal saleVolume = req.getSaleVolume(); + Integer bulkCementTankNum = req.getBulkCementTankNum(); + BigDecimal bulkCementTankCapacity = req.getBulkCementTankCapacity(); + BigDecimal cementUsage = req.getCementUsage(); + BigDecimal readyMixedConcreteBulkCementUsage = req.getReadyMixedConcreteBulkCementUsage(); + BigDecimal cementProductsBulkCementUsage = req.getCementProductsBulkCementUsage(); + BigDecimal readyMixedConcreteOutput = req.getReadyMixedConcreteOutput(); + String remark = req.getRemark(); + Integer reportYear = req.getReportYear(); + + ResNonProhibitedAreasDataUploadDetailVO vo = new ResNonProhibitedAreasDataUploadDetailVO(); + vo.setSaleVolume(saleVolume); + vo.setBulkCementTankNum(bulkCementTankNum); + vo.setBulkCementTankCapacity(bulkCementTankCapacity); + vo.setCementUsage(cementUsage); + vo.setReadyMixedConcreteBulkCementUsage(readyMixedConcreteBulkCementUsage); + vo.setCementProductsBulkCementUsage(cementProductsBulkCementUsage); + vo.setReadyMixedConcreteOutput(readyMixedConcreteOutput); + vo.setReportYear(reportYear); + vo.setRemark(remark); + + // 计算各数据 + // 非禁现区散装水泥销售点合计数量: 水泥企业建点数量 + 其它投资建点数量 + if (Objects.nonNull(cementCompanyBuildPointNum) && Objects.nonNull(otherInvestmentBuildPointNum)){ + int salePointAccumulativeNum = cementCompanyBuildPointNum + otherInvestmentBuildPointNum; + vo.setSalePointAccumulativeNum(salePointAccumulativeNum); + } + // 非禁现区散装水泥使用量: 生产预拌混凝土使用散装水泥量 + 生产水泥制品使用散装水泥量 + if (Objects.nonNull(readyMixedConcreteBulkCementUsage) && Objects.nonNull(cementProductsBulkCementUsage)){ + BigDecimal bulkCementUsage = readyMixedConcreteBulkCementUsage.add(cementProductsBulkCementUsage); + vo.setBulkCementUsage(bulkCementUsage); + // 非禁现区域散装水泥使用率:散装水泥使用量 / 水泥使用量 * 100 + if (Objects.nonNull(cementUsage)){ + BigDecimal bulkCementUsageRate = bulkCementUsage.divide(cementUsage, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + vo.setBulkCementUsageRate(bulkCementUsageRate); + } + } + return vo; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.java new file mode 100644 index 0000000..c7d16f5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥直报系统审核信息表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +public interface BulkCementDirectReportSystemAuditInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.xml new file mode 100644 index 0000000..c9d22a6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.java new file mode 100644 index 0000000..d55380f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥直报系统审核记录表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +public interface BulkCementDirectReportSystemAuditRecordMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.xml new file mode 100644 index 0000000..a848c30 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemAuditRecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.java new file mode 100644 index 0000000..017a2b5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥直报系统市级上报数据关联表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-30 + */ +public interface BulkCementDirectReportSystemDataRelevanceMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.xml new file mode 100644 index 0000000..2f1c7ee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemDataRelevanceMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.java new file mode 100644 index 0000000..05d2cd6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemIndex; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥直报系统指标数据 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +public interface BulkCementDirectReportSystemIndexMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.xml new file mode 100644 index 0000000..afad4ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemIndexMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.java new file mode 100644 index 0000000..0d2343a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemUniversalIndex; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥直报系统通用指标 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-10-02 + */ +public interface BulkCementDirectReportSystemUniversalIndexMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.xml new file mode 100644 index 0000000..fefac1e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementDirectReportSystemUniversalIndexMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.java new file mode 100644 index 0000000..7847c33 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementLogisticFacilityStatisticAnnualReport; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥物流设施统计年报表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface BulkCementLogisticFacilityStatisticAnnualReportMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.xml new file mode 100644 index 0000000..bf10cfe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementLogisticFacilityStatisticAnnualReportMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.java new file mode 100644 index 0000000..ca33a04 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementSupplyBulletin; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥供应量快报 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface BulkCementSupplyBulletinMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.xml new file mode 100644 index 0000000..658ef79 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementSupplyBulletinMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.java new file mode 100644 index 0000000..3b55da9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementThreeCityUsageBulletin; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 温州、台州、舟山使用量快报 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface BulkCementThreeCityUsageBulletinMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.xml new file mode 100644 index 0000000..83b37a4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementThreeCityUsageBulletinMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.java new file mode 100644 index 0000000..18efa2a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.BulkCementTransferBulletin; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 中转库进出量快报 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface BulkCementTransferBulletinMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.xml new file mode 100644 index 0000000..55e8b6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/BulkCementTransferBulletinMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.java new file mode 100644 index 0000000..b2acd74 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.ConcreteSupplyBulletin; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 混凝土供应量快报 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface ConcreteSupplyBulletinMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.xml new file mode 100644 index 0000000..3d53e9d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/ConcreteSupplyBulletinMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.java new file mode 100644 index 0000000..99511da --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.MaterialLogisticEquipmentStatisticAnnualReport; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 散装水泥、预拌混凝土、干混砂浆物流装备统计年报表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface MaterialLogisticEquipmentStatisticAnnualReportMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.xml new file mode 100644 index 0000000..745ca31 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MaterialLogisticEquipmentStatisticAnnualReportMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.java new file mode 100644 index 0000000..1ec496c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.MortarSupplyBulletin; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 砂浆供应量快报 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface MortarSupplyBulletinMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.xml new file mode 100644 index 0000000..f7e6d06 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/MortarSupplyBulletinMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.java new file mode 100644 index 0000000..3e0b9b5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.mapper; + +import com.ningdatech.carapi.report.model.entity.NonProhibitedAreasBulkCementSalesUse; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 非禁现区域散装水泥销售使用情况统计年报表 Mapper 接口 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface NonProhibitedAreasBulkCementSalesUseMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.xml new file mode 100644 index 0000000..bcc60c5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/mapper/NonProhibitedAreasBulkCementSalesUseMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementLogFacStaQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementLogFacStaQueryDataExportDTO.java new file mode 100644 index 0000000..1a2fbe0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementLogFacStaQueryDataExportDTO.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class BulkCementLogFacStaQueryDataExportDTO { + + @NotNull(message = "年初数量不能为空") + @Excel(name = "数量",groupName = "年初") + private Integer yearBeginNum; + @Excel(name = "容量") + @NotNull(message = "年初容量不能为空") + private BigDecimal yearBeginCapacity; + + @NotNull(message = "本年新增数量不能为空") + @Excel(name = "数量",groupName = "本年新增") + private Integer thisYearNewAddNum; + @Excel(name = "容量") + @NotNull(message = "本年新增容量不能为空") + private BigDecimal thisYearNewAddCapacity; + + @NotNull(message = "本年报废数量不能为空") + @Excel(name = "数量",groupName = "本年报废") + private Integer thisYearScrapNum; + @Excel(name = "容量") + @NotNull(message = "本年报废容量不能为空") + private BigDecimal thisYearScrapCapacity; + + @NotNull(message = "年末数量不能为空") + @Excel(name = "数量",groupName = "年末") + private Integer yearEndNum; + @Excel(name = "容量") + @NotNull(message = "年末容量不能为空") + private BigDecimal yearEndCapacity; + + @Excel(name = "本年实际作业量") + @NotNull(message = "本年实际作业量不能为空") + private BigDecimal thisYearWorkAmount; + + @Excel(name = "设施名称") + @NotNull(message = "设施名称不能为空") + private String regionName; + + @Excel(name = "备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementSupplyQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementSupplyQueryDataExportDTO.java new file mode 100644 index 0000000..10be57d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementSupplyQueryDataExportDTO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class BulkCementSupplyQueryDataExportDTO { + @NotNull(message = "散装水泥总量不能为空") + @Excel(name = "散装水泥总量",groupName = "本月实际") + private BigDecimal bulkCementAmount; + @Excel(name = "水泥产量") + @NotNull(message = "水泥产量不能为空") + private BigDecimal cementOutput; + + @Excel(name = "完成量",groupName = "年初至本月累计") + @NotNull(message = "完成量不能为空") + private BigDecimal completedTotalAmount; + @Excel(name = "散装率") + @NotNull(message = "散装率不能为空") + private BigDecimal bulkRate; + @Excel(name = "本月止累计水泥产量") + @NotNull(message = "本月止累计水泥产量不能为空") + private BigDecimal cumulativeCementProduction; + + @Excel(name = "增加量",groupName = "比去年同期") + @NotNull(message = "增加量不能为空") + private BigDecimal increment; + @Excel(name = "增长率") + @NotNull(message = "增长率不能为空") + private BigDecimal increaseRate; + + @Excel(name = "单位") + @NotNull(message = "单位不能为空") + private String unitName; + + @Excel(name = "散装率目标") + private BigDecimal bulkRateTarget; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementThreeCityUsageQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementThreeCityUsageQueryDataExportDTO.java new file mode 100644 index 0000000..79e19a0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementThreeCityUsageQueryDataExportDTO.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class BulkCementThreeCityUsageQueryDataExportDTO { + @NotNull(message = "本月使用量不能为空") + @Excel(name = "本月",groupName = "合计") + private BigDecimal thisMonthUsage; + @Excel(name = "累计") + @NotNull(message = "本月累计使用量不能为空") + private BigDecimal accumulativeUsage; + @Excel(name = "同比增长率") + @NotNull(message = "同比增长率不能为空") + private BigDecimal growthRate; + + @Excel(name = "本月",groupName = "本省") + @NotNull(message = "本省本月使用量不能为空") + private BigDecimal thisProvinceThisMonthUsage; + @Excel(name = "累计") + @NotNull(message = "本省累计使用量不能为空") + private BigDecimal thisProvinceAccumulativeUsage; + + @Excel(name = "本月",groupName = "外省") + @NotNull(message = "外省本月使用量不能为空") + private BigDecimal otherProvinceThisMonthUsage; + @Excel(name = "累计") + @NotNull(message = "外省累计使用量不能为空") + private BigDecimal otherProvinceAccumulativeUsage; + + @Excel(name = "单位") + @NotNull(message = "单位名称不能为空") + private String unitName; + + @Excel(name = "年目标") + @NotNull(message = "年目标不能为空") + private BigDecimal yearTarget; + + @Excel(name = "占全年目标%") + @NotNull(message = "占全年目标百分比不能为空") + private BigDecimal percentageOfAnnualTarget; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementTransferQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementTransferQueryDataExportDTO.java new file mode 100644 index 0000000..68057fd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/BulkCementTransferQueryDataExportDTO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class BulkCementTransferQueryDataExportDTO { + @NotNull(message = "本月进库量不能为空") + @Excel(name = "本月",groupName = "进库量") + private BigDecimal thisMonthIncomingStorage; + @Excel(name = "累计") + @NotNull(message = "累计进库量不能为空") + private BigDecimal cumulativeIncomingStorage; + + @Excel(name = "本月",groupName = "出库量") + @NotNull(message = "本月出库量不能为空") + private BigDecimal thisMonthOutgoingStorage; + @Excel(name = "累计") + @NotNull(message = "累计出库量不能为空") + private BigDecimal cumulativeOutgoingStorage; + + @Excel(name = "库存量",groupName = "月末库存") + @NotNull(message = "月末库存量不能为空") + private BigDecimal monthEndInventory; + @Excel(name = "同比增长率") + @NotNull(message = "月末库存同比增长率不能为空") + private BigDecimal monthEndInventoryGrowthRate; + + @Excel(name = "单位") + @NotNull(message = "单位名称不能为空") + private String unitName; + + @Excel(name = "上月末库存") + @NotNull(message = "上月末库存不能为空") + private BigDecimal lastMonthEndInventory; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ConcreteSupplyQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ConcreteSupplyQueryDataExportDTO.java new file mode 100644 index 0000000..eeab8e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ConcreteSupplyQueryDataExportDTO.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class ConcreteSupplyQueryDataExportDTO { + @NotNull(message = "本月实际产量不能为空") + @Excel(name = "本月",groupName = "实际产量(立方米)") + private BigDecimal thisMonthOutput; + @Excel(name = "累计") + @NotNull(message = "累计实际产量不能为空") + private BigDecimal accumulativeOutput; + + @Excel(name = "本月",groupName = "使用散装水泥量(吨)") + @NotNull(message = "本月使用散装水泥量不能为空") + private BigDecimal thisMonthCementUsage; + @Excel(name = "累计") + @NotNull(message = "累计使用散装水泥量不能为空") + private BigDecimal cementAccumulativeUsage; + + @Excel(name = "本月",groupName = "废弃物综合利用量(吨)") + @NotNull(message = "本月废弃物综合利用量不能为空") + private BigDecimal thisMonthWasteUtilization; + @Excel(name = "累计") + @NotNull(message = "累计废弃物综合利用量不能为空") + private BigDecimal accumulativeWasteUtilization; + + @Excel(name = "单位") + @NotNull(message = "单位不能为空") + private String unitName; + + @Excel(name = "三类指导目标(万立方米)") + @NotNull(message = "三类指导目标不能为空") + private BigDecimal threeCategoryGuidGoal; + + @Excel(name = "生产企业数量(个)") + @NotNull(message = "生产企业数量不能为空") + private Integer productionCompanyNums; + + @Excel(name = "年设计生产能力(万立方米)") + @NotNull(message = "年设计生产能力不能为空") + private BigDecimal annualDesignProductionCapacity; + + @Excel(name = "备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MaterialLogEquipStaQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MaterialLogEquipStaQueryDataExportDTO.java new file mode 100644 index 0000000..9994487 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MaterialLogEquipStaQueryDataExportDTO.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class MaterialLogEquipStaQueryDataExportDTO { + + @NotNull(message = "年初数量不能为空") + @Excel(name = "数量",groupName = "年初") + private Integer yearBeginNum; + @Excel(name = "额定量") + @NotNull(message = "年初额定量不能为空") + private BigDecimal yearBeginCapacity; + + @NotNull(message = "本年新增数量不能为空") + @Excel(name = "数量",groupName = "本年新增") + private Integer thisYearNewAddNum; + @Excel(name = "额定量") + @NotNull(message = "本年新增额定量不能为空") + private BigDecimal thisYearNewAddCapacity; + + @NotNull(message = "本年减少数量不能为空") + @Excel(name = "数量",groupName = "本年减少") + private Integer thisYearScrapNum; + @Excel(name = "额定量") + @NotNull(message = "本年减少额定量不能为空") + private BigDecimal thisYearScrapCapacity; + + @NotNull(message = "年末数量不能为空") + @Excel(name = "数量",groupName = "年末") + private Integer yearEndNum; + @Excel(name = "额定量") + @NotNull(message = "年末额定量不能为空") + private BigDecimal yearEndCapacity; + + + @Excel(name = "装备名称") + @NotNull(message = "装备名称不能为空") + private String regionName; + + @Excel(name = "备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MortarSupplyQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MortarSupplyQueryDataExportDTO.java new file mode 100644 index 0000000..2faa54d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/MortarSupplyQueryDataExportDTO.java @@ -0,0 +1,142 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class MortarSupplyQueryDataExportDTO { + + @ApiModelProperty("地区名称") + private String regionName; + + @ApiModelProperty("二类指导目标(万吨)") + private BigDecimal twoCategoryGuidGoal; + @ApiModelProperty("当前市二类指导目标(万吨)合计") + private BigDecimal twoCategoryGuidGoalTotal; + + @ApiModelProperty("普通干混砂浆生产企业数量(个)") + private Integer dryMixedMortarProductionCompanyNum; + @ApiModelProperty("当前市普通干混砂浆生产企业数量(个)合计") + private Integer dryMixedMortarProductionCompanyNumTotal; + + @ApiModelProperty("普通干混砂浆生产总能力(万吨)") + private BigDecimal dryMixedMortarProductiveCapacity; + @ApiModelProperty("当前市普通干混砂浆生产总能力(万吨)合计") + private BigDecimal dryMixedMortarProductiveCapacityTotal; + + @ApiModelProperty("普通干混砂浆散装能力(万吨)") + private BigDecimal dryMixedMortarBulkCapacity; + @ApiModelProperty("当前市普通干混砂浆散装能力(万吨)合计") + private BigDecimal dryMixedMortarBulkCapacityTotal; + + @ApiModelProperty("本月总产量(吨)") + private BigDecimal thisMonthTotalOutput; + @ApiModelProperty("当前市本月总产量(吨)合计") + private BigDecimal thisMonthTotalOutputTotal; + + @ApiModelProperty("本月累计产量(吨)") + private BigDecimal thisMonthAccumulativeOutput; + @ApiModelProperty("当前市本月累计产量(吨)合计") + private BigDecimal thisMonthAccumulativeOutputTotal; + + @ApiModelProperty("普通干混砂浆本月产量(吨)") + private BigDecimal dryMixedMortarThisMonthOutput; + @ApiModelProperty("当前市普通干混砂浆本月产量(吨)合计") + private BigDecimal dryMixedMortarThisMonthOutputTotal; + + @ApiModelProperty("普通干混砂浆累计产量(吨)") + private BigDecimal dryMixedMortarThisMonthAccumulativeOutput; + @ApiModelProperty("当前市普通干混砂浆累计产量(吨)合计") + private BigDecimal dryMixedMortarThisMonthAccumulativeOutputTotal; + + @ApiModelProperty("普通干混砂浆同比增长量(吨)") + private BigDecimal dryMixedMortarIncrement; + @ApiModelProperty("当前市普通干混砂浆同比增长量(吨)合计") + private BigDecimal dryMixedMortarIncrementTotal; + + @ApiModelProperty("普通干混砂浆增长率(%)") + private BigDecimal dryMixedMortarGrowthRate; + @ApiModelProperty("当前市普通干混砂浆增长率(%)合计") + private BigDecimal dryMixedMortarGrowthRateTotal; + + @ApiModelProperty("普通干混砂浆本月散装量(吨)") + private BigDecimal dryMixedMortarThisMonthBulkQuantity; + @ApiModelProperty("当前市普通干混砂浆本月散装量(吨)合计") + private BigDecimal dryMixedMortarThisMonthBulkQuantityTotal; + + @ApiModelProperty("普通干混砂浆累计散装量(吨)") + private BigDecimal dryMixedMortarAccumulativeBulkQuantity; + @ApiModelProperty("当前市普通干混砂浆累计散装量(吨)合计") + private BigDecimal dryMixedMortarAccumulativeBulkQuantityTotal; + + @ApiModelProperty("湿拌砂浆本月产量(立方)") + private BigDecimal wetMortarThisMonthOutput; + @ApiModelProperty("当前市湿拌砂浆本月产量(立方)合计") + private BigDecimal wetMortarThisMonthOutputTotal; + + @ApiModelProperty("湿拌砂浆累计产量(立方)") + private BigDecimal wetMortarAccumulativeOutput; + @ApiModelProperty("当前市拌砂浆累计产量(立方)合计") + private BigDecimal wetMortarAccumulativeOutputTotal; + + @ApiModelProperty("散装水泥本月使用量(吨)") + private BigDecimal bulkCementThisMonthUsage; + @ApiModelProperty("当前市散装水泥本月使用量(吨)合计") + private BigDecimal bulkCementThisMonthUsageTotal; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal bulkCementAccumulativeUsage; + @ApiModelProperty("当前市散装水泥累计使用量(吨)合计") + private BigDecimal bulkCementAccumulativeUsageTotal; + + @ApiModelProperty("废弃物累计综合利用量(吨)") + private BigDecimal wasteAccumulativeComprehensiveUtilization; + @ApiModelProperty("当前市废弃物累计综合利用量(吨)合计") + private BigDecimal wasteAccumulativeComprehensiveUtilizationTotal; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/NonProAreasQueryDataExportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/NonProAreasQueryDataExportDTO.java new file mode 100644 index 0000000..ed260a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/NonProAreasQueryDataExportDTO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/10/02 10:54 + */ +@Data +public class NonProAreasQueryDataExportDTO { + @NotNull(message = "非禁现区散装水泥销售点合计数量不能为空") + @Excel(name = "合计(个)",groupName = "非禁现区散装水泥销售点") + private Integer salePointAccumulativeNum; + @Excel(name = "水泥企业建点数量(个)") + @NotNull(message = "非禁现区水泥企业建点数量不能为空") + private Integer cementCompanyBuildPointNum; + @Excel(name = "其他投资建点数量(个)") + @NotNull(message = "非禁现区其它投资建点数量不能为空") + private Integer otherInvestmentBuildPointNum; + @Excel(name = "销售量(万吨)") + @NotNull(message = "非禁现区散装水泥销售量不能为空") + private BigDecimal saleVolume; + @Excel(name = "数量(个)",groupName = "散装水泥罐") + @NotNull(message = "非禁现区散装水泥罐数量不能为空") + private Integer bulkCementTankNum; + @Excel(name = "容量(吨)") + @NotNull(message = "非禁现区散装水泥罐容量不能为空") + private BigDecimal bulkCementTankCapacity; + + + @Excel(name = "水泥使用量(万吨)",groupName = "非禁现区散装水泥使用情况") + @NotNull(message = "非禁现区水泥使用量不能为空") + private BigDecimal cementUsage; + @Excel(name = "散装水泥使用量(万吨)") + @NotNull(message = "非禁现区散装水泥使用量不能为空") + private BigDecimal bulkCementUsage; + @Excel(name = "生产预拌混凝土使用散装水泥量(万吨)") + @NotNull(message = "生产预拌混凝土散装水泥使用量不能为空") + private BigDecimal readyMixedConcreteBulkCementUsage; + @Excel(name = "生产水泥制品使用散装水泥量(万立方米)") + @NotNull(message = "生产水泥制品使用散装水泥量不能为空") + private BigDecimal cementProductsBulkCementUsage; + + @Excel(name = "地区") + @NotNull(message = "地区不能为空") + private String regionName; + + @Excel(name = "非禁现区域散装水泥使用率%") + @NotNull(message = "非禁现区域散装水泥使用率不能为空") + private BigDecimal bulkCementUsageRate; + + @Excel(name = "非禁现区域生产预拌混凝土产量(万立方米)") + @NotNull(message = "非禁现区域生产预拌混凝土产量不能为空") + private BigDecimal readyMixedConcreteOutput; + + @Excel(name = "备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqBulkCementLogFacStaDataUploadDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqBulkCementLogFacStaDataUploadDTO.java new file mode 100644 index 0000000..14c40fd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqBulkCementLogFacStaDataUploadDTO.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "散装水泥物流设施统计年报上报数据") +public class ReqBulkCementLogFacStaDataUploadDTO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("地区") + private String regionName; + + @ApiModelProperty("设备名称") + private String facilityName; + + @ApiModelProperty("年初数量(个)") + private Integer yearBeginNum; + + @ApiModelProperty("年初容量(万吨)") + private BigDecimal yearBeginCapacity; + + @ApiModelProperty("本年新增数量(个)") + private Integer thisYearNewAddNum; + + @ApiModelProperty("本年新增容量(万吨)") + private BigDecimal thisYearNewAddCapacity; + + @ApiModelProperty("本年报废数量(个)") + private Integer thisYearScrapNum; + + @ApiModelProperty("本年报废容量(万吨)") + private BigDecimal thisYearScrapCapacity; + + @ApiModelProperty("年末数量(个)") + private Integer yearEndNum; + + @ApiModelProperty("年末容量(万吨)") + private BigDecimal yearEndCapacity; + + @ApiModelProperty("本年实际作业量(万吨)") + private BigDecimal thisYearWorkAmount; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqMaterialLogEquipStaDataUploadDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqMaterialLogEquipStaDataUploadDTO.java new file mode 100644 index 0000000..1113c88 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/dto/ReqMaterialLogEquipStaDataUploadDTO.java @@ -0,0 +1,79 @@ +package com.ningdatech.carapi.report.model.dto; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "散装水泥、预拌混凝土、干混砂浆物流装备统计年报上报数据") +public class ReqMaterialLogEquipStaDataUploadDTO { + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区") + private String regionName; + + @ApiModelProperty("装备名称") + private String equipmentName; + + @ApiModelProperty("年初数量(辆、个)") + private Integer yearBeginNum; + + @ApiModelProperty("年初额定量(吨、立方米)") + private BigDecimal yearBeginNominalRate; + + @ApiModelProperty("本年新增数量") + private Integer thisYearNewAddNum; + + @ApiModelProperty("本年新增额定量") + private BigDecimal thisYearNewAddNominalRate; + + @ApiModelProperty("本年减少数量") + private Integer thisYearDecreaseNum; + + @ApiModelProperty("本年减少额定量") + private BigDecimal thisYearDecreaseNominalRate; + + @ApiModelProperty("年末数量") + private Integer yearEndNum; + + @ApiModelProperty("年末额定量") + private BigDecimal yearEndNominal; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditInfo.java new file mode 100644 index 0000000..5f820c9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditInfo.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥直报系统审核信息表 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +@Data +@TableName("nd_bulk_cement_direct_report_system_audit_info") +@ApiModel(value = "BulkCementDirectReportSystemAuditInfo对象", description = "散装水泥直报系统审核信息表") +public class BulkCementDirectReportSystemAuditInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("审核状态 1 待审核 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("审核数据类型 1 散装水泥供应量快报数据、2 中转库进出量统计数据、3 温台舟使用量快报数据、4 混凝土供应量快报数据、5 砂浆供应量快报数据、6 非禁现区域散装水泥销售使用情况数据、7 散装水泥物流设施统计年报表数据、8 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据") + private Integer auditDataType; + + @ApiModelProperty("审核类型 1 市级散办审核 2 省散办审核") + private Integer auditType; + + @ApiModelProperty("审核意见") + private String auditOpinion; + + @ApiModelProperty("审核时间") + private LocalDateTime auditTime; + + @ApiModelProperty("审核人") + private Long auditBy; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditRecord.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditRecord.java new file mode 100644 index 0000000..a1b2bd6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemAuditRecord.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥直报系统审核记录表 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +@Data +@TableName("nd_bulk_cement_direct_report_system_audit_record") +@ApiModel(value = "BulkCementDirectReportSystemAuditRecord对象", description = "散装水泥直报系统审核记录表") +public class BulkCementDirectReportSystemAuditRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("审核数据ID") + private Long auditDataId; + + @ApiModelProperty("审核数据类型 1 散装水泥供应量快报数据、2 中转库进出量统计数据、3 温台舟使用量快报数据、4 混凝土供应量快报数据、5 砂浆供应量快报数据、6 非禁现区域散装水泥销售使用情况数据、7 散装水泥物流设施统计年报表数据、8 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据") + private Integer auditDataType; + + @ApiModelProperty("审核类型 1 市级散办审核 2 省散办审核") + private Integer auditType; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 0 待审核 1 审核通过 2 被退回") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemDataRelevance.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemDataRelevance.java new file mode 100644 index 0000000..3367797 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemDataRelevance.java @@ -0,0 +1,85 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥直报系统市级上报数据关联表 + *

+ * + * @author CMM + * @since 2023-09-30 + */ +@Data +@TableName("nd_bulk_cement_direct_report_system_data_relevance") +@ApiModel(value = "BulkCementDirectReportSystemDataRelevance对象", description = "散装水泥直报系统市级上报数据关联表") +public class BulkCementDirectReportSystemDataRelevance implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 0 审核中 1 审核通过 2 被退回") + private Integer auditStatus; + + @ApiModelProperty("审核类型 1 市级散办审核 2 省散办审核") + private Integer auditType; + + @ApiModelProperty("市级上报审核关联数据ID列表") + private String auditDataIdList; + + @ApiModelProperty("审核数据类型 1 散装水泥供应量快报数据、2 中转库进出量统计数据、3 温台舟使用量快报数据、4 混凝土供应量快报数据、5 砂浆供应量快报数据、6 非禁现区域散装水泥销售使用情况数据、7 散装水泥物流设施统计年报表数据、8 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据") + private Integer auditDataType; + + @ApiModelProperty("最近一次更新时间") + private LocalDateTime lastUpdateTime; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemIndex.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemIndex.java new file mode 100644 index 0000000..b4b76ed --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemIndex.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥直报系统指标数据 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +@Data +@TableName("nd_bulk_cement_direct_report_system_index") +@ApiModel(value = "BulkCementDirectReportSystemIndex对象", description = "散装水泥直报系统指标数据") +public class BulkCementDirectReportSystemIndex implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("指标类型 1 散装率目标 2 二类指导目标 3 三类指导目标") + private Integer indexType; + + @ApiModelProperty("指标名称") + private String indexName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemUniversalIndex.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemUniversalIndex.java new file mode 100644 index 0000000..97b5b0c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementDirectReportSystemUniversalIndex.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥直报系统通用指标 + *

+ * + * @author CMM + * @since 2023-10-02 + */ +@Data +@TableName("nd_bulk_cement_direct_report_system_universal_index") +@ApiModel(value = "BulkCementDirectReportSystemUniversalIndex对象", description = "散装水泥直报系统通用指标") +public class BulkCementDirectReportSystemUniversalIndex implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("散装率目标") + private BigDecimal bulkRateTarget; + + @ApiModelProperty("温州、台州、舟山三市散装水泥使用量") + private BigDecimal bulkCementUsageYearTarget; + + @ApiModelProperty("混凝土供应量三类指导目标(万立方米)") + private BigDecimal concreteSupplyThreeCategoryGuidGoal; + + @ApiModelProperty("砂浆供应量二类指导目标(万吨)") + private BigDecimal mortarSupplyTwoCategoryGuidGoal; + + @ApiModelProperty("年份") + private Integer year; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateBy; + + @ApiModelProperty("更新人") + private Long updateOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementLogisticFacilityStatisticAnnualReport.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementLogisticFacilityStatisticAnnualReport.java new file mode 100644 index 0000000..e39a608 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementLogisticFacilityStatisticAnnualReport.java @@ -0,0 +1,108 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥物流设施统计年报表 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_bulk_cement_logistic_facility_statistic_annual_report") +@ApiModel(value = "BulkCementLogisticFacilityStatisticAnnualReport对象", description = "散装水泥物流设施统计年报表") +public class BulkCementLogisticFacilityStatisticAnnualReport implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区") + private String regionName; + + @ApiModelProperty("设备名称") + private String facilityName; + + @ApiModelProperty("年初数量(个)") + private Integer yearBeginNum; + + @ApiModelProperty("年初容量(万吨)") + private BigDecimal yearBeginCapacity; + + @ApiModelProperty("本年新增数量(个)") + private Integer thisYearNewAddNum; + + @ApiModelProperty("本年新增容量(万吨)") + private BigDecimal thisYearNewAddCapacity; + + @ApiModelProperty("本年报废数量(个)") + private Integer thisYearScrapNum; + + @ApiModelProperty("本年报废容量(万吨)") + private BigDecimal thisYearScrapCapacity; + + @ApiModelProperty("年末数量(个)") + private Integer yearEndNum; + + @ApiModelProperty("年末容量(万吨)") + private BigDecimal yearEndCapacity; + + @ApiModelProperty("本年实际作业量(万吨)") + private BigDecimal thisYearWorkAmount; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementSupplyBulletin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementSupplyBulletin.java new file mode 100644 index 0000000..391faa0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementSupplyBulletin.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥供应量快报 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_bulk_cement_supply_bulletin") +@ApiModel(value = "BulkCementSupplyBulletin对象", description = "散装水泥供应量快报") +public class BulkCementSupplyBulletin implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("散装率目标") + private BigDecimal bulkRateTarget; + + @ApiModelProperty("散装水泥总量") + private BigDecimal bulkCementAmount; + + @ApiModelProperty("水泥产量") + private BigDecimal cementOutput; + + @ApiModelProperty("年初至本月累计完成总量") + private BigDecimal completedTotalAmount; + + @ApiModelProperty("年初至本月累计散装率") + private BigDecimal bulkRate; + + @ApiModelProperty("年初至本月累计 比去年同期 增加量") + private BigDecimal increment; + + @ApiModelProperty("年初至本月累计 比去年同期 增长率") + private BigDecimal increaseRate; + + @ApiModelProperty("本月止累计水泥产量") + private BigDecimal cumulativeCementProduction; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementThreeCityUsageBulletin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementThreeCityUsageBulletin.java new file mode 100644 index 0000000..b35963a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementThreeCityUsageBulletin.java @@ -0,0 +1,102 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 温州、台州、舟山使用量快报 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_bulk_cement_three_city_usage_bulletin") +@ApiModel(value = "BulkCementThreeCityUsageBulletin对象", description = "温州、台州、舟山使用量快报") +public class BulkCementThreeCityUsageBulletin implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("年目标") + private BigDecimal yearTarget; + + @ApiModelProperty("占全年目标百分比") + private BigDecimal percentageOfAnnualTarget; + + @ApiModelProperty("本月使用量") + private BigDecimal thisMonthUsage; + + @ApiModelProperty("累计使用量") + private BigDecimal accumulativeUsage; + + @ApiModelProperty("同比增长率") + private BigDecimal growthRate; + + @ApiModelProperty("本省本月使用量") + private BigDecimal thisProvinceThisMonthUsage; + + @ApiModelProperty("本省累计使用量") + private BigDecimal thisProvinceAccumulativeUsage; + + @ApiModelProperty("外省本月使用量") + private BigDecimal otherProvinceThisMonthUsage; + + @ApiModelProperty("外省累计使用量") + private BigDecimal otherProvinceAccumulativeUsage; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementTransferBulletin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementTransferBulletin.java new file mode 100644 index 0000000..c52f9ad --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/BulkCementTransferBulletin.java @@ -0,0 +1,96 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 中转库进出量快报 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_bulk_cement_transfer_bulletin") +@ApiModel(value = "BulkCementTransferBulletin对象", description = "中转库进出量快报") +public class BulkCementTransferBulletin implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("上月末库存") + private BigDecimal lastMonthEndInventory; + + @ApiModelProperty("本月进库量") + private BigDecimal thisMonthIncomingStorage; + + @ApiModelProperty("累计进库量") + private BigDecimal cumulativeIncomingStorage; + + @ApiModelProperty("本月出库量") + private BigDecimal thisMonthOutgoingStorage; + + @ApiModelProperty("累计出库量") + private BigDecimal cumulativeOutgoingStorage; + + @ApiModelProperty("月末库存量") + private BigDecimal monthEndInventory; + + @ApiModelProperty("月末库存同比增长率") + private BigDecimal monthEndInventoryGrowthRate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/ConcreteSupplyBulletin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/ConcreteSupplyBulletin.java new file mode 100644 index 0000000..30588ca --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/ConcreteSupplyBulletin.java @@ -0,0 +1,105 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 混凝土供应量快报 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_concrete_supply_bulletin") +@ApiModel(value = "ConcreteSupplyBulletin对象", description = "混凝土供应量快报") +public class ConcreteSupplyBulletin implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("三类指导目标(万立方米)") + private BigDecimal threeCategoryGuidGoal; + + @ApiModelProperty("生产企业数量(个)") + private Integer productionCompanyNums; + + @ApiModelProperty("年设计生产能力(万立方米)") + private BigDecimal annualDesignProductionCapacity; + + @ApiModelProperty("本月实际产量(立方米)") + private BigDecimal thisMonthOutput; + + @ApiModelProperty("累计产量(立方米)") + private BigDecimal accumulativeOutput; + + @ApiModelProperty("本月散装水泥使用量(吨)") + private BigDecimal thisMonthCementUsage; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal cementAccumulativeUsage; + + @ApiModelProperty("本月废弃物综合利用量(吨)") + private BigDecimal thisMonthWasteUtilization; + + @ApiModelProperty("累计废弃物综合利用量(吨)") + private BigDecimal accumulativeWasteUtilization; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域ID") + private Long companyId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MaterialLogisticEquipmentStatisticAnnualReport.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MaterialLogisticEquipmentStatisticAnnualReport.java new file mode 100644 index 0000000..aa2b1d5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MaterialLogisticEquipmentStatisticAnnualReport.java @@ -0,0 +1,105 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 散装水泥、预拌混凝土、干混砂浆物流装备统计年报表 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_material_logistic_equipment_statistic_annual_report") +@ApiModel(value = "MaterialLogisticEquipmentStatisticAnnualReport对象", description = "散装水泥、预拌混凝土、干混砂浆物流装备统计年报表") +public class MaterialLogisticEquipmentStatisticAnnualReport implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区") + private String regionName; + + @ApiModelProperty("装备名称") + private String equipmentName; + + @ApiModelProperty("年初数量(辆、个)") + private Integer yearBeginNum; + + @ApiModelProperty("年初额定量(吨、立方米)") + private BigDecimal yearBeginNominalRate; + + @ApiModelProperty("本年新增数量") + private Integer thisYearNewAddNum; + + @ApiModelProperty("本年新增额定量") + private BigDecimal thisYearNewAddNominalRate; + + @ApiModelProperty("本年减少数量") + private Integer thisYearDecreaseNum; + + @ApiModelProperty("本年减少额定量") + private BigDecimal thisYearDecreaseNominalRate; + + @ApiModelProperty("年末数量") + private Integer yearEndNum; + + @ApiModelProperty("年末额定量") + private BigDecimal yearEndNominal; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MortarSupplyBulletin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MortarSupplyBulletin.java new file mode 100644 index 0000000..b991af3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/MortarSupplyBulletin.java @@ -0,0 +1,129 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 砂浆供应量快报 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_mortar_supply_bulletin") +@ApiModel(value = "MortarSupplyBulletin对象", description = "砂浆供应量快报") +public class MortarSupplyBulletin implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区名称") + private String regionName; + + @ApiModelProperty("二类指导目标(万吨)") + private BigDecimal twoCategoryGuidGoal; + + @ApiModelProperty("普通干混砂浆生产企业数量(个)") + private Integer dryMixedMortarProductionCompanyNum; + + @ApiModelProperty("普通干混砂浆生产总能力(万吨)") + private BigDecimal dryMixedMortarProductiveCapacity; + + @ApiModelProperty("普通干混砂浆散装能力(万吨)") + private BigDecimal dryMixedMortarBulkCapacity; + + @ApiModelProperty("本月总产量(吨)") + private BigDecimal thisMonthTotalOutput; + + @ApiModelProperty("本月累计产量(吨)") + private BigDecimal thisMonthAccumulativeOutput; + + @ApiModelProperty("普通干混砂浆本月产量(吨)") + private BigDecimal dryMixedMortarThisMonthOutput; + + @ApiModelProperty("普通干混砂浆累计产量(吨)") + private BigDecimal dryMixedMortarThisMonthAccumulativeOutput; + + @ApiModelProperty("普通干混砂浆同比增长量(吨)") + private BigDecimal dryMixedMortarIncrement; + + @ApiModelProperty("普通干混砂浆增长率(%)") + private BigDecimal dryMixedMortarGrowthRate; + + @ApiModelProperty("普通干混砂浆本月散装量(吨)") + private BigDecimal dryMixedMortarThisMonthBulkQuantity; + + @ApiModelProperty("普通干混砂浆累计散装量(吨)") + private BigDecimal dryMixedMortarAccumulativeBulkQuantity; + + @ApiModelProperty("湿拌砂浆本月产量(立方)") + private BigDecimal wetMortarThisMonthOutput; + + @ApiModelProperty("湿拌砂浆累计产量(立方)") + private BigDecimal wetMortarAccumulativeOutput; + + @ApiModelProperty("散装水泥本月使用量(吨)") + private BigDecimal bulkCementThisMonthUsage; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal bulkCementAccumulativeUsage; + + @ApiModelProperty("废弃物本月综合利用量(吨)") + private BigDecimal wasteThisMonthComprehensiveUtilization; + + @ApiModelProperty("废弃物累计综合利用量(吨)") + private BigDecimal wasteAccumulativeComprehensiveUtilization; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/NonProhibitedAreasBulkCementSalesUse.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/NonProhibitedAreasBulkCementSalesUse.java new file mode 100644 index 0000000..430f250 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/entity/NonProhibitedAreasBulkCementSalesUse.java @@ -0,0 +1,114 @@ +package com.ningdatech.carapi.report.model.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 非禁现区域散装水泥销售使用情况统计年报表 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Data +@TableName("nd_non_prohibited_areas_bulk_cement_sales_use") +@ApiModel(value = "NonProhibitedAreasBulkCementSalesUse对象", description = "非禁现区域散装水泥销售使用情况统计年报表") +public class NonProhibitedAreasBulkCementSalesUse implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("非禁现区散装水泥销售点合计数量(个)") + private Integer salePointAccumulativeNum; + + @ApiModelProperty("非禁现区水泥企业建点数量(个)") + private Integer cementCompanyBuildPointNum; + + @ApiModelProperty("非禁现区其它投资建点数量(个)") + private Integer otherInvestmentBuildPointNum; + + @ApiModelProperty("非禁现区散装水泥销售量(万吨)") + private BigDecimal saleVolume; + + @ApiModelProperty("非禁现区散装水泥罐数量(个)") + private Integer bulkCementTankNum; + + @ApiModelProperty("非禁现区散装水泥罐容量(吨)") + private BigDecimal bulkCementTankCapacity; + + @ApiModelProperty("非禁现区水泥使用量(万吨)") + private BigDecimal cementUsage; + + @ApiModelProperty("非禁现区散装水泥使用量(万吨)") + private BigDecimal bulkCementUsage; + + @ApiModelProperty("生产预拌混凝土散装水泥使用量(万吨)") + private BigDecimal readyMixedConcreteBulkCementUsage; + + @ApiModelProperty("生产水泥制品散装水泥使用量(万立方米)") + private BigDecimal cementProductsBulkCementUsage; + + @ApiModelProperty("非禁现区域散装水泥使用率(%)") + private BigDecimal bulkCementUsageRate; + + @ApiModelProperty("非禁现区域生产预拌混凝土产量(万立方米)") + private BigDecimal readyMixedConcreteOutput; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出时间") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态 1 审核中 2 审核通过 3 被退回 4 待上报") + private Integer auditStatus; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementLogFacStaDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementLogFacStaDataUploadPO.java new file mode 100644 index 0000000..b113d9c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementLogFacStaDataUploadPO.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.report.model.po; + +import java.time.LocalDateTime; + +import com.ningdatech.carapi.report.model.dto.ReqBulkCementLogFacStaDataUploadDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "散装水泥物流设施统计年报上报数据") +public class ReqBulkCementLogFacStaDataUploadPO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("发放库上报数据") + private ReqBulkCementLogFacStaDataUploadDTO issueLibraryData; + + @ApiModelProperty("中转库上报数据") + private ReqBulkCementLogFacStaDataUploadDTO transferLibraryData; + + @ApiModelProperty("固定接收库上报数据") + private ReqBulkCementLogFacStaDataUploadDTO fixedReceiveLibraryData; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("上报年份") + private Integer reportYear; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementSupplyDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementSupplyDataUploadPO.java new file mode 100644 index 0000000..f88b0bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementSupplyDataUploadPO.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.report.model.po; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "散装水泥供应量上报数据") +public class ReqBulkCementSupplyDataUploadPO { + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("散装水泥总量") + private BigDecimal bulkCementAmount; + + @ApiModelProperty("水泥产量") + private BigDecimal cementOutput; + + @ApiModelProperty("年初至本月累计完成总量") + private BigDecimal completedTotalAmount; + + @ApiModelProperty("年初至本月累计散装率") + private BigDecimal bulkRate; + + @ApiModelProperty("年初至本月累计 比去年同期 增加量") + private BigDecimal increment; + + @ApiModelProperty("年初至本月累计 比去年同期 增长率") + private BigDecimal increaseRate; + + @ApiModelProperty("本月止累计水泥产量") + private BigDecimal cumulativeCementProduction; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementThreeCityUsageDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementThreeCityUsageDataUploadPO.java new file mode 100644 index 0000000..776deac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementThreeCityUsageDataUploadPO.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.report.model.po; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "温台舟使用量上报数据") +public class ReqBulkCementThreeCityUsageDataUploadPO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("年目标") + private BigDecimal yearTarget; + + @ApiModelProperty("本月使用量") + private BigDecimal thisMonthUsage; + + @ApiModelProperty("累计使用量") + private BigDecimal accumulativeUsage; + + @ApiModelProperty("同比增长率") + private BigDecimal growthRate; + + @ApiModelProperty("占全年目标百分比") + private BigDecimal percentageOfAnnualTarget; + + @ApiModelProperty("本省本月使用量") + private BigDecimal thisProvinceThisMonthUsage; + + @ApiModelProperty("本省累计使用量") + private BigDecimal thisProvinceAccumulativeUsage; + + @ApiModelProperty("外省本月使用量") + private BigDecimal otherProvinceThisMonthUsage; + + @ApiModelProperty("外省累计使用量") + private BigDecimal otherProvinceAccumulativeUsage; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementTransferDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementTransferDataUploadPO.java new file mode 100644 index 0000000..c111a17 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqBulkCementTransferDataUploadPO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.report.model.po; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "中转库进出量上报数据") +public class ReqBulkCementTransferDataUploadPO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("上月末库存") + private BigDecimal lastMonthEndInventory; + + @ApiModelProperty("本月进库量") + private BigDecimal thisMonthIncomingStorage; + + @ApiModelProperty("累计进库量") + private BigDecimal cumulativeIncomingStorage; + + @ApiModelProperty("本月出库量") + private BigDecimal thisMonthOutgoingStorage; + + @ApiModelProperty("累计出库量") + private BigDecimal cumulativeOutgoingStorage; + + @ApiModelProperty("月末库存量") + private BigDecimal monthEndInventory; + + @ApiModelProperty("月末库存同比增长率") + private BigDecimal monthEndInventoryGrowthRate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqConcreteSupplyDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqConcreteSupplyDataUploadPO.java new file mode 100644 index 0000000..8289c4b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqConcreteSupplyDataUploadPO.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.report.model.po; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "混凝土供应量上报数据") +public class ReqConcreteSupplyDataUploadPO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("三类指导目标(万立方米)") + private BigDecimal threeCategoryGuidGoal; + + @ApiModelProperty("生产企业数量(个)") + private Integer productionCompanyNums; + + @ApiModelProperty("年设计生产能力(万立方米)") + private BigDecimal annualDesignProductionCapacity; + + @ApiModelProperty("本月实际产量(立方米)") + private BigDecimal thisMonthOutput; + + @ApiModelProperty("累计产量(立方米)") + private BigDecimal accumulativeOutput; + + @ApiModelProperty("本月散装水泥使用量(吨)") + private BigDecimal thisMonthCementUsage; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal cementAccumulativeUsage; + + @ApiModelProperty("本月废弃物综合利用量(吨)") + private BigDecimal thisMonthWasteUtilization; + + @ApiModelProperty("累计废弃物综合利用量(吨)") + private BigDecimal accumulativeWasteUtilization; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataAuditPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataAuditPO.java new file mode 100644 index 0000000..8cea548 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataAuditPO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.report.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "数据审核请求") +public class ReqDataAuditPO { + + @ApiModelProperty("审核数据Id") + private Long auditDataId; + + @ApiModelProperty("审核信息Id") + private Long auditInfoId; + + @ApiModelProperty("审核记录ID") + private Long auditRecordId; + + @ApiModelProperty("审核意见") + private String auditOpinion; + + @ApiModelProperty("审核结果") + private Integer auditStatus; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核数据类型 1 散装水泥供应量快报数据、2 中转库进出量统计数据、3 温台舟使用量快报数据、4 混凝土供应量快报数据、5 砂浆供应量快报数据、6 非禁现区域散装水泥销售使用情况数据、7 散装水泥物流设施统计年报表数据、8 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据") + private Integer auditDataType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataQueryModifyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataQueryModifyPO.java new file mode 100644 index 0000000..407b3ac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataQueryModifyPO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.report.model.po; + +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "数据上报查询编辑请求参数") +public class ReqDataQueryModifyPO { + + @ApiModelProperty("关联数据ID") + private Long relevanceId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadDetailPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadDetailPO.java new file mode 100644 index 0000000..3d53920 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadDetailPO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.report.model.po; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "数据上报详情查询请求") +public class ReqDataUploadDetailPO { + + @ApiModelProperty("审核数据类型 1 散装水泥供应量快报数据、2 中转库进出量统计数据、3 温台舟使用量快报数据、4 混凝土供应量快报数据、5 砂浆供应量快报数据、6 非禁现区域散装水泥销售使用情况数据、7 散装水泥物流设施统计年报表数据、8 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据") + @NotNull(message = "请传入数据类型!") + private Integer auditDataType; + + @ApiModelProperty("审核数据ID") + @NotNull(message = "请传入数据ID!") + private Long auditDataId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadListPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadListPO.java new file mode 100644 index 0000000..c04c515 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqDataUploadListPO.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.report.model.po; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "数据上报列表查询请求") +public class ReqDataUploadListPO extends PagePo { + + @ApiModelProperty("上报开始月份") + private LocalDateTime reportStartMonth; + @ApiModelProperty("上报开始年份") + private Integer reportStartYear; + + @ApiModelProperty("上报结束月份") + private LocalDateTime reportEndMonth; + @ApiModelProperty("上报结束年份") + private Integer reportEndYear; + + @ApiModelProperty("审核状态") + private Integer auditStatus; + + @ApiModelProperty("审核状态列表") + private List auditStatusList; + + @ApiModelProperty("区域信息id") + private Long regionId; + + @ApiModelProperty("审核数据类型 1 散装水泥供应量快报数据、2 中转库进出量统计数据、3 温台舟使用量快报数据、4 混凝土供应量快报数据、5 砂浆供应量快报数据、6 非禁现区域散装水泥销售使用情况数据、7 散装水泥物流设施统计年报表数据、8 散装水泥、预拌砂浆、干混砂浆物流装备统计年报表数据") + private Integer auditDataType; + + @ApiModelProperty("审核数据(对应上报数据)ID列表") + private List auditDataIdList; + + @ApiModelProperty("审核数据ID列表Map") + private Map> auditDataIdListMap; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("关联数据ID") + private Long relevanceDataId; + + @ApiModelProperty("查询类型 1 审核列表查询 2 查询列表查询") + private Integer queryType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMaterialLogEquipStaDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMaterialLogEquipStaDataUploadPO.java new file mode 100644 index 0000000..3c41e35 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMaterialLogEquipStaDataUploadPO.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.report.model.po; + +import java.time.LocalDateTime; + +import com.ningdatech.carapi.report.model.dto.ReqMaterialLogEquipStaDataUploadDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "散装水泥、预拌混凝土、干混砂浆物流装备统计年报上报数据") +public class ReqMaterialLogEquipStaDataUploadPO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("专用汽车上报数据") + private ReqMaterialLogEquipStaDataUploadDTO specialVehicleData; + + @ApiModelProperty("专用船上报数据") + private ReqMaterialLogEquipStaDataUploadDTO specialVesselData; + + @ApiModelProperty("散装水泥罐上报数据") + private ReqMaterialLogEquipStaDataUploadDTO bulkCementTankData; + + @ApiModelProperty("混凝土搅拌车上报数据") + private ReqMaterialLogEquipStaDataUploadDTO concreteMixerTruckData; + + @ApiModelProperty("混凝土泵车上报数据") + private ReqMaterialLogEquipStaDataUploadDTO concretePumpTruckData; + + @ApiModelProperty("干混砂浆运输车上报数据") + private ReqMaterialLogEquipStaDataUploadDTO dryMixMortarTruckData; + + @ApiModelProperty("干混砂浆移动简仓上报数据") + private ReqMaterialLogEquipStaDataUploadDTO dryMixMortarMovingStorageData; + + @ApiModelProperty("干混砂浆背罐车上报数据") + private ReqMaterialLogEquipStaDataUploadDTO dryMixMortarBackTankCarData; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("上报年份") + private Integer reportYear; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMortarSupplyDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMortarSupplyDataUploadPO.java new file mode 100644 index 0000000..6ddf704 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqMortarSupplyDataUploadPO.java @@ -0,0 +1,98 @@ +package com.ningdatech.carapi.report.model.po; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "砂浆供应量上报数据") +public class ReqMortarSupplyDataUploadPO { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("地区名称") + private String regionName; + + @ApiModelProperty("二类指导目标(万吨)") + private BigDecimal twoCategoryGuidGoal; + + @ApiModelProperty("普通干混砂浆生产企业数量(个)") + private Integer dryMixedMortarProductionCompanyNum; + + @ApiModelProperty("普通干混砂浆生产总能力(万吨)") + private BigDecimal dryMixedMortarProductiveCapacity; + + @ApiModelProperty("普通干混砂浆散装能力(万吨)") + private BigDecimal dryMixedMortarBulkCapacity; + + @ApiModelProperty("本月总产量(吨)") + private BigDecimal thisMonthTotalOutput; + + @ApiModelProperty("本月累计产量(吨)") + private BigDecimal thisMonthAccumulativeOutput; + + @ApiModelProperty("普通干混砂浆本月产量(吨)") + private BigDecimal dryMixedMortarThisMonthOutput; + + @ApiModelProperty("普通干混砂浆累计产量(吨)") + private BigDecimal dryMixedMortarThisMonthAccumulativeOutput; + + @ApiModelProperty("普通干混砂浆同比增长量(吨)") + private BigDecimal dryMixedMortarIncrement; + + @ApiModelProperty("普通干混砂浆增长率(%)") + private BigDecimal dryMixedMortarGrowthRate; + + @ApiModelProperty("普通干混砂浆本月散装量(吨)") + private BigDecimal dryMixedMortarThisMonthBulkQuantity; + + @ApiModelProperty("普通干混砂浆累计散装量(吨)") + private BigDecimal dryMixedMortarAccumulativeBulkQuantity; + + @ApiModelProperty("湿拌砂浆本月产量(立方)") + private BigDecimal wetMortarThisMonthOutput; + + @ApiModelProperty("湿拌砂浆累计产量(立方)") + private BigDecimal wetMortarAccumulativeOutput; + + @ApiModelProperty("散装水泥本月使用量(吨)") + private BigDecimal bulkCementThisMonthUsage; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal bulkCementAccumulativeUsage; + + @ApiModelProperty("废弃物本月综合利用量(吨)") + private BigDecimal wasteThisMonthComprehensiveUtilization; + + @ApiModelProperty("废弃物累计综合利用量(吨)") + private BigDecimal wasteAccumulativeComprehensiveUtilization; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqNonProhibitedAreasDataUploadPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqNonProhibitedAreasDataUploadPO.java new file mode 100644 index 0000000..d4ac4e4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/po/ReqNonProhibitedAreasDataUploadPO.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.report.model.po; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:43 + */ +@Data +@ApiModel(description = "非禁现区域散装水泥销售使用情况上报数据") +public class ReqNonProhibitedAreasDataUploadPO { + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("非禁现区散装水泥销售点合计数量(个)") + private Integer salePointAccumulativeNum; + + @ApiModelProperty("非禁现区水泥企业建点数量(个)") + private Integer cementCompanyBuildPointNum; + + @ApiModelProperty("非禁现区其它投资建点数量(个)") + private Integer otherInvestmentBuildPointNum; + + @ApiModelProperty("非禁现区散装水泥销售量(万吨)") + private BigDecimal saleVolume; + + @ApiModelProperty("非禁现区散装水泥罐数量(个)") + private Integer bulkCementTankNum; + + @ApiModelProperty("非禁现区散装水泥罐容量(吨)") + private BigDecimal bulkCementTankCapacity; + + @ApiModelProperty("非禁现区水泥使用量(万吨)") + private BigDecimal cementUsage; + + @ApiModelProperty("非禁现区散装水泥使用量(万吨)") + private BigDecimal bulkCementUsage; + + @ApiModelProperty("生产预拌混凝土散装水泥使用量(万吨)") + private BigDecimal readyMixedConcreteBulkCementUsage; + + @ApiModelProperty("生产水泥制品散装水泥使用量(万立方米)") + private BigDecimal cementProductsBulkCementUsage; + + @ApiModelProperty("非禁现区域散装水泥使用率(%)") + private BigDecimal bulkCementUsageRate; + + @ApiModelProperty("非禁现区域生产预拌混凝土产量(万立方米)") + private BigDecimal readyMixedConcreteOutput; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出时间") + private LocalDateTime submissionDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryDetailVO.java new file mode 100644 index 0000000..df52d85 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryDetailVO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥物流设施统计年报数据查询详情VO") +public class ResBulkCementLogFacStaDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("散装水泥物流设施统计年报数据关联集合Map") + private Map bulkCementLogFacDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryVO.java new file mode 100644 index 0000000..6bed472 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataQueryVO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥物流设施统计年报数据查询详情VO") +public class ResBulkCementLogFacStaDataQueryVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("散装水泥物流设施统计年报数据关联集合Map") + private Map bulkCementLogFacStaDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataUploadDetailVO.java new file mode 100644 index 0000000..e26c0ce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaDataUploadDetailVO.java @@ -0,0 +1,116 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥物流设施统计年报数据上报详情VO") +public class ResBulkCementLogFacStaDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("地区") + private String regionName; + + @ApiModelProperty("设备名称") + private String facilityName; + + @ApiModelProperty("年初数量(个)") + private Integer yearBeginNum; + @ApiModelProperty("当前市年初数量(个)合计") + private Integer yearBeginNumTotal; + + @ApiModelProperty("年初容量(万吨)") + private BigDecimal yearBeginCapacity; + @ApiModelProperty("当前市年初容量(万吨)合计") + private BigDecimal yearBeginCapacityTotal; + + @ApiModelProperty("本年新增数量(个)") + private Integer thisYearNewAddNum; + @ApiModelProperty("当前市本年新增数量(个)合计") + private Integer thisYearNewAddNumTotal; + + @ApiModelProperty("本年新增容量(万吨)") + private BigDecimal thisYearNewAddCapacity; + @ApiModelProperty("当前市本年新增容量(万吨)合计") + private BigDecimal thisYearNewAddCapacityTotal; + + @ApiModelProperty("本年报废数量(个)") + private Integer thisYearScrapNum; + @ApiModelProperty("当前市本年报废数量(个)合计") + private Integer thisYearScrapNumTotal; + + @ApiModelProperty("本年报废容量(万吨)") + private BigDecimal thisYearScrapCapacity; + @ApiModelProperty("当前市本年报废容量(万吨)合计") + private BigDecimal thisYearScrapCapacityTotal; + + @ApiModelProperty("年末数量(个)") + private Integer yearEndNum; + @ApiModelProperty("当前市年末数量(个)合计") + private Integer yearEndNumTotal; + + @ApiModelProperty("年末容量(万吨)") + private BigDecimal yearEndCapacity; + @ApiModelProperty("当前市年末容量(万吨)合计") + private BigDecimal yearEndCapacityTotal; + + @ApiModelProperty("本年实际作业量(万吨)") + private BigDecimal thisYearWorkAmount; + @ApiModelProperty("当前市本年实际作业量(万吨)合计") + private BigDecimal thisYearWorkAmountTotal; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaRelatedDataVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaRelatedDataVO.java new file mode 100644 index 0000000..9480adb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementLogFacStaRelatedDataVO.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥物流设施统计年报相关数据详情VO") +public class ResBulkCementLogFacStaRelatedDataVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("年初数量(个)") + private Integer yearBeginNum; + + @ApiModelProperty("年初容量(万吨)") + private BigDecimal yearBeginCapacity; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataQueryDetailVO.java new file mode 100644 index 0000000..e2a488d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataQueryDetailVO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥供应量数据上报详情VO") +public class ResBulkCementSupplyDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("散装水泥供应量数据关联集合Map") + private Map bulkCementSupplyDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataUploadDetailVO.java new file mode 100644 index 0000000..d3b1d7d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementSupplyDataUploadDetailVO.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥供应量数据上报详情VO") +public class ResBulkCementSupplyDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("散装率目标") + private BigDecimal bulkRateTarget; + + @ApiModelProperty("散装水泥总量") + private BigDecimal bulkCementAmount; + @ApiModelProperty("当前市散装水泥总量合计") + private BigDecimal bulkCementAmountTotal; + + @ApiModelProperty("水泥产量") + private BigDecimal cementOutput; + @ApiModelProperty("当前市水泥产量合计") + private BigDecimal cementOutputTotal; + + @ApiModelProperty("年初至本月累计完成总量") + private BigDecimal completedTotalAmount; + @ApiModelProperty("当前市年初至本月累计完成总量合计") + private BigDecimal completedTotalAmountTotal; + + @ApiModelProperty("年初至本月累计散装率") + private BigDecimal bulkRate; + @ApiModelProperty("当前市年初至本月累计散装率合计") + private BigDecimal bulkRateTotal; + + @ApiModelProperty("年初至本月累计 比去年同期 增加量") + private BigDecimal increment; + @ApiModelProperty("当前市年初至本月累计 比去年同期 增加量合计") + private BigDecimal incrementTotal; + + @ApiModelProperty("年初至本月累计 比去年同期 增长率") + private BigDecimal increaseRate; + @ApiModelProperty("当前市年初至本月累计 比去年同期 增长率合计") + private BigDecimal increaseRateTotal; + + @ApiModelProperty("本月止累计水泥产量") + private BigDecimal cumulativeCementProduction; + @ApiModelProperty("当前市本月止累计水泥产量合计") + private BigDecimal cumulativeCementProductionTotal; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataQueryDetailVO.java new file mode 100644 index 0000000..b6f3fc1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataQueryDetailVO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("温台舟数据上报详情VO") +public class ResBulkCementThreeCityUsageDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("温台舟数据关联集合Map") + private Map bulkCementThreeCityUsageDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataUploadDetailVO.java new file mode 100644 index 0000000..b284650 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementThreeCityUsageDataUploadDetailVO.java @@ -0,0 +1,110 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("温台舟使用量数据上报详情VO") +public class ResBulkCementThreeCityUsageDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("年目标") + private BigDecimal yearTarget; + @ApiModelProperty("当前市年目标合计") + private BigDecimal yearTargetTotal; + + @ApiModelProperty("占全年目标百分比") + private BigDecimal percentageOfAnnualTarget; + @ApiModelProperty("当前市占全年目标百分比合计") + private BigDecimal percentageOfAnnualTargetTotal; + + @ApiModelProperty("本月使用量") + private BigDecimal thisMonthUsage; + @ApiModelProperty("当前市本月使用量合计") + private BigDecimal thisMonthUsageTotal; + + @ApiModelProperty("累计使用量") + private BigDecimal accumulativeUsage; + @ApiModelProperty("当前市累计使用量合计") + private BigDecimal accumulativeUsageTotal; + + @ApiModelProperty("同比增长率") + private BigDecimal growthRate; + @ApiModelProperty("当前市同比增长率合计") + private BigDecimal growthRateTotal; + + @ApiModelProperty("本省本月使用量") + private BigDecimal thisProvinceThisMonthUsage; + @ApiModelProperty("当前市本省本月使用量合计") + private BigDecimal thisProvinceThisMonthUsageTotal; + + @ApiModelProperty("本省累计使用量") + private BigDecimal thisProvinceAccumulativeUsage; + @ApiModelProperty("当前市本省累计使用量合计") + private BigDecimal thisProvinceAccumulativeUsageTotal; + + @ApiModelProperty("外省本月使用量") + private BigDecimal otherProvinceThisMonthUsage; + @ApiModelProperty("当前市外省本月使用量合计") + private BigDecimal otherProvinceThisMonthUsageTotal; + + @ApiModelProperty("外省累计使用量") + private BigDecimal otherProvinceAccumulativeUsage; + @ApiModelProperty("当前市外省累计使用量合计") + private BigDecimal otherProvinceAccumulativeUsageTotal; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataQueryDetailVO.java new file mode 100644 index 0000000..d4871e5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataQueryDetailVO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("中转库进出量数据上报详情VO") +public class ResBulkCementTransferDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("中转库进出量数据关联集合Map") + private Map bulkCementTransferDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataUploadDetailVO.java new file mode 100644 index 0000000..7761188 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResBulkCementTransferDataUploadDetailVO.java @@ -0,0 +1,88 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("中转库进出量数据上报详情VO") +public class ResBulkCementTransferDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("上月末库存") + private BigDecimal lastMonthEndInventory; + @ApiModelProperty("当前市上月末库存合计") + private BigDecimal lastMonthEndInventoryTotal; + + @ApiModelProperty("本月进库量") + private BigDecimal thisMonthIncomingStorage; + @ApiModelProperty("当前市本月进库量合计") + private BigDecimal thisMonthIncomingStorageTotal; + + @ApiModelProperty("累计进库量") + private BigDecimal cumulativeIncomingStorage; + @ApiModelProperty("当前市累计进库量合计") + private BigDecimal cumulativeIncomingStorageTotal; + + @ApiModelProperty("本月出库量") + private BigDecimal thisMonthOutgoingStorage; + @ApiModelProperty("当前市本月出库量合计") + private BigDecimal thisMonthOutgoingStorageTotal; + + @ApiModelProperty("累计出库量") + private BigDecimal cumulativeOutgoingStorage; + @ApiModelProperty("当前市累计出库量合计") + private BigDecimal cumulativeOutgoingStorageTotal; + + @ApiModelProperty("月末库存量") + private BigDecimal monthEndInventory; + @ApiModelProperty("当前市月末库存量合计") + private BigDecimal monthEndInventoryTotal; + + @ApiModelProperty("月末库存同比增长率") + private BigDecimal monthEndInventoryGrowthRate; + @ApiModelProperty("当前市月末库存同比增长率合计") + private BigDecimal monthEndInventoryGrowthRateTotal; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataQueryDetailVO.java new file mode 100644 index 0000000..cb97720 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataQueryDetailVO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("混凝土供应量数据查询详情VO") +public class ResConcreteSupplyDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("混凝土供应量数据关联集合Map") + private Map concreteSupplyDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataUploadDetailVO.java new file mode 100644 index 0000000..67322fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyDataUploadDetailVO.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("混凝土供应量数据上报详情VO") +public class ResConcreteSupplyDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("三类指导目标(万立方米)") + private BigDecimal threeCategoryGuidGoal; + @ApiModelProperty("当前市三类指导目标(万立方米)合计") + private BigDecimal threeCategoryGuidGoalTotal; + + @ApiModelProperty("生产企业数量(个)") + private Integer productionCompanyNums; + @ApiModelProperty("当前市生产企业数量(个)合计") + private Integer productionCompanyNumsTotal; + + @ApiModelProperty("年设计生产能力(万立方米)") + private BigDecimal annualDesignProductionCapacity; + @ApiModelProperty("当前市年设计生产能力(万立方米)合计") + private BigDecimal annualDesignProductionCapacityTotal; + + @ApiModelProperty("本月实际产量(立方米)") + private BigDecimal thisMonthOutput; + @ApiModelProperty("当前市本月实际产量(立方米)合计") + private BigDecimal thisMonthOutputTotal; + + @ApiModelProperty("累计产量(立方米)") + private BigDecimal accumulativeOutput; + @ApiModelProperty("当前市累计产量(立方米)合计") + private BigDecimal accumulativeOutputTotal; + + @ApiModelProperty("本月散装水泥使用量(吨)") + private BigDecimal thisMonthCementUsage; + @ApiModelProperty("当前市本月散装水泥使用量(吨)合计") + private BigDecimal thisMonthCementUsageTotal; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal cementAccumulativeUsage; + @ApiModelProperty("当前市散装水泥累计使用量(吨)合计") + private BigDecimal cementAccumulativeUsageTotal; + + @ApiModelProperty("本月废弃物综合利用量(吨)") + private BigDecimal thisMonthWasteUtilization; + @ApiModelProperty("当前市本月废弃物综合利用量(吨)合计") + private BigDecimal thisMonthWasteUtilizationTotal; + + @ApiModelProperty("累计废弃物综合利用量(吨)") + private BigDecimal accumulativeWasteUtilization; + @ApiModelProperty("当前市累计废弃物综合利用量(吨)合计") + private BigDecimal accumulativeWasteUtilizationTotal; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyRelatedDataVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyRelatedDataVO.java new file mode 100644 index 0000000..6751f83 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResConcreteSupplyRelatedDataVO.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("混凝土供应量相关数据详情VO") +public class ResConcreteSupplyRelatedDataVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("三类指导目标(万立方米)") + private BigDecimal threeCategoryGuidGoal; + + @ApiModelProperty("生产企业数量(个)") + private Integer productionCompanyNums; + + @ApiModelProperty("年设计生产能力(万立方米)") + private BigDecimal annualDesignProductionCapacity; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryDetailVO.java new file mode 100644 index 0000000..1ff68a9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryDetailVO.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("数据查询详情返回VO") +public class ResDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("散装水泥供应量数据查询VO") + private ResBulkCementSupplyDataQueryDetailVO bulkCementSupplyDataVo; + + @ApiModelProperty("中转库进出量数据查询VO") + private ResBulkCementTransferDataQueryDetailVO bulkCementTransferDataVo; + + @ApiModelProperty("温台舟使用量数据查询VO") + private ResBulkCementThreeCityUsageDataQueryDetailVO bulkCementThreeCityUsageDataVo; + + @ApiModelProperty("混凝土供应量数据查询VO") + private ResConcreteSupplyDataQueryDetailVO concreteSupplyDataVo; + + @ApiModelProperty("砂浆供应量数据查询VO") + private ResMortarSupplyDataQueryDetailVO mortarSupplyDataVo; + + @ApiModelProperty("非禁现区域散装水泥销售使用情况数据查询VO") + private ResNonProhibitedAreasDataQueryDetailVO nonProAreasDataVo; + + @ApiModelProperty("散装水泥物流设施统计年报数据查询VO") + private ResBulkCementLogFacStaDataQueryVO bulkCementLogFacStaDataVo; + + @ApiModelProperty("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据查询VO") + private ResMaterialLogEquipStaDataQueryVO materialLogEquipStaDataVo; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryListVO.java new file mode 100644 index 0000000..56bba78 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataQueryListVO.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("数据查询列表返回VO") +public class ResDataQueryListVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("关联数据ID") + private Long relevanceDataId; + + @ApiModelProperty("审核记录ID") + private Long auditRecordId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("所属区域") + private String regionName; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态") + private Integer auditStatus; + + @ApiModelProperty("审核状态名称") + private String auditStatusName; + + @ApiModelProperty("审核意见") + private String auditOpinion; + + @ApiModelProperty("审核数据(对应上报数据)ID列表") + private List auditDataIdList; + + @ApiModelProperty("审核数据ID列表Map") + private Map> auditDataIdListMap; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("最近一次更新时间") + private LocalDateTime updateTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadDetailVO.java new file mode 100644 index 0000000..51ef68d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadDetailVO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("数据上报详情VO") +public class ResDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("散装水泥供应量数据上报详情VO") + private ResBulkCementSupplyDataUploadDetailVO bulkCementSupplyDataUploadDetailVo; + + @ApiModelProperty("中转库进出量数据上报详情VO") + private ResBulkCementTransferDataUploadDetailVO bulkCementTransferDataUploadDetailVo; + + @ApiModelProperty("温台舟使用量数据上报详情VO") + private ResBulkCementThreeCityUsageDataUploadDetailVO bulkCementThreeCityUsageDataUploadDetailVo; + + @ApiModelProperty("混凝土供应量数据上报详情VO") + private ResConcreteSupplyDataUploadDetailVO concreteSupplyDataUploadDetailVO; + + @ApiModelProperty("砂浆供应量数据上报详情VO") + private ResMortarSupplyDataUploadDetailVO mortarSupplyDataUploadDetailVO; + + @ApiModelProperty("非禁现区散装水泥销售使用情况年报数据上报详情VO") + private ResNonProhibitedAreasDataUploadDetailVO nonProhibitedAreasDataUploadDetailVO; + + @ApiModelProperty("散装水泥物流设施统计年报数据上报详情VO") + private Map bulkCementLogFacStaDataUploadDetailVO; + + @ApiModelProperty("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据上报详情VO") + private Map materialLogEquipStaDataUploadDetailVO; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadListVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadListVO.java new file mode 100644 index 0000000..ac974b9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResDataUploadListVO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("数据上报返回列表VO") +public class ResDataUploadListVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("审核记录ID") + private Long auditRecordId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("所属区域") + private String regionName; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("审核状态") + private Integer auditStatus; + + @ApiModelProperty("审核状态名称") + private String auditStatusName; + + @ApiModelProperty("审核意见") + private String auditOpinion; + + @ApiModelProperty("审核时间") + private LocalDateTime auditTime; + + @ApiModelProperty("审核数据ID") + private Long auditDataId; + + @ApiModelProperty("审核数据ID列表") + private List auditDataIdList; + + @ApiModelProperty("审核数据ID列表Map") + private Map> auditDataIdListMap; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("提交时间") + private LocalDateTime submitTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryDetailVO.java new file mode 100644 index 0000000..b68dba8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryDetailVO.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥物流设施统计年报数据查询详情VO") +public class ResMaterialLogEquipStaDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据关联集合Map") + private Map materialLogEquipDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryVO.java new file mode 100644 index 0000000..c70da2c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataQueryVO.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥物流设施统计年报数据查询详情VO") +public class ResMaterialLogEquipStaDataQueryVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据关联集合Map") + private Map materialLogEquipStaDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataUploadDetailVO.java new file mode 100644 index 0000000..743046c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaDataUploadDetailVO.java @@ -0,0 +1,111 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥、预拌混凝土、干混砂浆物流装备统计年报数据上报详情VO") +public class ResMaterialLogEquipStaDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("地区") + private String regionName; + + @ApiModelProperty("装备名称") + private String equipmentName; + + @ApiModelProperty("年初数量(辆、个)") + private Integer yearBeginNum; + @ApiModelProperty("当前市年初数量(辆、个)合计") + private Integer yearBeginNumTotal; + + @ApiModelProperty("年初额定量(吨、立方米)") + private BigDecimal yearBeginNominalRate; + @ApiModelProperty("当前市年初额定量(吨、立方米)合计") + private BigDecimal yearBeginNominalRateTotal; + + @ApiModelProperty("本年新增数量") + private Integer thisYearNewAddNum; + @ApiModelProperty("当前市本年新增数量合计") + private Integer thisYearNewAddNumTotal; + + @ApiModelProperty("本年新增额定量") + private BigDecimal thisYearNewAddNominalRate; + @ApiModelProperty("当前市本年新增额定量合计") + private BigDecimal thisYearNewAddNominalRateTotal; + + @ApiModelProperty("本年减少数量") + private Integer thisYearDecreaseNum; + @ApiModelProperty("当前市本年减少数量合计") + private Integer thisYearDecreaseNumTotal; + + @ApiModelProperty("本年减少额定量") + private BigDecimal thisYearDecreaseNominalRate; + @ApiModelProperty("当前市本年减少额定量合计") + private BigDecimal thisYearDecreaseNominalRateTotal; + + @ApiModelProperty("年末数量") + private Integer yearEndNum; + @ApiModelProperty("当前市年末数量合计") + private Integer yearEndNumTotal; + + @ApiModelProperty("年末额定量") + private BigDecimal yearEndNominal; + @ApiModelProperty("当前市年末额定量合计") + private BigDecimal yearEndNominalTotal; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaRelatedDataVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaRelatedDataVO.java new file mode 100644 index 0000000..db73078 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMaterialLogEquipStaRelatedDataVO.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("散装水泥、预拌混凝土、干混砂浆物流装备统计年报相关数据详情VO") +public class ResMaterialLogEquipStaRelatedDataVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("年初数量(辆、个)") + private Integer yearBeginNum; + + @ApiModelProperty("年初额定量(吨、立方米)") + private BigDecimal yearBeginNominalRate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataQueryDetailVO.java new file mode 100644 index 0000000..2b05f2e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataQueryDetailVO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("砂浆供应量数据查询详情VO") +public class ResMortarSupplyDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("砂浆供应量数据关联集合Map") + private Map mortarSupplyDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataUploadDetailVO.java new file mode 100644 index 0000000..b7bbda5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyDataUploadDetailVO.java @@ -0,0 +1,159 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("砂浆供应量数据上报详情VO") +public class ResMortarSupplyDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("地区名称") + private String regionName; + + @ApiModelProperty("二类指导目标(万吨)") + private BigDecimal twoCategoryGuidGoal; + @ApiModelProperty("当前市二类指导目标(万吨)合计") + private BigDecimal twoCategoryGuidGoalTotal; + + @ApiModelProperty("普通干混砂浆生产企业数量(个)") + private Integer dryMixedMortarProductionCompanyNum; + @ApiModelProperty("当前市普通干混砂浆生产企业数量(个)合计") + private Integer dryMixedMortarProductionCompanyNumTotal; + + @ApiModelProperty("普通干混砂浆生产总能力(万吨)") + private BigDecimal dryMixedMortarProductiveCapacity; + @ApiModelProperty("当前市普通干混砂浆生产总能力(万吨)合计") + private BigDecimal dryMixedMortarProductiveCapacityTotal; + + @ApiModelProperty("普通干混砂浆散装能力(万吨)") + private BigDecimal dryMixedMortarBulkCapacity; + @ApiModelProperty("当前市普通干混砂浆散装能力(万吨)合计") + private BigDecimal dryMixedMortarBulkCapacityTotal; + + @ApiModelProperty("本月总产量(吨)") + private BigDecimal thisMonthTotalOutput; + @ApiModelProperty("当前市本月总产量(吨)合计") + private BigDecimal thisMonthTotalOutputTotal; + + @ApiModelProperty("本月累计产量(吨)") + private BigDecimal thisMonthAccumulativeOutput; + @ApiModelProperty("当前市本月累计产量(吨)合计") + private BigDecimal thisMonthAccumulativeOutputTotal; + + @ApiModelProperty("普通干混砂浆本月产量(吨)") + private BigDecimal dryMixedMortarThisMonthOutput; + @ApiModelProperty("当前市普通干混砂浆本月产量(吨)合计") + private BigDecimal dryMixedMortarThisMonthOutputTotal; + + @ApiModelProperty("普通干混砂浆累计产量(吨)") + private BigDecimal dryMixedMortarThisMonthAccumulativeOutput; + @ApiModelProperty("当前市普通干混砂浆累计产量(吨)合计") + private BigDecimal dryMixedMortarThisMonthAccumulativeOutputTotal; + + @ApiModelProperty("普通干混砂浆同比增长量(吨)") + private BigDecimal dryMixedMortarIncrement; + @ApiModelProperty("当前市普通干混砂浆同比增长量(吨)合计") + private BigDecimal dryMixedMortarIncrementTotal; + + @ApiModelProperty("普通干混砂浆增长率(%)") + private BigDecimal dryMixedMortarGrowthRate; + @ApiModelProperty("当前市普通干混砂浆增长率(%)合计") + private BigDecimal dryMixedMortarGrowthRateTotal; + + @ApiModelProperty("普通干混砂浆本月散装量(吨)") + private BigDecimal dryMixedMortarThisMonthBulkQuantity; + @ApiModelProperty("当前市普通干混砂浆本月散装量(吨)合计") + private BigDecimal dryMixedMortarThisMonthBulkQuantityTotal; + + @ApiModelProperty("普通干混砂浆累计散装量(吨)") + private BigDecimal dryMixedMortarAccumulativeBulkQuantity; + @ApiModelProperty("当前市普通干混砂浆累计散装量(吨)合计") + private BigDecimal dryMixedMortarAccumulativeBulkQuantityTotal; + + @ApiModelProperty("湿拌砂浆本月产量(立方)") + private BigDecimal wetMortarThisMonthOutput; + @ApiModelProperty("当前市湿拌砂浆本月产量(立方)合计") + private BigDecimal wetMortarThisMonthOutputTotal; + + @ApiModelProperty("湿拌砂浆累计产量(立方)") + private BigDecimal wetMortarAccumulativeOutput; + @ApiModelProperty("当前市拌砂浆累计产量(立方)合计") + private BigDecimal wetMortarAccumulativeOutputTotal; + + @ApiModelProperty("散装水泥本月使用量(吨)") + private BigDecimal bulkCementThisMonthUsage; + @ApiModelProperty("当前市散装水泥本月使用量(吨)合计") + private BigDecimal bulkCementThisMonthUsageTotal; + + @ApiModelProperty("散装水泥累计使用量(吨)") + private BigDecimal bulkCementAccumulativeUsage; + @ApiModelProperty("当前市散装水泥累计使用量(吨)合计") + private BigDecimal bulkCementAccumulativeUsageTotal; + + @ApiModelProperty("废弃物本月综合利用量(吨)") + private BigDecimal wasteThisMonthComprehensiveUtilization; + @ApiModelProperty("当前市废弃物本月综合利用量(吨)合计") + private BigDecimal wasteThisMonthComprehensiveUtilizationTotal; + + @ApiModelProperty("废弃物累计综合利用量(吨)") + private BigDecimal wasteAccumulativeComprehensiveUtilization; + @ApiModelProperty("当前市废弃物累计综合利用量(吨)合计") + private BigDecimal wasteAccumulativeComprehensiveUtilizationTotal; + + @ApiModelProperty("上报月份") + private LocalDateTime reportMonth; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyRelatedDataVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyRelatedDataVO.java new file mode 100644 index 0000000..c1e7e68 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResMortarSupplyRelatedDataVO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("砂浆供应量相关数据详情VO") +public class ResMortarSupplyRelatedDataVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("二类指导目标(万吨)") + private BigDecimal twoCategoryGuidGoal; + + @ApiModelProperty("普通干混砂浆生产企业数量(个)") + private Integer dryMixedMortarProductionCompanyNum; + + @ApiModelProperty("普通干混砂浆生产总能力(万吨)") + private BigDecimal dryMixedMortarProductiveCapacity; + + @ApiModelProperty("普通干混砂浆散装能力(万吨)") + private BigDecimal dryMixedMortarBulkCapacity; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataQueryDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataQueryDetailVO.java new file mode 100644 index 0000000..c764fee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataQueryDetailVO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("非禁现区散装水泥销售情况年报数据查询详情VO") +public class ResNonProhibitedAreasDataQueryDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("非禁现区散装水泥销售情况年报数据关联集合Map") + private Map nonProAreasDataMap; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出日期") + private LocalDateTime submissionDate; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataUploadDetailVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataUploadDetailVO.java new file mode 100644 index 0000000..833ee66 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/model/vo/ResNonProhibitedAreasDataUploadDetailVO.java @@ -0,0 +1,132 @@ +package com.ningdatech.carapi.report.model.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author CMM + * @since 2023/09/28 11:38 + */ +@Data +@ApiModel("非禁现区散装水泥销售情况数据上报详情VO") +public class ResNonProhibitedAreasDataUploadDetailVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("非禁现区散装水泥销售点合计数量(个)") + private Integer salePointAccumulativeNum; + @ApiModelProperty("当前市非禁现区散装水泥销售点合计数量(个)合计") + private Integer salePointAccumulativeNumTotal; + + @ApiModelProperty("非禁现区水泥企业建点数量(个)") + private Integer cementCompanyBuildPointNum; + @ApiModelProperty("当前市非禁现区水泥企业建点数量(个)合计") + private Integer cementCompanyBuildPointNumTotal; + + @ApiModelProperty("非禁现区其它投资建点数量(个)") + private Integer otherInvestmentBuildPointNum; + @ApiModelProperty("当前市非禁现区其它投资建点数量(个)合计") + private Integer otherInvestmentBuildPointNumTotal; + + @ApiModelProperty("非禁现区散装水泥销售量(万吨)") + private BigDecimal saleVolume; + @ApiModelProperty("当前市非禁现区散装水泥销售量(万吨)合计") + private BigDecimal saleVolumeTotal; + + @ApiModelProperty("非禁现区散装水泥罐数量(个)") + private Integer bulkCementTankNum; + @ApiModelProperty("当前市非禁现区散装水泥罐数量(个)合计") + private Integer bulkCementTankNumTotal; + + @ApiModelProperty("非禁现区散装水泥罐容量(吨)") + private BigDecimal bulkCementTankCapacity; + @ApiModelProperty("当前市非禁现区散装水泥罐容量(吨)合计") + private BigDecimal bulkCementTankCapacityTotal; + + @ApiModelProperty("非禁现区水泥使用量(万吨)") + private BigDecimal cementUsage; + @ApiModelProperty("当前市非禁现区水泥使用量(万吨)合计") + private BigDecimal cementUsageTotal; + + @ApiModelProperty("非禁现区散装水泥使用量(万吨)") + private BigDecimal bulkCementUsage; + @ApiModelProperty("当前市非禁现区散装水泥使用量(万吨)合计") + private BigDecimal bulkCementUsageTotal; + + @ApiModelProperty("生产预拌混凝土散装水泥使用量(万吨)") + private BigDecimal readyMixedConcreteBulkCementUsage; + @ApiModelProperty("当前市生产预拌混凝土散装水泥使用量(万吨)合计") + private BigDecimal readyMixedConcreteBulkCementUsageTotal; + + @ApiModelProperty("生产水泥制品散装水泥使用量(万立方米)") + private BigDecimal cementProductsBulkCementUsage; + @ApiModelProperty("当前市生产水泥制品散装水泥使用量(万立方米)合计") + private BigDecimal cementProductsBulkCementUsageTotal; + + @ApiModelProperty("非禁现区域散装水泥使用率(%)") + private BigDecimal bulkCementUsageRate; + @ApiModelProperty("当前市非禁现区域散装水泥使用率(%)合计") + private BigDecimal bulkCementUsageRateTotal; + + @ApiModelProperty("非禁现区域生产预拌混凝土产量(万立方米)") + private BigDecimal readyMixedConcreteOutput; + @ApiModelProperty("当前市非禁现区域生产预拌混凝土产量(万立方米)合计") + private BigDecimal readyMixedConcreteOutputTotal; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("单位负责人") + private String unitResponsiblePerson; + + @ApiModelProperty("填表人") + private String preparer; + + @ApiModelProperty("复核人") + private String reviewer; + + @ApiModelProperty("报出时间") + private LocalDateTime submissionDate; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("上报年份") + private Integer reportYear; + + @ApiModelProperty("审核信息ID") + private Long auditInfoId; + + @ApiModelProperty("是否为市合计数据") + private Boolean isCityTotalData; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("更新时间") + private LocalDateTime updateOn; + + @ApiModelProperty("更新人") + private Long updateBy; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditInfoService.java new file mode 100644 index 0000000..da69bfb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditInfoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥直报系统审核信息表 服务类 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +public interface IBulkCementDirectReportSystemAuditInfoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditRecordService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditRecordService.java new file mode 100644 index 0000000..3500109 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemAuditRecordService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥直报系统审核记录表 服务类 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +public interface IBulkCementDirectReportSystemAuditRecordService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemDataRelevanceService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemDataRelevanceService.java new file mode 100644 index 0000000..f8163a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemDataRelevanceService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥直报系统市级上报数据关联表 服务类 + *

+ * + * @author CMM + * @since 2023-09-30 + */ +public interface IBulkCementDirectReportSystemDataRelevanceService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemIndexService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemIndexService.java new file mode 100644 index 0000000..ec6fdb5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemIndexService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemIndex; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥直报系统指标数据 服务类 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +public interface IBulkCementDirectReportSystemIndexService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemUniversalIndexService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemUniversalIndexService.java new file mode 100644 index 0000000..b7b388d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementDirectReportSystemUniversalIndexService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemUniversalIndex; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥直报系统通用指标 服务类 + *

+ * + * @author CMM + * @since 2023-10-02 + */ +public interface IBulkCementDirectReportSystemUniversalIndexService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementLogisticFacilityStatisticAnnualReportService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementLogisticFacilityStatisticAnnualReportService.java new file mode 100644 index 0000000..b9e4c71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementLogisticFacilityStatisticAnnualReportService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementLogisticFacilityStatisticAnnualReport; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥物流设施统计年报表 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IBulkCementLogisticFacilityStatisticAnnualReportService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementSupplyBulletinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementSupplyBulletinService.java new file mode 100644 index 0000000..78d79e2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementSupplyBulletinService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementSupplyBulletin; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥供应量快报 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IBulkCementSupplyBulletinService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementThreeCityUsageBulletinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementThreeCityUsageBulletinService.java new file mode 100644 index 0000000..12a9e76 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementThreeCityUsageBulletinService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementThreeCityUsageBulletin; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 温州、台州、舟山使用量快报 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IBulkCementThreeCityUsageBulletinService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementTransferBulletinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementTransferBulletinService.java new file mode 100644 index 0000000..5858a26 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IBulkCementTransferBulletinService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.BulkCementTransferBulletin; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 中转库进出量快报 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IBulkCementTransferBulletinService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IConcreteSupplyBulletinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IConcreteSupplyBulletinService.java new file mode 100644 index 0000000..b862611 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IConcreteSupplyBulletinService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.ConcreteSupplyBulletin; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 混凝土供应量快报 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IConcreteSupplyBulletinService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMaterialLogisticEquipmentStatisticAnnualReportService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMaterialLogisticEquipmentStatisticAnnualReportService.java new file mode 100644 index 0000000..bd3d78f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMaterialLogisticEquipmentStatisticAnnualReportService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.MaterialLogisticEquipmentStatisticAnnualReport; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 散装水泥、预拌混凝土、干混砂浆物流装备统计年报表 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IMaterialLogisticEquipmentStatisticAnnualReportService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMortarSupplyBulletinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMortarSupplyBulletinService.java new file mode 100644 index 0000000..3e2f18c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/IMortarSupplyBulletinService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.MortarSupplyBulletin; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 砂浆供应量快报 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface IMortarSupplyBulletinService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/INonProhibitedAreasBulkCementSalesUseService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/INonProhibitedAreasBulkCementSalesUseService.java new file mode 100644 index 0000000..a14e681 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/INonProhibitedAreasBulkCementSalesUseService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.report.service; + +import com.ningdatech.carapi.report.model.entity.NonProhibitedAreasBulkCementSalesUse; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 非禁现区域散装水泥销售使用情况统计年报表 服务类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +public interface INonProhibitedAreasBulkCementSalesUseService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditInfoServiceImpl.java new file mode 100644 index 0000000..c3253fa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditInfo; +import com.ningdatech.carapi.report.mapper.BulkCementDirectReportSystemAuditInfoMapper; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥直报系统审核信息表 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +@Service +public class BulkCementDirectReportSystemAuditInfoServiceImpl extends ServiceImpl implements IBulkCementDirectReportSystemAuditInfoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditRecordServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditRecordServiceImpl.java new file mode 100644 index 0000000..01a0b79 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemAuditRecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemAuditRecord; +import com.ningdatech.carapi.report.mapper.BulkCementDirectReportSystemAuditRecordMapper; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemAuditRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥直报系统审核记录表 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +@Service +public class BulkCementDirectReportSystemAuditRecordServiceImpl extends ServiceImpl implements IBulkCementDirectReportSystemAuditRecordService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemDataRelevanceServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemDataRelevanceServiceImpl.java new file mode 100644 index 0000000..635d122 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemDataRelevanceServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemDataRelevance; +import com.ningdatech.carapi.report.mapper.BulkCementDirectReportSystemDataRelevanceMapper; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemDataRelevanceService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥直报系统市级上报数据关联表 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-30 + */ +@Service +public class BulkCementDirectReportSystemDataRelevanceServiceImpl extends ServiceImpl implements IBulkCementDirectReportSystemDataRelevanceService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemIndexServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemIndexServiceImpl.java new file mode 100644 index 0000000..a075f63 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemIndexServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemIndex; +import com.ningdatech.carapi.report.mapper.BulkCementDirectReportSystemIndexMapper; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemIndexService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥直报系统指标数据 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-28 + */ +@Service +public class BulkCementDirectReportSystemIndexServiceImpl extends ServiceImpl implements IBulkCementDirectReportSystemIndexService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemUniversalIndexServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemUniversalIndexServiceImpl.java new file mode 100644 index 0000000..8e74097 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementDirectReportSystemUniversalIndexServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementDirectReportSystemUniversalIndex; +import com.ningdatech.carapi.report.mapper.BulkCementDirectReportSystemUniversalIndexMapper; +import com.ningdatech.carapi.report.service.IBulkCementDirectReportSystemUniversalIndexService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥直报系统通用指标 服务实现类 + *

+ * + * @author CMM + * @since 2023-10-02 + */ +@Service +public class BulkCementDirectReportSystemUniversalIndexServiceImpl extends ServiceImpl implements IBulkCementDirectReportSystemUniversalIndexService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementLogisticFacilityStatisticAnnualReportServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementLogisticFacilityStatisticAnnualReportServiceImpl.java new file mode 100644 index 0000000..fc83d26 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementLogisticFacilityStatisticAnnualReportServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementLogisticFacilityStatisticAnnualReport; +import com.ningdatech.carapi.report.mapper.BulkCementLogisticFacilityStatisticAnnualReportMapper; +import com.ningdatech.carapi.report.service.IBulkCementLogisticFacilityStatisticAnnualReportService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥物流设施统计年报表 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class BulkCementLogisticFacilityStatisticAnnualReportServiceImpl extends ServiceImpl implements IBulkCementLogisticFacilityStatisticAnnualReportService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementSupplyBulletinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementSupplyBulletinServiceImpl.java new file mode 100644 index 0000000..b89ab95 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementSupplyBulletinServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.service.IBulkCementSupplyBulletinService; +import com.ningdatech.carapi.report.model.entity.BulkCementSupplyBulletin; +import com.ningdatech.carapi.report.mapper.BulkCementSupplyBulletinMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥供应量快报 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class BulkCementSupplyBulletinServiceImpl extends ServiceImpl implements IBulkCementSupplyBulletinService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementThreeCityUsageBulletinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementThreeCityUsageBulletinServiceImpl.java new file mode 100644 index 0000000..1231989 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementThreeCityUsageBulletinServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementThreeCityUsageBulletin; +import com.ningdatech.carapi.report.mapper.BulkCementThreeCityUsageBulletinMapper; +import com.ningdatech.carapi.report.service.IBulkCementThreeCityUsageBulletinService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 温州、台州、舟山使用量快报 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class BulkCementThreeCityUsageBulletinServiceImpl extends ServiceImpl implements IBulkCementThreeCityUsageBulletinService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementTransferBulletinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementTransferBulletinServiceImpl.java new file mode 100644 index 0000000..c008b05 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/BulkCementTransferBulletinServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.BulkCementTransferBulletin; +import com.ningdatech.carapi.report.mapper.BulkCementTransferBulletinMapper; +import com.ningdatech.carapi.report.service.IBulkCementTransferBulletinService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 中转库进出量快报 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class BulkCementTransferBulletinServiceImpl extends ServiceImpl implements IBulkCementTransferBulletinService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/ConcreteSupplyBulletinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/ConcreteSupplyBulletinServiceImpl.java new file mode 100644 index 0000000..91eea74 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/ConcreteSupplyBulletinServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.ConcreteSupplyBulletin; +import com.ningdatech.carapi.report.mapper.ConcreteSupplyBulletinMapper; +import com.ningdatech.carapi.report.service.IConcreteSupplyBulletinService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 混凝土供应量快报 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class ConcreteSupplyBulletinServiceImpl extends ServiceImpl implements IConcreteSupplyBulletinService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MaterialLogisticEquipmentStatisticAnnualReportServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MaterialLogisticEquipmentStatisticAnnualReportServiceImpl.java new file mode 100644 index 0000000..f3c8b18 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MaterialLogisticEquipmentStatisticAnnualReportServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.MaterialLogisticEquipmentStatisticAnnualReport; +import com.ningdatech.carapi.report.mapper.MaterialLogisticEquipmentStatisticAnnualReportMapper; +import com.ningdatech.carapi.report.service.IMaterialLogisticEquipmentStatisticAnnualReportService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 散装水泥、预拌混凝土、干混砂浆物流装备统计年报表 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class MaterialLogisticEquipmentStatisticAnnualReportServiceImpl extends ServiceImpl implements IMaterialLogisticEquipmentStatisticAnnualReportService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MortarSupplyBulletinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MortarSupplyBulletinServiceImpl.java new file mode 100644 index 0000000..7c5a025 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/MortarSupplyBulletinServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.MortarSupplyBulletin; +import com.ningdatech.carapi.report.mapper.MortarSupplyBulletinMapper; +import com.ningdatech.carapi.report.service.IMortarSupplyBulletinService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 砂浆供应量快报 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class MortarSupplyBulletinServiceImpl extends ServiceImpl implements IMortarSupplyBulletinService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/NonProhibitedAreasBulkCementSalesUseServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/NonProhibitedAreasBulkCementSalesUseServiceImpl.java new file mode 100644 index 0000000..21ae644 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/report/service/impl/NonProhibitedAreasBulkCementSalesUseServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.report.service.impl; + +import com.ningdatech.carapi.report.model.entity.NonProhibitedAreasBulkCementSalesUse; +import com.ningdatech.carapi.report.mapper.NonProhibitedAreasBulkCementSalesUseMapper; +import com.ningdatech.carapi.report.service.INonProhibitedAreasBulkCementSalesUseService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 非禁现区域散装水泥销售使用情况统计年报表 服务实现类 + *

+ * + * @author CMM + * @since 2023-09-27 + */ +@Service +public class NonProhibitedAreasBulkCementSalesUseServiceImpl extends ServiceImpl implements INonProhibitedAreasBulkCementSalesUseService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/AccidentTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/AccidentTypeEnum.java new file mode 100644 index 0000000..ae7ca48 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/AccidentTypeEnum.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.safe.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 事故类型枚举 + * @return + * @author CMM + * @since 2023/05/16 15:32 + */ +@Getter +@AllArgsConstructor +public enum AccidentTypeEnum { + + INJURY(0,"伤人"), + + DEAD(1,"亡人"), + + OTHER(2,"其它"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (AccidentTypeEnum t : AccidentTypeEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/SecurityContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/SecurityContant.java new file mode 100644 index 0000000..06ca044 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/SecurityContant.java @@ -0,0 +1,13 @@ +package com.ningdatech.carapi.safe.constant; + +public interface SecurityContant { + + class Commitment { + public static final String COMMITMENT_SOCIAL = "社会"; + public static final String COMMITMENT_EMPLOYEE = "员工"; + public static final String COMMITMENT_GENERAL = "总经理"; + public static final String COMMITMENT_LEADER = "分管领导"; + public static final String COMMITMENT_TEAMLEADER = "车队长"; + public static final String COMMITMENT_DRIVER = "驾驶员"; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportEnum.java new file mode 100644 index 0000000..8a5cbee --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportEnum.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.safe.constant; + +import org.apache.commons.lang3.StringUtils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author CMM + * @since 2022/12/26 16:52 + */ +@Getter +@AllArgsConstructor +public enum VehicleAccidentReportEnum { + UN_AUDIT(0,"待审核"), + + AUDIT_APPROVED(1,"审核通过"), + + AUDIT_REJECTED(2,"审核不通过"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(String code) { + if(StringUtils.isBlank(code)){ + return StringUtils.EMPTY; + } + for (VehicleAccidentReportEnum t : VehicleAccidentReportEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportStatusEnum.java new file mode 100644 index 0000000..c98c741 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/constant/VehicleAccidentReportStatusEnum.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.safe.constant; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @return + * @author CMM + * @since 2022/12/27 10:29 + */ +@Getter +@AllArgsConstructor +public enum VehicleAccidentReportStatusEnum { + UNDER_REPORT(0,"未上报"), + + REPORTED(1,"已上报"); + + private Integer code; + private String desc; + + public void setDesc(String desc) { + this.desc = desc; + } + + public static String getDescByCode(Integer code) { + if(Objects.isNull(code)){ + return StringUtils.EMPTY; + } + for (VehicleAccidentReportStatusEnum t : VehicleAccidentReportStatusEnum.values()) { + if (code.equals(t.getCode())) { + return t.desc; + } + } + return StringUtils.EMPTY; + } + + public boolean eq(String val) { + return this.name().equals(val); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/LawEnforcementController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/LawEnforcementController.java new file mode 100644 index 0000000..700d007 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/LawEnforcementController.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.safe.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.safe.manage.LawEnforcementManage; +import com.ningdatech.carapi.safe.model.dto.LawEnforcementPageQuery; +import com.ningdatech.carapi.safe.model.vo.LawCertificateVerificationVO; +import com.ningdatech.carapi.safe.model.vo.LawEquipmentInstallVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/law-enforcement") +@Api(value = "LawEnforcement", tags = "安全管理-行政执法") +@RequiredArgsConstructor +public class LawEnforcementController { + + private final LawEnforcementManage lawEnforcementManage; + + @ApiOperation(value = "设备安装", notes = "设备安装") + @GetMapping("/equipment-install") + public PageVo queryEquipmentInstall(@Valid @ModelAttribute LawEnforcementPageQuery lawEnforcementPageQuery) { + return lawEnforcementManage.queryEquipmentInstall(lawEnforcementPageQuery); + } + + @ApiOperation(value = "证件核查", notes = "证件核查") + @GetMapping("/certificate-verification") + public PageVo queryCertificateVerification(@Valid @ModelAttribute LawEnforcementPageQuery lawEnforcementPageQuery) { + return lawEnforcementManage.queryCertificateVerification(lawEnforcementPageQuery); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleAccidentController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleAccidentController.java new file mode 100644 index 0000000..7961171 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleAccidentController.java @@ -0,0 +1,105 @@ +package com.ningdatech.carapi.safe.controller; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.safe.entity.VehicleAccidentReport; +import com.ningdatech.carapi.safe.manage.VehicleAccidentManage; +import com.ningdatech.carapi.safe.model.dto.AccidentAuditDTO; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; +import com.ningdatech.carapi.safe.model.dto.VehicleAccidentReportDTO; +import com.ningdatech.carapi.safe.model.dto.VehicleAccidentReportQueryDTO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentReportVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/accident") +@Api(value = "Accident", tags = "安全管理-事故管理") +@RequiredArgsConstructor +public class NdVehicleAccidentController { + + private final VehicleAccidentManage vehicleAccidentManage; + + private final RegionsCacheHelper regionsCacheHelper; + + @ApiOperation(value = "车辆事故信息", notes = "车辆事故信息") + @GetMapping("/vehicle") + public PageVo queryVehicle(@Valid @ModelAttribute AccidentPageQuery accidentPageQuery) { + return vehicleAccidentManage.queryVehicleAccident(accidentPageQuery); + } + + @ApiOperation(value = "死亡事故资料", notes = "死亡事故资料") + @GetMapping("/dead") + public PageVo queryDead(@Valid @ModelAttribute AccidentPageQuery accidentPageQuery) { + return vehicleAccidentManage.queryDead(accidentPageQuery); + } + + @ApiOperation(value = "事故路段分析", notes = "事故路段分析") + @GetMapping("/analysis") + public PageVo queryAccidentAnalysis(@Valid @ModelAttribute AccidentPageQuery accidentPageQuery) { + return vehicleAccidentManage.queryAccidentAnalysis(accidentPageQuery); + } + + @ApiOperation(value = "事故上报审核列表", notes = "事故上报审核列表") + @GetMapping("/reportList") + public PageVo reportAccidentInfo(@Valid @ModelAttribute AccidentPageQuery accidentPageQuery) { + return vehicleAccidentManage.reportAccidentInfo(accidentPageQuery); + } + + @ApiOperation(value = "上报事故信息",notes = "上报事故信息") + @PostMapping("/save") + public VehicleAccidentReportQueryDTO report(@Valid @RequestBody VehicleAccidentReportDTO data){ + VehicleAccidentReport entity = vehicleAccidentManage.save(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(entity, VehicleAccidentReportQueryDTO.class); + } + + @ApiOperation(value = "获取审核记录详情",notes = "获取审核记录详情") + @GetMapping("/detail/{id}") + public VehicleAccidentReport getDetail(@Valid @PathVariable Long id){ + return vehicleAccidentManage.getDetail(id); + } + + @ApiOperation(value = "删除审核记录",notes = "删除审核记录") + @DeleteMapping("/delete/{id}") + public Boolean delete(@Valid @PathVariable Long id){ + return vehicleAccidentManage.delete(id); + } + + @ApiOperation(value = "审核上报事故信息") + @PostMapping("/audit") + public Boolean audit(@Valid @RequestBody AccidentAuditDTO param){ + return vehicleAccidentManage.audit(param); + } + + @PostMapping("/vehicle/data/export") + @ApiOperation(value = "车辆事故信息导出",notes = "车辆事故信息导出") + @WebLog(value = "车辆事故信息导出", modular = "事故管理-车辆事故信息导出") + public void uploadDataQueryExport(@Valid @RequestBody AccidentPageQuery accidentPageQuery, HttpServletResponse response) { + vehicleAccidentManage.exportVehicleAccidentData(accidentPageQuery,response); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleInsureController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleInsureController.java new file mode 100644 index 0000000..01a4c24 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleInsureController.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.safe.controller; + +import java.io.FileNotFoundException; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.safe.manage.VehicleInsureManage; +import com.ningdatech.carapi.safe.model.dto.InsurePageQuery; +import com.ningdatech.carapi.safe.model.vo.NdInsureInfoVO; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerVO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/insure") +@Api(value = "Insure", tags = "安全管理-保险管理") +@RequiredArgsConstructor +public class NdVehicleInsureController { + + private final VehicleInsureManage vehicleInsureManage; + + @ApiOperation(value = "承保信息", notes = "承保信息") + @GetMapping("/underwriting") + public PageVo queryVehicle(@Valid @ModelAttribute InsurePageQuery insurePageQuery) { + return vehicleInsureManage.queryVehicleInsure(insurePageQuery); + } + + @ApiOperation(value = "出险信息", notes = "出险信息") + @GetMapping("/outDanger") + public PageVo queryOutDanger(@Valid @ModelAttribute InsurePageQuery insurePageQuery) { + return vehicleInsureManage.queryOutDanger(insurePageQuery); + } + + @ApiOperation(value = "出险分析", notes = "出险分析") + @GetMapping("/analysis") + public PageVo queryInsureOutDangerAnalysis(@Valid @ModelAttribute InsurePageQuery insurePageQuery) { + return vehicleInsureManage.queryInsureOutDangerAnalysis(insurePageQuery); + } + + @GetMapping("/exportOutDanger") + @ApiOperation("导出出险信息") + public void export(InsurePageQuery req, HttpServletResponse response) { + ExcelDownUtil.downXls(response, req, vehicleInsureManage::exportOutDanger); + } + + + @GetMapping("/importOutDanger") + @ApiOperation("手动导入出险信息") + public void importOutDanger() throws FileNotFoundException { + vehicleInsureManage.importOutDanger(); + } + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleOverspeedController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleOverspeedController.java new file mode 100644 index 0000000..5a41389 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleOverspeedController.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.safe.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.safe.model.dto.OverspeedPageQuery; +import com.ningdatech.carapi.safe.manage.VehicleOverspeedManage; +import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedCompanyVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedVehicleVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedWaysectionVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/overspeed") +@Api(value = "Overspeed", tags = "安全管理-超速管理") +@RequiredArgsConstructor +public class NdVehicleOverspeedController { + + private final VehicleOverspeedManage vehicleOverspeedManage; + + @ApiOperation(value = "企业超速", notes = "企业超速") + @GetMapping("/company") + public PageVo queryCompanyOverspeed(@Valid @ModelAttribute OverspeedPageQuery overspeedPageQuery) { + return vehicleOverspeedManage.queryCompanyOverspeed(overspeedPageQuery); + } + + @ApiOperation(value = "车辆超速", notes = "车辆超速") + @GetMapping("/vehicle") + public PageVo queryVihicleOverspeed(@Valid @ModelAttribute OverspeedPageQuery overspeedPageQuery) { + return vehicleOverspeedManage.queryVihicleOverspeed(overspeedPageQuery); + } + + @ApiOperation(value = "超速路段分析", notes = "超速路段分析") + @GetMapping("/waySection") + public PageVo queryWaySectionOverspeed(@Valid @ModelAttribute OverspeedPageQuery overspeedPageQuery) { + return vehicleOverspeedManage.queryWaySectionOverspeed(overspeedPageQuery); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleViolationController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleViolationController.java new file mode 100644 index 0000000..22a078c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/NdVehicleViolationController.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.safe.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.safe.model.dto.ViolationPageQuery; +import com.ningdatech.carapi.safe.manage.VehicleViolationManage; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/violation") +@Api(value = "Violation", tags = "安全管理-违章管理") +@RequiredArgsConstructor +public class NdVehicleViolationController { + + private final VehicleViolationManage vehicleViolationManage; + + @ApiOperation(value = "违章管理", notes = "违章管理-列表") + @GetMapping("/list") + public PageVo query(@Valid @ModelAttribute ViolationPageQuery violationPageQuery) { + return vehicleViolationManage.query(violationPageQuery); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityAdvisoryController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityAdvisoryController.java new file mode 100644 index 0000000..d0b1e1b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityAdvisoryController.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.safe.controller; + +import com.ningdatech.basic.model.IdVo; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.safe.entity.NdSecurityNoticeSaveReq; +import com.ningdatech.carapi.safe.manage.SecurityAdvisoryManage; +import com.ningdatech.carapi.safe.model.dto.SecurityAdvisoryPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdSecurityAdvisoryVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; + +/** + * @Classname SecurityAdvisoryController + * @Description + * @Date 2022/10/19 16:03 + * @Created by PoffyZhang + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/security-advisory") +@Api(value = "SecurityAdvisory", tags = "安全管理-安全通报") +@RequiredArgsConstructor +public class SecurityAdvisoryController { + private final SecurityAdvisoryManage securityAdvisoryManage; + + @ApiOperation(value = "安全通报", notes = "安全通报") + @GetMapping("/list") + public PageVo queryList(@Valid @ModelAttribute SecurityAdvisoryPageQuery securityAdvisoryPageQuery) { + CodeUtil.convertRegionCodeToId(securityAdvisoryPageQuery); + return securityAdvisoryManage.buildWrapper(securityAdvisoryPageQuery); + } + + @ApiOperation("新增安全通报") + @PostMapping("/add") + public void save(@RequestBody NdSecurityNoticeSaveReq req){ + securityAdvisoryManage.saveSecurityNotice(req); + } + + @ApiOperation("删除安全通报") + @DeleteMapping("/delete") + public void delete(@RequestBody IdVo id){ + securityAdvisoryManage.deleteSecurityNotice(id.getId()); + } + + @ApiOperation("增加下载次数") + @GetMapping("/incrementDownCount/{id}") + public void incrementDownCount(@PathVariable Long id) { + securityAdvisoryManage.incrementDownCount(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityHonestyController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityHonestyController.java new file mode 100644 index 0000000..4a78cf4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityHonestyController.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.safe.controller; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.safe.manage.SecurityHonestyManage; +import com.ningdatech.carapi.safe.model.dto.SecurityHonestyPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdSafetyCommitmentVO; +import com.ningdatech.carapi.safe.model.vo.NdSafetyCreditVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * @Classname SecurityHonestyController + * @Description + * @Date 2022/10/20 16:03 + * @Created by PoffyZhang + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/security-honesty") +@Api(value = "SecurityHonesty", tags = "安全管理-安全诚信") +@RequiredArgsConstructor +public class SecurityHonestyController { + + private final SecurityHonestyManage securityHonestyManage; + + @ApiOperation(value = "安全承诺", notes = "安全承诺") + @GetMapping("/commitment") + public PageVo queryCommitment(@Valid @ModelAttribute SecurityHonestyPageQuery securityAdvisoryPageQuery) { + return securityHonestyManage.queryCommitment(securityAdvisoryPageQuery); + } + + @ApiOperation(value = "安全信用", notes = "安全信用") + @GetMapping("/credit") + public PageVo queryCredit(@Valid @ModelAttribute SecurityHonestyPageQuery securityAdvisoryPageQuery) { + return securityHonestyManage.queryCredit(securityAdvisoryPageQuery); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityManageDataScreenController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityManageDataScreenController.java new file mode 100644 index 0000000..2a335d2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/controller/SecurityManageDataScreenController.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.safe.controller; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.safe.model.dto.LongitudeLatitudeDTO; +import com.ningdatech.carapi.safe.service.SecurityManageDataScreenService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author PoffyZhang + * @since 2022-10-22 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/safe/data-screen") +@Api(value = "Security", tags = "安全管理-大屏") +@RequiredArgsConstructor +public class SecurityManageDataScreenController { + + private final SecurityManageDataScreenService securityManageDataScreenService; + private static final Integer OUT_DANGER = 1; + private static final Integer INJURIES = 2; + private static final Integer DEATH_TOLL = 3; + + @ApiOperation(value = "近三年出险次数对比", notes = "近三年出险次数对比") + @GetMapping("/out-danger") + public JSONObject outDanger(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getInsureAnalysis(param,OUT_DANGER); + } + + @ApiOperation(value = "近三年受伤人数对比", notes = "近三年受伤人数对比") + @GetMapping("/injuries") + public JSONObject injuries(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getInsureAnalysis(param,INJURIES); + } + + @ApiOperation(value = "近三年死亡人数对比", notes = "近三年死亡人数对比") + @GetMapping("/death") + public JSONObject death(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getInsureAnalysis(param,DEATH_TOLL); + } + + @ApiOperation(value = "浙江省事故分布", notes = "浙江省事故分布") + @GetMapping("/accident-distribute") + public List accidentDistribute(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getAccidentLongitudeLatitude(param); + } + + @ApiOperation(value = "本月累积出险时段统计", notes = "本月累积出险时段统计") + @GetMapping("/out-danger-current-month") + public JSONObject outDangerCurrentMonth(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getOutDangerCurrentMonth(param); + } + + @ApiOperation(value = "近30天超速车辆数", notes = "近30天超速车辆数") + @GetMapping("/overspeed") + public JSONObject overspeed(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getOverSpeedCurrentMonth(param); + } + + @ApiOperation(value = "近三年各城市出险次数", notes = "近三年各城市出险次数") + @GetMapping("/out-danger-city") + public JSONObject outDangerCity(@Valid @ModelAttribute DataScreenParam param) { + CodeUtil.convertRegionCodeToId(param); + return securityManageDataScreenService.getOutDangerCity(param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataPicture.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataPicture.java new file mode 100644 index 0000000..c4eb027 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataPicture.java @@ -0,0 +1,159 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @Classname AlarmDataPicture + * @Description + * @Date 2022/10/28 10:47 + * @Created by PoffyZhang + */ +@Data +@TableName("nd_alarm_data_picture") +@ApiModel(value = "AlarmDataPicture", description = "告警数据 图片") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class AlarmDataPicture extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + *设备上报图片ID + */ + @ApiModelProperty("设备上报图片ID") + @NotBlank(message = "设备上报图片ID不能为空") + private String originPicId; + + /** + *车辆编号 + */ + @ApiModelProperty("车辆编号") + @NotBlank(message = "车辆编号不能为空") + private String vehicleIndexCode; + + /** + *车辆自编号 + */ + @ApiModelProperty("车辆自编号") + private String vehicleSelfNo; + + /** + *监控点编号 + */ + @ApiModelProperty("监控点编号") + @NotBlank(message = "监控点编号不能为空") + private String cameraIndexCode; + + /** + *监控点名称 + */ + @ApiModelProperty("监控点名称") + @NotBlank(message = "监控点名称不能为空") + private String cameraName; + + /** + *上传类型 + */ + @ApiModelProperty("上传类型 2:报警") + @NotNull(message = "上传类型不能为空") + private Integer uploadType; + + /** + * 告警ID + */ + @ApiModelProperty("告警ID") + @NotBlank(message = "告警ID不能为空") + private String alarmId; + + /** + * 事件类型 + */ + @ApiModelProperty("事件类型") + private String alarmType; + + /** + * 事件类型名 + */ + @ApiModelProperty("事件类型名 如:接打电话") + private String alarmTypeName; + + /** + * 抓拍时间 + */ + @ApiModelProperty("抓拍时间") + @NotNull(message = "抓拍时间不能为空") + private String captureTime; + + /** + * 图片地址 + */ + @ApiModelProperty("图片地址") + @NotBlank(message = "图片地址不能为空") + private String url; + + /** + * 缩略图地址 + */ + @ApiModelProperty("缩略图地址") + @NotBlank(message = "缩略图地址不能为空") + private String thumbUrl; + + /** + * 本图片所关联的抓拍图片的唯一标识 + */ + @ApiModelProperty("本图片所关联的抓拍图片的唯一标识") + private String parentPicId; + + /** + * 人脸小图在关联的抓拍图片上的坐标 + */ + @ApiModelProperty("人脸小图在关联的抓拍图片上的坐标") + private String faceRect; + + /** + * 图片类型 + */ + @ApiModelProperty("图片类型 可选项,0x01标识可见光,0x02标识热成像,若没有,则默认为可见光") + private String picType; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String plateNo; + + /** + * 区域编码 + */ + @ApiModelProperty("区域编码") + @NotBlank(message = "区域编码不能为空") + private String regionIndexCode; + + /** + * 区域名称 + */ + @ApiModelProperty("区域名称") + @NotBlank(message = "区域名称不能为空") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataVideo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataVideo.java new file mode 100644 index 0000000..3aa45a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/AlarmDataVideo.java @@ -0,0 +1,182 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @Classname AlarmDataVideo + * @Description + * @Date 2022/10/28 10:47 + * @Created by PoffyZhang + */ +@Data +@TableName("nd_alarm_data_video") +@ApiModel(value = "AlarmDataVideo", description = "告警数据 短视频") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class AlarmDataVideo extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + *设备上报短视频唯一标识 + */ + @ApiModelProperty("设备上报短视频唯一标识") + @NotBlank(message = "设备上报短视频唯一标识不能为空") + private String orginVideoId; + + /** + *车辆编号 + */ + @ApiModelProperty("车辆编号") + @NotBlank(message = "车辆编号不能为空") + private String vehicleIndexCode; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空") + private String plateNo; + + /** + *车辆自编号 + */ + @ApiModelProperty("车辆自编号") + private String vehicleSelfNo; + + /** + * 区域编码 + */ + @ApiModelProperty("区域编码") + @NotBlank(message = "区域编码不能为空") + private String regionIndexCode; + + /** + * 区域名称 + */ + @ApiModelProperty("区域名称") + @NotBlank(message = "区域名称不能为空") + private String regionName; + + /** + *监控点编号 + */ + @ApiModelProperty("监控点编号") + @NotBlank(message = "监控点编号不能为空") + private String cameraIndexCode; + + /** + *监控点名称 + */ + @ApiModelProperty("监控点名称") + @NotBlank(message = "监控点名称不能为空") + private String cameraName; + + /** + *服务编号 + */ + @ApiModelProperty("服务编号") + @NotBlank(message = "服务编号不能为空") + private String serviceIndexCode; + + /** + *开始时间 + */ + @ApiModelProperty("开始时间") + @NotBlank(message = "开始时间不能为空") + private String beginTime; + + /** + *结束时间 + */ + @ApiModelProperty("结束时间") + @NotBlank(message = "结束时间不能为空") + private String endTime; + + /** + *流码开始时间 + */ + @ApiModelProperty("流码开始时间") + @NotBlank(message = "流码开始时间不能为空") + private String streamBeginTime; + + /** + *流码结束时间 + */ + @ApiModelProperty("流码结束时间") + @NotBlank(message = "流码结束时间不能为空") + private String streamEndTime; + + /** + *片段时长 + */ + @ApiModelProperty("片段时长 秒") + @NotNull(message = "片段时长不能为空") + private Integer videoLength; + + /** + * 告警ID + */ + @ApiModelProperty("告警ID") + @NotBlank(message = "告警ID不能为空") + private String alarmId; + + /** + * 告警时间 + */ + @ApiModelProperty("告警时间") + @NotBlank(message = "告警时间不能为空") + private String alarmTime; + + /** + * 事件类型 + */ + @ApiModelProperty("事件类型") + private String alarmType; + + /** + * 事件类型名 + */ + @ApiModelProperty("事件类型名 如:接打电话") + private String alarmTypeName; + + /** + * 片段编号 + */ + @ApiModelProperty("片段编号") + @NotBlank(message = "片段编号不能为空") + private String recordIndexCode; + + /** + * 短视频地址 + */ + @ApiModelProperty("短视频地址") + @NotBlank(message = "短视频地址不能为空") + private String url; + + /** + * 封面url + */ + @ApiModelProperty("封面url") + private String coverUrl; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureInfo.java new file mode 100644 index 0000000..ec1fa49 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureInfo.java @@ -0,0 +1,110 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_insure_info") +@Data +@ApiModel(value = "NdInsureInfo", description = "安全管理-保险管理-承保信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureInfo extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 起包时间 + */ + @ApiModelProperty("起包时间") + @TableField(value = "insure_time_start") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime insureTimeStart; + + /** + * 到期时间 + */ + @ApiModelProperty("到期时间") + @TableField(value = "insure_time_end") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime insureTimeEnd; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 保险公司 + */ + @ApiModelProperty("保险公司") + @TableField(value = "insure_company") + private String insureCompany; + + /** + * 保险公司全称 + */ + @ApiModelProperty("保险公司全称") + @TableField(value = "insure_company_full_name") + private String insureCompanyFullName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDanger.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDanger.java new file mode 100644 index 0000000..67de516 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDanger.java @@ -0,0 +1,138 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_insure_out_danger") +@Data +@ApiModel(value = "NdInsureOutDanger", description = "安全管理-保险管理-出险信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureOutDanger extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @TableField(value = "accident_time") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime accidentTime; + + /** + * 事故地点 + */ + @ApiModelProperty("事故地点") + @TableField(value = "accident_address") + private String accidentAddress; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 保险公司 + */ + @ApiModelProperty("保险公司") + @TableField(value = "insure_company") + private String insureCompany; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + @TableField(value = "injuries") + private Integer injuries; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + @TableField(value = "death_toll") + private Integer deathToll; + + /** + * 理赔金额 + */ + @ApiModelProperty("理赔金额") + @TableField(value = "compensate_amount") + private BigDecimal compensateAmount; + + /** + * 上报状态 + */ + @ApiModelProperty("上报状态") + @TableField(value = "report_status") + private Integer reportStatus; + + /** + * 保险公司全称 + */ + @ApiModelProperty("保险公司全称") + @TableField(value = "insure_company_full_name") + private String insureCompanyFullName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDangerAnalysis.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDangerAnalysis.java new file mode 100644 index 0000000..9a68a12 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdInsureOutDangerAnalysis.java @@ -0,0 +1,94 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_insure_out_danger_analysis") +@Data +@ApiModel(value = "NdInsureOutDangerAnalysis", description = "安全管理-保险管理-出险分析") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureOutDangerAnalysis extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 出险次数 + */ + @ApiModelProperty("出险次数") + @TableField(value = "out_danger_times") + private Integer outDangerTimes; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @TableField(value = "accident_time") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + @TableField(value = "injuries") + private Integer injuries; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + @TableField(value = "death_toll") + private Integer deathToll; + + /** + * 公司ID + */ + @ApiModelProperty("公司ID") + @TableField(value = "company_id") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawCertificateVerification.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawCertificateVerification.java new file mode 100644 index 0000000..5ce75b7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawCertificateVerification.java @@ -0,0 +1,149 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_law_certificate_verification") +@Data +@ApiModel(value = "NdLawCertificateVerification", description = "安全管理-行政执法-证件核查") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdLawCertificateVerification extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + @TableField(value = "driver_id") + private Long driverId; + + /** + * 驾驶员名字 + */ + @ApiModelProperty("驾驶员名字") + @TableField(value = "driver_name") + private String driverName; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + @TableField(value = "id_card") + private String idCard; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 检查日期 + */ + @ApiModelProperty("检查日期") + @TableField(value = "check_date") + private LocalDateTime checkDate; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 是否有驾驶证 + */ + @ApiModelProperty("是否有驾驶证 0没有 1有") + @TableField(value = "have_driver_license") + private Integer haveDriverLicense; + + /** + * 是否有行驶证 + */ + @ApiModelProperty("是否有行驶证 0没有 1有") + @TableField(value = "have_driving_license") + private Integer haveDrivingLicense; + + /** + * 检查地址 + */ + @ApiModelProperty("检查地址") + @TableField(value = "check_address") + private String checkAddress; + + /** + * 检查人员 + */ + @ApiModelProperty("检查人员") + @TableField(value = "inspectors") + private String inspectors; + + /** + * 处理结束 + */ + @ApiModelProperty("处理结束") + @TableField(value = "process_result") + private String processResult; + + /** + * 备注 + */ + @ApiModelProperty("备注") + @TableField(value = "remark") + private String remark; + + /** + * 区域id + */ + @ApiModelProperty("区域id") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawEquipmentInstall.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawEquipmentInstall.java new file mode 100644 index 0000000..027684c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdLawEquipmentInstall.java @@ -0,0 +1,142 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_law_equipment_install") +@Data +@ApiModel(value = "NdLawEquipmentInstall", description = "安全管理-行政执法-设备安装") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdLawEquipmentInstall extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + @TableField(value = "driver_id") + private Long driverId; + + /** + * 驾驶员名字 + */ + @ApiModelProperty("驾驶员名字") + @TableField(value = "driver_name") + private String driverName; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + @TableField(value = "id_card") + private String idCard; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 检查日期 + */ + @ApiModelProperty("检查日期") + @TableField(value = "check_date") + private LocalDateTime checkDate; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 设备名字 + */ + @ApiModelProperty("设备名字") + @TableField(value = "equipment_name") + private String equipmentName; + + /** + * 检查地址 + */ + @ApiModelProperty("检查地址") + @TableField(value = "check_address") + private String checkAddress; + + /** + * 检查人员 + */ + @ApiModelProperty("检查人员") + @TableField(value = "inspectors") + private String inspectors; + + /** + * 处理结束 + */ + @ApiModelProperty("处理结束") + @TableField(value = "process_result") + private String processResult; + + /** + * 备注 + */ + @ApiModelProperty("备注") + @TableField(value = "remark") + private String remark; + + /** + * 区域id + */ + @ApiModelProperty("区域id") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCommitment.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCommitment.java new file mode 100644 index 0000000..e1bec78 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCommitment.java @@ -0,0 +1,127 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_safety_commitment") +@Data +@ApiModel(value = "NdSafetyCommitment", description = "安全管理-安全承诺") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdSafetyCommitment extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 公司ID + */ + @ApiModelProperty("公司ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 公司名 + */ + @ApiModelProperty("公司名") + @TableField(value = "company_name") + private String companyName; + + /** + * 公司地址 + */ + @ApiModelProperty("公司地址") + @TableField(value = "company_address") + private String companyAddress; + + /** + * 法人代表 + */ + @ApiModelProperty("法人代表") + @TableField(value = "legal_person") + private String legalPerson; + + /** + * 向社会承诺 + */ + @ApiModelProperty("向社会承诺") + @TableField(value = "commitments_to_social") + private String commitmentsToSocial; + + /** + * 向员工承诺 + */ + @ApiModelProperty("向员工承诺") + @TableField(value = "commitments_to_employee") + private String commitmentsToEmployee; + + /** + * 总经理承诺 + */ + @ApiModelProperty("总经理承诺") + @TableField(value = "general_manager_commitment") + private String generalManagercommitment; + + /** + * 分管总承诺 + */ + @ApiModelProperty("分管总承诺") + @TableField(value = "leader_in_charge_commitment") + private String leaderInChargeCommitment; + + /** + * 车队长承诺 + */ + @ApiModelProperty("车队长承诺") + @TableField(value = "team_leader_commitment") + private String teamLeaderCommitment; + + /** + * 驾驶员承诺 + */ + @ApiModelProperty("驾驶员承诺") + @TableField(value = "driver_commitment") + private String driverCommitment; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCredit.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCredit.java new file mode 100644 index 0000000..d7fb795 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSafetyCredit.java @@ -0,0 +1,155 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_safety_credit") +@Data +@ApiModel(value = "NdSafetyCredit", description = "安全管理-安全信用") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdSafetyCredit extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 公司ID + */ + @ApiModelProperty("公司ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 公司名 + */ + @ApiModelProperty("公司名") + @TableField(value = "company_name") + private String companyName; + + /** + * 公司地址 + */ + @ApiModelProperty("公司地址") + @TableField(value = "company_address") + private String companyAddress; + + /** + * 法人代表 + */ + @ApiModelProperty("法人代表") + @TableField(value = "legal_person") + private String legalPerson; + + /** + * 死亡事故数量 + */ + @ApiModelProperty("死亡事故数量") + @TableField(value = "fatal_accidents_num") + private Integer fatalAccidentsNum; + + /** + * 安全整治记录 + */ + @ApiModelProperty("安全整治记录") + @TableField(value = "safety_rectification_record") + private String safetyRectificationRecord; + + /** + * 执行监督指令 + */ + @ApiModelProperty("执行监督指令") + @TableField(value = "execute_supervision_instructions") + private String executeSupervisionInstructions; + + /** + * 执行安全处罚 + */ + @ApiModelProperty("执行安全处罚") + @TableField(value = "implement_safety_punishment") + private String implementSafetyPunishment; + + /** + * 报送安全报表 + */ + @ApiModelProperty("报送安全报表") + @TableField(value = "submit_safety_report") + private String submitSafetyReport; + + /** + * 制定救援预案 + */ + @ApiModelProperty("制定救援预案") + @TableField(value = "formulate_rescue_plan") + private String formulateRescuePlan; + + /** + * 安全教育培训 + */ + @ApiModelProperty("安全教育培训") + @TableField(value = "safety_education_training") + private String safetyEducationTraining; + + /** + * 瞒报事故 + */ + @ApiModelProperty("瞒报事故") + @TableField(value = "concealing_accidents") + private String concealingAccidents; + + /** + * 无证生产 + */ + @ApiModelProperty("无证生产") + @TableField(value = "production_no_certificate") + private String productionNoCertificate; + + /** + * 无证驾驶 + */ + @ApiModelProperty("无证驾驶") + @TableField(value = "driving_no_license") + private String drivingNoLicense; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityAdvisory.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityAdvisory.java new file mode 100644 index 0000000..604ecb8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityAdvisory.java @@ -0,0 +1,100 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_security_advisory") +@Data +@ApiModel(value = "NdSecurityAdvisory", description = "安全管理-安全通报") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdSecurityAdvisory extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 通报日期 + */ + @ApiModelProperty("通报日期") + @TableField(value = "advisory_date") + private LocalDateTime advisoryDate; + + /** + * 通报文件名 + */ + @ApiModelProperty("通报文件名") + @TableField(value = "advisory_file_name") + private String advisoryFileName; + + /** + * 通报文件url + */ + @ApiModelProperty("通报文件url") + @TableField(value = "advisory_file_url") + private String advisoryFileUrl; + + /** + * 通报次数 + */ + @ApiModelProperty("通报次数") + @TableField(value = "download_times") + private Integer downloadTimes; + + /** + * 上传文件id + */ + @ApiModelProperty("文件id") + @TableField(value = "file_id") + private Long fileId; + + /** + * 公司ID + */ + @ApiModelProperty("公司ID") + @TableField(value = "company_id") + private Long companyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityNoticeSaveReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityNoticeSaveReq.java new file mode 100644 index 0000000..f4ee5e5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdSecurityNoticeSaveReq.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.safe.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + + +@Data +@ApiModel(value = "安全通报新增实体") +public class NdSecurityNoticeSaveReq { + + @ApiModelProperty("区域Id") + @NotNull(message = "区域Id不能为空") + private Long regionId; + + @ApiModelProperty("年月") + @NotNull(message = "年月不能为空") + private LocalDateTime yearMonth; + + @ApiModelProperty("文件ID") + @NotNull(message = "文件ID不能为空") + private Long fileId; + + @ApiModelProperty("文件名") + @NotNull(message = "文件名不能为空") + private String fileName; + + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccident.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccident.java new file mode 100644 index 0000000..f9e959d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccident.java @@ -0,0 +1,149 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_accident") +@Data +@ApiModel(value = "NdVehicleAccident", description = "安全管理-事故管理-车辆事故") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccident extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @TableField(value = "accident_time") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + @TableField(value = "accident_driver") + private String accidentDriver; + + /** + * 事故驾驶员ID + */ + @ApiModelProperty("事故驾驶员ID") + @TableField(value = "driver_id") + private String driverId; + + /** + * 车辆类型 + */ + @ApiModelProperty("车辆类型") + @TableField(value = "vehicle_type") + private Integer vehicleType; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 事故地址 + */ + @ApiModelProperty("事故地址") + @TableField(value = "accident_address") + private String accidentAddress; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; + + @ApiModelProperty("出险id") + private Long insureOutId; + + @ApiModelProperty("受伤人数") + private Integer injuries; + + @ApiModelProperty("死亡人数") + private Integer deathToll; + + @ApiModelProperty("保险ID") + private Long insureId; + + @ApiModelProperty("上报状态") + private Integer reportStatus; + + @ApiModelProperty("事故类型") + private Integer accidentType; + + @ApiModelProperty("简要案情") + private String briefCase; + + @ApiModelProperty("事故编号") + private String accidentNo; + + @ApiModelProperty("事故责任认定书认定内容") + private String firmContent; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentAnalysis.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentAnalysis.java new file mode 100644 index 0000000..cb1ddfc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentAnalysis.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_accident_analysis") +@Data +@ApiModel(value = "NdVehicleAccidentAnalysis", description = "安全管理-事故管理-事故分析") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentAnalysis extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @TableField(value = "accident_time") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + @TableField(value = "accident_driver") + private String accidentDriver; + + /** + * 经纬度 + */ + @ApiModelProperty("经纬度") + @TableField(value = "longitude_latitude") + private String longitudeLatitude; + + /** + * 事故地点 + */ + @ApiModelProperty("事故地点") + @TableField(value = "accident_address") + private String accidentAddress; + + @ApiModelProperty("公司ID") + @TableField(value = "company_id") + private Long companyId; + + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentDead.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentDead.java new file mode 100644 index 0000000..5698485 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleAccidentDead.java @@ -0,0 +1,131 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_accident_dead") +@Data +@ApiModel(value = "NdVehicleAccidentDead", description = "安全管理-事故管理-死亡事故") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentDead extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @TableField(value = "accident_time") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + @TableField(value = "accident_driver") + private String accidentDriver; + + /** + * 事故驾驶员ID + */ + @ApiModelProperty("事故驾驶员ID") + @TableField(value = "driver_id") + private String driverId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @TableField(value = "company_id") + private Long companyId; + + /** + * 事故地址 + */ + @ApiModelProperty("事故地址") + @TableField(value = "accident_address") + private String accidentAddress; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; + + @ApiModelProperty("受伤人数") + private Integer injuries; + + @ApiModelProperty("死亡人数") + private Integer deathToll; + + @ApiModelProperty("上报状态") + private Integer reportStatus; + + @ApiModelProperty("简要案情") + private String briefCase; + + @ApiModelProperty("事故编号") + private String accidentNo; + + @ApiModelProperty("事故责任认定书认定内容") + private String firmContent; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedCompany.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedCompany.java new file mode 100644 index 0000000..4ad3b63 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedCompany.java @@ -0,0 +1,98 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_overspeed_company") +@Data +@ApiModel(value = "NdVehicleOverspeedCompany", description = "安全管理-超速管理-企业超速") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedCompany extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @TableField(value = "overspeed_date") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + @TableField(value = "overspeed_times") + private Integer overspeedTimes; + + /** + * 最高速率 + */ + @ApiModelProperty("最高速率") + @TableField(value = "max_speed") + private Double maxSpeed; + + /** + * 排名 + */ + @ApiModelProperty("排名") + @TableField(value = "rank") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + @TableField(value = "city") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + @TableField(value = "distinguish") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedVehicle.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedVehicle.java new file mode 100644 index 0000000..80cd10d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedVehicle.java @@ -0,0 +1,107 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_overspeed_vehicle") +@Data +@ApiModel(value = "NdVehicleOverspeedCompany", description = "安全管理-超速管理-车辆超速") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedVehicle extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @TableField(value = "overspeed_date") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + @TableField(value = "overspeed_times") + private Integer overspeedTimes; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 最高速率 + */ + @ApiModelProperty("最高速率") + @TableField(value = "max_speed") + private Double maxSpeed; + + /** + * 排名 + */ + @ApiModelProperty("排名") + @TableField(value = "rank") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + @TableField(value = "city") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + @TableField(value = "distinguish") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedWaysection.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedWaysection.java new file mode 100644 index 0000000..a38c07b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleOverspeedWaysection.java @@ -0,0 +1,121 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_overspeed_waysection") +@Data +@ApiModel(value = "NdVehicleOverspeedCompany", description = "安全管理-超速管理-超速路段") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedWaysection extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @TableField(value = "overspeed_date") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + @TableField(value = "overspeed_times") + private Integer overspeedTimes; + + /** + * 路段名字 + */ + @ApiModelProperty("路段名字") + @TableField(value = "way_section") + private String waySection; + + /** + * 路段开始名字 + */ + @ApiModelProperty("路段开始名字") + @TableField(value = "way_section_start") + private String waySectionStart; + + /** + * 路段结束名字 + */ + @ApiModelProperty("路段结束名字") + @TableField(value = "way_section_end") + private String waySectionEnd; + + /** + * 排名 + */ + @ApiModelProperty("排名") + @TableField(value = "rank") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + @TableField(value = "city") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + @TableField(value = "distinguish") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleViolation.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleViolation.java new file mode 100644 index 0000000..ac4d0bc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/NdVehicleViolation.java @@ -0,0 +1,181 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@TableName("nd_vehicle_violation") +@Data +@ApiModel(value = "NdVehicleViolation", description = "安全管理-违章管理") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleViolation extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @TableField(value = "region_name") + private String regionName; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + + /** + * 企业id + */ + @ApiModelProperty("企业id") + @TableField(value = "company_id") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 驾驶员 + */ + @ApiModelProperty("驾驶员") + @TableField(value = "driver_name") + private String driverName; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + @TableField(value = "driver_id") + private Long driverId; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + @TableField(value = "id_card") + private String idCard; + + /** + * 违章时间 + */ + @ApiModelProperty("违章时间") + @TableField(value = "violation_date") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime violationDate; + + /** + * 违章类型 + */ + @ApiModelProperty("违章类型") + @TableField(value = "violation_type") + private Integer violationType; + + /** + * 缺少证件类型 + */ + @ApiModelProperty("缺少证件类型") + @TableField(value = "missing_certificate_type") + private Integer missingCertificateType; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate; + + /** + * 闯红灯地址 + */ + @ApiModelProperty("闯红灯地址") + @TableField(value = "address_red_light") + private String addressRedLight; + + /** + * 违规路段名 + */ + @ApiModelProperty("违规路段名") + @TableField(value = "way_section") + private String waySection; + + /** + * 违章次数 + */ + @ApiModelProperty("违章次数") + @TableField(value = "violation_times") + private Integer violationTimes; + + /** + * 违章时间段 + */ + @ApiModelProperty("违章时间段") + @TableField(value = "violation_period") + private String violationPeriod; + + /** + * 违章地点 + */ + @ApiModelProperty("违章地点") + @TableField(value = "violation_address") + private String violationAddress; + + /** + * 违章编号 + */ + @ApiModelProperty("违章编号") + @TableField(value = "violation_no") + private String violationNo; + + /** + * 经度 + */ + @ApiModelProperty("经度") + @TableField(value = "longitude") + private String longitude; + + /** + * 经度 + */ + @ApiModelProperty("纬度") + @TableField(value = "latitude") + private String latitude; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleAccidentReport.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleAccidentReport.java new file mode 100644 index 0000000..ac065a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleAccidentReport.java @@ -0,0 +1,112 @@ +package com.ningdatech.carapi.safe.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author CMM + * @since 2022-12-26 + */ +@Data +@TableName("nd_vehicle_accident_report") +@ApiModel(value = "VehicleAccidentReport对象", description = "安全管理-事故管理-事故上报") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleAccidentReport implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("地区名") + private String regionName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("事故日期") + private LocalDateTime accidentTime; + + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("事故地点") + private String accidentAddress; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; + + @ApiModelProperty("出险id 关联赔付信息") + private Long insureOutId; + + @ApiModelProperty("受伤人数") + private Integer injuries; + + @ApiModelProperty("死亡人数") + private Integer deathToll; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("保险ID") + private Long insureId; + + @ApiModelProperty("审核状态 0:待审核,1:审核通过,2:审核不通过") + private Integer auditStatus; + + @ApiModelProperty("审核意见") + private String auditOpinion; + + @ApiModelProperty("审核人") + private String auditor; + + @ApiModelProperty("审核人id") + private Long auditorUserId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleOverspeedInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleOverspeedInfo.java new file mode 100644 index 0000000..7e7b668 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/entity/VehicleOverspeedInfo.java @@ -0,0 +1,100 @@ +package com.ningdatech.carapi.safe.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 车辆超速信息表 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +@TableName("nd_vehicle_overspeed_info") +@Data +@ApiModel(value = "VehicleOverspeedInfo对象", description = "车辆超速信息表") +public class VehicleOverspeedInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("超速时间") + private LocalDateTime overspeedDate; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("最高速率") + private BigDecimal maxSpeed; + + @ApiModelProperty("公司名") + private String companyName; + + @ApiModelProperty("所属城市") + private String city; + + @ApiModelProperty("所属县区") + private String distinguish; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名字") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("限速") + private BigDecimal limitSpeed; + + @ApiModelProperty("地点") + private String address; + + @ApiModelProperty("经度") + private BigDecimal longitude; + + @ApiModelProperty("纬度") + private BigDecimal latitude; + + @ApiModelProperty("路段") + private String waySection; + + @ApiModelProperty("开始路段") + private String waySectionStart; + + @ApiModelProperty("结束路段") + private String waySectionEnd; + + private LocalDateTime startTime; + private LocalDateTime endTime; + + private Long alarmMsgSn; + private Long gnssCenterId; + + @ApiModelProperty("是否删除") + private Integer deleted; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/LawEnforcementManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/LawEnforcementManage.java new file mode 100644 index 0000000..4784558 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/LawEnforcementManage.java @@ -0,0 +1,109 @@ +package com.ningdatech.carapi.safe.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.safe.entity.NdLawCertificateVerification; +import com.ningdatech.carapi.safe.entity.NdLawEquipmentInstall; +import com.ningdatech.carapi.safe.model.dto.LawEnforcementPageQuery; +import com.ningdatech.carapi.safe.model.vo.LawCertificateVerificationVO; +import com.ningdatech.carapi.safe.model.vo.LawEquipmentInstallVO; +import com.ningdatech.carapi.safe.service.INdLawCertificateVerificationService; +import com.ningdatech.carapi.safe.service.INdLawEquipmentInstallService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; + +/** + * @author PoffyZhang + * @date 2022/10/19 上午11:18 + */ +@Component +@RequiredArgsConstructor +public class LawEnforcementManage { + + private final INdLawEquipmentInstallService equipmentInstallService; + private final INdLawCertificateVerificationService certificateVerificationService; + private final RegionsCacheHelper regionsCacheHelper; + + /** + * 执行 设备安装 查询 + * @param lawEnforcementPageQuery + * @return + */ + public PageVo queryEquipmentInstall(LawEnforcementPageQuery lawEnforcementPageQuery) { + Page page = lawEnforcementPageQuery.page(); + equipmentInstall(page, lawEnforcementPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + LawEquipmentInstallVO vo = BeanUtil.copyProperties(e, LawEquipmentInstallVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + /** + * 证件核查 + * @param lawEnforcementPageQuery + * @return + */ + public PageVo queryCertificateVerification(LawEnforcementPageQuery lawEnforcementPageQuery) { + Page page = lawEnforcementPageQuery.page(); + certificateVerification(page, lawEnforcementPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + LawCertificateVerificationVO vo = BeanUtil.copyProperties(e, LawCertificateVerificationVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + private void certificateVerification(Page page, LawEnforcementPageQuery lawEnforcementPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdLawCertificateVerification.class); + LawEnforcementManage context = (LawEnforcementManage)AopContext.currentProxy(); + context.searchCert(page,wrapper,lawEnforcementPageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public void searchCert(Page page, LambdaQueryWrapper wrapper, LawEnforcementPageQuery lawEnforcementPageQuery) { + wrapper.ge(Objects.nonNull(lawEnforcementPageQuery.getStartTime()),NdLawCertificateVerification::getCheckDate, lawEnforcementPageQuery.getStartTime()) + .le(Objects.nonNull(lawEnforcementPageQuery.getEndTime()),NdLawCertificateVerification::getCheckDate, lawEnforcementPageQuery.getEndTime()) + .like(Objects.nonNull(lawEnforcementPageQuery.getCarPlate()),NdLawCertificateVerification::getCarPlate, lawEnforcementPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(lawEnforcementPageQuery.getCompanyName()),NdLawCertificateVerification::getCompanyName, lawEnforcementPageQuery.getCompanyName()) + .like(StringUtils.isNotBlank(lawEnforcementPageQuery.getDriverName()),NdLawCertificateVerification::getDriverName, lawEnforcementPageQuery.getDriverName()); + wrapper.orderBy(Boolean.TRUE,Boolean.FALSE,NdLawCertificateVerification::getCheckDate); + certificateVerificationService.page(page, wrapper); + } + + + private void equipmentInstall(Page page, LawEnforcementPageQuery lawEnforcementPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdLawEquipmentInstall.class); + LawEnforcementManage context = (LawEnforcementManage)AopContext.currentProxy(); + context.searchInstall(page,wrapper,lawEnforcementPageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchInstall(Page page, LambdaQueryWrapper wrapper, LawEnforcementPageQuery lawEnforcementPageQuery) { + wrapper.ge(Objects.nonNull(lawEnforcementPageQuery.getStartTime()),NdLawEquipmentInstall::getCheckDate, lawEnforcementPageQuery.getStartTime()) + .le(Objects.nonNull(lawEnforcementPageQuery.getEndTime()),NdLawEquipmentInstall::getCheckDate, lawEnforcementPageQuery.getEndTime()) + .eq(StringUtils.isNotBlank(lawEnforcementPageQuery.getEquipmentName()),NdLawEquipmentInstall::getEquipmentName, lawEnforcementPageQuery.getEquipmentName()) + .like(Objects.nonNull(lawEnforcementPageQuery.getCarPlate()),NdLawEquipmentInstall::getCarPlate, lawEnforcementPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(lawEnforcementPageQuery.getCompanyName()),NdLawEquipmentInstall::getCompanyName, lawEnforcementPageQuery.getCompanyName()) + .like(StringUtils.isNotBlank(lawEnforcementPageQuery.getDriverName()),NdLawEquipmentInstall::getDriverName, lawEnforcementPageQuery.getDriverName()); + wrapper.orderBy(Boolean.TRUE,Boolean.FALSE,NdLawEquipmentInstall::getCheckDate); + equipmentInstallService.page(page, wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityAdvisoryManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityAdvisoryManage.java new file mode 100644 index 0000000..0a2c666 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityAdvisoryManage.java @@ -0,0 +1,119 @@ +package com.ningdatech.carapi.safe.manage; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.safe.entity.NdSecurityAdvisory; +import com.ningdatech.carapi.safe.entity.NdSecurityNoticeSaveReq; +import com.ningdatech.carapi.safe.model.dto.SecurityAdvisoryPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdSecurityAdvisoryVO; +import com.ningdatech.carapi.safe.service.INdSecurityAdvisoryService; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @description + * @since 2022/11/16 16:00 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class SecurityAdvisoryManage { + private final INdSecurityAdvisoryService ndSecurityAdvisoryService; + private final RegionsCacheHelper regionsCacheHelper; + + public PageVo buildWrapper(SecurityAdvisoryPageQuery securityAdvisoryPageQuery) { + // Page page = securityAdvisoryPageQuery.page(); + + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + + Integer pageNumber = securityAdvisoryPageQuery.getPageNumber(); + Integer pageSize = securityAdvisoryPageQuery.getPageSize(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdSecurityAdvisory.class); + // SecurityAdvisoryManage context = (SecurityAdvisoryManage) AopContext.currentProxy(); + List securityAdvisoryList = + ndSecurityAdvisoryService.dataScopeList(wrapper, securityAdvisoryPageQuery); + // 省里上传的文件,下级账号也要能看到 + if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) { + List securityAdvisories = ndSecurityAdvisoryService + .list(Wrappers.lambdaQuery(NdSecurityAdvisory.class).isNotNull(NdSecurityAdvisory::getRegionId) + .eq(NdSecurityAdvisory::getRegionId, DefValConstants.ZJREGION_ID) + .eq(Objects.nonNull(securityAdvisoryPageQuery.getAdvisoryDate()),NdSecurityAdvisory::getAdvisoryDate, + securityAdvisoryPageQuery.getAdvisoryDate())); + securityAdvisoryList.addAll(securityAdvisories); + } + + if (CollUtil.isEmpty(securityAdvisoryList)) { + return PageVo.empty(); + } + + List records = securityAdvisoryList.stream() + .skip((long)(pageNumber - 1) * pageSize) + .limit(pageSize).collect(Collectors.toList()); + + // context.searAdvisory(page, wrapper, securityAdvisoryPageQuery); + + List data = CollUtils.convert(records, e -> { + NdSecurityAdvisoryVO vo = BeanUtil.copyProperties(e, NdSecurityAdvisoryVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + return PageVo.of(data, securityAdvisoryList.size()); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1, entityIndex = 2) + public void searAdvisory(Page page, LambdaQueryWrapper wrapper, + SecurityAdvisoryPageQuery securityAdvisoryPageQuery) { + LocalDateTime time = securityAdvisoryPageQuery.getAdvisoryDate(); + if (Objects.nonNull(time)) { + wrapper.ge(NdSecurityAdvisory::getAdvisoryDate, time).lt(NdSecurityAdvisory::getAdvisoryDate, + time.plusMonths(1)); + } + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, NdSecurityAdvisory::getAdvisoryDate); + ndSecurityAdvisoryService.page(page, wrapper); + } + + public void saveSecurityNotice(NdSecurityNoticeSaveReq req) { + NdSecurityAdvisory ndSecurityAdvisory = BeanUtil.copyProperties(req, NdSecurityAdvisory.class); + ndSecurityAdvisory.setCreateBy(LoginUserUtil.getUserId()); + ndSecurityAdvisory.setCreateOn(LocalDateTime.now()); + ndSecurityAdvisory.setRegionId(req.getRegionId()); + ndSecurityAdvisory.setRegionName(regionsCacheHelper.getDisplayName(req.getRegionId())); + ndSecurityAdvisory.setAdvisoryDate(req.getYearMonth()); + ndSecurityAdvisory.setFileId(req.getFileId()); + ndSecurityAdvisory.setAdvisoryFileName(req.getFileName()); + ndSecurityAdvisory.setCompanyId(LoginUserUtil.loginUserDetail().getCompanyId()); + ndSecurityAdvisoryService.save(ndSecurityAdvisory); + } + + public void deleteSecurityNotice(Long id) { + ndSecurityAdvisoryService.deleteById(id); + } + + public void incrementDownCount(Long id) { + ndSecurityAdvisoryService.incrementDownCount(id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityHonestyManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityHonestyManage.java new file mode 100644 index 0000000..23e1a1b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/SecurityHonestyManage.java @@ -0,0 +1,163 @@ +package com.ningdatech.carapi.safe.manage; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.CompanySecurityCommitment; +import com.ningdatech.carapi.company.service.ICompanySecurityCommitmentService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.safe.constant.SecurityContant; +import com.ningdatech.carapi.safe.entity.NdSafetyCommitment; +import com.ningdatech.carapi.safe.entity.NdSafetyCredit; +import com.ningdatech.carapi.safe.model.dto.SecurityHonestyPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdSafetyCommitmentVO; +import com.ningdatech.carapi.safe.model.vo.NdSafetyCreditVO; +import com.ningdatech.carapi.safe.service.INdSafetyCommitmentService; +import com.ningdatech.carapi.safe.service.INdSafetyCreditService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.manage.CompanyManage; +import com.ningdatech.carapi.sys.service.CompanyService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author CMM + * @description SecurityHonestyManage + * @since 2022/11/16 16:00 + */ +@Component +@RequiredArgsConstructor +public class SecurityHonestyManage { + private final INdSafetyCommitmentService safetyCommitmentService; + private final INdSafetyCreditService safetyCreditService; + + private final CompanyService companyService; + + private final ICompanySecurityCommitmentService commitmentService; + + public PageVo queryCommitment(SecurityHonestyPageQuery param) { + Page page = param.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class) + .ne(Company::getCompanyType,0); + companyService.pageDataScope(page,wrapper,param); + if(0L == page.getTotal()){ + return PageVo.empty(); + } + + List companyIds = page.getRecords().stream().map(Company::getId).collect(Collectors.toList()); + //去查出 安全承诺 列表 + List commitments = commitmentService.list(Wrappers.lambdaQuery(CompanySecurityCommitment.class) + .in(CompanySecurityCommitment::getCompanyId,companyIds)); + //分组 map + Map> dataMap = commitments.stream().collect(Collectors.groupingBy(CompanySecurityCommitment::getCompanyId)); + + final Long[] index = {1L}; + List data = CollUtils.convert(page.getRecords(), e -> { + NdSafetyCommitmentVO vo = BeanUtil.copyProperties(e, NdSafetyCommitmentVO.class); + vo.setId(index[0]); + vo.setCompanyId(e.getId()); + vo.setCompanyAddress(e.getAddress()); + CodeUtil.searchCompanyNameAndRegionName(vo); + countCommitment(vo,dataMap.get(e.getId())); + index[0]++; + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + //统计 安全承诺数 + private void countCommitment(NdSafetyCommitmentVO vo, List companySecurityCommitments) { + if(CollUtil.isEmpty(companySecurityCommitments)){ + return; + } + //向社会承诺 + Integer commitmentsToSocial = 0; + //向员工承诺 + Integer commitmentsToEmployee = 0; + //总经理承诺 + Integer generalManagercommitment = 0; + //分管总承诺 + Integer leaderInChargeCommitment = 0; + //车队长承诺 + Integer teamLeaderCommitment = 0; + //驾驶员承诺 + Integer driverCommitment = 0; + for(CompanySecurityCommitment commitment : companySecurityCommitments){ + if(SecurityContant.Commitment.COMMITMENT_SOCIAL.equals( + commitment.getCommitmentTarget())){ + commitmentsToSocial++; + }else if(SecurityContant.Commitment.COMMITMENT_EMPLOYEE.equals( + commitment.getCommitmentTarget())){ + commitmentsToEmployee++; + }else if(SecurityContant.Commitment.COMMITMENT_GENERAL.equals( + commitment.getPromisee())){ + generalManagercommitment++; + }else if(SecurityContant.Commitment.COMMITMENT_LEADER.equals( + commitment.getPromisee())){ + leaderInChargeCommitment++; + }else if(SecurityContant.Commitment.COMMITMENT_TEAMLEADER.equals( + commitment.getPromisee())){ + teamLeaderCommitment++; + }else if(SecurityContant.Commitment.COMMITMENT_DRIVER.equals( + commitment.getPromisee())){ + driverCommitment++; + } + } + vo.setCommitmentsToSocial(commitmentsToSocial); + vo.setCommitmentsToEmployee(commitmentsToEmployee); + vo.setGeneralManagercommitment(generalManagercommitment); + vo.setLeaderInChargeCommitment(leaderInChargeCommitment); + vo.setDriverCommitment(driverCommitment); + vo.setTeamLeaderCommitment(teamLeaderCommitment); + } + + public void buildCommitmentWrapper(Page page, SecurityHonestyPageQuery securityAdvisoryPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdSafetyCommitment.class); + SecurityHonestyManage context = (SecurityHonestyManage)AopContext.currentProxy(); + context.searchCommitment(page,wrapper,securityAdvisoryPageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchCommitment(Page page, LambdaQueryWrapper wrapper, SecurityHonestyPageQuery securityAdvisoryPageQuery) { + wrapper.like(StringUtils.isNotBlank(securityAdvisoryPageQuery.getCompanyName()),NdSafetyCommitment::getCompanyName,securityAdvisoryPageQuery.getCompanyName()); + wrapper.orderBy(Boolean.TRUE,Boolean.FALSE,NdSafetyCommitment::getUpdateOn); + safetyCommitmentService.page(page, wrapper); + } + + public PageVo queryCredit(SecurityHonestyPageQuery securityAdvisoryPageQuery) { + Page page = securityAdvisoryPageQuery.page(); + buildCreditWrapper(page, securityAdvisoryPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdSafetyCreditVO vo = BeanUtil.copyProperties(e, NdSafetyCreditVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + public void buildCreditWrapper(Page page, SecurityHonestyPageQuery securityAdvisoryPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdSafetyCredit.class); + SecurityHonestyManage context = (SecurityHonestyManage)AopContext.currentProxy(); + context.searchCredit(page, wrapper, securityAdvisoryPageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public void searchCredit(Page page, LambdaQueryWrapper wrapper, SecurityHonestyPageQuery securityAdvisoryPageQuery) { + wrapper.like(StringUtils.isNotBlank(securityAdvisoryPageQuery.getCompanyName()),NdSafetyCredit::getCompanyName,securityAdvisoryPageQuery.getCompanyName()); + wrapper.orderBy(Boolean.TRUE,Boolean.FALSE,NdSafetyCredit::getUpdateOn); + safetyCreditService.page(page, wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleAccidentManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleAccidentManage.java new file mode 100644 index 0000000..4b9a07a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleAccidentManage.java @@ -0,0 +1,665 @@ +package com.ningdatech.carapi.safe.manage; + +import java.io.*; +import java.net.URLEncoder; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.aop.framework.AopContext; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.report.constants.ReportConstant; +import com.ningdatech.carapi.safe.constant.AccidentTypeEnum; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportEnum; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportStatusEnum; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentAnalysis; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.entity.VehicleAccidentReport; +import com.ningdatech.carapi.safe.model.dto.AccidentAuditDTO; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; +import com.ningdatech.carapi.safe.model.dto.NdVehicleAccidentDTO; +import com.ningdatech.carapi.safe.model.dto.VehicleAccidentReportDTO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentReportVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentAnalysisService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import com.ningdatech.carapi.safe.service.IVehicleAccidentReportService; +import com.ningdatech.carapi.scheduler.enums.DataTypeEnum; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.TemplateExportParams; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.poi.excel.ExcelUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author PoffyZhang + * @date 2022/10/19 上午11:18 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class VehicleAccidentManage { + + private final INdVehicleAccidentService vehicleAccidentService; + private final INdVehicleAccidentDeadService vehicleAccidentDeadService; + private final INdVehicleAccidentAnalysisService vehicleAccidentAnalysisService; + private final IVehicleAccidentReportService vehicleAccidentReportService; + private final ApplicationContext applicationContext; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final CompaniesCacheHelper companiesCacheHelper; + private final RegionsCacheHelper regionsCacheHelper; + + public PageVo queryVehicleAccident(AccidentPageQuery accidentPageQuery) { + ((VehicleAccidentManage) AopContext.currentProxy()).queryAccident(); + // 以车辆事故维度 + Page page = accidentPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + accidentPageQuery.setCarPlateList(carPlateList); + } + + vehicleAccident(page, accidentPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentVO.class); + + String desc = VehicleTypeEnum.getDescByCode(vo.getVehicleType()); + Integer injuries = e.getInjuries(); + Integer deathToll = e.getDeathToll(); + vo.setInjuries(injuries); + vo.setDeathToll(deathToll); + vo.setAccidentType(e.getAccidentType()); + vo.setAccidentTypeName(AccidentTypeEnum.getDescByCode(e.getAccidentType())); + vo.setBriefCase(e.getBriefCase()); + vo.setFirmContent(e.getFirmContent()); + //if (injuries == 0 && deathToll == 0){ + // vo.setAccidentType(AccidentTypeEnum.OTHER.getCode()); + // vo.setAccidentTypeName(AccidentTypeEnum.OTHER.getDesc()); + //}else if (injuries != 0 && deathToll == 0){ + // vo.setAccidentType(AccidentTypeEnum.INJURY.getCode()); + // vo.setAccidentTypeName(AccidentTypeEnum.INJURY.getDesc()); + //}else { + // vo.setAccidentType(AccidentTypeEnum.DEAD.getCode()); + // vo.setAccidentTypeName(AccidentTypeEnum.DEAD.getDesc()); + //} + vo.setVehicleTypeName(desc); + vo.setReportStatusName(VehicleAccidentReportStatusEnum.getDescByCode(e.getReportStatus())); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + public PageVo queryVehicleAccidentOpen(AccidentPageQuery accidentPageQuery) { + ((VehicleAccidentManage) AopContext.currentProxy()).queryAccident(); + // 以车辆事故维度 + Page page = accidentPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccident.class); + searchVehicleAccidentWrapper(wrapper, accidentPageQuery); + vehicleAccidentService.page(page, wrapper); + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentVO.class); + String desc = VehicleTypeEnum.getDescByCode(vo.getVehicleType()); + vo.setVehicleTypeName(desc); + vo.setReportStatusName(VehicleAccidentReportStatusEnum.getDescByCode(e.getReportStatus())); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + @Async + protected void queryAccident() { + log.info("查询时车辆出险上报校对"); + //获取事故上报审核列表中通过审核的上报信息 + List reportList = vehicleAccidentReportService.list(Wrappers.lambdaQuery(VehicleAccidentReport.class) + .select(VehicleAccidentReport::getCarPlate, VehicleAccidentReport::getAccidentTime) + .eq(VehicleAccidentReport::getAuditStatus, VehicleAccidentReportEnum.AUDIT_APPROVED.getCode())); + Map> carPlateMapDate = reportList.stream() + .collect(Collectors.groupingBy(VehicleAccidentReport::getCarPlate, + Collectors.mapping(w -> w.getAccidentTime().toLocalDate(), Collectors.toSet()))); + //获取车辆事故信息表中的所有数据 + List records = vehicleAccidentService.list(Wrappers.lambdaQuery(NdVehicleAccident.class) + .select(NdVehicleAccident::getCarPlate, NdVehicleAccident::getAccidentTime)); + //对比两个列表中的数据,更新车辆事故信息表中的上报状态 + List reported = records.stream().filter(w -> { + Set dates = carPlateMapDate.get(w.getCarPlate()); + if (CollUtil.isNotEmpty(dates)) { + return dates.contains(w.getAccidentTime().toLocalDate()); + } + return false; + }).map(NdVehicleAccident::getId).collect(Collectors.toList()); + if (!reported.isEmpty()) { + LambdaUpdateWrapper update = Wrappers.lambdaUpdate(NdVehicleAccident.class) + .set(NdVehicleAccident::getReportStatus, VehicleAccidentReportStatusEnum.REPORTED.getCode()) + .in(NdVehicleAccident::getId, reported); + vehicleAccidentService.update(update); + } + } + + public PageVo queryDead(AccidentPageQuery accidentPageQuery) { + ((VehicleAccidentManage) AopContext.currentProxy()).queryAccidentDead(); + //以死亡事故为维度 + Page page = accidentPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + accidentPageQuery.setCarPlateList(carPlateList); + } + + vehicleAccidentDead(page, accidentPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentDeadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setReportStatusName(VehicleAccidentReportStatusEnum.getDescByCode(e.getReportStatus())); + vo.setBriefCase(e.getBriefCase()); + vo.setFirmContent(e.getFirmContent()); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + public PageVo queryDeadOpen(AccidentPageQuery accidentPageQuery) { + ((VehicleAccidentManage) AopContext.currentProxy()).queryAccidentDead(); + //以死亡事故为维度 + Page page = accidentPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccidentDead.class); + searchvehicleAccidentDeadWrapper(page, wrapper, accidentPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentDeadVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setReportStatusName(VehicleAccidentReportStatusEnum.getDescByCode(e.getReportStatus())); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + @Async + protected void queryAccidentDead() { + log.info("查询时车辆出险上报校对"); + //获取事故上报审核列表中通过审核的上报信息 + List reportList = vehicleAccidentReportService.list(Wrappers.lambdaQuery(VehicleAccidentReport.class) + .select(VehicleAccidentReport::getCarPlate, VehicleAccidentReport::getAccidentTime) + .eq(VehicleAccidentReport::getAuditStatus, VehicleAccidentReportEnum.AUDIT_APPROVED.getCode())); + Map> carPlateMapDate = reportList.stream() + .collect(Collectors.groupingBy(VehicleAccidentReport::getCarPlate, + Collectors.mapping(w -> w.getAccidentTime().toLocalDate(), Collectors.toSet()))); + //获取车辆死亡事故信息表中的所有数据 + List records = vehicleAccidentDeadService.list(Wrappers.lambdaQuery(NdVehicleAccidentDead.class) + .select(NdVehicleAccidentDead::getCarPlate, NdVehicleAccidentDead::getAccidentTime)); + //对比两个列表中的数据,更新车辆死亡事故信息表中的上报状态 + List reported = records.stream().filter(w -> { + Set dates = carPlateMapDate.get(w.getCarPlate()); + if (CollUtil.isNotEmpty(dates)) { + return dates.contains(w.getAccidentTime().toLocalDate()); + } + return false; + }).map(NdVehicleAccidentDead::getId).collect(Collectors.toList()); + if (!reported.isEmpty()) { + LambdaUpdateWrapper update = Wrappers.lambdaUpdate(NdVehicleAccidentDead.class) + .set(NdVehicleAccidentDead::getReportStatus, VehicleAccidentReportStatusEnum.REPORTED.getCode()) + .in(NdVehicleAccidentDead::getId, reported); + vehicleAccidentDeadService.update(update); + } + } + + public PageVo queryAccidentAnalysis(AccidentPageQuery accidentPageQuery) { + //事故分析 + Page page = accidentPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + accidentPageQuery.setCarPlateList(carPlateList); + } + + vehicleAccidentAnalysisService.pageAnalysis(page, accidentPageQuery); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentAnalysisVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + public PageVo queryAccidentAnalysisOpen(AccidentPageQuery accidentPageQuery) { + //事故分析 + Page page = accidentPageQuery.page(); + vehicleAccidentAnalysisService.pageAnalysisOpen(page, accidentPageQuery); + if (0L == page.getTotal()) { + return PageVo.empty(); + } + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentAnalysisVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + public void vehicleAccident(Page page, AccidentPageQuery accidentPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccident.class); + VehicleAccidentManage clazz = (VehicleAccidentManage) AopContext.currentProxy(); + clazz.searchVehicleAccidentWrapper(wrapper, accidentPageQuery); + vehicleAccidentService.page(page,wrapper); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public void searchVehicleAccidentWrapper(LambdaQueryWrapper wrapper, AccidentPageQuery param) { + wrapper.ge(Objects.nonNull(param.getStartTime()), NdVehicleAccident::getAccidentTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), NdVehicleAccident::getAccidentTime, param.getEndTime()) + .like(Objects.nonNull(param.getCarPlate()), NdVehicleAccident::getCarPlate, param.getCarPlate()) + .like(StringUtils.isNotBlank(param.getCompanyName()), NdVehicleAccident::getCompanyName, param.getCompanyName()) + .eq(Objects.nonNull(param.getVehicleType()), NdVehicleAccident::getVehicleType, param.getVehicleType()) + .in(CollUtil.isNotEmpty(param.getCarPlateList()),NdVehicleAccident::getCarPlate,param.getCarPlateList()) + .eq(Objects.nonNull(param.getAccidentType()),NdVehicleAccident::getAccidentType,param.getAccidentType()) + .eq(Objects.nonNull(param.getReportStatus()), NdVehicleAccident::getReportStatus, param.getReportStatus()); + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, NdVehicleAccident::getAccidentTime); + } + + public void vehicleAccidentDead(Page page, AccidentPageQuery accidentPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccidentDead.class); + VehicleAccidentManage clazz = (VehicleAccidentManage) AopContext.currentProxy(); + clazz.searchvehicleAccidentDeadWrapper(page, wrapper, accidentPageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchvehicleAccidentDeadWrapper(Page page, LambdaQueryWrapper wrapper, AccidentPageQuery param) { + wrapper.ge(Objects.nonNull(param.getStartTime()), NdVehicleAccidentDead::getAccidentTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), NdVehicleAccidentDead::getAccidentTime, param.getEndTime()) + .like(Objects.nonNull(param.getCarPlate()), NdVehicleAccidentDead::getCarPlate, param.getCarPlate()) + .like(StringUtils.isNotBlank(param.getCompanyName()), NdVehicleAccidentDead::getCompanyName, param.getCompanyName()) + .eq(Objects.nonNull(param.getReportStatus()), NdVehicleAccidentDead::getReportStatus, param.getReportStatus()); + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, NdVehicleAccidentDead::getAccidentTime); + vehicleAccidentDeadService.page(page, wrapper); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchvehicleAccidentAnalysisWrapper(Page page, LambdaQueryWrapper wrapper, AccidentPageQuery param) { + wrapper.ge(Objects.nonNull(param.getStartTime()), NdVehicleAccidentAnalysis::getAccidentTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), NdVehicleAccidentAnalysis::getAccidentTime, param.getEndTime()); + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, NdVehicleAccidentAnalysis::getAccidentTime); + vehicleAccidentAnalysisService.page(page, wrapper); + } + + public PageVo reportAccidentInfo(AccidentPageQuery accidentPageQuery) { + Page page = accidentPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆所在的所有企业 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + accidentPageQuery.setCarPlateList(carPlateList); + } + + vehicleAccidentReport(page, accidentPageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdVehicleAccidentReportVO vo = BeanUtil.copyProperties(e, NdVehicleAccidentReportVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + String createTime = LocalDateTimeUtil.format(e.getCreateOn(), "yyyy-MM-dd HH:mm"); + vo.setCreateTime(createTime); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + private void vehicleAccidentReport(Page page, AccidentPageQuery accidentPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleAccidentReport.class); + VehicleAccidentManage clazz = (VehicleAccidentManage) AopContext.currentProxy(); + clazz.searchvehicleAccidentReportWrapper(page, wrapper, accidentPageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchvehicleAccidentReportWrapper(Page page, LambdaQueryWrapper wrapper, AccidentPageQuery param) { + wrapper.ge(Objects.nonNull(param.getStartTime()), VehicleAccidentReport::getAccidentTime, param.getStartTime()) + .le(Objects.nonNull(param.getEndTime()), VehicleAccidentReport::getAccidentTime, param.getEndTime()) + .like(Objects.nonNull(param.getCarPlate()), VehicleAccidentReport::getCarPlate, param.getCarPlate()) + .in(CollUtil.isNotEmpty(param.getCarPlateList()),VehicleAccidentReport::getCarPlate,param.getCarPlateList()) + .eq(Objects.nonNull(param.getAuditStatus()), VehicleAccidentReport::getAuditStatus, param.getAuditStatus()); + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, VehicleAccidentReport::getCreateOn); + vehicleAccidentReportService.page(page, wrapper); + } + + @Transactional(rollbackFor = Exception.class) + public VehicleAccidentReport save(VehicleAccidentReportDTO data, Long userId) { + //获取登录用户信息 + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + //获取入参信息 + Long vehicleAccidentReportId = data.getId(); + VehicleAccidentReport vehicleAccidentReport; + if (Objects.isNull(vehicleAccidentReportId)) { + vehicleAccidentReport = new VehicleAccidentReport(); + BeanUtil.copyProperties(data, vehicleAccidentReport); + vehicleAccidentReport.setRegionId(userInfoDetails.getRegionId()); + vehicleAccidentReport.setRegionName(userInfoDetails.getRegionName()); + vehicleAccidentReport.setCompanyId(userInfoDetails.getCompanyId()); + vehicleAccidentReport.setCompanyName(userInfoDetails.getCompanyName()); + vehicleAccidentReport.setCreateOn(LocalDateTime.now()); + vehicleAccidentReport.setCreateBy(userId); + vehicleAccidentReport.setUpdateBy(userId); + vehicleAccidentReport.setUpdateOn(LocalDateTime.now()); + vehicleAccidentReport.setAuditStatus(VehicleAccidentReportEnum.UN_AUDIT.getCode()); + vehicleAccidentReportService.save(vehicleAccidentReport); + } else { + vehicleAccidentReport = vehicleAccidentReportService.getById(vehicleAccidentReportId); + BeanUtil.copyProperties(data, vehicleAccidentReport); + vehicleAccidentReport.setRegionId(userInfoDetails.getRegionId()); + vehicleAccidentReport.setRegionName(userInfoDetails.getRegionName()); + vehicleAccidentReport.setCompanyId(userInfoDetails.getCompanyId()); + vehicleAccidentReport.setCompanyName(userInfoDetails.getCompanyName()); + vehicleAccidentReport.setUpdateBy(userId); + vehicleAccidentReport.setUpdateOn(LocalDateTime.now()); + vehicleAccidentReport.setAuditStatus(VehicleAccidentReportEnum.UN_AUDIT.getCode()); + vehicleAccidentReportService.updateById(vehicleAccidentReport); + } + return vehicleAccidentReport; + } + + public VehicleAccidentReport getDetail(Long id) { + return vehicleAccidentReportService.getById(id); + } + + public Boolean delete(Long id) { + VehicleAccidentReport vehicleAccidentReport = vehicleAccidentReportService.getById(id); + Long companyId = vehicleAccidentReport.getCompanyId(); + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + // 判断上报数据的企业所在的区域是否在登录用户所属的区域权限下 + Long countryRegionId = companyDto.getRegionId(); + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + List childList = regionsCacheHelper.listChildRegionId(regionId, true, true); + // 不在本级及下级区域的上报数据,不允许删除 + if (!childList.contains(countryRegionId)){ + return Boolean.FALSE; + } + return vehicleAccidentReportService.removeById(id); + } + + public Boolean audit(AccidentAuditDTO param) { + + VehicleAccidentReport vehicleAccidentReport = vehicleAccidentReportService.getById(param.getId()); + Long companyId = vehicleAccidentReport.getCompanyId(); + CompanyDTO companyDto = companiesCacheHelper.getById(companyId); + // 判断上报数据的企业所在的区域是否在登录用户所属的区域权限下 + Long countryRegionId = companyDto.getRegionId(); + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long regionId = userDetail.getRegionId(); + List childList = regionsCacheHelper.listChildRegionId(regionId, true, true); + // 不在本级及下级区域的上报数据,不允许审核 + if (!childList.contains(countryRegionId)){ + return Boolean.FALSE; + } + + if (Objects.isNull(vehicleAccidentReport)) { + throw new BizException("审核记录不存在!"); + } + if (!VehicleAccidentReportEnum.UN_AUDIT.getCode().equals(vehicleAccidentReport.getAuditStatus())) { + throw new BizException("只能审核待审核的上报信息!"); + } + vehicleAccidentReport.setAuditStatus(param.getAuditStatus()); + vehicleAccidentReport.setAuditOpinion(param.getAuditOpinion()); + vehicleAccidentReport.setAuditor(LoginUserUtil.getUsername()); + vehicleAccidentReport.setAuditorUserId(LoginUserUtil.getUserId()); + vehicleAccidentReport.setUpdateOn(LocalDateTime.now()); + boolean result = vehicleAccidentReportService.updateById(vehicleAccidentReport); + Integer injuries = vehicleAccidentReport.getInjuries(); + Integer deathToll = vehicleAccidentReport.getDeathToll(); + + // 如果审核通过 + if (VehicleAccidentReportEnum.AUDIT_APPROVED.getCode().equals(param.getAuditStatus())){ + // 判断该数据是否在车辆事故信息表和车辆死亡事故信息中,如果不在要发布事件 + LocalDateTime accidentTime = vehicleAccidentReport.getAccidentTime(); + LocalDateTime startTime = accidentTime.minusMinutes(5L); + LocalDateTime endTime = accidentTime.plusMinutes(5L); + String startTimeFormat = NdDateUtils.format(startTime, "yyyy-MM-dd HH:mm:00"); + String endTimeFormat = NdDateUtils.format(endTime, "yyyy-MM-dd HH:mm:59"); + LocalDateTime queryStartTime = LocalDateTimeUtil.parse(startTimeFormat,"yyyy-MM-dd HH:mm:00"); + LocalDateTime queryEndTime = LocalDateTimeUtil.parse(endTimeFormat,"yyyy-MM-dd HH:mm:59"); + + NdVehicleAccident vehicleAccident = vehicleAccidentService.getOne(Wrappers.lambdaQuery(NdVehicleAccident.class) + .eq(NdVehicleAccident::getCarPlate, vehicleAccidentReport.getCarPlate()) + .eq(NdVehicleAccident::getAccidentTime, vehicleAccidentReport.getAccidentTime()) + .ge(NdVehicleAccident::getAccidentTime,queryStartTime) + .le(NdVehicleAccident::getAccidentTime,queryEndTime) + .eq(NdVehicleAccident::getAccidentDriver, vehicleAccidentReport.getAccidentDriver())); + + NdVehicleAccidentDead vehicleAccidentDead = vehicleAccidentDeadService.getOne(Wrappers.lambdaQuery(NdVehicleAccidentDead.class) + .eq(NdVehicleAccidentDead::getCarPlate, vehicleAccidentReport.getCarPlate()) + .eq(NdVehicleAccidentDead::getAccidentDriver, vehicleAccidentReport.getAccidentDriver()) + .ge(NdVehicleAccidentDead::getAccidentTime,queryStartTime) + .le(NdVehicleAccidentDead::getAccidentTime,queryEndTime) + .eq(NdVehicleAccidentDead::getDeathToll, vehicleAccidentReport.getDeathToll())); + + // 既没有受伤人数也没有死亡人数,不发布事件 + if (injuries == 0 && deathToll == 0){ + return result; + } + } + return result; + } + + public void exportVehicleAccidentData(AccidentPageQuery accidentPageQuery, HttpServletResponse response) { + ((VehicleAccidentManage) AopContext.currentProxy()).queryAccident(); + // 以车辆事故维度 + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + accidentPageQuery.setCarPlateList(carPlateList); + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccident.class); + VehicleAccidentManage clazz = (VehicleAccidentManage) AopContext.currentProxy(); + clazz.searchVehicleAccidentWrapper(wrapper, accidentPageQuery); + List accidents = vehicleAccidentService.list(wrapper); + + List data = CollUtils.convert(accidents, e -> { + NdVehicleAccidentDTO vo = BeanUtil.copyProperties(e, NdVehicleAccidentDTO.class); + vo.setCarPlate(e.getCarPlate()); + vo.setAccidentTime(NdDateUtils.format(e.getAccidentTime(),NdDateUtils.DEFAULT_DATE_TIME_FORMAT)); + String desc = VehicleTypeEnum.getDescByCode(e.getVehicleType()); + Integer injuries = e.getInjuries(); + Integer deathToll = e.getDeathToll(); + vo.setInjuries(injuries); + vo.setDeathToll(deathToll); + vo.setAccidentTypeName(AccidentTypeEnum.getDescByCode(e.getAccidentType())); + vo.setBriefCase(e.getBriefCase()); + vo.setAccidentNo(e.getAccidentNo()); + vo.setFirmContent(e.getFirmContent()); + vo.setVehicleTypeName(desc); + vo.setReportStatusName(VehicleAccidentReportStatusEnum.getDescByCode(e.getReportStatus())); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + + File directory = new File(""); + String templateName; + String templatePath; + List dtoList = Lists.newArrayList(); + if (CollUtil.isNotEmpty(data)) { + templateName = ReportConstant.VEHICLE_ACCIDENT_DATA_TEMPLATE; + List dataList = new ArrayList<>(); + data.forEach(m -> { + LinkedHashMap dataMap = new LinkedHashMap<>(); + dataMap.put("regionName",m.getRegionName()); + dataMap.put("carPlate",m.getCarPlate()); + dataMap.put("accidentTime",m.getAccidentTime()); + dataMap.put("accidentDriver",m.getAccidentDriver()); + dataMap.put("vehicleTypeName",m.getVehicleTypeName()); + dataMap.put("companyName",m.getCompanyName()); + dataMap.put("accidentAddress",m.getAccidentAddress()); + dataMap.put("injuries",m.getInjuries()); + dataMap.put("deathToll",m.getDeathToll()); + dataMap.put("reportStatusName",m.getReportStatusName()); + dataMap.put("accidentTypeName",m.getAccidentTypeName()); + dataMap.put("briefCase",m.getBriefCase()); + dataMap.put("accidentNo",m.getAccidentNo()); + dataMap.put("firmContent",m.getFirmContent()); + dataList.add(dataMap); + }); + dtoList = dataList; + }else { + templateName = ReportConstant.VEHICLE_ACCIDENT_DATA_TEMPLATE_EMPTY; + } + templatePath = directory.getAbsolutePath() + File.separator + "template" + File.separator + templateName + ".xlsx"; + // 获取本地目录的Excel模板 + TemplateExportParams temp = new TemplateExportParams(templatePath); + temp.setSheetNum(new Integer[] {0}); + temp.setSheetName(new String[] {templateName}); + Map map = new HashMap<>(4); + map.put("mapList", dtoList); + Workbook workbook = ExcelExportUtil.exportExcel(temp, map); + Sheet sheet = workbook.getSheet(templateName); + sheet.autoSizeColumn(0); + // 设置所有列宽自适应 + for (int colnum = 0; colnum < 13; colnum++) { + sheet.autoSizeColumn(colnum); + } + if (CollUtil.isEmpty(dtoList)) { + // 输出空模板 + // 获取本地目录的空Excel模板 + try { + InputStream templateInputStream = this.getClass().getClassLoader().getResourceAsStream("template" + File.separator + templateName + ".xlsx"); + OutputStream outputStream = response.getOutputStream(); + // 设置要下载的文件的名称 + ExcelDownUtil.setFileName(templateName, response); + // 设置文件的MIME类型 + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + + byte[] b = new byte[2048]; + int len; + while ((len = templateInputStream.read(b)) != -1) { + outputStream.write(b, 0, len); + } + templateInputStream.close(); + outputStream.flush(); + outputStream.close(); + } catch (IOException e) { + throw new BizException("读取模板失败!"); + } + return; + } + if (workbook == null){ + throw new BizException("读取编辑表模板失败!"); + } + // 重置响应对象 + response.reset(); + try { + response.setHeader("Content-disposition", + "attachment;filename*=utf-8''" + URLEncoder.encode(Objects.requireNonNull(templateName), "UTF-8") + ".xlsx"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setContentType(ExcelUtil.XLS_CONTENT_TYPE); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + // 写出数据输出流到页面 + try { + OutputStream output = response.getOutputStream(); + BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output); + workbook.write(bufferedOutPut); + bufferedOutPut.flush(); + bufferedOutPut.close(); + output.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleInsureManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleInsureManage.java new file mode 100644 index 0000000..74b68ce --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleInsureManage.java @@ -0,0 +1,415 @@ +package com.ningdatech.carapi.safe.manage; + +import java.io.*; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.aop.framework.AopContext; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.ValidUtil; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.common.util.ExcelDownUtil; +import com.ningdatech.carapi.common.util.ExcelExportStyle; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.industry.model.dto.LabAcceptanceCertificateImportDto; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportEnum; +import com.ningdatech.carapi.safe.constant.VehicleAccidentReportStatusEnum; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.entity.VehicleAccidentReport; +import com.ningdatech.carapi.safe.model.dto.InsurePageQuery; +import com.ningdatech.carapi.safe.model.dto.NdInsureOutDangerImportDTO; +import com.ningdatech.carapi.safe.model.po.NdInsureOutDangerAnalysisPO; +import com.ningdatech.carapi.safe.model.vo.NdInsureInfoVO; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerAnalysisVO; +import com.ningdatech.carapi.safe.model.vo.NdInsureOutDangerVO; +import com.ningdatech.carapi.safe.service.INdInsureInfoService; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerAnalysisService; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerService; +import com.ningdatech.carapi.safe.service.IVehicleAccidentReportService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.event.ImportDataEvent; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author PoffyZhang + * @date 2022/10/19 上午11:18 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class VehicleInsureManage { + + private final INdInsureInfoService insureInfoService; + private final INdInsureOutDangerService insureOutDangerService; + private final INdInsureOutDangerAnalysisService insureOutDangerAnalysisService; + private final CompaniesCacheHelper companiesCacheHelper; + private final CompanyService companyService; + private final IVehicleAccidentReportService vehicleAccidentReportService; + private final VehiclesCacheHelper vehiclesCacheHelper; + private final INdInsureOutDangerService outDangerService; + + + public PageVo queryVehicleInsure(InsurePageQuery insurePageQuery) { + //承保信息 + Page page = insurePageQuery.page(); + insureInfo(page, insurePageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdInsureInfoVO vo = BeanUtil.copyProperties(e, NdInsureInfoVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + public PageVo queryOutDanger(InsurePageQuery insurePageQuery) { + ((VehicleInsureManage) AopContext.currentProxy()). queryOutDanger(); + //出险信息 + Page page = insurePageQuery.page(); + insureOutDanger(page, insurePageQuery); + List data = CollUtils.convert(page.getRecords(), e -> { + NdInsureOutDangerVO vo = BeanUtil.copyProperties(e, NdInsureOutDangerVO.class); + CodeUtil.searchCompanyNameAndRegionName(vo); + vo.setReportStatusName(VehicleAccidentReportStatusEnum.getDescByCode(e.getReportStatus())); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + @Async() + protected void queryOutDanger() { + log.info("查询时车辆出险上报校对"); + //获取事故上报审核列表中通过审核的上报信息 + List reportList = vehicleAccidentReportService.list(Wrappers.lambdaQuery(VehicleAccidentReport.class) + .select(VehicleAccidentReport::getCarPlate, VehicleAccidentReport::getAccidentTime) + .eq(VehicleAccidentReport::getAuditStatus, VehicleAccidentReportEnum.AUDIT_APPROVED.getCode())); + Map> carPlateMapDate = reportList.stream() + .collect(Collectors.groupingBy(VehicleAccidentReport::getCarPlate, + Collectors.mapping(w -> w.getAccidentTime().toLocalDate(), Collectors.toSet()))); + //获取车辆出险信息表中的所有数据 + List records = insureOutDangerService.list(Wrappers.lambdaQuery(NdInsureOutDanger.class) + .select(NdInsureOutDanger::getCarPlate, NdInsureOutDanger::getAccidentTime)); + //对比两个列表中的数据,更新车辆出险信息表中的上报状态 + List reported = records.stream().filter(w -> { + Set dates = carPlateMapDate.get(w.getCarPlate()); + if (CollUtil.isNotEmpty(dates)) { + return dates.contains(w.getAccidentTime().toLocalDate()); + } + return false; + }).map(NdInsureOutDanger::getId).collect(Collectors.toList()); + if (!reported.isEmpty()) { + LambdaUpdateWrapper update = Wrappers.lambdaUpdate(NdInsureOutDanger.class) + .set(NdInsureOutDanger::getReportStatus, VehicleAccidentReportStatusEnum.REPORTED.getCode()) + .in(NdInsureOutDanger::getId, reported); + insureOutDangerService.update(update); + } + } + + public PageVo queryInsureOutDangerAnalysis(InsurePageQuery insurePageQuery) { + //出险分析 + Page page = insurePageQuery.page(); + analysis(page, insurePageQuery); + List data = CollUtils.convert(page.getRecords(), + e -> { + NdInsureOutDangerAnalysisVO vo = BeanUtil.copyProperties(e, NdInsureOutDangerAnalysisVO.class); + CodeUtil.searchRegionName(vo); + return vo; + }); + return PageVo.of(data, page.getTotal()); + } + + public void insureInfo(Page page, InsurePageQuery insurePageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdInsureInfo.class); + VehicleInsureManage clazz = (VehicleInsureManage) AopContext.currentProxy(); + clazz.searchInsureInfo(page, wrapper, insurePageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchInsureInfo(Page page, LambdaQueryWrapper wrapper, InsurePageQuery insurePageQuery) { + wrapper.ge(Objects.nonNull(insurePageQuery.getQibaoStartTime()), NdInsureInfo::getInsureTimeStart, insurePageQuery.getQibaoStartTime()) + .le(Objects.nonNull(insurePageQuery.getQibaoEndTime()), NdInsureInfo::getInsureTimeStart, insurePageQuery.getQibaoEndTime()) + .ge(Objects.nonNull(insurePageQuery.getDaoqiStartTime()), NdInsureInfo::getInsureTimeEnd, insurePageQuery.getDaoqiStartTime()) + .le(Objects.nonNull(insurePageQuery.getDaoqiEndTime()), NdInsureInfo::getInsureTimeEnd, insurePageQuery.getDaoqiEndTime()) + .like(Objects.nonNull(insurePageQuery.getCarPlate()), NdInsureInfo::getCarPlate, insurePageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(insurePageQuery.getCompanyName()), NdInsureInfo::getCompanyName, insurePageQuery.getCompanyName()); + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, NdInsureInfo::getUpdateOn); + insureInfoService.page(page, wrapper); + } + + public void insureOutDanger(Page page, InsurePageQuery insurePageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdInsureOutDanger.class); + VehicleInsureManage clazz = (VehicleInsureManage) AopContext.currentProxy(); + clazz.searchInsureOutDanger(page, wrapper, insurePageQuery); + } + + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1) + public void searchInsureOutDanger(Page page, LambdaQueryWrapper wrapper, InsurePageQuery insurePageQuery) { + wrapper.like(Objects.nonNull(insurePageQuery.getCarPlate()), NdInsureOutDanger::getCarPlate, insurePageQuery.getCarPlate()); + wrapper.eq(Objects.nonNull(insurePageQuery.getReportStatus()),NdInsureOutDanger::getReportStatus,insurePageQuery.getReportStatus()); + wrapper.orderBy(Boolean.TRUE, Boolean.FALSE, NdInsureOutDanger::getUpdateOn); + insureOutDangerService.page(page, wrapper); + } + + public void analysis(Page page, InsurePageQuery insurePageQuery) { + VehicleInsureManage clazz = (VehicleInsureManage) AopContext.currentProxy(); + clazz.searchInsureAnalysis(page, insurePageQuery); + } + + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public void searchInsureAnalysis(Page page, InsurePageQuery param) { + insureOutDangerAnalysisService.pageAnalysis(page, param); + } + + @EventListener(condition = "event.getTemplate() == T(com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum).INSURE_OUT_DANGER") + public void importDataListener(ImportDataEvent event) throws IOException { + MultipartFile file = (MultipartFile) event.getSource(); + EasyExcel.read(file.getInputStream(), LabAcceptanceCertificateImportDto.class, + new ReadListener() { + + final List insert = new ArrayList<>(); + + @Override + public void invoke(NdInsureOutDangerImportDTO data, AnalysisContext context) { + String s = ValidUtil.validFast(data); + Assert.isTrue(StrUtil.isBlank(s), s); + insert.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + log.info("所有数据读取完成:{}", insert.size()); + importDataSave(insert); + } + }).sheet(0).doRead(); + } + + private void importDataSave(List records) { + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + List companyNames = CollUtils.fieldList(records, NdInsureOutDangerImportDTO::getCompanyName); + List companies = companyService.listCompanyByCompanyNames(companyNames); + Map companyMap = CollUtils.listToMap(companies, Company::getName); + List list = new ArrayList<>(); + records.forEach(w -> { + Company company = companyMap.get(w.getCompanyName()); + if (company == null) { + return; + } + NdInsureOutDanger outDanger = new NdInsureOutDanger(); + outDanger.setAccidentAddress(w.getAccidentAddress()); + outDanger.setCompanyId(company.getId()); + outDanger.setCompanyName(company.getName()); + outDanger.setRegionId(company.getRegionId()); + outDanger.setRegionName(company.getRegionName()); + outDanger.setAccidentTime(w.getAccidentTime()); + outDanger.setInjuries(w.getInjuries()); + outDanger.setInsureCompany(w.getInsureCompany()); + outDanger.setCarPlate(w.getCarPlate()); + outDanger.setDeathToll(w.getDeathToll()); + outDanger.setCompensateAmount(w.getCompensateAmount()); + outDanger.setCreateBy(userId); + outDanger.setCreateOn(now); + outDanger.setUpdateBy(userId); + outDanger.setUpdateOn(now); + list.add(outDanger); + }); + insureOutDangerService.saveBatch(list); + } + + //================================================================================================================== + + public void exportOutDanger(HttpServletResponse response, InsurePageQuery insurePageQuery) { + insurePageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE); + Page page = insurePageQuery.page(); + insureOutDanger(page, insurePageQuery); + List collect = page.getRecords().stream().map(w -> { + NdInsureOutDangerVO vo = BeanUtil.copyProperties(w, NdInsureOutDangerVO.class); + return vo; + }).collect(Collectors.toList()); + String fileName = "出险信息"; + ExcelDownUtil.setFileName(fileName, response); + // 数据导出处理函数 + try { + EasyExcel.write(response.getOutputStream(), NdInsureOutDangerVO.class) + .autoCloseStream(false) + .registerWriteHandler(ExcelExportStyle.formalStyle()) + .sheet(fileName) + .doWrite(collect); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void saveOrUpdate(NdInsureOutDangerVO req) { + Long userId = LoginUserUtil.getUserId(); + LocalDateTime now = LocalDateTime.now(); + NdInsureOutDanger insert = BeanUtil.copyProperties(req, NdInsureOutDanger.class); + insert.setUpdateBy(userId); + insert.setUpdateOn(now); + insert.setRegionId(companiesCacheHelper.getById(req.getCompanyId()).getRegionId()); + if (insert.getId() == null) { + insert.setCreateBy(userId); + insert.setUpdateOn(now); + } + insureOutDangerService.saveOrUpdate(insert); + } + + public void importOutDanger() throws FileNotFoundException { + + // 获取所有出险数据信息 + Map> insureMap = insureOutDangerService.list().stream().collect(Collectors.groupingBy(NdInsureOutDanger::getCarPlate)); + File directory = new File(""); + // 临时文件存储路径 + String filePath = directory.getAbsolutePath() + File.separator + "outInsure"; + File file = new File(filePath + File.separator + "保险出险数据.xlsx"); + Workbook wb = readExcel(new FileInputStream(file),file.getName()); + Row row = null; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i outDangers = insureMap.get(carPlate); + List dangers = Lists.newArrayList(); + if (CollUtil.isNotEmpty(outDangers)) { + // 去重 + HashSet hashSet = new HashSet<>(); + dangers = outDangers.stream() + .filter(c -> hashSet.add(c.getAccidentTime() + c.getAccidentAddress())) + .collect(Collectors.toList()); + } + if (CollUtil.isNotEmpty(dangers)) { + Map dangerMap = dangers.stream() + .collect(Collectors.toMap(w -> w.getAccidentTime() + w.getAccidentAddress(), w -> w)); + LocalDateTime accidentTime = NdDateUtils.date2LocalDateTime(outDangerTime); + String key = accidentTime + address; + // 只插入新增的 + if (!dangerMap.containsKey(key)) { + NdInsureOutDanger outDanger = new NdInsureOutDanger(); + outDanger.setCarPlate(carPlate); + outDanger.setInsureCompany(insureCompany); + outDanger.setAccidentTime(accidentTime); + + outDanger.setCompanyId(car.getCompanyId()); + CompanyDTO company = companiesCacheHelper.getById(car.getCompanyId()); + outDanger.setCompanyName(Objects.nonNull(company) ? company.getName() : StringUtils.EMPTY); + outDanger.setRegionId(car.getRegionId()); + + outDanger.setDeathToll(Double.valueOf(deathToll).intValue()); + outDanger.setInjuries(Double.valueOf(injuies).intValue()); + outDanger.setCompensateAmount(compensateAmount); + outDanger.setAccidentAddress(address); + outDangerService.save(outDanger); + log.info("准备插入 " + i + "条:" + JSON.toJSONString(outDanger)); + } + } + } + } + } + + public static Workbook readExcel(InputStream is, String extString){ + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if(".xls".equals(extString)){ + return wb = new HSSFWorkbook(is); + }else if(".xlsx".equals(extString)){ + return wb = new XSSFWorkbook(is); + }else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleOverspeedManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleOverspeedManage.java new file mode 100644 index 0000000..f92cef1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleOverspeedManage.java @@ -0,0 +1,189 @@ +package com.ningdatech.carapi.safe.manage; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedVehicle; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection; +import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo; +import com.ningdatech.carapi.safe.model.dto.OverspeedPageQuery; +import com.ningdatech.carapi.safe.model.po.NdVehicleOverspeedWaysectionPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedCompanyPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedVehiclePO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedCompanyVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedVehicleVO; +import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedWaysectionVO; +import com.ningdatech.carapi.safe.service.INdVehicleOverspeedCompanyService; +import com.ningdatech.carapi.safe.service.INdVehicleOverspeedVehicleService; +import com.ningdatech.carapi.safe.service.INdVehicleOverspeedWaysectionService; +import com.ningdatech.carapi.safe.service.IVehicleOverspeedInfoService; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author PoffyZhang + * @date 2022/10/19 上午11:18 + */ +@Component +@RequiredArgsConstructor +public class VehicleOverspeedManage { + + private final INdVehicleOverspeedCompanyService overspeedCompanyService; + private final INdVehicleOverspeedVehicleService overspeedVehicleService; + private final INdVehicleOverspeedWaysectionService overspeedWaysectionService; + private final RegionsCacheHelper regionsCacheHelper; + private final IVehicleOverspeedInfoService vehicleOverspeedInfoService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final CompaniesCacheHelper companiesCacheHelper; + + public PageVo queryCompanyOverspeed(OverspeedPageQuery overspeedPageQuery) { + + //以企业为维度 + Page page = overspeedPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆所在的所有企业 + List companyIds = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)) + .stream().map(NdVehicleBaseInfo::getCompanyId).collect(Collectors.toList()); + HashSet set = new HashSet<>(); + List companyIdList = companyIds.stream().filter(c -> set.add(c)).collect(Collectors.toList()); + // 过滤掉不在这些企业下的数据 + overspeedPageQuery.setCompanyIds(companyIdList); + } + vehicleOverspeedInfoService.pageGroupCompany(page, overspeedPageQuery); + Map> listMap = vehicleOverspeedInfoService.list(Wrappers.lambdaQuery(VehicleOverspeedInfo.class) + .isNotNull(VehicleOverspeedInfo::getCompanyName).isNotNull(VehicleOverspeedInfo::getOverspeedDate) + .select(VehicleOverspeedInfo::getOverspeedDate,VehicleOverspeedInfo::getCompanyId)) + .stream().collect(Collectors.groupingBy(VehicleOverspeedInfo::getCompanyId)); + List data = page.getRecords().stream().map(e -> { + NdVehicleOverspeedCompanyVO vo = new NdVehicleOverspeedCompanyVO(); + BeanUtil.copyProperties(e, vo); + CompanyDTO companyDto = companiesCacheHelper.getById(vo.getCompanyId()); + Long regionId = companyDto.getRegionId(); + String displayName = regionsCacheHelper.getDisplayName(regionId); + vo.setRegionId(regionId); + vo.setRegionName(displayName); + List infoList = listMap.get(e.getCompanyId()); + if (CollUtil.isNotEmpty(infoList)) { + Optional time = infoList.stream().map(VehicleOverspeedInfo::getOverspeedDate).max(LocalDateTime::compareTo); + if (time.isPresent()) { + LocalDateTime maxTime = time.get(); + Date date = NdDateUtils.localDateTime2Date(maxTime); + vo.setOverspeedDate(date); + } + } + return vo; + }).collect(Collectors.toList()); + return PageVo.of(data, page.getTotal()); + } + + public PageVo queryVihicleOverspeed(OverspeedPageQuery overspeedPageQuery) { + //以车辆为维度 + Page page = overspeedPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 获取运营商下的所有与车辆 + List vehicleBaseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = vehicleBaseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + // 过滤掉不在登录运营商下的车辆 + overspeedPageQuery.setCarPlateList(carPlateList); + } + vehicleOverspeedInfoService.pageGroupVehicle(page, overspeedPageQuery); + List data = CollUtils.convert(page.getRecords(), + e -> BeanUtil.copyProperties(e, NdVehicleOverspeedVehicleVO.class)); + return PageVo.of(data, page.getTotal()); + } + + public PageVo queryWaySectionOverspeed(OverspeedPageQuery overspeedPageQuery) { + //以路段分析为维度 + Page page = overspeedPageQuery.page(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 获取运营商下的所有与车辆 + List vehicleBaseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List carPlateList = vehicleBaseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + // 过滤掉不在登录运营商下的车辆 + overspeedPageQuery.setCarPlateList(carPlateList); + } + + vehicleOverspeedInfoService.pageGroupWaysection(page, overspeedPageQuery); + List data = CollUtils.convert(page.getRecords(), + e -> BeanUtil.copyProperties(e, NdVehicleOverspeedWaysectionVO.class)); + return PageVo.of(data, page.getTotal()); + } + + public void vehicleOverspeed(Page page, OverspeedPageQuery overspeedPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleOverspeedVehicle.class); + wrapper.ge(Objects.nonNull(overspeedPageQuery.getStartTime()), NdVehicleOverspeedVehicle::getOverspeedDate, overspeedPageQuery.getStartTime()) + .le(Objects.nonNull(overspeedPageQuery.getEndTime()), NdVehicleOverspeedVehicle::getOverspeedDate, overspeedPageQuery.getEndTime()) + .le(Objects.nonNull(overspeedPageQuery.getRank()), NdVehicleOverspeedVehicle::getRank, overspeedPageQuery.getRank()); + wrapper.orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleOverspeedVehicle::getRank); + overspeedVehicleService.page(page, wrapper); + } + + public void waysectionOverspeedSearch(Page page, OverspeedPageQuery overspeedPageQuery) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleOverspeedWaysection.class); + if (Objects.nonNull(overspeedPageQuery.getRegionId())) { + List regionIds = regionsCacheHelper.listChildRegionId(overspeedPageQuery.getRegionId()); + wrapper.in(CollUtil.isNotEmpty(regionIds), NdVehicleOverspeedWaysection::getRegionId, regionIds); + } + wrapper.ge(Objects.nonNull(overspeedPageQuery.getStartTime()), NdVehicleOverspeedWaysection::getOverspeedDate, overspeedPageQuery.getStartTime()) + .le(Objects.nonNull(overspeedPageQuery.getEndTime()), NdVehicleOverspeedWaysection::getOverspeedDate, overspeedPageQuery.getEndTime()) + .le(Objects.nonNull(overspeedPageQuery.getRank()), NdVehicleOverspeedWaysection::getRank, overspeedPageQuery.getRank()) + .like(StringUtils.isNotBlank(overspeedPageQuery.getWaySection()), NdVehicleOverspeedWaysection::getWaySection, overspeedPageQuery.getWaySection()) + .like(StringUtils.isNotBlank(overspeedPageQuery.getCarPlate()), NdVehicleOverspeedWaysection::getCarPlate, overspeedPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(overspeedPageQuery.getCompanyName()), NdVehicleOverspeedWaysection::getCompanyName, overspeedPageQuery.getCompanyName()); + wrapper.orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleOverspeedWaysection::getRank); + overspeedWaysectionService.page(page, wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleViolationManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleViolationManage.java new file mode 100644 index 0000000..d6b2e35 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/manage/VehicleViolationManage.java @@ -0,0 +1,188 @@ +package com.ningdatech.carapi.safe.manage; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.MissCertEnum; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.ViolationTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; +import com.ningdatech.carapi.safe.model.dto.ViolationPageQuery; +import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author PoffyZhang + * @date 2022/10/19 上午11:18 + */ +@Component +@RequiredArgsConstructor +public class VehicleViolationManage { + + private final INdVehicleViolationService vehicleViolationService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleBaseInfoService vehicleBaseInfoService; + + public PageVo query(ViolationPageQuery violationPageQuery) { + Page page = violationPageQuery.page(); + Integer pageNumber = violationPageQuery.getPageNumber(); + Integer pageSize = violationPageQuery.getPageSize(); + Integer violationType = violationPageQuery.getViolationType(); + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商ID + Long operatorId = operatorQueryDTO.getId(); + // 查询出该运营商下所有车辆所在的所有企业 + List baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getOperatorId, operatorId)); + List companyIds = baseInfoList.stream() + .map(NdVehicleBaseInfo::getCompanyId) + .collect(Collectors.toList()); + List carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList()); + HashSet set = new HashSet<>(); + List companyIdList = companyIds.stream().filter(c -> set.add(c)).collect(Collectors.toList()); + // 若为无证驾驶列表,过滤掉不在这些企业下的数据,否则根据车牌号筛选 + if (ViolationTypeEnum.MISS_CERT.getCode().equals(violationPageQuery.getViolationType())) { + violationPageQuery.setCompanyIds(companyIdList); + }else { + violationPageQuery.setCarPlateList(carPlateList); + } + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleViolation.class); + List violationList = ((VehicleViolationManage) AopContext.currentProxy()).commonSearch(page, wrapper, violationPageQuery); + // 对结果进行去重,并统计对应违章次数 + List data = removeDuplicate(violationList,violationType); + if (CollUtil.isEmpty(data)){ + return PageVo.empty(); + } + List records = data.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize) + .collect(Collectors.toList()); + List results = CollUtils.convert(records, e -> { + NdVehicleViolationVO vo = new NdVehicleViolationVO(); + BeanUtils.copyProperties(e,vo); + if(Objects.nonNull(vo.getViolationType())){ + vo.setViolationTypeName(ViolationTypeEnum.getDescByCode(vo.getViolationType())); + } + if(Objects.nonNull(vo.getMissingCertificateType())){ + vo.setMissingCertificateTypeName(MissCertEnum.getDescByCode(vo.getMissingCertificateType())); + } + CodeUtil.searchCompanyNameAndRegionName(vo); + return vo; + }); + return PageVo.of(results, records.size()); + } + + private List removeDuplicate(List violationList, Integer violationType) { + List data; + switch (violationType) { + // 无证驾驶 + case 1: + HashSet missCertSet = new HashSet<>(); + data = violationList.stream().filter(v -> + missCertSet.add(v.getDriverName() + v.getCarPlate() + + v.getViolationDate() + v.getMissingCertificateType())) + .collect(Collectors.toList()); + break; + // 闯红灯 + case 2: + HashSet redLightSet = new HashSet<>(); + data = violationList.stream().filter(v -> + redLightSet.add(v.getDriverName() + v.getCarPlate() + + v.getViolationDate() + v.getAddressRedLight())) + .collect(Collectors.toList()); + break; + // 超载 + case 3: + HashSet overLoadSet = new HashSet<>(); + data = violationList.stream().filter(v -> + overLoadSet.add(v.getDriverName() + v.getCarPlate() + + v.getViolationTimes() + v.getViolationDate())) + .collect(Collectors.toList()); + countViolationTimes(data); + break; + // 闯禁行路段 + case 4: + HashSet sectionSet = new HashSet<>(); + data = violationList.stream().filter(v -> + sectionSet.add(v.getDriverName() + v.getCarPlate() + + v.getWaySection() + v.getViolationTimes() + + v.getViolationDate())) + .collect(Collectors.toList()); + countViolationTimes(data); + break; + // 闯禁行时间 + case 5: + HashSet periodSet = new HashSet<>(); + data = violationList.stream().filter(v -> + periodSet.add(v.getDriverName() + v.getCarPlate() + + v.getViolationPeriod() + v.getViolationTimes())) + .collect(Collectors.toList()); + countViolationTimes(data); + break; + default: + throw new IllegalStateException("Unexpected value: " + violationType); + } + return data; + } + + private void countViolationTimes(List data) { + data.forEach(d -> { + String carPlate = d.getCarPlate(); + if (StringUtils.isNotBlank(carPlate)) { + List violations = data.stream() + .filter(c -> carPlate.equals(c.getCarPlate())) + .collect(Collectors.toList()); + d.setViolationTimes(violations.size()); + } + }); + } + + @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1) + public List commonSearch(Page page,LambdaQueryWrapper wrapper, ViolationPageQuery violationPageQuery) { + wrapper.ge(Objects.nonNull(violationPageQuery.getStartTime()), NdVehicleViolation::getViolationDate, violationPageQuery.getStartTime()) + .le(Objects.nonNull(violationPageQuery.getEndTime()), NdVehicleViolation::getViolationDate, violationPageQuery.getEndTime()) + .like(Objects.nonNull(violationPageQuery.getDriverName()), NdVehicleViolation::getDriverName, violationPageQuery.getDriverName()) + .like(StringUtils.isNotBlank(violationPageQuery.getCompanyName()), NdVehicleViolation::getCompanyName, violationPageQuery.getCompanyName()) + .like(Objects.nonNull(violationPageQuery.getIdCard()), NdVehicleViolation::getIdCard, violationPageQuery.getIdCard()) + .like(Objects.nonNull(violationPageQuery.getCarPlate()), NdVehicleViolation::getCarPlate, violationPageQuery.getCarPlate()) + .eq(Objects.nonNull(violationPageQuery.getViolationType()), NdVehicleViolation::getViolationType, violationPageQuery.getViolationType()) + // 过滤掉不在这些运营商下车辆关联企业下的数据 + .in(CollUtil.isNotEmpty(violationPageQuery.getCompanyIds()),NdVehicleViolation::getCompanyId,violationPageQuery.getCompanyIds()) + .in(CollUtil.isNotEmpty(violationPageQuery.getCarPlateList()),NdVehicleViolation::getCarPlate,violationPageQuery.getCarPlateList()) + .orderBy(Boolean.TRUE, Boolean.FALSE, NdVehicleViolation::getViolationDate); + + return vehicleViolationService.pageDataScope(page, wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.java new file mode 100644 index 0000000..c9190c1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.AlarmDataPicture; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface AlarmDataPictureMapper extends BaseMapper { + + /** + * 批量保存用sql + * @param list + * @return + */ + boolean saveBatchForSql(@Param("list") List list); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.xml new file mode 100644 index 0000000..07904c0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataPictureMapper.xml @@ -0,0 +1,50 @@ + + + + + + INSERT INTO nd_alarm_data_picture + (origin_pic_id, + vehicle_index_code, + vehicle_self_no, + camera_index_code, + camera_name, + upload_type, + alarm_id, + alarm_type, + alarm_type_name, + capture_time, + url, + thumb_url, + parent_pic_id, + face_rect, + pic_type, + plate_no, + region_index_code, + region_name + ) + values + + ( + #{item.originPicId}, + #{item.vehicleIndexCode}, + #{item.vehicleSelfNo}, + #{item.cameraIndexCode}, + #{item.cameraName}, + #{item.uploadType}, + #{item.alarmId}, + #{item.alarmType}, + #{item.alarmTypeName}, + #{item.captureTime}, + #{item.url}, + #{item.thumbUrl}, + #{item.parentPicId}, + #{item.faceRect}, + #{item.picType}, + #{item.plateNo}, + #{item.regionIndexCode}, + #{item.regionName} + ) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.java new file mode 100644 index 0000000..06dac8a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.AlarmDataVideo; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface AlarmDataVideoMapper extends BaseMapper { + /** + * 批量保存用sql + * @param list + * @return + */ + boolean saveBatchForSql(List list); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.xml new file mode 100644 index 0000000..710d885 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/AlarmDataVideoMapper.xml @@ -0,0 +1,56 @@ + + + + + + INSERT INTO nd_alarm_data_video + (orgin_video_id, + vehicle_index_code, + plate_no, + vehicle_self_no, + region_index_code, + region_name, + camera_index_code, + camera_name, + service_index_code, + begin_time, + end_time, + stream_begin_time, + stream_end_time, + video_length, + alarm_id, + alarm_time, + alarm_type, + alarm_type_name, + record_index_code, + url, + cover_url + ) + values + + ( + #{item.orginVideoId}, + #{item.vehicleIndexCode}, + #{item.plateNo}, + #{item.vehicleSelfNo}, + #{item.regionIndexCode}, + #{item.regionName}, + #{item.cameraIndexCode}, + #{item.cameraName}, + #{item.serviceIndexCode}, + #{item.beginTime}, + #{item.endTime}, + #{item.streamBeginTime}, + #{item.streamEndTime}, + #{item.videoLength}, + #{item.alarmId}, + #{item.alarmTime}, + #{item.alarmType}, + #{item.alarmTypeName}, + #{item.recordIndexCode}, + #{item.url}, + #{item.coverUrl} + ) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureInfoMapper.java new file mode 100644 index 0000000..51d119f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdInsureInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.java new file mode 100644 index 0000000..75e9939 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.entity.NdInsureOutDangerAnalysis; +import com.ningdatech.carapi.safe.model.dto.InsurePageQuery; +import com.ningdatech.carapi.safe.model.po.NdInsureOutDangerAnalysisPO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdInsureOutDangerAnalysisMapper extends BaseMapper { + + Page pageAnalysis(Page page, @Param("po") InsurePageQuery param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.xml new file mode 100644 index 0000000..4983a0a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerAnalysisMapper.xml @@ -0,0 +1,45 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.java new file mode 100644 index 0000000..0e8c7c3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdInsureOutDangerMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.xml new file mode 100644 index 0000000..2a38695 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdInsureOutDangerMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawCertificateVerificationMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawCertificateVerificationMapper.java new file mode 100644 index 0000000..a9c4fa3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawCertificateVerificationMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdLawCertificateVerification; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdLawCertificateVerificationMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawEquipmentInstallMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawEquipmentInstallMapper.java new file mode 100644 index 0000000..0fd9386 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdLawEquipmentInstallMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdLawEquipmentInstall; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdLawEquipmentInstallMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCommitmentMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCommitmentMapper.java new file mode 100644 index 0000000..06b8f1d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCommitmentMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdSafetyCommitment; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdSafetyCommitmentMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCreditMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCreditMapper.java new file mode 100644 index 0000000..c31f3db --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSafetyCreditMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdSafetyCredit; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdSafetyCreditMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.java new file mode 100644 index 0000000..ba1f715 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdSecurityAdvisory; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdSecurityAdvisoryMapper extends BaseMapper { + + int incrementDownCount(Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.xml new file mode 100644 index 0000000..e6e4056 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdSecurityAdvisoryMapper.xml @@ -0,0 +1,9 @@ + + + + + update nd_security_advisory set download_times = download_times + 1 where id = #{id} + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.java new file mode 100644 index 0000000..99acf80 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentAnalysis; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleAccidentAnalysisMapper extends BaseMapper { + + Page pageAnalysis(Page page, + @Param("param") AccidentPageQuery accidentPageQuery); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.xml new file mode 100644 index 0000000..060df1e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentAnalysisMapper.xml @@ -0,0 +1,102 @@ + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.java new file mode 100644 index 0000000..5086b20 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleAccidentDeadMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.xml new file mode 100644 index 0000000..90efd85 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentDeadMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentMapper.java new file mode 100644 index 0000000..e0f2b9a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleAccidentMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleAccidentMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.java new file mode 100644 index 0000000..d01b444 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleOverspeedCompanyMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.xml new file mode 100644 index 0000000..4a2a714 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedCompanyMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedVehicleMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedVehicleMapper.java new file mode 100644 index 0000000..2e71e47 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedVehicleMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedVehicle; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleOverspeedVehicleMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedWaysectionMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedWaysectionMapper.java new file mode 100644 index 0000000..61b6db8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleOverspeedWaysectionMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleOverspeedWaysectionMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleViolationMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleViolationMapper.java new file mode 100644 index 0000000..a09874d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/NdVehicleViolationMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface NdVehicleViolationMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.java new file mode 100644 index 0000000..a95d726 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.java @@ -0,0 +1,26 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.safe.model.po.*; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Classname SecurityManageDataScreenMapper + * @Description + * @Date 2022/10/26 15:03 + * @Created by PoffyZhang + */ +public interface SecurityManageDataScreenMapper { + + List getOutDangerAnalysis(@Param("param") DataScreenParam param); + + List getOverspeedAnalysis(@Param("param") DataScreenParam param); + + OutDangerPeriodTimePO getOutDangerPeriodTime(@Param("param") DataScreenParam param); + + List getOverSpeedCurrentMonth(@Param("param") DataScreenParam param); + + List getOutDangerRegions(@Param("param") DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.xml new file mode 100644 index 0000000..058db56 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/SecurityManageDataScreenMapper.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.java new file mode 100644 index 0000000..21b8083 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.ningdatech.carapi.safe.entity.VehicleAccidentReport; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2022-12-26 + */ +public interface VehicleAccidentReportMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.xml new file mode 100644 index 0000000..3917f5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleAccidentReportMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.java new file mode 100644 index 0000000..d5964cf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.safe.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedCompany; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection; +import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo; +import com.ningdatech.carapi.safe.model.dto.OverspeedPageQuery; +import com.ningdatech.carapi.safe.model.po.NdVehicleOverspeedWaysectionPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedCompanyPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedVehiclePO; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 车辆超速信息表 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +public interface VehicleOverspeedInfoMapper extends BaseMapper { + + Long countDailyToll(@Param("regionIds") List regionIds, @Param("startTime") LocalDateTime todayStart, + @Param("endTime") LocalDateTime todayEnd); + + Page pageGroupCompany(Page page, + @Param("ov") OverspeedPageQuery overspeedPageQuery); + + Page pageGroupVehicle(Page page, + @Param("ov") OverspeedPageQuery overspeedPageQuery); + + Page pageGroupWaysection(Page page, + @Param("ov") OverspeedPageQuery overspeedPageQuery); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.xml new file mode 100644 index 0000000..7352d16 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/mapper/VehicleOverspeedInfoMapper.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentAuditDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentAuditDTO.java new file mode 100644 index 0000000..d6a85a2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentAuditDTO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.safe.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author CMM + * @since 2022/12/26 18:23 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AccidentAuditDTO", description = "事故审核") +public class AccidentAuditDTO { + + @ApiModelProperty("id") + @NotNull(message = "请传入审核记录id!") + private Long id; + + @ApiModelProperty("审核结果") + @NotNull(message = "审核结果不能为空!") + private Integer auditStatus; + + @ApiModelProperty("审核意见") + @NotBlank(message = "审核意见不能为空!") + @Length(max = 200) + private String auditOpinion; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentPageQuery.java new file mode 100644 index 0000000..e2e8547 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/AccidentPageQuery.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.safe.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 事故管理 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "AccidentPageQuery", description = "事故管理") +public class AccidentPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 开始时间 + */ + @ApiModelProperty("开始时间") + private String startTime; + + /** + * 结束时间 + */ + @ApiModelProperty("结束时间") + private String endTime; + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + /** + * 区域ID集合 + */ + private List regionIds; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + /** + * 车牌号集合 + */ + @ApiModelProperty("车牌号集合") + private List carPlateList; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 车辆类型 + */ + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + /** + * 审核状态 + */ + @ApiModelProperty(notes = "审核状态",allowableValues = "0 待审核, 1 审核通过, 2 审核不通过") + private Integer auditStatus; + + /** + * 上报状态 + */ + @ApiModelProperty(notes = "上报状态",allowableValues = "0 未上报, 1 已上报") + private Integer reportStatus; + + @ApiModelProperty(notes = "事故类型") + private Integer accidentType; + + + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/InsurePageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/InsurePageQuery.java new file mode 100644 index 0000000..014dc8a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/InsurePageQuery.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.safe.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 保险管理 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "InsurePageQuery", description = "保险管理") +public class InsurePageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 起包开始时间 + */ + @ApiModelProperty("起包开始时间") + private String qibaoStartTime; + + /** + * 起包结束时间 + */ + @ApiModelProperty("起包结束时间") + private String qibaoEndTime; + + /** + * 到期开始时间 + */ + @ApiModelProperty("到期开始时间") + private String daoqiStartTime; + + /** + * 到期结束时间 + */ + @ApiModelProperty("到期结束时间") + private String daoqiEndTime; + + /** + * 开始时间 + */ + @ApiModelProperty("开始时间") + private String startTime; + + /** + * 结束时间 + */ + @ApiModelProperty("结束时间") + private String endTime; + + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + @ApiModelProperty("区域IDs") + private List regionIds; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 出险次数排名 + */ + @ApiModelProperty("出险次数排名") + private Integer outDangerRank; + + /** + * 上报状态 + */ + @ApiModelProperty(value = "上报状态",allowableValues = "0 未上报,1 已上报") + private Integer reportStatus; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LawEnforcementPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LawEnforcementPageQuery.java new file mode 100644 index 0000000..493a1d4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LawEnforcementPageQuery.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.safe.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 行政执法query + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "LawEnforcementPageQuery", description = "行政执法query") +public class LawEnforcementPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 开始时间 + */ + @ApiModelProperty("开始时间") + private String startTime; + + /** + * 结束时间 + */ + @ApiModelProperty("结束时间") + private String endTime; + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 驾驶员名 + */ + @ApiModelProperty("驾驶员名") + private String driverName; + + /** + * 设备名 + */ + @ApiModelProperty("设备名") + private String equipmentName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LongitudeLatitudeDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LongitudeLatitudeDTO.java new file mode 100644 index 0000000..600fa28 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/LongitudeLatitudeDTO.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.safe.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Classname LongitudeLatitudeDTO + * @Description + * @Date 2022/10/27 11:19 + * @Created by PoffyZhang + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "LongitudeLatitudeDTO", description = "经纬度") +public class LongitudeLatitudeDTO { + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdInsureOutDangerImportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdInsureOutDangerImportDTO.java new file mode 100644 index 0000000..1e607ac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdInsureOutDangerImportDTO.java @@ -0,0 +1,117 @@ +package com.ningdatech.carapi.safe.model.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdInsureOutDangerImportDTO", description = "安全管理-保险管理-出险信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureOutDangerImportDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + @ExcelProperty("id") + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @ExcelProperty("事故时间") + private LocalDateTime accidentTime; + + /** + * 事故地点 + */ + @ApiModelProperty("事故地点") + @ExcelProperty("事故地点") + private String accidentAddress; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @ExcelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + @ExcelProperty("区域名") + private String regionName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @ExcelProperty("企业名") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + @ExcelProperty("企业ID") + private Long companyId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String carPlate; + + /** + * 保险公司 + */ + @ApiModelProperty("保险公司") + @ExcelProperty("保险公司") + private String insureCompany; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + @ExcelProperty("受伤人数") + private Integer injuries; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + @ExcelProperty("死亡人数") + private Integer deathToll; + + /** + * 理赔金额 + */ + @ApiModelProperty("理赔金额") + @ExcelProperty("理赔金额") + private BigDecimal compensateAmount; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdVehicleAccidentDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdVehicleAccidentDTO.java new file mode 100644 index 0000000..bad5cd2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/NdVehicleAccidentDTO.java @@ -0,0 +1,118 @@ +package com.ningdatech.carapi.safe.model.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleAccidentDTO", description = "安全管理-事故管理-车辆事故") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + private String accidentTime; + + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + + /** + * 车辆类型名 + */ + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 事故地址 + */ + @ApiModelProperty("事故地址") + private String accidentAddress; + + /** + * 上报状态名称 + */ + @ApiModelProperty("上报状态名称") + private String reportStatusName; + + /** + * 事故类型名称 + */ + @ApiModelProperty("事故类型名称") + private String accidentTypeName; + + /** + * 伤人数 + */ + @ApiModelProperty("伤人数") + private Integer injuries; + + /** + * 亡人数 + */ + @ApiModelProperty("亡人数") + private Integer deathToll; + + /** + * 简要案情 + */ + @ApiModelProperty("简要案情") + private String briefCase; + + /** + * 事故编号 + */ + @ApiModelProperty("事故编号") + private String accidentNo; + + /** + * 事故责任认定书认定内容 + */ + @ApiModelProperty("事故责任认定书认定内容") + private String firmContent; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/OverspeedPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/OverspeedPageQuery.java new file mode 100644 index 0000000..6c1a68f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/OverspeedPageQuery.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.safe.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 超速管理 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "OverspeedPageQuery", description = "超速管理") +public class OverspeedPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 开始时间 + */ + @ApiModelProperty("开始时间") + private String startTime; + + /** + * 结束时间 + */ + @ApiModelProperty("结束时间") + private String endTime; + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + private List regionIds; + + /** + * 排名 + */ + @ApiModelProperty("排名") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + /** + * 企业ID列表 + */ + @ApiModelProperty("企业列表") + private List companyIds; + + /** + * 车辆 车牌号 + */ + @ApiModelProperty("车辆 车牌号") + private String carPlate; + /** + * 车辆 车牌号列表 + */ + @ApiModelProperty("车辆 车牌号列表") + private List carPlateList; + + /** + * 路段名 + */ + @ApiModelProperty("路段名") + private String waySection; + + private String dataScopeSql; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityAdvisoryPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityAdvisoryPageQuery.java new file mode 100644 index 0000000..8ca8697 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityAdvisoryPageQuery.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.safe.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 安全通报query + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "SecurityAdvisoryPageQuery", description = "安全通报query") +public class SecurityAdvisoryPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 通报年月 + */ + @ApiModelProperty("通报年月") + private LocalDateTime advisoryDate; + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityHonestyPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityHonestyPageQuery.java new file mode 100644 index 0000000..bd56cb1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/SecurityHonestyPageQuery.java @@ -0,0 +1,43 @@ +package com.ningdatech.carapi.safe.model.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 实体类 + * 安全诚信q + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "SecurityHonestyPageQuery", description = "安全诚信query") +public class SecurityHonestyPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 所属企业 + */ + @ApiModelProperty("所属企业") + private String companyName; + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportDTO.java new file mode 100644 index 0000000..a945b48 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportDTO.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.safe.model.dto; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * @author CMM + * @since 2022/12/26 15:28 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "VehicleAccidentReportDTO", description = "车辆事故上报信息保存") +public class VehicleAccidentReportDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + private Long id; + + @ApiModelProperty("车牌号") + @NotBlank(message = "请输入车牌号!") + private String carPlate; + + @ApiModelProperty("事故驾驶员") + @NotBlank(message = "请输入驾驶员姓名!") + private String accidentDriver; + + @ApiModelProperty("事故日期") + @NotNull(message = "请输入事故发生时间!") + private LocalDateTime accidentTime; + + @ApiModelProperty("事故地点") + @NotBlank(message = "请填写事故地点!") + @Length(max = 100) + private String accidentAddress; + + @ApiModelProperty("受伤人数") + @NotNull(message = "请填写受伤人数!") + @Range(min = 0,max = 100) + private Integer injuries; + + @ApiModelProperty("死亡人数") + @NotNull(message = "请填写死亡人数!") + @Range(min = 0,max = 100) + private Integer deathToll; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportQueryDTO.java new file mode 100644 index 0000000..34a71a0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/VehicleAccidentReportQueryDTO.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.safe.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author CMM + * @since 2022/12/26 15:25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +public class VehicleAccidentReportQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("最后修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("最后修改人") + private Long updateBy; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("地区名") + private String regionName; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("事故日期") + private LocalDateTime accidentTime; + + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + @ApiModelProperty("企业名") + private String companyName; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("事故地点") + private String accidentAddress; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("纬度") + private String latitude; + + @ApiModelProperty("出险id 关联赔付信息") + private Long insureOutId; + + @ApiModelProperty("受伤人数") + private Integer injuries; + + @ApiModelProperty("死亡人数") + private Integer deathToll; + + @ApiModelProperty("驾驶员ID") + private Long driverId; + + @ApiModelProperty("保险ID") + private Long insureId; + + @ApiModelProperty("审核状态 0:待审核,1:审核通过,2:审核不通过") + private Integer auditStatus; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/ViolationPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/ViolationPageQuery.java new file mode 100644 index 0000000..9cdcb71 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/dto/ViolationPageQuery.java @@ -0,0 +1,91 @@ +package com.ningdatech.carapi.safe.model.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 违章管理 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "ViolationPageQuery", description = "违章管理") +public class ViolationPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 开始时间 + */ + @ApiModelProperty("开始时间") + private String startTime; + + /** + * 结束时间 + */ + @ApiModelProperty("结束时间") + private String endTime; + + /** + * 区域code 拼接 code,level + */ + @ApiModelProperty("区域id") + private Long regionId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业ID集合 + */ + @ApiModelProperty("企业ID集合") + private List companyIds; + + /** + * 车辆 车牌号 + */ + @ApiModelProperty("车辆 车牌号") + private String carPlate; + /** + * 车辆 车牌号集合 + */ + @ApiModelProperty("车辆 车牌号集合") + private List carPlateList; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + private String idCard; + + /** + * 驾驶员名字 + */ + @ApiModelProperty("驾驶员名字") + private String driverName; + + /** + * 违章类型 + */ + @ApiModelProperty("违章类型 1.无证驾驶 2.闯红灯 3.超载 4.违规路段行驶 5.违规时间行驶") + private Integer violationType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdInsureOutDangerAnalysisPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdInsureOutDangerAnalysisPO.java new file mode 100644 index 0000000..54e9479 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdInsureOutDangerAnalysisPO.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.safe.model.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdInsureOutDangerAnalysisPO", description = "安全管理-保险管理-出险分析") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureOutDangerAnalysisPO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 出险次数 + */ + @ApiModelProperty("出险次数") + private Integer outDangerTimes; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + private String accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + private Integer injuries; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + private Integer deathToll; + + private Integer rank; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdVehicleOverspeedWaysectionPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdVehicleOverspeedWaysectionPO.java new file mode 100644 index 0000000..aff1a39 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/NdVehicleOverspeedWaysectionPO.java @@ -0,0 +1,105 @@ +package com.ningdatech.carapi.safe.model.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleOverspeedWaysectionPO", description = "安全管理-超速管理-超速路段") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedWaysectionPO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + private Integer overspeedTimes; + + /** + * 路段名字 + */ + @ApiModelProperty("路段名字") + private String waySection; + + /** + * 排名 + */ + @ApiModelProperty("排名") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业id + */ + @ApiModelProperty("企业id") + private Long companyId; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域ID + */ + @ApiModelProperty("区域") + private String regionName; + + @ApiModelProperty("开始路段") + private String waySectionStart; + + @ApiModelProperty("结束路段") + private String waySectionEnd; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerAnalysisPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerAnalysisPO.java new file mode 100644 index 0000000..e31dc72 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerAnalysisPO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.safe.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author PoffyZhang + * @date 2022/10/25 + */ +@Data +@ApiModel("统计次数PO") +public class OutDangerAnalysisPO { + + @ApiModelProperty("出险次数") + private Integer outDangerTimes; + + @ApiModelProperty("受伤人数") + private Integer injuries; + + @ApiModelProperty("死亡人数") + private Integer deathToll; + + @ApiModelProperty("年份") + private String year; + + @ApiModelProperty("月份") + private String month; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerCityPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerCityPO.java new file mode 100644 index 0000000..b7b014e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerCityPO.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.safe.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/25 + */ +@Data +@ApiModel("城市出险PO") +public class OutDangerCityPO { + + @ApiModelProperty("城市名") + private String regionName; + + @ApiModelProperty("地区CODE") + private String regionCode; + + @ApiModelProperty("地区ID") + private Long regionId; + + @ApiModelProperty("前年出险次数") + private Integer beforeOutDanger; + + @ApiModelProperty("去年出险次数") + private Integer lastOutDanger; + + @ApiModelProperty("前年出险次数") + private Integer currentOutDanger; + + @ApiModelProperty("总数") + private Integer total; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerPeriodTimePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerPeriodTimePO.java new file mode 100644 index 0000000..a16df6d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OutDangerPeriodTimePO.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.safe.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/25 + */ +@Data +@ApiModel("时间段出险次数PO") +public class OutDangerPeriodTimePO { + + @ApiModelProperty("第一时间段出险次数") + private Integer firstPeriodTime; + + @ApiModelProperty("第二时间段") + private Integer secondPeriodTime; + + @ApiModelProperty("第三时间段") + private Integer thirdPeriodTime; + + @ApiModelProperty("第四时间段") + private Integer fourthPeriodTime; + + @ApiModelProperty("第五时间段") + private Integer fifthPeriodTime; + + @ApiModelProperty("第六时间段") + private Integer sixthPeriodTime; + + @ApiModelProperty("第七时间段") + private Integer seventhPeriodTime; + + @ApiModelProperty("第八时间段") + private Integer eighthPeriodTime; + + @ApiModelProperty("第九时间段") + private Integer ninthPeriodTime; + + @ApiModelProperty("第十时间段") + private Integer tenthPeriodTime; + + @ApiModelProperty("第十一时间段") + private Integer eleventhPeriodTime; + + @ApiModelProperty("最后时间段") + private Integer lastPeriodTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedAnalysisPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedAnalysisPO.java new file mode 100644 index 0000000..47cddfd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedAnalysisPO.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.safe.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/11/17 + */ +@Data +@ApiModel("统计超速次数PO") +public class OverspeedAnalysisPO { + + @ApiModelProperty("超速次数") + private Integer times; + + @ApiModelProperty("年份") + private String year; + + @ApiModelProperty("月份") + private String month; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedTimesPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedTimesPO.java new file mode 100644 index 0000000..9564f3f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/OverspeedTimesPO.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.safe.model.po; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @date 2022/10/25 + */ +@Data +@ApiModel("超速次数PO") +public class OverspeedTimesPO { + + @ApiModelProperty("月份日期") + private String monthDay; + + @ApiModelProperty("超速次数") + private Integer overspeedTimes; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedCompanyPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedCompanyPO.java new file mode 100644 index 0000000..9f8cd87 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedCompanyPO.java @@ -0,0 +1,104 @@ +package com.ningdatech.carapi.safe.model.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "VehicleOverspeedCompanyPO", description = "安全管理-超速管理-企业超速") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleOverspeedCompanyPO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @TableField(value = "overspeed_date") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + @TableField(value = "overspeed_times") + private Integer overspeedTimes; + + /** + * 最高速率 + */ + @ApiModelProperty("最高速率") + @TableField(value = "max_speed") + private Double maxSpeed; + + /** + * 排名 + */ + @ApiModelProperty("排名") + @TableField(value = "rank") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业id") + @TableField(value = "company_id") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + @TableField(value = "city") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + @TableField(value = "distinguish") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedVehiclePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedVehiclePO.java new file mode 100644 index 0000000..24f52d3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/po/VehicleOverspeedVehiclePO.java @@ -0,0 +1,104 @@ +package com.ningdatech.carapi.safe.model.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author CMM + * @description + * @since 2022/11/18 15:50 + */ +@Data +@ApiModel(value = "VehicleOverspeedVehiclePO", description = "安全管理-超速管理-车辆超速") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class VehicleOverspeedVehiclePO extends BaseEntity implements Serializable { + + + private static final long serialVersionUID = 970486512217363874L; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @TableField(value = "overspeed_date") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + @TableField(value = "overspeed_times") + private Integer overspeedTimes; + + /** + * 最高速率 + */ + @ApiModelProperty("最高速率") + @TableField(value = "max_speed") + private Double maxSpeed; + + /** + * 排名 + */ + @ApiModelProperty("排名") + @TableField(value = "rank") + private Integer rank; + + /** + * 企业id + */ + @ApiModelProperty("企业id") + @TableField(value = "company_id") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + @TableField(value = "company_name") + private String companyName; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + @TableField(value = "city") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + @TableField(value = "distinguish") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + @TableField(value = "region_id") + private Long regionId; + private String regionName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @TableField(value = "car_plate") + private String carPlate ; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawCertificateVerificationVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawCertificateVerificationVO.java new file mode 100644 index 0000000..3dbb579 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawCertificateVerificationVO.java @@ -0,0 +1,128 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdLawCertificateVerification", description = "安全管理-行政执法-证件核查") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class LawCertificateVerificationVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private Long driverId; + + /** + * 驾驶员名字 + */ + @ApiModelProperty("驾驶员名字") + private String driverName; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + private String idCard; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 检查日期 + */ + @ApiModelProperty("检查日期") + private LocalDateTime checkDate; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 是否有驾驶证 + */ + @ApiModelProperty("是否有驾驶证 0没有 1有") + private Integer haveDriverLicense; + + /** + * 是否有行驶证 + */ + @ApiModelProperty("是否有行驶证 0没有 1有") + private Integer haveDrivingLicense; + + /** + * 检查地址 + */ + @ApiModelProperty("检查地址") + private String checkAddress; + + /** + * 检查人员 + */ + @ApiModelProperty("检查人员") + private String inspectors; + + /** + * 处理结束 + */ + @ApiModelProperty("处理结束") + private String processResult; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String remark; + + /** + * 区域id + */ + @ApiModelProperty("区域id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawEquipmentInstallVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawEquipmentInstallVO.java new file mode 100644 index 0000000..f2443c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/LawEquipmentInstallVO.java @@ -0,0 +1,122 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "LawEquipmentInstallVO", description = "安全管理-行政执法-设备安装") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class LawEquipmentInstallVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private Long driverId; + + /** + * 驾驶员名字 + */ + @ApiModelProperty("驾驶员名字") + private String driverName; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + private String idCard; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 检查日期 + */ + @ApiModelProperty("检查日期") + private LocalDateTime checkDate; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 设备名字 + */ + @ApiModelProperty("设备名字") + private String equipmentName; + + /** + * 检查地址 + */ + @ApiModelProperty("检查地址") + private String checkAddress; + + /** + * 检查人员 + */ + @ApiModelProperty("检查人员") + private String inspectors; + + /** + * 处理结束 + */ + @ApiModelProperty("处理结束") + private String processResult; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String remark; + + /** + * 区域id + */ + @ApiModelProperty("区域id") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureInfoVO.java new file mode 100644 index 0000000..e53d5bf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureInfoVO.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdInsureInfoVO", description = "安全管理-保险管理-承保信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureInfoVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 起包时间 + */ + @ApiModelProperty("起包时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime insureTimeStart; + + /** + * 到期时间 + */ + @ApiModelProperty("到期时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime insureTimeEnd; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 保险公司 + */ + @ApiModelProperty("保险公司") + private String insureCompany; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerAnalysisVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerAnalysisVO.java new file mode 100644 index 0000000..feb581a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerAnalysisVO.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdInsureOutDangerAnalysisVO", description = "安全管理-保险管理-出险分析") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureOutDangerAnalysisVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 出险次数 + */ + @ApiModelProperty("出险次数") + private Integer outDangerTimes; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + private String accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + private Integer injuries; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + private Integer deathToll; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerVO.java new file mode 100644 index 0000000..c835085 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdInsureOutDangerVO.java @@ -0,0 +1,122 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@TableName("nd_insure_out_danger") +@ApiModel(value = "NdInsureOutDangerVO", description = "安全管理-保险管理-出险信息") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdInsureOutDangerVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime accidentTime; + + /** + * 事故地点 + */ + @ApiModelProperty("事故地点") + private String accidentAddress; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 保险公司 + */ + @ApiModelProperty("保险公司") + private String insureCompany; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + private Integer injuries; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + private Integer deathToll; + + /** + * 理赔金额 + */ + @ApiModelProperty("理赔金额") + private BigDecimal compensateAmount; + + /** + * 上报状态 + */ + @ApiModelProperty("上报状态") + private Integer reportStatus; + + /** + * 上报状态名称 + */ + @ApiModelProperty("上报状态名称") + private String reportStatusName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCommitmentVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCommitmentVO.java new file mode 100644 index 0000000..5cf8377 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCommitmentVO.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdSafetyCommitment", description = "安全管理-安全承诺") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdSafetyCommitmentVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 公司ID + */ + @ApiModelProperty("公司ID") + private Long companyId; + + /** + * 公司名 + */ + @ApiModelProperty("公司名") + private String companyName; + + /** + * 公司地址 + */ + @ApiModelProperty("公司地址") + private String companyAddress; + + /** + * 法人代表 + */ + @ApiModelProperty("法人代表") + private String legalPerson; + + /** + * 向社会承诺 + */ + @ApiModelProperty("向社会承诺") + private Integer commitmentsToSocial = 0; + + /** + * 向员工承诺 + */ + @ApiModelProperty("向员工承诺") + private Integer commitmentsToEmployee = 0; + + /** + * 总经理承诺 + */ + @ApiModelProperty("总经理承诺") + private Integer generalManagercommitment = 0; + + /** + * 分管总承诺 + */ + @ApiModelProperty("分管总承诺") + private Integer leaderInChargeCommitment = 0; + + /** + * 车队长承诺 + */ + @ApiModelProperty("车队长承诺") + private Integer teamLeaderCommitment = 0; + + /** + * 驾驶员承诺 + */ + @ApiModelProperty("驾驶员承诺") + private Integer driverCommitment = 0; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCreditVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCreditVO.java new file mode 100644 index 0000000..bc586c6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSafetyCreditVO.java @@ -0,0 +1,137 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdSafetyCredit", description = "安全管理-安全信用") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdSafetyCreditVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 公司ID + */ + @ApiModelProperty("公司ID") + private Long companyId; + + /** + * 公司名 + */ + @ApiModelProperty("公司名") + private String companyName; + + /** + * 公司地址 + */ + @ApiModelProperty("公司地址") + private String companyAddress; + + /** + * 法人代表 + */ + @ApiModelProperty("法人代表") + private String legalPerson; + + /** + * 死亡事故数量 + */ + @ApiModelProperty("死亡事故数量") + private Integer fatalAccidentsNum; + + /** + * 安全整治记录 + */ + @ApiModelProperty("安全整治记录") + private String safetyRectificationRecord; + + /** + * 执行监督指令 + */ + @ApiModelProperty("执行监督指令") + private String executeSupervisionInstructions; + + /** + * 执行安全处罚 + */ + @ApiModelProperty("执行安全处罚") + private String implementSafetyPunishment; + + /** + * 报送安全报表 + */ + @ApiModelProperty("报送安全报表") + private String submitSafetyReport; + + /** + * 制定救援预案 + */ + @ApiModelProperty("制定救援预案") + private String formulateRescuePlan; + + /** + * 安全教育培训 + */ + @ApiModelProperty("安全教育培训") + private String safetyEducationTraining; + + /** + * 瞒报事故 + */ + @ApiModelProperty("瞒报事故") + private String concealingAccidents; + + /** + * 无证生产 + */ + @ApiModelProperty("无证生产") + private String productionNoCertificate; + + /** + * 无证驾驶 + */ + @ApiModelProperty("无证驾驶") + private String drivingNoLicense; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSecurityAdvisoryVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSecurityAdvisoryVO.java new file mode 100644 index 0000000..11667f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdSecurityAdvisoryVO.java @@ -0,0 +1,80 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdSecurityAdvisory", description = "安全管理-安全通报") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdSecurityAdvisoryVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 通报日期 + */ + @ApiModelProperty("通报日期") + private LocalDateTime advisoryDate; + + /** + * 通报文件名 + */ + @ApiModelProperty("通报文件名") + private String advisoryFileName; + + /** + * 通报文件url + */ + @ApiModelProperty("通报文件url") + private String advisoryFileUrl; + + /** + * 通报次数 + */ + @ApiModelProperty("通报次数") + private Integer downloadTimes; + + /** + * 文件Id + */ + @ApiModelProperty("文件ID") + private Long fileId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentAnalysisVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentAnalysisVO.java new file mode 100644 index 0000000..ff2136c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentAnalysisVO.java @@ -0,0 +1,82 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleAccidentAnalysisVO", description = "安全管理-事故管理-事故分析") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentAnalysisVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private String driverId; + + /** + * 经纬度 + */ + @ApiModelProperty("经纬度") + private String longitudeLatitude; + + /** + * 事故地点 + */ + @ApiModelProperty("事故地点") + private String accidentAddress; + + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentDeadVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentDeadVO.java new file mode 100644 index 0000000..abf8764 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentDeadVO.java @@ -0,0 +1,119 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleAccidentDeadVO", description = "安全管理-事故管理-死亡事故") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentDeadVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private String driverId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 事故地址 + */ + @ApiModelProperty("事故地址") + private String accidentAddress; + + @ApiModelProperty("死亡人数") + private Long deathToll; + + /** + * 上报状态 + */ + @ApiModelProperty("上报状态") + private Integer reportStatus; + + /** + * 上报状态名称 + */ + @ApiModelProperty("上报状态名称") + private String reportStatusName; + + /** + * 简要案情 + */ + @ApiModelProperty("简要案情") + private String briefCase; + + /** + * 事故责任认定书认定内容 + */ + @ApiModelProperty("事故责任认定书认定内容") + private String firmContent; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentReportVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentReportVO.java new file mode 100644 index 0000000..b0c35a4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentReportVO.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.safe.model.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * @author CMM + * @since 2022/12/26 13:47 + */ +@Data +@ApiModel(value = "NdVehicleAccidentReportVO", description = "安全管理-事故管理-事故上报") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentReportVO extends BaseEntity implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 事故车辆 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private String driverId; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + /** + * 事故日期 + */ + @ApiModelProperty("事故时间") + private LocalDateTime accidentTime; + + /** + * 事故地址 + */ + @ApiModelProperty("事故地址") + private String accidentAddress; + + /** + * 死亡人数 + */ + @ApiModelProperty("死亡人数") + private Long deathToll; + + /** + * 受伤人数 + */ + @ApiModelProperty("受伤人数") + private Long injuries; + + /** + * 审核状态 + */ + @ApiModelProperty(notes = "审核状态",allowableValues = "0 待审核, 1 审核通过, 2 审核不通过") + private Integer auditStatus; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentVO.java new file mode 100644 index 0000000..2d35321 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleAccidentVO.java @@ -0,0 +1,160 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleAccidentVO", description = "安全管理-事故管理-车辆事故") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleAccidentVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 事故时间 + */ + @ApiModelProperty("事故时间") + private LocalDateTime accidentTime; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private String driverId; + + /** + * 事故驾驶员 + */ + @ApiModelProperty("事故驾驶员") + private String accidentDriver; + + /** + * 车辆类型 + */ + @ApiModelProperty("车辆类型") + private Integer vehicleType; + + /** + * 车辆类型名 + */ + @ApiModelProperty("车辆类型名") + private String vehicleTypeName; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业ID + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 事故地址 + */ + @ApiModelProperty("事故地址") + private String accidentAddress; + + /** + * 上报状态 + */ + @ApiModelProperty("上报状态") + private Integer reportStatus; + + /** + * 上报状态名称 + */ + @ApiModelProperty("上报状态名称") + private String reportStatusName; + + /** + * 事故类型 + */ + @ApiModelProperty("事故类型") + private Integer accidentType; + + /** + * 事故类型名称 + */ + @ApiModelProperty("事故类型名称") + private String accidentTypeName; + + /** + * 伤人数 + */ + @ApiModelProperty("伤人数") + private Integer injuries; + + /** + * 亡人数 + */ + @ApiModelProperty("亡人数") + private Integer deathToll; + + /** + * 简要案情 + */ + @ApiModelProperty("简要案情") + private String briefCase; + + /** + * 事故编号 + */ + @ApiModelProperty("事故编号") + private String accidentNo; + + /** + * 事故责任认定书认定内容 + */ + @ApiModelProperty("事故责任认定书认定内容") + private String firmContent; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedCompanyVO.java new file mode 100644 index 0000000..175e911 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedCompanyVO.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleOverspeedCompanyVO", description = "安全管理-超速管理-企业超速") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedCompanyVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + private Integer overspeedTimes; + + /** + * 最高速率 + */ + @ApiModelProperty("最高速率") + private Double maxSpeed; + + /** + * 排名 + */ + @ApiModelProperty("排名") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业Id + */ + @ApiModelProperty("企业ID") + private Long companyId; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名称 + */ + @ApiModelProperty("区域名称") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedVehicleVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedVehicleVO.java new file mode 100644 index 0000000..7d8e3f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedVehicleVO.java @@ -0,0 +1,100 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleOverspeedCompany", description = "安全管理-超速管理-车辆超速") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedVehicleVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + private Integer overspeedTimes; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 最高速率 + */ + @ApiModelProperty("最高速率") + private Double maxSpeed; + + /** + * 排名 + */ + @ApiModelProperty("排名") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域名称 + */ + @ApiModelProperty("区域名称") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedWaysectionVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedWaysectionVO.java new file mode 100644 index 0000000..732daf4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleOverspeedWaysectionVO.java @@ -0,0 +1,116 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleOverspeedCompany", description = "安全管理-超速管理-超速路段") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleOverspeedWaysectionVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 超速时间 + */ + @ApiModelProperty("超速时间") + private LocalDateTime overspeedDate; + + /** + * 超速次数 + */ + @ApiModelProperty("超速次数") + private Integer overspeedTimes; + + /** + * 路段名字 + */ + @ApiModelProperty("路段名字") + private String waySection; + + /** + * 路段开始名字 + */ + @ApiModelProperty("路段开始名字") + private String waySectionStart; + + /** + * 路段结束名字 + */ + @ApiModelProperty("路段结束名字") + private String waySectionEnd; + + /** + * 排名 + */ + @ApiModelProperty("排名") + private Integer rank; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 企业id + */ + @ApiModelProperty("企业id") + private Long companyId; + + /** + * 所属市 + */ + @ApiModelProperty("所属市") + private String city; + + /** + * 所属区 + */ + @ApiModelProperty("所属区") + private String distinguish; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 区域 + */ + @ApiModelProperty("区域") + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleViolationVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleViolationVO.java new file mode 100644 index 0000000..c01743b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/model/vo/NdVehicleViolationVO.java @@ -0,0 +1,165 @@ +package com.ningdatech.carapi.safe.model.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ningdatech.carapi.common.base.BaseEntity; +import com.ningdatech.carapi.common.constant.MissCertEnum; +import com.ningdatech.carapi.common.constant.ViolationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Data +@ApiModel(value = "NdVehicleViolation", description = "安全管理-违章管理") +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@AllArgsConstructor +public class NdVehicleViolationVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("id") + private Long id; + + /** + * 区域名 + */ + @ApiModelProperty("区域名") + private String regionName; + + /** + * 区域ID + */ + @ApiModelProperty("区域ID") + private Long regionId; + + /** + * 企业 + */ + @ApiModelProperty("企业") + private Long companyId; + + /** + * 企业名 + */ + @ApiModelProperty("企业名") + private String companyName; + + /** + * 驾驶员 + */ + @ApiModelProperty("驾驶员") + private String driverName; + + /** + * 驾驶员ID + */ + @ApiModelProperty("驾驶员ID") + private String driverId; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + private String idCard; + + /** + * 违章时间 + */ + @ApiModelProperty("违章时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDateTime violationDate; + + /** + * 违章类型 + */ + @ApiModelProperty("违章类型") + private Integer violationType; + + /** + * 违章类型 + */ + @ApiModelProperty("违章类型") + private String violationTypeName; + + /** + * 缺少证件类型 + */ + @ApiModelProperty("缺少证件类型") + private Integer missingCertificateType; + + /** + * 缺少证件类型 + */ + @ApiModelProperty("缺少证件类型名") + private String missingCertificateTypeName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + private String carPlate; + + /** + * 闯红灯地址 + */ + @ApiModelProperty("闯红灯地址") + private String addressRedLight; + + /** + * 违规路段名 + */ + @ApiModelProperty("违规路段名") + private String waySection; + + /** + * 违章次数 + */ + @ApiModelProperty("违章次数") + private Integer violationTimes; + + /** + * 违章时间段 + */ + @ApiModelProperty("违章时间段") + private String violationPeriod; + + public String getViolationTypeName(){ + if(Objects.nonNull(this.violationType)){ + this.violationTypeName = ViolationTypeEnum.getDescByCode(this.violationType); + return this.violationTypeName; + } + return StringUtils.EMPTY; + } + public String getMissingCertificateTypeName(){ + if(Objects.nonNull(this.missingCertificateType)){ + this.missingCertificateTypeName = MissCertEnum.getDescByCode(this.missingCertificateType); + return this.missingCertificateTypeName; + } + return StringUtils.EMPTY; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataPictureService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataPictureService.java new file mode 100644 index 0000000..8c99819 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataPictureService.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.AlarmDataPicture; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface IAlarmDataPictureService extends IService { + + boolean saveBatchForSql(List queue); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataVideoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataVideoService.java new file mode 100644 index 0000000..8107978 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IAlarmDataVideoService.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.AlarmDataVideo; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface IAlarmDataVideoService extends IService { + + boolean saveBatchForSql(List queue); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureInfoService.java new file mode 100644 index 0000000..c5247cb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureInfoService.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; + +import java.util.Collection; +import java.util.Map; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdInsureInfoService extends IService { + + Map listInsureCompanyByCompanyIds(Collection companyIds); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerAnalysisService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerAnalysisService.java new file mode 100644 index 0000000..222502a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerAnalysisService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.entity.NdInsureOutDangerAnalysis; +import com.ningdatech.carapi.safe.model.dto.InsurePageQuery; +import com.ningdatech.carapi.safe.model.po.NdInsureOutDangerAnalysisPO; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdInsureOutDangerAnalysisService extends IService { + + Page pageAnalysis(Page page, InsurePageQuery param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerService.java new file mode 100644 index 0000000..42561ba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdInsureOutDangerService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdInsureOutDangerService extends IService { + + Long countStatistics(List regionIds, LocalDateTime yearStart, LocalDateTime yearEnd); + + List statistics(List regionIds, LocalDateTime yearStart, LocalDateTime yearEnd); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawCertificateVerificationService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawCertificateVerificationService.java new file mode 100644 index 0000000..6ea892d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawCertificateVerificationService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdLawCertificateVerification; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdLawCertificateVerificationService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawEquipmentInstallService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawEquipmentInstallService.java new file mode 100644 index 0000000..cca4cbb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdLawEquipmentInstallService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdLawEquipmentInstall; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdLawEquipmentInstallService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCommitmentService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCommitmentService.java new file mode 100644 index 0000000..b63cee1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCommitmentService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdSafetyCommitment; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdSafetyCommitmentService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCreditService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCreditService.java new file mode 100644 index 0000000..40bf3e3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSafetyCreditService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdSafetyCredit; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdSafetyCreditService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSecurityAdvisoryService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSecurityAdvisoryService.java new file mode 100644 index 0000000..e41ceb8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdSecurityAdvisoryService.java @@ -0,0 +1,25 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdSecurityAdvisory; +import com.ningdatech.carapi.safe.model.dto.SecurityAdvisoryPageQuery; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdSecurityAdvisoryService extends IService { + + boolean incrementDownCount(Long id); + + void deleteById(Long id); + + List dataScopeList(LambdaQueryWrapper wrapper, SecurityAdvisoryPageQuery securityAdvisoryPageQuery); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentAnalysisService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentAnalysisService.java new file mode 100644 index 0000000..9094fe1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentAnalysisService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentAnalysis; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleAccidentAnalysisService extends IService { + + Page pageAnalysis(Page page, AccidentPageQuery accidentPageQuery); + + Page pageAnalysisOpen(Page page, AccidentPageQuery accidentPageQuery); + +} + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentDeadService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentDeadService.java new file mode 100644 index 0000000..d6c551d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentDeadService.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleAccidentDeadService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentService.java new file mode 100644 index 0000000..58663f9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleAccidentService.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedVehicle; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleAccidentService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedCompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedCompanyService.java new file mode 100644 index 0000000..3b2210d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedCompanyService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedCompany; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleOverspeedCompanyService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedVehicleService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedVehicleService.java new file mode 100644 index 0000000..54e4a53 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedVehicleService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedVehicle; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleOverspeedVehicleService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedWaysectionService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedWaysectionService.java new file mode 100644 index 0000000..3deaf82 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleOverspeedWaysectionService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleOverspeedWaysectionService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleViolationService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleViolationService.java new file mode 100644 index 0000000..43d8211 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/INdVehicleViolationService.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface INdVehicleViolationService extends IService { + Long countStatistics(List regionIds, LocalDateTime start, LocalDateTime end); + + List pageDataScope(Page page, LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleAccidentReportService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleAccidentReportService.java new file mode 100644 index 0000000..a3410eb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleAccidentReportService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.safe.service; + +import com.ningdatech.carapi.safe.entity.VehicleAccidentReport; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2022-12-26 + */ +public interface IVehicleAccidentReportService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleOverspeedInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleOverspeedInfoService.java new file mode 100644 index 0000000..123a4e8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/IVehicleOverspeedInfoService.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.safe.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection; +import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo; +import com.ningdatech.carapi.safe.model.dto.OverspeedPageQuery; +import com.ningdatech.carapi.safe.model.po.NdVehicleOverspeedWaysectionPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedCompanyPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedVehiclePO; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 车辆超速信息表 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +public interface IVehicleOverspeedInfoService extends IService { + Long countStatistics(List regionIds, LocalDateTime todayStart, LocalDateTime todayEnd); + + Page pageGroupCompany(Page page, OverspeedPageQuery overspeedPageQuery); + + Page pageGroupVehicle(Page page, OverspeedPageQuery overspeedPageQuery); + + Page pageGroupWaysection(Page page, OverspeedPageQuery overspeedPageQuery); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/SecurityManageDataScreenService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/SecurityManageDataScreenService.java new file mode 100644 index 0000000..6e35408 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/SecurityManageDataScreenService.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.safe.service; + + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.safe.model.dto.LongitudeLatitudeDTO; +import com.ningdatech.carapi.safe.model.po.OutDangerAnalysisPO; +import com.ningdatech.carapi.safe.model.po.OverspeedAnalysisPO; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +public interface SecurityManageDataScreenService { + + JSONObject getInsureAnalysis(DataScreenParam param,Integer type); + + List getAccidentLongitudeLatitude(DataScreenParam param); + + JSONObject getOutDangerCurrentMonth(DataScreenParam param); + + JSONObject getOverSpeedCurrentMonth(DataScreenParam param); + + JSONObject getOutDangerCity(DataScreenParam param); + + List getOutDangerAnalysis(DataScreenParam param); + + List getOverspeedAnalysis(DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataPictureServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataPictureServiceImpl.java new file mode 100644 index 0000000..ce2c009 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataPictureServiceImpl.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.AlarmDataPicture; +import com.ningdatech.carapi.safe.mapper.AlarmDataPictureMapper; +import com.ningdatech.carapi.safe.service.IAlarmDataPictureService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class AlarmDataPictureServiceImpl extends ServiceImpl + implements IAlarmDataPictureService { + + private final AlarmDataPictureMapper alarmDataPictureMapper; + + @Override + public boolean saveBatchForSql(List list) { + return alarmDataPictureMapper.saveBatchForSql(list); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataVideoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataVideoServiceImpl.java new file mode 100644 index 0000000..434bd5a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/AlarmDataVideoServiceImpl.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.AlarmDataVideo; +import com.ningdatech.carapi.safe.mapper.AlarmDataVideoMapper; +import com.ningdatech.carapi.safe.service.IAlarmDataVideoService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class AlarmDataVideoServiceImpl extends ServiceImpl + implements IAlarmDataVideoService { + + private final AlarmDataVideoMapper alarmDataVideoMapper; + @Override + public boolean saveBatchForSql(List list) { + return alarmDataVideoMapper.saveBatchForSql(list); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceAnalysisImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceAnalysisImpl.java new file mode 100644 index 0000000..017151a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceAnalysisImpl.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentAnalysis; +import com.ningdatech.carapi.safe.mapper.NdVehicleAccidentAnalysisMapper; +import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentAnalysisService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class NdAccidentServiceAnalysisImpl extends ServiceImpl + implements INdVehicleAccidentAnalysisService { + + private final NdVehicleAccidentAnalysisMapper mapper; + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page pageAnalysis(Page page, AccidentPageQuery accidentPageQuery) { + return mapper.pageAnalysis(page,accidentPageQuery); + } + + @Override + public Page pageAnalysisOpen(Page page, AccidentPageQuery accidentPageQuery) { + return mapper.pageAnalysis(page,accidentPageQuery); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceDeadImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceDeadImpl.java new file mode 100644 index 0000000..bf2adb8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceDeadImpl.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.mapper.NdVehicleAccidentDeadMapper; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class NdAccidentServiceDeadImpl extends ServiceImpl + implements INdVehicleAccidentDeadService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceImpl.java new file mode 100644 index 0000000..3525670 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdAccidentServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.mapper.NdVehicleAccidentMapper; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdAccidentServiceImpl extends ServiceImpl + implements INdVehicleAccidentService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureInfoServiceImpl.java new file mode 100644 index 0000000..a4161a7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureInfoServiceImpl.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.mapper.NdInsureInfoMapper; +import com.ningdatech.carapi.safe.service.INdInsureInfoService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdInsureInfoServiceImpl extends ServiceImpl + implements INdInsureInfoService { + + @Override + public Map listInsureCompanyByCompanyIds(Collection companyIds) { + if(CollectionUtils.isEmpty(companyIds)){ + return Collections.emptyMap(); + } + List ndInsureInfos = list(Wrappers.lambdaQuery(NdInsureInfo.class) + .in(NdInsureInfo::getCompanyId, companyIds)); + return CollUtils.listToMap(ndInsureInfos,NdInsureInfo::getCompanyId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerAnalysisServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerAnalysisServiceImpl.java new file mode 100644 index 0000000..ea7def4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerAnalysisServiceImpl.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdInsureOutDangerAnalysis; +import com.ningdatech.carapi.safe.mapper.NdInsureOutDangerAnalysisMapper; +import com.ningdatech.carapi.safe.model.dto.InsurePageQuery; +import com.ningdatech.carapi.safe.model.po.NdInsureOutDangerAnalysisPO; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerAnalysisService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class NdInsureOutDangerAnalysisServiceImpl extends ServiceImpl + implements INdInsureOutDangerAnalysisService { + + private final NdInsureOutDangerAnalysisMapper mapper; + + @Override + public Page pageAnalysis(Page page, InsurePageQuery param) { + return mapper.pageAnalysis(page,param); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerServiceImpl.java new file mode 100644 index 0000000..3579eb5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdInsureOutDangerServiceImpl.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.safe.service.impl; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.datascreen.model.po.OverspeedStatisticsPO; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.mapper.NdInsureOutDangerMapper; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerService; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class NdInsureOutDangerServiceImpl extends ServiceImpl + implements INdInsureOutDangerService { + + private final NdInsureOutDangerMapper insureOutDangerMapper; + + @Override + public Long countStatistics(List regionIds, LocalDateTime start, LocalDateTime end) { + NdInsureOutDangerServiceImpl contex = (NdInsureOutDangerServiceImpl)AopContext.currentProxy(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdInsureOutDanger.class); + contex.searchStatisticsCount(wrapper,regionIds,start,end); + return count(); + } + + @LambdaDataScope + public void searchStatisticsCount(LambdaQueryWrapper wrapper, List regionIds, LocalDateTime start, LocalDateTime end) { + wrapper.in(CollUtil.isNotEmpty(regionIds),NdInsureOutDanger::getRegionId, regionIds) + .ge(NdInsureOutDanger::getAccidentTime, start) + .le(NdInsureOutDanger::getAccidentTime, end); + } + + @Override + public List statistics(List regionIds, LocalDateTime start, LocalDateTime end) { + NdInsureOutDangerServiceImpl contex = (NdInsureOutDangerServiceImpl)AopContext.currentProxy(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdInsureOutDanger.class); + contex.searchStatistics(wrapper,regionIds,start,end); + return list(wrapper); + } + + @LambdaDataScope + public void searchStatistics(LambdaQueryWrapper wrapper, List regionIds, LocalDateTime start, LocalDateTime end) { + wrapper.in(CollUtil.isNotEmpty(regionIds),NdInsureOutDanger::getRegionId, regionIds) + .ge(NdInsureOutDanger::getAccidentTime, start) + .le(NdInsureOutDanger::getAccidentTime, end); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawCertificateVerificationServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawCertificateVerificationServiceImpl.java new file mode 100644 index 0000000..56e5b7f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawCertificateVerificationServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdLawCertificateVerification; +import com.ningdatech.carapi.safe.mapper.NdLawCertificateVerificationMapper; +import com.ningdatech.carapi.safe.service.INdLawCertificateVerificationService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdLawCertificateVerificationServiceImpl extends ServiceImpl + implements INdLawCertificateVerificationService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawEquipmentInstallServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawEquipmentInstallServiceImpl.java new file mode 100644 index 0000000..dea0345 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdLawEquipmentInstallServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdLawEquipmentInstall; +import com.ningdatech.carapi.safe.mapper.NdLawEquipmentInstallMapper; +import com.ningdatech.carapi.safe.service.INdLawEquipmentInstallService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdLawEquipmentInstallServiceImpl extends ServiceImpl + implements INdLawEquipmentInstallService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCommitmentServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCommitmentServiceImpl.java new file mode 100644 index 0000000..28e5e27 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCommitmentServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdSafetyCommitment; +import com.ningdatech.carapi.safe.mapper.NdSafetyCommitmentMapper; +import com.ningdatech.carapi.safe.service.INdSafetyCommitmentService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdSafetyCommitmentServiceImpl extends ServiceImpl + implements INdSafetyCommitmentService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCreditServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCreditServiceImpl.java new file mode 100644 index 0000000..ac3fe72 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSafetyCreditServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdSafetyCredit; +import com.ningdatech.carapi.safe.mapper.NdSafetyCreditMapper; +import com.ningdatech.carapi.safe.service.INdSafetyCreditService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdSafetyCreditServiceImpl extends ServiceImpl + implements INdSafetyCreditService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSecurityAdvisoryServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSecurityAdvisoryServiceImpl.java new file mode 100644 index 0000000..4e29ad9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdSecurityAdvisoryServiceImpl.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.safe.entity.NdSecurityAdvisory; +import com.ningdatech.carapi.safe.mapper.NdSecurityAdvisoryMapper; +import com.ningdatech.carapi.safe.model.dto.SecurityAdvisoryPageQuery; +import com.ningdatech.carapi.safe.service.INdSecurityAdvisoryService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdSecurityAdvisoryServiceImpl extends ServiceImpl + implements INdSecurityAdvisoryService { + + @Override + public boolean incrementDownCount(Long id) { + return baseMapper.incrementDownCount(id) > 0; + } + + @Override + public void deleteById(Long id) { + baseMapper.deleteById(id); + } + + @Override + @LambdaDataScope + @BuildChildrenRegionWrapper + public List dataScopeList(LambdaQueryWrapper wrapper, SecurityAdvisoryPageQuery securityAdvisoryPageQuery) { + wrapper.eq(Objects.nonNull(securityAdvisoryPageQuery.getAdvisoryDate()),NdSecurityAdvisory::getAdvisoryDate,securityAdvisoryPageQuery.getAdvisoryDate()); + wrapper.eq(Objects.nonNull(securityAdvisoryPageQuery.getRegionId()),NdSecurityAdvisory::getRegionId,securityAdvisoryPageQuery.getRegionId()); + wrapper.orderBy(Boolean.TRUE,Boolean.FALSE,NdSecurityAdvisory::getUpdateOn); + return baseMapper.selectList(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedCompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedCompanyServiceImpl.java new file mode 100644 index 0000000..4887bfe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedCompanyServiceImpl.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedCompany; +import com.ningdatech.carapi.safe.mapper.NdVehicleOverspeedCompanyMapper; +import com.ningdatech.carapi.safe.service.INdVehicleOverspeedCompanyService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class NdVehicleOverspeedCompanyServiceImpl extends ServiceImpl + implements INdVehicleOverspeedCompanyService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedVehicleServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedVehicleServiceImpl.java new file mode 100644 index 0000000..d2a61b2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedVehicleServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedVehicle; +import com.ningdatech.carapi.safe.mapper.NdVehicleOverspeedCompanyMapper; +import com.ningdatech.carapi.safe.mapper.NdVehicleOverspeedVehicleMapper; +import com.ningdatech.carapi.safe.service.INdVehicleOverspeedVehicleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdVehicleOverspeedVehicleServiceImpl extends ServiceImpl implements INdVehicleOverspeedVehicleService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedWaysectionServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedWaysectionServiceImpl.java new file mode 100644 index 0000000..ac4cb65 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleOverspeedWaysectionServiceImpl.java @@ -0,0 +1,21 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection; +import com.ningdatech.carapi.safe.mapper.NdVehicleOverspeedWaysectionMapper; +import com.ningdatech.carapi.safe.service.INdVehicleOverspeedWaysectionService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +public class NdVehicleOverspeedWaysectionServiceImpl extends ServiceImpl + implements INdVehicleOverspeedWaysectionService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleViolationServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleViolationServiceImpl.java new file mode 100644 index 0000000..8edcae3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/NdVehicleViolationServiceImpl.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.safe.service.impl; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.safe.entity.NdVehicleViolation; +import com.ningdatech.carapi.safe.mapper.NdVehicleViolationMapper; +import com.ningdatech.carapi.safe.service.INdVehicleViolationService; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class NdVehicleViolationServiceImpl extends ServiceImpl + implements INdVehicleViolationService { + + private final NdVehicleViolationMapper mapper; + + @Override + public Long countStatistics(List regionIds, LocalDateTime start, LocalDateTime end) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleViolation.class); + NdVehicleViolationServiceImpl context = (NdVehicleViolationServiceImpl)AopContext.currentProxy(); + context.dataScopeCount(wrapper,regionIds,start,end); + return count(wrapper); + } + + @LambdaDataScope + public void dataScopeCount(LambdaQueryWrapper wrapper, List regionIds, LocalDateTime start, LocalDateTime end) { + wrapper.in(CollUtil.isNotEmpty(regionIds),NdVehicleViolation::getRegionId, regionIds) + .ge(NdVehicleViolation::getViolationDate, start) + .le(NdVehicleViolation::getViolationDate, end); + } + + @Override + @LambdaDataScope(wrapperIndex = 1,type = LambdaDataScopeTypeEnum.ALL) + public List pageDataScope(Page page, LambdaQueryWrapper wrapper) { + return mapper.selectList(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/SecurityManageDataScreenServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/SecurityManageDataScreenServiceImpl.java new file mode 100644 index 0000000..f35913d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/SecurityManageDataScreenServiceImpl.java @@ -0,0 +1,308 @@ +package com.ningdatech.carapi.safe.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Maps; +import com.ningdatech.basic.model.DateRange; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.DateRangeUtil; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.NdVehicleAccident; +import com.ningdatech.carapi.safe.entity.NdVehicleAccidentDead; +import com.ningdatech.carapi.safe.mapper.SecurityManageDataScreenMapper; +import com.ningdatech.carapi.safe.model.dto.LongitudeLatitudeDTO; +import com.ningdatech.carapi.safe.model.po.*; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService; +import com.ningdatech.carapi.safe.service.INdVehicleAccidentService; +import com.ningdatech.carapi.safe.service.SecurityManageDataScreenService; +import com.ningdatech.carapi.safe.utils.InitDataUtil; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-10-12 + */ +@Service +@RequiredArgsConstructor +public class SecurityManageDataScreenServiceImpl implements SecurityManageDataScreenService { + + private final RegionsCacheHelper regionsCacheHelper; + private final SecurityManageDataScreenMapper securityManageDataScreenMapper; + private final INdVehicleAccidentService accidentService; + private final INdVehicleAccidentDeadService accidentDeadService; + + private final String FIRST_PERIOD_TIME = "0:00-02:00"; + private final String SECOND_PERIOD_TIME = "2:00-4:00"; + private final String THIRD_PERIOD_TIME = "4:00-6:00"; + private final String FOURTH_PERIOD_TIME = "6:00-8:00"; + private final String FIFTH_PERIOD_TIME = "8:00-10:00"; + private final String SIXTH_PERIOD_TIME = "10:00-12:00"; + private final String SEVENTH_PERIOD_TIME = "12:00-14:00"; + private final String EIGHTH_PERIOD_TIME = "14:00-16:00"; + private final String NINTH_PERIOD_TIME = "16:00-18:00"; + private final String TENTH_PERIOD_TIME = "18:00-20:00"; + private final String ELEVENTH_PERIOD_TIME = "20:00-22:00"; + private final String LAST_PERIOD_TIME = "22:00-24:00"; + + /** + * 近三年保险分析对比 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public JSONObject getInsureAnalysis(DataScreenParam param, Integer type) { + param.setType(type); + List times = securityManageDataScreenMapper.getOutDangerAnalysis(param); + return convert(times, type); + } + + /** + * 浙江省事故 经纬度分布 + * + * @param param + * @return + */ + @Override + public List getAccidentLongitudeLatitude(DataScreenParam param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleAccident.class); + LambdaQueryWrapper wrapperDead = Wrappers.lambdaQuery(NdVehicleAccidentDead.class); + SecurityManageDataScreenServiceImpl context = (SecurityManageDataScreenServiceImpl) AopContext.currentProxy(); + List searchAccidents = context.searchAccidents(wrapper, param); + List accidentDeads = context.searchAccidentDeads(wrapperDead, param); + List accidents = searchAccidents.stream().map(accident -> new LongitudeLatitudeDTO(accident.getLongitude(), accident.getLatitude())).collect(Collectors.toList()); + List deads = accidentDeads.stream().map(dead -> new LongitudeLatitudeDTO(dead.getLongitude(), dead.getLatitude())).collect(Collectors.toList()); + return Stream.of(accidents, deads).flatMap(Collection::stream).distinct().collect(Collectors.toList()); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public List searchAccidents(LambdaQueryWrapper wrapper, DataScreenParam param) { + return accidentService.list(wrapper); + } + + @LambdaDataScope + @BuildChildrenRegionWrapper + public List searchAccidentDeads(LambdaQueryWrapper wrapper, DataScreenParam param) { + return accidentDeadService.list(wrapper); + } + + /** + * 本月 各时段出险 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public JSONObject getOutDangerCurrentMonth(DataScreenParam param) { + JSONObject res = new JSONObject(); + if (param.getStartTime() == null || param.getEndTime() == null) { + // 默认查询上月数据 + DateRange monthRange = DateRangeUtil.monthsAgo(1); + param.setStartTime(monthRange.getStart().atStartOfDay()); + param.setEndTime(monthRange.getEnd().atTime(LocalTime.MAX)); + } + OutDangerPeriodTimePO outDangerPeriodTime = securityManageDataScreenMapper.getOutDangerPeriodTime(param); + return convertJson(outDangerPeriodTime, res); + } + + /** + * 超速本月数据 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public JSONObject getOverSpeedCurrentMonth(DataScreenParam param) { + JSONObject res = new JSONObject(); + List overspeedTimes = securityManageDataScreenMapper.getOverSpeedCurrentMonth(param); + return convertOverspeedJson(overspeedTimes, res); + } + + /** + * 近三年各城市出险次数 + * + * @param param + * @return + */ + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public JSONObject getOutDangerCity(DataScreenParam param) { + JSONObject res = new JSONObject(); + CodeUtil.buildRegionLevel(param); + List outDangers = securityManageDataScreenMapper.getOutDangerRegions(param); + complementaryRegion(outDangers, param.getRegionId()); + return convertCityOutDangerJson(outDangers, res); + } + + @Override + @XmlDataScope + public List getOutDangerAnalysis(DataScreenParam param) { + return securityManageDataScreenMapper.getOutDangerAnalysis(param); + } + + @Override + @XmlDataScope + public List getOverspeedAnalysis(DataScreenParam param) { + return securityManageDataScreenMapper.getOverspeedAnalysis(param); + } + + private JSONObject convertCityOutDangerJson(List outDangerCities, JSONObject res) { + if (CollUtil.isEmpty(outDangerCities)) { + return res; + } + JSONObject total = new JSONObject(); + JSONObject data = new JSONObject(true); + Integer beforeTotal = 0; + Integer lastTotal = 0; + Integer currentTotal = 0; + for (OutDangerCityPO po : outDangerCities) { + beforeTotal += po.getBeforeOutDanger(); + lastTotal += po.getLastOutDanger(); + currentTotal += po.getCurrentOutDanger(); + JSONObject innerData = new JSONObject(); + innerData.put(String.valueOf(LocalDateTime.now().minusYears(2).getYear()), po.getBeforeOutDanger()); + innerData.put(String.valueOf(LocalDateTime.now().minusYears(1).getYear()), po.getLastOutDanger()); + innerData.put(String.valueOf(LocalDateTime.now().getYear()), po.getCurrentOutDanger()); + data.put(po.getRegionName(), innerData); + } + total.put(String.valueOf(LocalDateTime.now().minusYears(2).getYear()), beforeTotal); + total.put(String.valueOf(LocalDateTime.now().minusYears(1).getYear()), lastTotal); + total.put(String.valueOf(LocalDateTime.now().getYear()), currentTotal); + res.put("total", total); + res.put("data", data); + return res; + } + + private JSONObject convertOverspeedJson(List overspeedTimes, JSONObject res) { + Map dataMap = CollUtils.listToMap(overspeedTimes, o -> o.getMonthDay()); + TreeMap innerData = new TreeMap(); + for (int i = 30; i >= 0; i--) { + String dateStr = NdDateUtils.format(LocalDateTime.now().minusDays(i), DatePattern.NORM_DATE_PATTERN); + if (dataMap.containsKey(dateStr)) { + innerData.put(dataMap.get(dateStr).getMonthDay(), dataMap.get(dateStr).getOverspeedTimes()); + } else { + innerData.put(dateStr, 0); + } + } + + res.put("total", overspeedTimes.stream().mapToInt(overspeedTime -> overspeedTime.getOverspeedTimes()).sum()); + res.put("data", innerData); + return res; + } + + private JSONObject convertJson(OutDangerPeriodTimePO po, JSONObject res) { + if (Objects.isNull(po)) { + return res; + } + res.put(FIRST_PERIOD_TIME, po.getFirstPeriodTime()); + res.put(SECOND_PERIOD_TIME, po.getSecondPeriodTime()); + res.put(THIRD_PERIOD_TIME, po.getThirdPeriodTime()); + res.put(FOURTH_PERIOD_TIME, po.getFourthPeriodTime()); + res.put(FIFTH_PERIOD_TIME, po.getFifthPeriodTime()); + res.put(SIXTH_PERIOD_TIME, po.getSixthPeriodTime()); + res.put(SEVENTH_PERIOD_TIME, po.getSeventhPeriodTime()); + res.put(EIGHTH_PERIOD_TIME, po.getEighthPeriodTime()); + res.put(NINTH_PERIOD_TIME, po.getNinthPeriodTime()); + res.put(TENTH_PERIOD_TIME, po.getTenthPeriodTime()); + res.put(ELEVENTH_PERIOD_TIME, po.getEleventhPeriodTime()); + res.put(LAST_PERIOD_TIME, po.getLastPeriodTime()); + return res; + } + + private JSONObject convert(List outDangerTimes, Integer type) { + Map> yearMap = InitDataUtil.initThreeYears(); + for (OutDangerAnalysisPO outDangerTime : outDangerTimes) { + if (yearMap.containsKey(outDangerTime.getYear())) { + Map monthMap = yearMap.get(outDangerTime.getYear()); + if (monthMap.containsKey(outDangerTime.getMonth())) { + switch (type) { + case 1: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getOutDangerTimes()); + break; + case 2: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getInjuries()); + break; + case 3: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getDeathToll()); + break; + default: + monthMap.put(outDangerTime.getMonth(), outDangerTime.getOutDangerTimes()); + } + } + } + } + Map total = countTotal(yearMap); + yearMap.put("total", total); + return JSONObject.parseObject(JSON.toJSONString(yearMap)); + } + + private Map countTotal(Map> yearMap) { + Map total = Maps.newHashMap(); + Map currentMap = yearMap.get(String.valueOf(LocalDateTime.now().getYear())); + int currentSum = currentMap.values().stream().mapToInt(o -> Integer.parseInt(String.valueOf(o))).sum(); + total.put(String.valueOf(LocalDateTime.now().getYear()), currentSum); + Map lastMap = yearMap.get(String.valueOf(LocalDateTime.now().minusYears(1).getYear())); + int lastSum = lastMap.values().stream().mapToInt(o -> Integer.parseInt(String.valueOf(o))).sum(); + total.put(String.valueOf(LocalDateTime.now().minusYears(1).getYear()), lastSum); + Map beforeMap = yearMap.get(String.valueOf(LocalDateTime.now().minusYears(2).getYear())); + int beforeSum = beforeMap.values().stream().mapToInt(o -> Integer.parseInt(String.valueOf(o))).sum(); + total.put(String.valueOf(LocalDateTime.now().minusYears(2).getYear()), beforeSum); + return total; + } + + public void complementaryRegion(List list, Long regionId) { + Map dataMap = CollUtils.listToMap(list, OutDangerCityPO::getRegionId); + List regions = regionsCacheHelper.listChildOnly(regionId, true); + List tmpList = new ArrayList<>(); + regions.forEach(w -> { + OutDangerCityPO odc = dataMap.get(w.getId()); + if (odc == null) { + odc = new OutDangerCityPO(); + odc.setRegionId(w.getId()); + odc.setRegionName(w.getRegionName()); + odc.setRegionName(w.getRegionName()); + odc.setRegionCode(w.getRegionCode()); + odc.setTotal(0); + odc.setLastOutDanger(0); + odc.setCurrentOutDanger(0); + odc.setBeforeOutDanger(0); + } + tmpList.add(odc); + }); + list.clear(); + list.addAll(tmpList); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleAccidentReportServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleAccidentReportServiceImpl.java new file mode 100644 index 0000000..3d35f55 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleAccidentReportServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.safe.service.impl; + +import com.ningdatech.carapi.safe.entity.VehicleAccidentReport; +import com.ningdatech.carapi.safe.mapper.VehicleAccidentReportMapper; +import com.ningdatech.carapi.safe.service.IVehicleAccidentReportService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2022-12-26 + */ +@Service +public class VehicleAccidentReportServiceImpl extends ServiceImpl implements IVehicleAccidentReportService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleOverspeedInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleOverspeedInfoServiceImpl.java new file mode 100644 index 0000000..35639c0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/service/impl/VehicleOverspeedInfoServiceImpl.java @@ -0,0 +1,131 @@ +package com.ningdatech.carapi.safe.service.impl; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo; +import com.ningdatech.carapi.safe.mapper.VehicleOverspeedInfoMapper; +import com.ningdatech.carapi.safe.model.dto.OverspeedPageQuery; +import com.ningdatech.carapi.safe.model.po.NdVehicleOverspeedWaysectionPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedCompanyPO; +import com.ningdatech.carapi.safe.model.po.VehicleOverspeedVehiclePO; +import com.ningdatech.carapi.safe.service.IVehicleOverspeedInfoService; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 车辆超速信息表 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-17 + */ +@Service +@RequiredArgsConstructor +public class VehicleOverspeedInfoServiceImpl extends ServiceImpl implements IVehicleOverspeedInfoService { + + private final VehicleOverspeedInfoMapper vehicleOverspeedInfoMapper; + private final VehicleBaseInfoMapper vehicleBaseInfoMapper; + + + @Override + public Long countStatistics(List regionIds,LocalDateTime todayStart, LocalDateTime todayEnd) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(VehicleOverspeedInfo.class); + VehicleOverspeedInfoServiceImpl contex = (VehicleOverspeedInfoServiceImpl)AopContext.currentProxy(); + contex.dataScopeCount(wrapper,regionIds,todayStart,todayEnd); + // 根据车辆类型,过滤出真实超速的 + Map baseInfoMap = vehicleBaseInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)).stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + List overspeedInfos = vehicleOverspeedInfoMapper.selectList(wrapper); + List list = overspeedInfos.stream().filter(v -> { + NdVehicleBaseInfo baseInfo = baseInfoMap.get(v.getCarPlate()); + if (Objects.nonNull(baseInfo)) { + if (Boolean.TRUE.equals(checkIsOverSpeed(v, baseInfo))){ + return true; + } + } + return false; + }).collect(Collectors.toList()); + return (long) list.size(); + } + + @LambdaDataScope + public void dataScopeCount(LambdaQueryWrapper wrapper, List regionIds, LocalDateTime todayStart, LocalDateTime todayEnd) { + wrapper.in(CollUtil.isNotEmpty(regionIds),VehicleOverspeedInfo::getRegionId, regionIds) + .ge(VehicleOverspeedInfo::getOverspeedDate, todayStart) + .le(VehicleOverspeedInfo::getOverspeedDate, todayEnd); + } + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page pageGroupCompany(Page page, OverspeedPageQuery overspeedPageQuery) { + vehicleOverspeedInfoMapper.pageGroupCompany(page, overspeedPageQuery); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return page; + } + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page pageGroupVehicle(Page page, OverspeedPageQuery overspeedPageQuery) { + vehicleOverspeedInfoMapper.pageGroupVehicle(page, overspeedPageQuery); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return page; + } + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page pageGroupWaysection(Page page, OverspeedPageQuery overspeedPageQuery) { + vehicleOverspeedInfoMapper.pageGroupWaysection(page, overspeedPageQuery); + CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords()); + return page; + } + + private Boolean checkIsOverSpeed(VehicleOverspeedInfo overspeedInfo, NdVehicleBaseInfo baseInfo) { + // 混凝土和移动泵车 是50 + Integer vehicleType = baseInfo.getVehicleType(); + VehicleTypeEnum enumByValue = VehicleTypeEnum.getEnumByValue(vehicleType); + if (VehicleTypeEnum.OTHER.equals(enumByValue)) { + if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.KRHP.equals(enumByValue)) { + if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(50)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.MIXER.equals(enumByValue)) { + if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(50)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.BULK_CEMENT_TRUCK.equals(enumByValue)) { + if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0) { + return Boolean.TRUE; + } + } else if (VehicleTypeEnum.READY_MIXED_MORTAR_TRUC.equals(enumByValue)) { + return overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0; + } + return Boolean.FALSE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/utils/InitDataUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/utils/InitDataUtil.java new file mode 100644 index 0000000..0421b19 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/safe/utils/InitDataUtil.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.safe.utils; + +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Maps; + +import java.time.LocalDateTime; +import java.util.Map; + +/** + * @Classname InitDataUtil + * @Description + * @Date 2022/10/26 15:42 + * @Created by PoffyZhang + */ +public class InitDataUtil { + private static JSONObject MONTHS = JSON.parseObject("{\"01\":0,\"02\":0,\"03\":0,\"04\":0,\"05\":0,\"06\":0" + + ",\"07\":0,\"08\":0,,\"09\":0,\"10\":0,\"11\":0,\"12\":0}"); + + public static Map> initThreeYears(){ + Map> res = Maps.newHashMap(); + res.put(String.valueOf(LocalDateTime.now().minusYears(2).getYear()),BeanUtil.beanToMap(MONTHS)); + res.put(String.valueOf(LocalDateTime.now().minusYears(1).getYear()),BeanUtil.beanToMap(MONTHS)); + res.put(String.valueOf(LocalDateTime.now().getYear()),BeanUtil.beanToMap(MONTHS)); + return res; + } + + public static Map> initTwoYears(){ + Map> res = Maps.newHashMap(); + res.put(String.valueOf(LocalDateTime.now().minusYears(1).getYear()),BeanUtil.beanToMap(MONTHS)); + res.put(String.valueOf(LocalDateTime.now().getYear()),BeanUtil.beanToMap(MONTHS)); + return res; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/TaskContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/TaskContant.java new file mode 100644 index 0000000..76521b6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/TaskContant.java @@ -0,0 +1,144 @@ +package com.ningdatech.carapi.scheduler.contants; + +import java.math.BigDecimal; + +/** + * @author PoffyZhang + * @Classname TaskContant + * @Description + * @Date 2022/12/7 11:00 + */ +public interface TaskContant { + class Host { + public static final String HOST_ZPF = "LAPTOP-NQGEQP03"; + public static final String HOST_CMM2 = "DESKTOP-KN1L6HL"; + public static final String HOST_CMM = "LAPTOP-PCISPN2O"; + + public static final String HOST_207 = "iZbp13nwyvib53j4j1p2xoZ"; + } + + class DataField { + + public static final String GPS = "GPS"; + + public static final String ADAS = "ADAS"; + public static final String ROAD_SIGN_TYPE = "roadSignType"; + public static final String ROAD_SIGN_DATA = "roadSignData"; + public static final String LONGITUDE = "longitude"; + + public static final String LATITUDE = "latitude"; + } + + class Data{ + public static final Integer ROAD_SIGN_TYPE_OVERSPEED = 1; + public static final Integer STAR_NUMBER_RANGE_ZERO = 0; + public static final Integer STAR_NUMBER_RANGE_TWENTY = 20; + public static final Integer STAR_NUMBER_RANGE_FORTY = 40; + public static final Integer STAR_NUMBER_RANGE_SIXTY = 60; + public static final Integer STAR_NUMBER_RANGE_EIGHTY = 80; + + public static final Integer DRIVER_STAR_DATA_CNT_ONE = 1; + + public static final Integer OPERATOR_ASSESSMENT_SCORE_ZERO = 0; + public static final Integer OPERATOR_ASSESSMENT_SCORE_HUNDRED = 100; + + public static final Integer MONTH_VALUE_ONE = 1; + public static final Integer MONTH_VALUE_TWO = 2; + public static final Integer MONTH_VALUE_THREE = 3; + public static final Integer MONTH_VALUE_FOUR = 4; + public static final Integer MONTH_VALUE_FIVE = 5; + public static final Integer MONTH_VALUE_SIX = 6; + public static final Integer MONTH_VALUE_SEVEN = 7; + public static final Integer MONTH_VALUE_EIGHT = 8; + public static final Integer MONTH_VALUE_NINE = 9; + public static final Integer MONTH_VALUE_TEN = 10; + public static final Integer MONTH_VALUE_ELEVEN = 11; + public static final Integer MONTH_VALUE_TWELVE = 12; + + public static final Integer SUB_LIST_SIZE = 2000; + public static final Integer VIOLATION_TIME_SEVEN = 7; + public static final Integer VIOLATION_TIME_NINE = 9; + public static final Integer VIOLATION_TIME_SIXTEEN = 16; + public static final Integer VIOLATION_TIME_EIGHTEEN = 18; + public static final String VIOLATION_TIME_AM_START = "7:00"; + public static final String VIOLATION_TIME_AM_END = "9:00"; + public static final String VIOLATION_TIME_PM_START = "16:30"; + public static final String VIOLATION_TIME_PM_END = "18:30"; + public static final String VIOLATION_TIME_HALF = ":30"; + public static final String VIOLATION_TIME_START = ":00"; + public static final Integer GPS_TIME_BUCKET = 5; + + } + + class RedisKey { + public static final String OVERSPEED_TASK_LOCK = "cm:task:overspeed:task_lock"; + + public static final String OVERSPEED_ALARM_DATA_INDEX = "cm:task:overspeed:alarm_data_index"; + public static final String OVERSPEED_GPS_DATA_INDEX = "cm:task:overspeed:gps_data_index"; + + public static final String DRIVER_STAR_MANAGE_OUT_DANGER = "cm:task:driver:star_manage_out_danger_index"; + + public static final String DRIVER_BLACK_LIST = "cm:task:driver:black_list_index"; + + public static final String COMPANY_VEHICLE_NOT_GET_ON = "cm:task:company:not_get_on_index"; + + public static final String DRIVER_STAR_MANAGE_ACCIDENT = "cm:task:driver:star_manage_accident_index"; + + public static final String DRIVER_STAR_MANAGE_DEATH_ACCIDENT = "cm:task:driver:star_manage_death_accident_index"; + + public static final String DRIVER_ABNORMAL_BEHAVIOR_ANALYSIS = "cm:task:driver:driver_abnormal_behavior_analysis_index"; + + public static final String VEHICLE_ALARM_DATA_INDEX = "cm:task:vehicle:alarm_data_index"; + + public static final String OPERATOR_ASSESSMENT_SCORE = "cm:task:operator:operator_assessment_score_index"; + public static final String ACCIDENT_QUERY_IRS = "cm:task:irs:accident_query_irs_index"; + public static final String VEHICLE_ILLEGAL_QUERY_IRS = "cm:task:irs:vehicle_illegal_query_irs_index"; + public static final String DRIVING_LICENCE_IRS = "cm:task:irs:driving_license_irs_index"; + public static final String VEHICLE_LICENSE_IRS = "cm:task:irs:vehicle_license_irs_index"; + public static final String IRS_VEHICLE_ILLEGAL_REQUEST_SECRET = "cm:task:irs:irs_vehicle_illegal_request_secret_index"; + public static final String IRS_VEHICLE_ILLEGAL_REFRESH_SECRET = "cm:task:irs:irs_vehicle_illegal_refresh_secret_index"; + public static final String IRS_VEHICLE_LICENSE_REQUEST_SECRET = "cm:task:irs:irs_vehicle_license_request_secret_index"; + public static final String IRS_VEHICLE_LICENSE_REFRESH_SECRET = "cm:task:irs:irs_vehicle_license_refresh_secret_index"; + public static final String IRS_ACCIDENT_QUERY_REQUEST_SECRET = "cm:task:irs:irs_accident_query_request_secret_index"; + public static final String IRS_ACCIDENT_QUERY_REFRESH_SECRET = "cm:task:irs:irs_accident_query_refresh_secret_index"; + public static final String IRS_ACCIDENT_DUTY_REQUEST_SECRET = "cm:task:irs:irs_accident_duty_request_secret_index"; + public static final String IRS_ACCIDENT_DUTY_REFRESH_SECRET = "cm:task:irs:irs_accident_duty_refresh_secret_index"; + + public static final String IRS_ACCIDENT_QUERY_REQUEST_SECRET_TEST = "cm:task:irs:irs_accident_query_request_secret_test_index"; + public static final String IRS_ACCIDENT_QUERY_REFRESH_SECRET_TEST = "cm:task:irs:irs_accident_query_refresh_secret_test_index"; + + public static final Integer IRS_SECRET_TIME_INTERVAL = 10; + + + } + + class Math { + public static final BigDecimal LONGITUDE_UNITS = BigDecimal.valueOf(1000000); + + public static final BigDecimal SPEED_UNITS = BigDecimal.valueOf(0.036); + + public static final BigDecimal ALTITUDE_UNITS = BigDecimal.valueOf(100); + + public static final BigDecimal DIRECTION_UNITS = BigDecimal.valueOf(10); + } + + + class Msg { + public static final String REDIS_KEY_NOT_FOUND = "redis key {} not found 请查找原因!"; + public static final String REFRESH_KEY_FREQUENTLY = "请求过于频繁,请稍候再试"; + } + + class Code { + public static final String REFRESH_KEY_FREQUENTLY_CODE = "88"; + } + + class Star{ + public static final Double ONE_STAR = 1.0; + public static final Double TWO_STAR = 2.0; + public static final Double THREE_STAR = 3.0; + public static final Double FOUR_STAR = 4.0; + public static final Double FIVE_STAR = 5.0; + + + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/VehicleTaskContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/VehicleTaskContant.java new file mode 100644 index 0000000..45071c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/contants/VehicleTaskContant.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.scheduler.contants; + +/** + * @Classname VehicleTaskContant + * @Description + * @Date 2022/11/29 10:48 + * @Created by PoffyZhang + */ +public interface VehicleTaskContant { + /** + * GPS 状态的二进制 位数 0 是ACC点火状态 22是车辆是否行驶 + */ + + public static final Integer GPS_STATUS_ACC = 0; + public static final Integer GPS_STATUS_MOVING = 22; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/GpsData.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/GpsData.java new file mode 100644 index 0000000..7fa55af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/GpsData.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.scheduler.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @author CMM + * @description + * @since 2022/12/07 15:19 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class GpsData { + @ApiModelProperty("高度") + private BigDecimal altitude; + + @ApiModelProperty("方向") + private BigDecimal direction; + + @ApiModelProperty("纬度") + private BigDecimal latitude; + + @ApiModelProperty("精度") + private BigDecimal longitude; + + @ApiModelProperty("速度") + private BigDecimal speed; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusDay.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusDay.java new file mode 100644 index 0000000..e20cc2f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusDay.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.scheduler.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 统计车辆上线状态 按天 + *

+ * + * @author PoffyZhang + * @since 2022-12-18 + */ +@TableName("nd_vehicle_online_status_day") +@ApiModel(value = "VehicleOnlineStatusDay对象", description = "统计车辆上线状态 按天") +@Data +public class VehicleOnlineStatusDay implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年") + private String year; + + @ApiModelProperty("月") + private String month; + + @ApiModelProperty("日") + private String day; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("0未删除1已删除") + private Boolean deleted; + + @ApiModelProperty("在线时间") + private LocalDateTime onlineTime; + + @ApiModelProperty("距离上次在线时间间隔") + private Integer onlineTimeInterval; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusHour.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusHour.java new file mode 100644 index 0000000..a310c62 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/entity/VehicleOnlineStatusHour.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.scheduler.entity; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 统计车辆上线状态 按小时 + *

+ * + * @author PoffyZhang + * @since 2022-11-29 + */ +@TableName("nd_vehicle_online_status_hour") +@ApiModel(value = "VehicleOnlineStatusHour对象", description = "统计车辆上线状态 按小时") +@Data +public class VehicleOnlineStatusHour implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("创建时间") + private LocalDateTime createOn; + + @ApiModelProperty("创建人") + private Long createBy; + + @ApiModelProperty("修改时间") + private LocalDateTime updateOn; + + @ApiModelProperty("修改人") + private Long updateBy; + + @ApiModelProperty("0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("年") + private String year; + + @ApiModelProperty("月") + private String month; + + @ApiModelProperty("日") + private String day; + + @ApiModelProperty("小时") + private String hour; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("在线时间") + private LocalDateTime onlineTime; + + @ApiModelProperty("距离上次在线时间间隔") + private Integer onlineTimeInterval; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/DataTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/DataTypeEnum.java new file mode 100644 index 0000000..ac0bb77 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/DataTypeEnum.java @@ -0,0 +1,15 @@ +package com.ningdatech.carapi.scheduler.enums; + +public enum DataTypeEnum { + /** + * 数据类型 + */ + EMPLOYEE, + VEHICLE, + COMPANY, + DRIVER_ACCIDENT, + DRIVER_DEAD_ACCIDENT, + DRIVER_OUT_DANGER, + + DRIVER_ACCIDENT_REPORT_REVIEW; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/OperatorTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/OperatorTypeEnum.java new file mode 100644 index 0000000..51f4c24 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/enums/OperatorTypeEnum.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.scheduler.enums; + +public enum OperatorTypeEnum { + /** + * 操作类型 + */ + ADD, + + UPDATE, + + DELETE, + + /** + * 车辆状态 + */ + ONLINE, + + OFFLINE, + + EXCEPTION; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.java new file mode 100644 index 0000000..cb872bd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.scheduler.mapper; + +import java.time.LocalDateTime; +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.ningdatech.carapi.scheduler.model.dto.GpsSpeedDataDTO; +import com.ningdatech.carapi.scheduler.model.dto.OverSpeedGpsDataDTO; + +/** + * @return + * @author CMM + * @since 2023/05/29 16:06 + */ +public interface OverSpeedGpsDataMapper { + + + /** + * 从每天的GPS数据表中获取车辆GPS速度数据 + * @param date + * @param startIndex + * @param endIndex + * @return + */ + List getOverSpeedDataInGps(@Param("date") String date , @Param("startIndex") Long startIndex, @Param("endIndex") Long endIndex); + + /** + * 获取超速报警时刻5分钟后的GPS数据 + * @param carPlate + * @param warnTime + * @param date + * @param timeBucket + * @return + */ + List getDataInGps(@Param("carPlate") String carPlate, @Param("warnTime") LocalDateTime warnTime, @Param("date") String date, @Param("timeBucket") Integer timeBucket); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.xml new file mode 100644 index 0000000..cb6c6fb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/OverSpeedGpsDataMapper.xml @@ -0,0 +1,41 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.java new file mode 100644 index 0000000..84ce409 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.scheduler.mapper; + +import java.util.List; +import java.util.Set; + +import org.apache.ibatis.annotations.Param; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusDay; + +/** + *

+ * 统计车辆上线状态 按天 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-12-18 + */ +public interface VehicleOnlineStatusDayMapper extends BaseMapper { + Integer countTable(@Param("tableName") String tableName); + + VehicleOnlineStatusDay selectOneByTable(@Param("tableName") String tableName, @Param("statusDay") VehicleOnlineStatusDay statusDay); + + Integer createTable(@Param("tableName") String tableName); + + Boolean saveByReqInMonthTable(@Param("tableName") String tableName,@Param("statusDay") VehicleOnlineStatusDay statusDay); + + Boolean updateByReqInMonthTable(@Param("tableName") String tableName,@Param("statusDay") VehicleOnlineStatusDay statusDay); + + Set selectOnlineCarPlatesInMonthTable(@Param("tableName") String tableName, @Param("date") String date); + + List listByTable(@Param("tableName") String tableName, @Param("statusDay") VehicleOnlineStatusDay statusDay); + + Boolean batchSave(@Param("tableName") String tableName,@Param("statusDays") List statusDays); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.xml new file mode 100644 index 0000000..d60b074 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusDayMapper.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + CREATE TABLE ${tableName} ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` bigint(20) DEFAULT NULL COMMENT '创建人', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `update_by` bigint(20) DEFAULT NULL COMMENT '修改人', + `status` tinyint(2) DEFAULT NULL COMMENT '0离线 1在线 2异常', + `car_plate` varchar(32) DEFAULT NULL COMMENT '车牌号', + `year` varchar(16) DEFAULT NULL COMMENT '年', + `month` varchar(16) DEFAULT NULL COMMENT '月', + `day` varchar(16) DEFAULT NULL COMMENT '日', + `company_id` bigint(20) DEFAULT NULL COMMENT '公司ID', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域ID', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0未删除1已删除', + `online_time` datetime DEFAULT NULL COMMENT '车辆在线时间', + `online_time_interval` int(11) DEFAULT NULL COMMENT '距离上次在线时间间隔', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_car_plate_day` (`deleted`,`year`,`month`,`day`,`car_plate`) USING BTREE + ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='统计车辆上线状态 按天 月份表'; + + + + insert into ${tableName} + (status,car_plate,year, + month,day,company_id,region_id) + values + (#{statusDay.status},#{statusDay.carPlate},#{statusDay.year}, + #{statusDay.month},#{statusDay.day}, + #{statusDay.companyId},#{statusDay.regionId}) + + + + update ${tableName} + set status = #{statusDay.status} + where id = #{statusDay.id} + + + + INSERT INTO ${tableName} + (status,car_plate,year, + month,day,company_id,region_id,online_time,online_time_interval) + values + + (#{statusDay.status},#{statusDay.carPlate},#{statusDay.year}, + #{statusDay.month},#{statusDay.day}, + #{statusDay.companyId},#{statusDay.regionId}, + #{statusDay.onlineTime},#{statusDay.onlineTimeInterval}) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.java new file mode 100644 index 0000000..88bb372 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.scheduler.mapper; + +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusHour; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 统计车辆上线状态 按小时 Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-29 + */ +public interface VehicleOnlineStatusHourMapper extends BaseMapper { + + Integer countTable(@Param("tableName") String tableName); + + VehicleOnlineStatusHour selectOneByTable(@Param("tableName") String tableName, @Param("statusHour") VehicleOnlineStatusHour statusHour); + + Integer createTable(@Param("tableName") String tableName); + + Boolean saveByReqInMonthTable(@Param("tableName") String tableName,@Param("statusHour") VehicleOnlineStatusHour statusHour); + + Boolean updateByReqInMonthTable(@Param("tableName") String tableName,@Param("statusHour") VehicleOnlineStatusHour statusHour); + + List listByTable(@Param("tableName") String tableName,@Param("statusHour") VehicleOnlineStatusHour statusHour); + + Boolean batchSave(@Param("tableName") String tableName, @Param("statusHours")List batchOnlineStatusHourToAdd); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.xml new file mode 100644 index 0000000..21a4379 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleOnlineStatusHourMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + CREATE TABLE ${tableName} ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` bigint(20) DEFAULT NULL COMMENT '创建人', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `update_by` bigint(20) DEFAULT NULL COMMENT '修改人', + `status` tinyint(2) DEFAULT NULL COMMENT '0离线 1在线 2异常', + `car_plate` varchar(32) DEFAULT NULL COMMENT '车牌号', + `year` varchar(16) DEFAULT NULL COMMENT '年', + `month` varchar(16) DEFAULT NULL COMMENT '月', + `day` varchar(16) DEFAULT NULL COMMENT '日', + `hour` varchar(16) DEFAULT NULL COMMENT '小时', + `company_id` bigint(20) DEFAULT NULL COMMENT '公司ID', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域ID', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0未删除1已删除', + `online_time` datetime DEFAULT NULL COMMENT '车辆在线时间', + `online_time_interval` int(11) DEFAULT NULL COMMENT '距离上次在线时间间隔', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_car_plate_hour` (`deleted`,`year`,`month`,`day`,`hour`,`car_plate`) USING BTREE + ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='统计车辆上线状态 按小时 月份表'; + + + + insert into ${tableName} + (status,car_plate,year, + month,day,hour,company_id,region_id) + values + (#{statusHour.status},#{statusHour.carPlate},#{statusHour.year}, + #{statusHour.month},#{statusHour.day},#{statusHour.hour}, + #{statusHour.companyId},#{statusHour.regionId}) + + + + update ${tableName} + set status = #{statusHour.status} + where id = #{statusHour.id} + + + + INSERT INTO ${tableName} + (status,car_plate,year, + month,day,hour,company_id,region_id,online_time,online_time_interval) + values + + (#{statusHour.status},#{statusHour.carPlate},#{statusHour.year}, + #{statusHour.month},#{statusHour.day},#{statusHour.hour}, + #{statusHour.companyId},#{statusHour.regionId}, + #{statusHour.onlineTime},#{statusHour.onlineTimeInterval}) + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.java new file mode 100644 index 0000000..1745cc4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.scheduler.mapper; + +import com.ningdatech.carapi.scheduler.model.dto.VehicleStatusDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Classname VehicleStatusMapper + * @Description + * @Date 2022/11/22 14:15 + * @Created by PoffyZhang + */ +public interface VehicleStatusMapper { + + List getVehicleStatusInGps(@Param("date") String date , @Param("timeScope") int timeScope); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.xml new file mode 100644 index 0000000..1f44d4a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/mapper/VehicleStatusMapper.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/AccidentQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/AccidentQueryDTO.java new file mode 100644 index 0000000..4aed18e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/AccidentQueryDTO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.scheduler.model.dto; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 事故查询入参实体 + * + * @author CMM + * @since 2023/04/28 10:09 + */ +@Data +public class AccidentQueryDTO { + + @ApiModelProperty("事故编号") + private String sgbh; + + @ApiModelProperty("登记编号") + private String djbh; + + @ApiModelProperty("车牌号") + private String carNo; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/GpsSpeedDataDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/GpsSpeedDataDTO.java new file mode 100644 index 0000000..71b62ef --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/GpsSpeedDataDTO.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.scheduler.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @return + * @author CMM + * @since 2023/05/29 15:54 + */ +@Data +public class GpsSpeedDataDTO { + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("速度") + private Integer speed; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/OverSpeedGpsDataDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/OverSpeedGpsDataDTO.java new file mode 100644 index 0000000..79cfb82 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/OverSpeedGpsDataDTO.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.scheduler.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @return + * @author CMM + * @since 2023/05/29 15:54 + */ +@Data +public class OverSpeedGpsDataDTO { + + @ApiModelProperty("GPS数据ID") + private Long id; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("经度") + private BigDecimal longitude; + + @ApiModelProperty("纬度") + private BigDecimal latitude; + + @ApiModelProperty("速度") + private BigDecimal speed; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("超速时间") + private LocalDateTime overSpeedTime; + + @ApiModelProperty("运营商ID") + private String operatorId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/VehicleStatusDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/VehicleStatusDTO.java new file mode 100644 index 0000000..ed59b56 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/model/dto/VehicleStatusDTO.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.scheduler.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @Classname VehicleStatusDTO + * @Description + * @Date 2022/11/22 14:09 + * @Created by PoffyZhang + */ +@Data +public class VehicleStatusDTO { + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("GPS的状态值") + private Long status; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("创建时间") + private LocalDateTime updateTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusDayService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusDayService.java new file mode 100644 index 0000000..a4eec36 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusDayService.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.scheduler.service; + +import java.util.List; +import java.util.Set; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusDay; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusHour; + +/** + *

+ * 统计车辆上线状态 按天 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-12-18 + */ +public interface IVehicleOnlineStatusDayService extends IService { + + VehicleOnlineStatusDay getOneByReqInMonthTable(VehicleOnlineStatusDay statusDay); + + Boolean saveByReqInMonthTable(VehicleOnlineStatusDay statusDay); + + Boolean updateByReqInMonthTable(VehicleOnlineStatusDay statusDay); + + Set getOnlineCarPlatesInMonthTables(); + + List listByReqInMonthTable(VehicleOnlineStatusDay statusDay); + + Boolean batchSave(List batchOnlineStatusDayToAdd); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusHourService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusHourService.java new file mode 100644 index 0000000..a574eac --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/IVehicleOnlineStatusHourService.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.scheduler.service; + +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusHour; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 统计车辆上线状态 按小时 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-29 + */ +public interface IVehicleOnlineStatusHourService extends IService { + + VehicleOnlineStatusHour getOneByReqInMonthTable(VehicleOnlineStatusHour statusHour); + + List listByReqInMonthTable(VehicleOnlineStatusHour statusHour); + + Boolean saveByReqInMonthTable(VehicleOnlineStatusHour statusHour); + + Boolean updateByReqInMonthTable(VehicleOnlineStatusHour oldValue); + + Boolean batchSave(List batchOnlineStatusHourToAdd); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/OverSpeedGpsDataService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/OverSpeedGpsDataService.java new file mode 100644 index 0000000..bdb2d59 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/OverSpeedGpsDataService.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.scheduler.service; + +import java.time.LocalDateTime; +import java.util.List; + +import com.ningdatech.carapi.scheduler.model.dto.GpsSpeedDataDTO; +import com.ningdatech.carapi.scheduler.model.dto.OverSpeedGpsDataDTO; + +/** + * @return + * @author CMM + * @since 2023/05/29 15:52 + */ +public interface OverSpeedGpsDataService { + + /** + * 获取GPS数据中的车辆速度信息 + * @param date + * @param startIndex + * @param endIndex + * @return + */ + List getDataInGps(String date, Long startIndex, Long endIndex); + + + /** + * 获取超速报警时刻5分钟后的GPS数据 + * @param carPlate + * @param timeBucket + * @param warnTime + * @return 返回数据列表 + * @author CMM + * @since 2023/06/01 14:59 + */ + List getDataInGps(String carPlate, LocalDateTime warnTime, Integer timeBucket); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/VehicleStatusService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/VehicleStatusService.java new file mode 100644 index 0000000..b25f2f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/VehicleStatusService.java @@ -0,0 +1,10 @@ +package com.ningdatech.carapi.scheduler.service; + +import com.ningdatech.carapi.scheduler.model.dto.VehicleStatusDTO; + +import java.util.List; + +public interface VehicleStatusService { + + List getVehicleStatusInGps(); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/OverSpeedGpsDataServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/OverSpeedGpsDataServiceImpl.java new file mode 100644 index 0000000..b02908c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/OverSpeedGpsDataServiceImpl.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.scheduler.service.impl; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.scheduler.mapper.OverSpeedGpsDataMapper; +import com.ningdatech.carapi.scheduler.model.dto.GpsSpeedDataDTO; +import com.ningdatech.carapi.scheduler.model.dto.OverSpeedGpsDataDTO; +import com.ningdatech.carapi.scheduler.service.OverSpeedGpsDataService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @return + * @author CMM + * @since 2023/05/29 16:04 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class OverSpeedGpsDataServiceImpl implements OverSpeedGpsDataService { + + private final OverSpeedGpsDataMapper overSpeedGpsDataMapper; + + @Override + public List getDataInGps(String date, Long startIndex, Long endIndex) { + return overSpeedGpsDataMapper.getOverSpeedDataInGps(date, startIndex, endIndex); + } + + @Override + public List getDataInGps(String carPlate, LocalDateTime warnTime, Integer timeBucket) { + return overSpeedGpsDataMapper.getDataInGps(carPlate,warnTime, NdDateUtils.format(LocalDateTime.now(),"yyyy_MM_dd"),timeBucket); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusDayServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusDayServiceImpl.java new file mode 100644 index 0000000..5e341b4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusDayServiceImpl.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.scheduler.service.impl; + +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusDay; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusHour; +import com.ningdatech.carapi.scheduler.mapper.VehicleOnlineStatusDayMapper; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusDayService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + *

+ * 统计车辆上线状态 按天 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-12-18 + */ +@Service +@AllArgsConstructor +@Slf4j +public class VehicleOnlineStatusDayServiceImpl extends ServiceImpl implements IVehicleOnlineStatusDayService { + + private final VehicleOnlineStatusDayMapper mapper; + + @Override + public VehicleOnlineStatusDay getOneByReqInMonthTable(VehicleOnlineStatusDay statusDay) { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.selectOneByTable(tableName,statusDay); + } + + @Override + public Boolean saveByReqInMonthTable(VehicleOnlineStatusDay statusDay) { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.saveByReqInMonthTable(tableName,statusDay); + } + + @Override + public Boolean updateByReqInMonthTable(VehicleOnlineStatusDay statusDay) { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.updateByReqInMonthTable(tableName,statusDay); + } + + @Override + public Set getOnlineCarPlatesInMonthTables() { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + String date = NdDateUtils.format(LocalDateTime.now(),NdDateUtils.DEFAULT_DATE_TIME_START_FORMAT); + return mapper.selectOnlineCarPlatesInMonthTable(tableName,date); + } + + @Override + public List listByReqInMonthTable(VehicleOnlineStatusDay statusDay) { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.listByTable(tableName,statusDay); + } + + @Override + public Boolean batchSave(List statusDays) { + String tableName = "nd_vehicle_online_status_day_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.batchSave(tableName,statusDays); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusHourServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusHourServiceImpl.java new file mode 100644 index 0000000..1063c13 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleOnlineStatusHourServiceImpl.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.scheduler.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusHour; +import com.ningdatech.carapi.scheduler.mapper.VehicleOnlineStatusHourMapper; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusHourService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; + +/** + *

+ * 统计车辆上线状态 按小时 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-29 + */ +@Service +@Slf4j +@AllArgsConstructor +public class VehicleOnlineStatusHourServiceImpl extends ServiceImpl implements IVehicleOnlineStatusHourService { + + private final VehicleOnlineStatusHourMapper mapper; + + @Override + public VehicleOnlineStatusHour getOneByReqInMonthTable(VehicleOnlineStatusHour statusHour) { + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.selectOneByTable(tableName,statusHour); + } + + @Override + public List listByReqInMonthTable(VehicleOnlineStatusHour statusHour) { + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.listByTable(tableName,statusHour); + } + + @Override + public Boolean saveByReqInMonthTable(VehicleOnlineStatusHour statusHour) { + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.saveByReqInMonthTable(tableName,statusHour); + } + + @Override + public Boolean updateByReqInMonthTable(VehicleOnlineStatusHour oldValue) { + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.updateByReqInMonthTable(tableName,oldValue); + } + + @Override + public Boolean batchSave(List batchOnlineStatusHourToAdd) { + String tableName = "nd_vehicle_online_status_hour_" + NdDateUtils.format(new Date(),"yyyy_MM"); + if(mapper.countTable(tableName) == 0){ + mapper.createTable(tableName); + } + return mapper.batchSave(tableName,batchOnlineStatusHourToAdd); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleStatusServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleStatusServiceImpl.java new file mode 100644 index 0000000..738bdb6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/service/impl/VehicleStatusServiceImpl.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.scheduler.service.impl; + +import cn.hutool.core.date.DatePattern; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.scheduler.model.dto.VehicleStatusDTO; +import com.ningdatech.carapi.scheduler.service.VehicleStatusService; +import com.ningdatech.carapi.scheduler.mapper.VehicleStatusMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @Classname VehicleStatusServiceImpl + * @Description + * @Date 2022/11/22 13:46 + * @Created by PoffyZhang + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class VehicleStatusServiceImpl implements VehicleStatusService { + + private final VehicleStatusMapper vehicleStatusMapper; + + @Override + public List getVehicleStatusInGps(){ + //设置 10分内 的GPS + int timeScope = 10; + return vehicleStatusMapper.getVehicleStatusInGps(NdDateUtils.format(LocalDateTime.now(),"yyyy_MM_dd"),timeScope); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/DriverScoreUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/DriverScoreUtils.java new file mode 100644 index 0000000..0e13ae8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/DriverScoreUtils.java @@ -0,0 +1,134 @@ +package com.ningdatech.carapi.scheduler.util; + +import java.lang.reflect.Field; +import java.time.LocalDateTime; +import java.util.Objects; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.archives.enums.DriverRelationConstant; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.driver.constant.ScoreOperateType; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.entity.DriverScoreInfo; +import com.ningdatech.carapi.driver.entity.DriverScoreRecord; +import com.ningdatech.carapi.driver.entity.StarManage; +import com.ningdatech.carapi.driver.helper.DriverBehaviorScoreHelper; +import com.ningdatech.carapi.driver.model.bo.CodingRuleBO; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.driver.service.IDriverScoreInfoService; +import com.ningdatech.carapi.driver.service.IDriverScoreRecordService; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2022/12/17 17:49 + */ +@Component +@Slf4j +public class DriverScoreUtils { + + @Autowired + private DriverBehaviorScoreHelper driverBehaviorScoreHelper; + @Autowired + private IDriverScoreInfoService iDriverScoreInfoService; + @Autowired + private IDriverScoreRecordService iDriverScoreRecordService; + + @Autowired + private IDriverInfoService driverInfoService; + + private static DriverScoreUtils driverScoreUtils; + + @PostConstruct + public void init(){ + driverScoreUtils = this; + driverScoreUtils.driverBehaviorScoreHelper = this.driverBehaviorScoreHelper; + driverScoreUtils.iDriverScoreInfoService = this.iDriverScoreInfoService; + driverScoreUtils.iDriverScoreRecordService = this.iDriverScoreRecordService; + driverScoreUtils.driverInfoService = this.driverInfoService; + } + + public static void updateDriverScoreAndRecord(T entity, CodingRuleBehaviorTypeEnum codingRuleBehaviorTypeEnum, VehicleTypeEnum vehicleTypeEnum){ + Class aClass = entity.getClass(); + Long driverId = null; + try { + Field driverIdField = aClass.getDeclaredField("driverId"); + driverIdField.setAccessible(Boolean.TRUE); + driverId = Objects.nonNull(driverIdField.get(entity)) ? (Long)driverIdField.get(entity) : null; + } catch (Exception e) { + log.error("成员变量不存在!"); + } + + CodingRuleBO codingRuleBehaviorScore = driverScoreUtils.driverBehaviorScoreHelper + .getCodingRuleBehaviorScore(codingRuleBehaviorTypeEnum,vehicleTypeEnum); + //获取对应行为类型的操作分 + Integer operationScore = codingRuleBehaviorScore.getOperationScore(); + //根据驾驶员ID获取驾驶员分数 + DriverScoreInfo driverScoreInfo = driverScoreUtils.iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class) + .eq(DriverScoreInfo::getDriverId,driverId).last(DefValConstants.LIMIT_1)); + DriverInfo driverInfo = driverScoreUtils.driverInfoService.getById(driverId); + if (Objects.isNull(driverInfo)){ + log.info("当前更新分数驾驶员信息不存在!"); + return; + } + if (Objects.isNull(driverScoreInfo)) { + driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + driverScoreInfo.setDriverScore(DriverRelationConstant.DRIVER_FULL_SCORE - operationScore); + } else { + Integer driverScore = driverScoreInfo.getDriverScore() - operationScore; + if (driverScore < 0){ + driverScore = 0; + } + driverScoreInfo.setDriverScore(driverScore); + } + driverScoreInfo.setUpdateOn(LocalDateTime.now()); + driverScoreUtils.iDriverScoreInfoService.saveOrUpdate(driverScoreInfo); + + DriverScoreRecord saveRecord = new DriverScoreRecord(); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setDriverId(driverInfo.getId()); + saveRecord.setOperateReason("驾驶员异常行为扣分"); + saveRecord.setOperateScore(DriverRelationConstant.DRIVER_FULL_SCORE); + saveRecord.setOperateType(ScoreOperateType.reduce.name()); + saveRecord.setUserId(driverInfo.getUserId()); + driverScoreUtils.iDriverScoreRecordService.save(saveRecord); + } + + public static void getCurrentStar(StarManage starManage) { + DriverScoreInfo scoreInfo = driverScoreUtils.iDriverScoreInfoService.getOne(Wrappers.lambdaQuery(DriverScoreInfo.class) + .eq(DriverScoreInfo::getDriverId, starManage.getDriverId())); + if (Objects.isNull(scoreInfo)){ + return; + } + Integer driverScore = scoreInfo.getDriverScore(); + if (driverScore >= TaskContant.Data.STAR_NUMBER_RANGE_ZERO && driverScore < TaskContant.Data.STAR_NUMBER_RANGE_TWENTY){ + starManage.setCurrentScore(driverScore); + starManage.setCurrentStar(TaskContant.Star.ONE_STAR); + } else if (driverScore >= TaskContant.Data.STAR_NUMBER_RANGE_TWENTY && driverScore < TaskContant.Data.STAR_NUMBER_RANGE_FORTY) { + starManage.setCurrentScore(driverScore); + starManage.setCurrentStar(TaskContant.Star.TWO_STAR); + }else if (driverScore >= TaskContant.Data.STAR_NUMBER_RANGE_FORTY && driverScore < TaskContant.Data.STAR_NUMBER_RANGE_SIXTY){ + starManage.setCurrentScore(driverScore); + starManage.setCurrentStar(TaskContant.Star.THREE_STAR); + }else if (driverScore >= TaskContant.Data.STAR_NUMBER_RANGE_SIXTY && driverScore < TaskContant.Data.STAR_NUMBER_RANGE_EIGHTY){ + starManage.setCurrentScore(driverScore); + starManage.setCurrentStar(TaskContant.Star.FOUR_STAR); + }else if (driverScore >= TaskContant.Data.STAR_NUMBER_RANGE_EIGHTY){ + starManage.setCurrentScore(driverScore); + starManage.setCurrentStar(TaskContant.Star.FIVE_STAR); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/GpsUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/GpsUtils.java new file mode 100644 index 0000000..9281feb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/GpsUtils.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.scheduler.util; + +import com.alibaba.fastjson.JSONObject; +import com.ningdatech.carapi.common.constant.GPSDataEnum; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.scheduler.entity.GpsData; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Optional; + +/** + * @author CMM + * @description + * @since 2022/12/07 15:23 + */ +public class GpsUtils { + + private GpsUtils() { + } + + public static GpsData getGpsData(JSONObject gpsJson) { + GpsData gpsData = new GpsData(); + BigDecimal altitudeTemp = gpsJson.getBigDecimal(GPSDataEnum.ALTITUDE.getDesc()); + Optional altitudeBigDecimal = Optional.ofNullable(altitudeTemp).map(a -> a.divide(TaskContant.Math.ALTITUDE_UNITS, RoundingMode.HALF_UP)); + if (altitudeBigDecimal.isPresent()) { + BigDecimal altitude = altitudeBigDecimal.get().setScale(2, RoundingMode.HALF_UP); + gpsData.setAltitude(altitude); + } + + BigDecimal longitudeTemp = gpsJson.getBigDecimal(GPSDataEnum.LONGITUDE.getDesc()); + Optional longitudeOptional = Optional.ofNullable(longitudeTemp).map(l -> l.divide(TaskContant.Math.LONGITUDE_UNITS, RoundingMode.HALF_UP)); + if (longitudeOptional.isPresent()) { + BigDecimal longitude = longitudeOptional.get().setScale(6, RoundingMode.HALF_UP); + gpsData.setLongitude(longitude); + } + BigDecimal latitudeTemp = gpsJson.getBigDecimal(GPSDataEnum.LATITUDE.getDesc()); + Optional latitudeOptional = Optional.ofNullable(latitudeTemp).map(l -> l.divide(TaskContant.Math.LONGITUDE_UNITS, RoundingMode.HALF_UP)); + if (latitudeOptional.isPresent()) { + BigDecimal latitude = latitudeOptional.get().setScale(6, RoundingMode.HALF_UP); + gpsData.setLatitude(latitude); + } + BigDecimal speedTemp = gpsJson.getBigDecimal(GPSDataEnum.SPEED.getDesc()); + Optional speedOptional = Optional.ofNullable(speedTemp).map(s -> s.multiply(TaskContant.Math.SPEED_UNITS)); + if (speedOptional.isPresent()) { + BigDecimal speed = speedOptional.get().setScale(2, RoundingMode.HALF_UP); + gpsData.setSpeed(speed); + } + + BigDecimal directionTemp = gpsJson.getBigDecimal(GPSDataEnum.DIRECTION.getDesc()); + Optional directionOptional = Optional.ofNullable(directionTemp).map(s -> s.divide(TaskContant.Math.DIRECTION_UNITS, RoundingMode.HALF_UP)); + if (directionOptional.isPresent()) { + BigDecimal direction = directionOptional.get().setScale(2, RoundingMode.HALF_UP); + gpsData.setDirection(direction); + } + return gpsData; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/SplitListUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/SplitListUtils.java new file mode 100644 index 0000000..3a633b7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/scheduler/util/SplitListUtils.java @@ -0,0 +1,74 @@ +package com.ningdatech.carapi.scheduler.util; + +import com.google.common.collect.Lists; +import org.apache.commons.collections.CollectionUtils; + +import java.util.List; + +/** + * 拆分结合工具类 + * + * @author shiwen + */ +public class SplitListUtils { + + /** + * 拆分集合 + * + * @param 泛型对象 + * @param resList 需要拆分的集合 + * @param subListLength 每个子集合的元素个数 + * @return 返回拆分后的各个集合组成的列表 + * 代码里面用到了guava和common的结合工具类 + **/ + public static List> split(List resList, int subListLength) { + if (CollectionUtils.isEmpty(resList) || subListLength <= 0) { + return Lists.newArrayList(); + } + List> ret = Lists.newArrayList(); + + int size = resList.size(); + if (size <= subListLength) { + // 数据量不足 subListLength 指定的大小 + ret.add(resList); + } else { + int pre = size / subListLength; + int last = size % subListLength; + // 前面pre个集合,每个大小都是 subListLength 个元素 + for (int i = 0; i < pre; i++) { + List itemList = Lists.newArrayList(); + for (int j = 0; j < subListLength; j++) { + itemList.add(resList.get(i * subListLength + j)); + } + ret.add(itemList); + } + + // last的进行处理 + if (last > 0) { + List itemList = Lists.newArrayList(); + for (int i = 0; i < last; i++) { + itemList.add(resList.get(pre * subListLength + i)); + } + ret.add(itemList); + } + } + return ret; + } + + // 运行代码 + public static void main(String[] args) { + List list = Lists.newArrayList(); + int size = 1099; + for (int i = 0; i < size; i++) { + list.add("hello-" + i); + } + // 大集合里面包含多个小集合 + List> temps = split(list, 100); + int j = 0; + // 对大集合里面的每一个小集合进行操作 + for (List obj : temps) { + System.out.println(String.format("row:%s -> size:%s,data:%s", ++j, obj.size(), obj)); + } + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/RegionContant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/RegionContant.java new file mode 100644 index 0000000..82deee3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/RegionContant.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.contants; + +/** + * @Classname RegionContant + * @Description + * @Date 2022/11/24 9:37 + * @Created by PoffyZhang + */ +public interface RegionContant { + + public static final Integer FIRST_LEVEL = 1; + + public static final Integer SECOND_LEVEL = 2; + + public static final Integer THIRD_LEVEL = 3; + + public static final Long EMPTY_PARENT_ID = 0L; + + public static final Long ZJ_REGION_ID = 77L; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/UserLoginConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/UserLoginConstant.java new file mode 100644 index 0000000..0279b19 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/contants/UserLoginConstant.java @@ -0,0 +1,15 @@ +package com.ningdatech.carapi.sys.contants; + +/** + * @author CMM + * @since 2023/01/06 10:18 + */ + +public interface UserLoginConstant { + class RedisKey { + public static final String USER_LOGIN = "cm:user:user_login_index"; + } + + String VERIFICATION_CODE = "123456"; + String LOGIN_PASSWORD = "123456Aa"; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CodingRuleController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CodingRuleController.java new file mode 100644 index 0000000..57c4bc2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CodingRuleController.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.sys.controller; + + +import com.ningdatech.carapi.sys.entity.req.ReqCodingRulePO; +import com.ningdatech.carapi.sys.entity.vo.ResCodingRuleVO; +import com.ningdatech.carapi.sys.manage.CodingRuleManage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + *

+ * 前端控制器 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/v1/coding-rule") +@Api(tags = "赋码规则") +@RequiredArgsConstructor +public class CodingRuleController { + + private final CodingRuleManage codingRuleManage; + + @ApiOperation(value = "获取赋码规则") + @PostMapping("/get") + public ResCodingRuleVO getCodingRule() { + return codingRuleManage.getCodingRule(); + } + + @ApiOperation(value = "保存赋码规则") + @PostMapping("/save") + public void saveCodingRule(@Valid @RequestBody ReqCodingRulePO request) { + codingRuleManage.saveCodingRule(request); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CompanyController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CompanyController.java new file mode 100644 index 0000000..f657255 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/CompanyController.java @@ -0,0 +1,123 @@ +package com.ningdatech.carapi.sys.controller; + +import java.util.List; +import java.util.Map; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.*; +import com.ningdatech.carapi.sys.entity.vo.CompanyVO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.manage.CompanyManage; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + * 企业管理 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/company") +@Api(value = "Company", tags = "系统管理-企业") +@RequiredArgsConstructor +public class CompanyController { + + private final CompanyManage companyManage; + private final CompanyService companyService; + private final CompaniesCacheHelper companiesCacheHelper; + + @GetMapping("/testCache") + public CompanyDTO testCache(@Valid @RequestParam Long id) { + return companiesCacheHelper.getById(id); + } + + @GetMapping("/asMap") + public Map testCache() { + return companiesCacheHelper.asMap(); + } + + @GetMapping("/refresh") + public String refresh() { + companiesCacheHelper.afterPropertiesSet(); + return "success"; + } + + @ApiOperation(value = "根据地区ID集合 查询企业ID集合", notes = "根据地区ID集合 查询企业ID集合") + @PostMapping("/getIdsByRegionIds") + public List getIdsByRegionIds(@Valid @RequestBody List regionIds) { + return companyManage.getIdsByRegionIds(regionIds); + } + + @ApiOperation(value = "企业类型级联", notes = "企业类型级联") + @GetMapping("/types") + public List queryTypes() { + return companyManage.queryCompanyTypes(); + } + + @ApiOperation(value = "企业列表查询", notes = "企业列表查询") + @GetMapping("/list") + public PageVo queryList(@Valid @ModelAttribute CompanyPageQuery companyPageQuery) { + return companyManage.queryList(companyPageQuery); + } + + @ApiOperation(value = "使用企业列表查询", notes = "使用企业列表查询") + @GetMapping("/useCompanyList") + public PageVo queryUseCompanyList(@Valid @ModelAttribute CompanyPageQuery companyPageQuery) { + return companyManage.queryUseCompanyList(companyPageQuery); + } + + /** + * 查询企业详情 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询企业详情", notes = "查询企业详情") + @GetMapping("/details") + public CompanyQueryDTO getDetails(@Valid @RequestParam Long id) { + return companyManage.getDetails(id); + } + + @ApiOperation(value = "保存新企业", notes = "保存新企业") + @PostMapping("/save") + @WebLog(value = "新增企业", modular = "系统管理-企业管理") + public CompanyVO handlerSave(@Valid @RequestBody CompanySaveDTO data) { + Company company = companyManage.save(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(company, CompanyVO.class); + } + + @ApiOperation(value = "编辑企业", notes = "编辑企业") + @PostMapping("/modify") + @WebLog(value = "编辑企业", modular = "系统管理-企业管理") + public CompanyVO handlerUpdate(@Valid @RequestBody CompanyUpdateDTO data) { + Company company = companyManage.update(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(company, CompanyVO.class); + } + + @ApiOperation(value = "删除企业", notes = "删除企业") + @PostMapping("/remove") + @WebLog(value = "删除企业", modular = "系统管理-企业管理") + public Boolean handlerDelete(@Valid @RequestBody List ids) { + return companyManage.removeByIdWithCache(ids); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/ImportTemplateDownController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/ImportTemplateDownController.java new file mode 100644 index 0000000..dd0ada0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/ImportTemplateDownController.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.sys.controller; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.poi.excel.ExcelUtil; +import cn.hutool.poi.excel.ExcelWriter; +import com.ningdatech.basic.util.SpringUtils; +import com.ningdatech.carapi.sys.entity.constant.ImportTemplateConstant; +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; +import com.ningdatech.carapi.sys.event.ImportDataEvent; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.List; + +/** + *

+ * ImportTemplateDownController + *

+ * + * @author WendyYang + * @since 16:50 2022/10/15 + */ +@RestController +@Api(tags = "导入模版下载") +@RequestMapping("/api/v1/importTemplate") +public class ImportTemplateDownController { + + @GetMapping("/down/{template}") + @ApiOperation("导入模板下载") + public void down(@PathVariable ImportTemplateEnum template, HttpServletResponse response) throws IOException { + ExcelWriter writer = ExcelUtil.getWriter(); + List colList = ImportTemplateConstant.getTemplateTitle(template); + writer.writeHeadRow(colList); + writer.getStyleSet().setBorder(BorderStyle.NONE, IndexedColors.AUTOMATIC); + CellStyle cellStyle = writer.getHeadCellStyle(); + cellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + response.setContentType("application/vnd.ms-excel;charset=utf-8"); + String fileName = URLEncoder.encode(template.getValue() + "模板", CharsetUtil.UTF_8); + response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xls"); + ServletOutputStream out = response.getOutputStream(); + writer.flush(out, true); + writer.close(); + IoUtil.close(out); + } + + @PostMapping("/import") + @ApiOperation("通用导入数据") + public void importData(@RequestParam ImportTemplateEnum template, MultipartFile file) throws IOException { + ImportDataEvent event = new ImportDataEvent(file); + event.setTemplate(template); + SpringUtils.publishEvent(event); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/MenuController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/MenuController.java new file mode 100644 index 0000000..4ef6743 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/MenuController.java @@ -0,0 +1,116 @@ +package com.ningdatech.carapi.sys.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.dto.MenuQueryDTO; +import com.ningdatech.carapi.sys.entity.dto.MenuSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.MenuUpdateDTO; +import com.ningdatech.carapi.sys.entity.vo.MenuRoleVO; +import com.ningdatech.carapi.sys.entity.vo.MenuVO; +import com.ningdatech.carapi.sys.manage.MenuManage; +import com.ningdatech.carapi.sys.service.IRoleMenuService; +import com.ningdatech.carapi.sys.service.MenuService; +import com.ningdatech.carapi.sys.utils.TreeUtil; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + *

+ * 前端控制器 + * 菜单 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Slf4j +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/menu") +@Api(value = "Menu", tags = "系统管理-菜单") +public class MenuController { + + private final MenuService menuService; + private final MenuManage menuManage; + private final IRoleMenuService roleMenuService; + + /** + * 查询系统中所有的的菜单树结构, 不用缓存,因为该接口很少会使用,就算使用,也会管理员维护菜单时使用 + */ + @ApiOperation(value = "查询系统所有的菜单", notes = "查询系统所有的菜单") + @GetMapping("/list") + public List allTree(@Valid @RequestParam(required = false,value = "title") String title) { + List list = menuService.list(Wrappers.lambdaQuery(Menu.class).orderByAsc(Menu::getSort)); + return TreeUtil.buildTree(list,title); + } + + @ApiOperation(value = "查询当前登录用户的菜单", notes = "查询当前登录用户的菜单") + @GetMapping("/current_user_menu") + public List currentUserMenu() { + List list = menuService.list(Wrappers.lambdaQuery(Menu.class).orderByAsc(Menu::getSort)); + return menuManage.buildUserMenu(list, LoginUserUtil.loginUserDetail()); + } + + /** + * 查询某个菜单 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询菜单", notes = "查询菜单") + @GetMapping("/details") + public MenuQueryDTO getDetails(@RequestParam Long id) { + Menu menu = menuService.getById(id); + MenuQueryDTO query = BeanUtil.toBean(menu, MenuQueryDTO.class); + return query; + } + + @ApiOperation(value = "保存新菜单", notes = "保存新菜单") + @PostMapping("/save") + @WebLog(value = "新增菜单", modular = "系统管理-菜单管理") + public MenuVO handlerSave(@RequestBody MenuSaveDTO data) { + menuService.save(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, MenuVO.class); + } + + @ApiOperation(value = "编辑菜单", notes = "编辑菜单") + @PostMapping("/modify") + @WebLog(value = "编辑菜单", modular = "系统管理-菜单管理") + public MenuVO handlerUpdate(@RequestBody MenuUpdateDTO data) { + menuService.update(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, MenuVO.class); + } + + @ApiOperation(value = "删除菜单", notes = "删除菜单") + @PostMapping("/remove") + @WebLog(value = "删除菜单", modular = "系统管理-菜单管理") + public Boolean handlerDelete(@RequestBody List ids) { + // 判断登录用户是否有菜单管理的权限 + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + List menuIdList = roleMenuService.list(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, roleId)).stream().map(RoleMenu::getMenuId).collect(Collectors.toList()); + Menu menu = menuService.getOne(Wrappers.lambdaQuery(Menu.class).eq(Menu::getTitle, "菜单管理")); + if (Objects.isNull(menu)){ + return false; + } + if (!menuIdList.contains(menu.getId())){ + return false; + } + return menuService.removeByIdWithCache(ids); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/OperatorController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/OperatorController.java new file mode 100644 index 0000000..848fe91 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/OperatorController.java @@ -0,0 +1,106 @@ +package com.ningdatech.carapi.sys.controller; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.dto.OperatorPageQuery; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorUpdateDTO; +import com.ningdatech.carapi.sys.entity.vo.OperatorVO; +import com.ningdatech.carapi.sys.manage.OperatorManage; +import com.ningdatech.carapi.sys.service.IRoleMenuService; +import com.ningdatech.carapi.sys.service.MenuService; +import com.ningdatech.carapi.sys.service.OperatorService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + * 运营商管理 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/operator") +@Api(value = "Operator", tags = "系统管理-运营商") +@RequiredArgsConstructor +public class OperatorController { + + private final OperatorManage operatorManage; + private final OperatorService operatorService; + private final IRoleMenuService roleMenuService; + private final MenuService menuService; + + @ApiOperation(value = "运营商列表查询", notes = "运营商列表查询") + @GetMapping("/list") + public PageVo queryList(@ModelAttribute OperatorPageQuery operatorPageQuery) { + return operatorManage.queryList(operatorPageQuery); + } + + /** + * 查询运营商详情 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询运营商详情", notes = "查询运营商详情") + @GetMapping("/details") + public OperatorQueryDTO getDetails(@RequestParam Long id) { + return operatorManage.getDetails(id); + } + + @ApiOperation(value = "保存新运营商", notes = "保存新运营商") + @PostMapping("/save") + @WebLog(value = "保存运营商信息", modular = "运营商管理") + public OperatorVO handlerSave(@RequestBody OperatorSaveDTO data) { + operatorService.save(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, OperatorVO.class); + } + + @ApiOperation(value = "编辑运营商", notes = "编辑运营商") + @PostMapping("/modify") + @WebLog(value = "编辑运营商信息", modular = "运营商管理") + public OperatorVO handlerUpdate(@RequestBody OperatorUpdateDTO data) { + operatorService.update(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, OperatorVO.class); + } + + @ApiOperation(value = "删除运营商", notes = "删除运营商") + @PostMapping("/remove") + @WebLog(value = "删除运营商信息", modular = "运营商管理") + public Boolean handlerDelete(@RequestBody List ids) { + // 判断登录用户是否有运营商管理的菜单权限 + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + List menuIdList = roleMenuService.list(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, roleId)).stream().map(RoleMenu::getMenuId).collect(Collectors.toList()); + Menu menu = menuService.getOne(Wrappers.lambdaQuery(Menu.class).eq(Menu::getTitle, "运营商管理")); + if (Objects.isNull(menu)){ + return false; + } + if (!menuIdList.contains(menu.getId())){ + return false; + } + return operatorService.removeByIdWithCache(ids); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RegionController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RegionController.java new file mode 100644 index 0000000..6c347d6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RegionController.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.sys.controller; + + +import com.ningdatech.carapi.sys.entity.req.RegionDeleteReq; +import com.ningdatech.carapi.sys.entity.req.RegionTreeReq; +import com.ningdatech.carapi.sys.entity.vo.CompanyCarInfoVO; +import com.ningdatech.carapi.sys.entity.vo.RegionCompanyCarTreeVo; +import com.ningdatech.carapi.sys.entity.vo.RegionTreeVO; +import com.ningdatech.carapi.sys.manage.RegionManage; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author LiuXinXin + * @since 2022-10-08 + */ +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/region") +@Api(tags = "系统管理-地域管理") +public class RegionController { + + private final RegionManage regionManage; + + @PostMapping("/tree") + @ApiOperation("获取区域编码的树状结构") + public List getRegionTree(@RequestBody(required = false) RegionTreeReq req) { + return regionManage.getRegionTree(req); + } + + @GetMapping("/tree/getCompanyCarInfo") + @ApiOperation("获取区域下的企业车辆树状结构") + public CompanyCarInfoVO getCompanyCarInfo(RegionTreeReq req) { + return regionManage.getCompanyCarInfo(req); + } + + @PostMapping("/regionCompanyCarNoTree") + @ApiOperation("获取区域编码的树状结构(子节点信息同名)") + public List getRegionCompanyCarNoTree(@RequestBody(required = false) RegionTreeReq req) { + return regionManage.getRegionCompanyCarNoTree(req); + } + + @PostMapping("/regionCompanyTree") + @ApiOperation("获取区域企业的树状结构") + public List getRegionCompanyTree(@RequestBody(required = false) RegionTreeReq req) { + return regionManage.getRegionCompanyTree(req); + } + + @PostMapping("/save") + @ApiOperation("保存或修改地域信息") + @WebLog(value = "保存/修改地域信息", modular = "地域管理") + public void saveRegion(@RequestBody @Valid RegionTreeVO region) { + regionManage.saveOrUpdate(region); + } + + @DeleteMapping("/delete") + @ApiOperation("删除地域信息") + @WebLog(value = "删除地域信息", modular = "地域管理") + public void deleteRegion(@RequestBody @Valid RegionDeleteReq req) { + regionManage.remove(req.getId(), req.getLevel()); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RoleController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RoleController.java new file mode 100644 index 0000000..44008c8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/RoleController.java @@ -0,0 +1,141 @@ +package com.ningdatech.carapi.sys.controller; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.dto.RolePageQuery; +import com.ningdatech.carapi.sys.entity.dto.RoleSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.RoleUpdateDTO; +import com.ningdatech.carapi.sys.entity.vo.RoleVO; +import com.ningdatech.carapi.sys.manage.RoleManage; +import com.ningdatech.carapi.sys.service.IRoleMenuService; +import com.ningdatech.carapi.sys.service.MenuService; +import com.ningdatech.carapi.sys.service.RoleService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; + +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 前端控制器 + * 角色 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/role") +@Api(value = "Role", tags = "系统管理-角色") +@RequiredArgsConstructor +public class RoleController { + + private final RoleService roleService; + + private final RoleManage roleManage; + private final IRoleMenuService roleMenuService; + private final MenuService menuService; + + @GetMapping("/test") + public Optional query() { + Optional currentUserDataScoper = roleManage.getCurrentUserDataScoper(); + return currentUserDataScoper; + } + + @ApiOperation(value = "角色列表查询", notes = "角色列表查询") + @GetMapping("/list") + public PageVo query(@Valid @ModelAttribute RolePageQuery rolePageQuery) { + return roleManage.queryList(rolePageQuery); + } + + /** + * 查询角色 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询角色", notes = "查询角色") + @GetMapping("/details") + public RoleVO getDetails(@Valid @RequestParam Long id) { + + // 判断登录用户是否有角色管理的权限 + if (!checkMenuPower()) { + return null; + } + + Role role = roleService.getById(id); + if (Objects.isNull(role)){ + return null; + } + RoleVO query = BeanUtil.toBean(role, RoleVO.class); + if(Objects.isNull(query)){ + return null; + } + //菜单 + roleManage.buildMenu(query); + return query; + } + + @ApiOperation(value = "保存新角色", notes = "保存新角色") + @PostMapping("/save") + @WebLog(value = "新增角色", modular = "系统管理-角色管理") + public RoleVO handlerSave(@Valid @RequestBody RoleSaveDTO data) { + roleService.saveRole(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, RoleVO.class); + } + + @ApiOperation(value = "编辑角色", notes = "编辑角色") + @PostMapping("/modify") + @WebLog(value = "编辑角色", modular = "系统管理-角色管理") + public RoleVO handlerUpdate(@Valid @RequestBody RoleUpdateDTO data) { + roleService.updateRole(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, RoleVO.class); + } + + @ApiOperation(value = "删除角色", notes = "删除角色") + @PostMapping("/remove") + @WebLog(value = "删除角色", modular = "系统管理-角色管理") + public Boolean handlerDelete(@Valid @RequestBody List ids) { + // 判断登录用户是否有角色管理的权限 + if (!checkMenuPower()) { + return false; + } + return roleService.removeByIdWithCache(ids); + } + + private boolean checkMenuPower() { + UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); + Long roleId = userInfoDetails.getRoleId(); + List menuIdList = roleMenuService.list(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, roleId)).stream().map(RoleMenu::getMenuId).collect(Collectors.toList()); + Menu menu = menuService.getOne(Wrappers.lambdaQuery(Menu.class).eq(Menu::getTitle, "角色管理")); + if (Objects.isNull(menu)){ + return true; + } + if (menuIdList.contains(menu.getId())){ + return true; + } + return false; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/UserController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/UserController.java new file mode 100644 index 0000000..008637c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/controller/UserController.java @@ -0,0 +1,85 @@ +package com.ningdatech.carapi.sys.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.carapi.sys.entity.dto.UserPageQuery; +import com.ningdatech.carapi.sys.entity.dto.UserSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.UserUpdateDTO; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.sys.manage.UserManage; +import com.ningdatech.carapi.user.util.LoginUserUtil; +import com.ningdatech.log.annotation.WebLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + *

+ * 前端控制器 + * 用户 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Slf4j +@Validated +@RestController +@RequestMapping("/api/user") +@Api(value = "User", tags = "系统管理-用户管理") +@RequiredArgsConstructor +public class UserController { + + private final UserManage userManage; + + @ApiOperation(value = "用户列表查询", notes = "用户列表查询") + @GetMapping("/list") + @WebLog(value = "用户列表查询", modular = "系统管理-用户管理") + public PageVo query(@Valid @ModelAttribute UserPageQuery userPageQuery) { + return userManage.queryUserList(userPageQuery); + } + + /** + * 查询用户 + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询用户", notes = "查询用户") + @GetMapping("/details") + @WebLog(value = "查询用户", modular = "系统管理-用户管理") + public UserInfoVO getDetails(@Valid @RequestParam Long id) { + return userManage.queryDetails(id); + } + + + @ApiOperation(value = "保存新用户", notes = "保存新用户") + @PostMapping("/save") + @WebLog(value = "保存新用户", modular = "系统管理-用户管理") + public UserInfoVO handlerSave(@Valid @RequestBody UserSaveDTO data) { + userManage.save(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, UserInfoVO.class); + } + + @ApiOperation(value = "编辑用户", notes = "编辑用户") + @PostMapping("/modify") + @WebLog(value = "编辑用户", modular = "系统管理-用户管理") + public UserInfoVO handlerUpdate(@Valid @RequestBody UserUpdateDTO data) { + userManage.update(data, LoginUserUtil.getUserId()); + return BeanUtil.toBean(data, UserInfoVO.class); + } + + @ApiOperation(value = "删除用户", notes = "删除用户") + @PostMapping("/remove") + @WebLog(value = "删除用户", modular = "系统管理-用户管理") + public Boolean handlerDelete(@Valid @RequestBody List ids) { + return userManage.remove(ids); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/RegionConverter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/RegionConverter.java new file mode 100644 index 0000000..6769d34 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/RegionConverter.java @@ -0,0 +1,196 @@ +package com.ningdatech.carapi.sys.convert; + +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.Pair; + +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.equipment.model.DataAccessDevices; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionTreeDTO; +import com.ningdatech.carapi.sys.entity.vo.CarVO; +import com.ningdatech.carapi.sys.entity.vo.RegionCompanyCarTreeVo; +import com.ningdatech.carapi.sys.entity.vo.RegionTreeCompanyVO; +import com.ningdatech.carapi.sys.entity.vo.RegionTreeVO; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; + +/** + *

+ * RegionConverter + *

+ * + * @author WendyYang + * @since 10:31 2022/10/12 + */ +public class RegionConverter { + + public static RegionDTO toRegionDTO(Region region) { + RegionDTO dto = new RegionDTO(); + dto.setRegionLevel(region.getLevel()); + dto.setRegionName(region.getName()); + dto.setParentCode(region.getParentCode()); + dto.setRegionCode(region.getRegionCode()); + dto.setId(region.getId()); + dto.setMapData(region.getMapData()); + dto.setDeleted(region.getDeleted()); + dto.setGovUnit(region.getGovUnit()); + dto.setParentId(region.getParentId()); + dto.unionCode(); + return dto; + } + + public static List toRegionTreeDTOList(List regionDTOList) { + if (CollectionUtils.isEmpty(regionDTOList)) { + return new ArrayList<>(); + } + return regionDTOList.stream().map(RegionConverter::toRegionTreeDTO).collect(Collectors.toList()); + } + + public static RegionTreeDTO toRegionTreeDTO(RegionDTO regionDTO) { + RegionTreeDTO treeDto = new RegionTreeDTO(); + treeDto.setLevel(regionDTO.getRegionLevel()); + treeDto.setName(regionDTO.getRegionName()); + treeDto.setParentCode(regionDTO.getParentCode()); + treeDto.setRegionCode(regionDTO.getRegionCode()); + treeDto.setUnionCode(regionDTO.getUnionCode()); + treeDto.setId(regionDTO.getId()); + treeDto.setMapData(regionDTO.getMapData()); + treeDto.setDeleted(regionDTO.getDeleted()); + treeDto.setGovUnit(regionDTO.getGovUnit()); + return treeDto; + } + + public static List toRegionTree(Long parentId, Map> regions, + boolean showDeleted, Map> carNoList, Map> companyMap) { + List treeList = new ArrayList<>(); + List children = regions.getOrDefault(parentId, Collections.emptyList()); + for (RegionDTO region : children) { + if (!showDeleted && region.getDeleted()) { + continue; + } + RegionTreeVO treeNode = new RegionTreeVO(); + treeNode.setLevel(region.getRegionLevel()); + treeNode.setName(region.getRegionName()); + treeNode.setParentCode(region.getParentCode()); + treeNode.setRegionCode(region.getRegionCode()); + List regionList = regions.get(region.getId()); + if (CollectionUtils.isNotEmpty(regionList)) { + treeNode.setChildren(toRegionTree(region.getId(), regions, showDeleted, carNoList, companyMap)); + } + + if (companyMap != null) { + List companyList = companyMap.get(region.getId()); + treeNode.setCompanyList(ObjectUtil.defaultIfNull(companyList, Collections.emptyList())); + if (treeNode.getCompanyList().size() > 0 && carNoList != null) { + treeNode.getCompanyList().forEach(company -> { + List carNos = carNoList.getOrDefault(company.getId(), Collections.emptyList()); + company.setCarNoList(carNos); + }); + } + } + treeNode.setMapData(region.getMapData()); + treeNode.setId(region.getId()); + treeNode.setUnionCode(region.getUnionCode()); + treeNode.setGovUnit(region.getGovUnit()); + treeList.add(treeNode); + } + return treeList; + } + + public static List toRegionCompanyCarNoTree(Long parentId, + Map> regions, boolean showDeleted, Map>> carNoList, + Map> companyMap, Map deviceMap, + Map> equipmentMap, Map channelsMap) { + List treeList = new ArrayList<>(); + List children = regions.getOrDefault(parentId, Collections.emptyList()); + for (RegionDTO region : children) { + if (!showDeleted && region.getDeleted()) { + continue; + } + RegionCompanyCarTreeVo regionNode = new RegionCompanyCarTreeVo(); + regionNode.setCode(region.getId()); + regionNode.setValue(region.getRegionName()); + regionNode.setType(RegionCompanyCarTreeVo.Type.REGION); + regionNode.setLevel(region.getRegionLevel()); + regionNode.setUnique(); + if (companyMap != null) { + List companies = null; + List companyList = companyMap.get(region.getId()); + boolean hasCompany = CollectionUtils.isNotEmpty(companyList); + if (hasCompany) { + companies = CollUtils.convert(companyList, w -> { + RegionCompanyCarTreeVo company = new RegionCompanyCarTreeVo(); + company.setCode(w.getId()); + company.setValue(w.getName()); + company.setType(RegionCompanyCarTreeVo.Type.COMPANY); + company.setUnique(); + return company; + }); + regionNode.getChildren().addAll(companies); + } + if (hasCompany && carNoList != null) { + companies.forEach(company -> { + List> carNos = carNoList.get(company.getCode()); + if (CollectionUtils.isNotEmpty(carNos)) { + List carNodes = CollUtils.convert(carNos, w -> { + CarVO car = w.getValue(); + RegionCompanyCarTreeVo carNo = new RegionCompanyCarTreeVo(); + carNo.setCode(w.getKey()); + carNo.setValue(car.getCarPlate()); + carNo.setStatus(car.getStatus()); + carNo.setMoving(car.getMoving()); + carNo.setType(RegionCompanyCarTreeVo.Type.CAR_NO); + carNo.setUnique(); + return carNo; + }); + company.getChildren().addAll(carNodes); + + carNodes.forEach(car -> { + List equipmentInfos = equipmentMap.get(car.getValue()); + if (CollUtil.isNotEmpty(equipmentInfos)) { + List equipNodes = CollUtils.convert(equipmentInfos, e -> { + RegionCompanyCarTreeVo equip = new RegionCompanyCarTreeVo(); + equip.setDeviceId(e.getEquipmentNo()); + NdVehicleEquipmentChannels channels = + channelsMap.get((e.getId())); + equip.setValue(channels.getName()); + // 根据平台ID和视频设备编号判断视频是否可以播放 + DataAccessDevices devices = + deviceMap.get(e.getEquipmentNo() + e.getPlatformId()); + if (Objects.nonNull(devices) && devices.getStatus() != null + && !StrPool.EMPTY.equals(devices.getStatus())) { + equip.setVideoStatus(devices.getStatus()); + } else { + equip.setVideoStatus("OFF"); + } + equip.setUnique(); + equip.setType(RegionCompanyCarTreeVo.Type.CAR_VIDEO); + return equip; + }); + car.getChildren().addAll(equipNodes); + } + }); + } + }); + + } + } + // 设置子节点信息 + List regionList = regions.get(region.getId()); + if (CollectionUtils.isNotEmpty(regionList)) { + regionNode.getChildren().addAll(toRegionCompanyCarNoTree(region.getId(), regions, showDeleted, + carNoList, companyMap, deviceMap, equipmentMap, channelsMap)); + } + treeList.add(regionNode); + } + return treeList; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserAuthConverter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserAuthConverter.java new file mode 100644 index 0000000..5321965 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserAuthConverter.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.sys.convert; + +import java.util.List; +import java.util.Objects; + +import com.ningdatech.carapi.sys.entity.dto.UserQueryDTO; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.user.entity.NdUserAuth; + +import cn.hutool.core.collection.CollUtil; + +/** + * @Classname UserAuthConverter + * @Description + * @Date 2022/10/9 10:30 + * @Created by PoffyZhang + */ +public class UserAuthConverter { + + public static UserInfoVO convert(UserInfoVO user, List auths) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(auths)){ + auths.forEach(auth -> { + if(user.getId().equals(auth.getUserId()) && Boolean.TRUE.equals(auth.getIsAvailable())){ + user.setAccount(auth.getIdentifier()); + } + }); + } + return user; + } + + public static UserQueryDTO convert(UserQueryDTO user, List auths) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(auths)){ + auths.forEach(auth -> { + if(user.getId().equals(auth.getUserId())){ + user.setAccount(auth.getIdentifier()); + user.setPassword(auth.getCredential()); + } + }); + } + return user; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserCompanyConverter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserCompanyConverter.java new file mode 100644 index 0000000..2a73851 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserCompanyConverter.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.sys.convert; + +import cn.hutool.core.collection.CollUtil; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.UserQueryDTO; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.user.entity.NdUserInfo; + +import java.util.List; +import java.util.Objects; + +/** + * @Classname UserCompanyConverter + * @Description + * @Date 2022/10/9 10:30 + * @Created by PoffyZhang + */ +public class UserCompanyConverter { + + public static UserInfoVO convert(UserInfoVO user, List companies) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(companies)){ + companies.forEach(company -> { + if(user.getCompanyId().equals(company.getId())){ + user.setCompanyName(company.getName()); + } + }); + } + return user; + } + + public static UserQueryDTO convert(UserQueryDTO user, List companies) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(companies)){ + companies.forEach(company -> { + if(user.getCompanyId().equals(company.getId())){ + user.setCompanyName(company.getName()); + } + }); + } + return user; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserRoleConverter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserRoleConverter.java new file mode 100644 index 0000000..3947ff7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/convert/UserRoleConverter.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.sys.convert; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.google.common.collect.Lists; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.UserQueryDTO; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; + +import cn.hutool.core.collection.CollUtil; + +/** + * @Classname UserRoleConverter + * @Description + * @Date 2022/10/9 10:30 + * @Created by PoffyZhang + */ +public class UserRoleConverter { + + public static UserInfoVO convert(UserInfoVO user, List roles) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(roles)){ + roles.forEach(role -> { + if(user.getRole().equals(role.getId())){ + user.setRoleName(role.getName()); + } + }); + } + return user; + } + + public static UserInfoVO convert(UserInfoVO user, List userRoles, List roles) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(userRoles) && CollUtil.isNotEmpty(roles)){ + List roleNames = Lists.newArrayList(); + roles.forEach(role -> { + userRoles.forEach(userRole -> { + if(userRole.getRoleId().equals(role.getId()) && + userRole.getUserId().equals(user.getId())){ + roleNames.add(role.getName()); + user.setRole(role.getId()); + } + }); + }); + user.setRoleName(roleNames.stream().collect(Collectors.joining(","))); + } + return user; + } + + public static UserQueryDTO convert(UserQueryDTO user, List userRoles, List roles) { + if(Objects.isNull(user) || Objects.isNull(user.getId())){ + return user; + } + if(CollUtil.isNotEmpty(userRoles) && CollUtil.isNotEmpty(roles)){ + List roleNames = Lists.newArrayList(); + roles.forEach(role -> { + userRoles.forEach(userRole -> { + if(userRole.getRoleId().equals(role.getId()) && + userRole.getUserId().equals(user.getId())){ + roleNames.add(role.getName()); + user.setRole(role.getId()); + } + }); + }); + user.setRoleName(roleNames.stream().collect(Collectors.joining(","))); + } + return user; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/BonusPointsRule.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/BonusPointsRule.java new file mode 100644 index 0000000..97c7395 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/BonusPointsRule.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.sys.entity; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/24 下午3:22 + */ +@ApiModel("加分规则") +@Data +public class BonusPointsRule { + + private List codingRuleInfoList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRule.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRule.java new file mode 100644 index 0000000..c092bb9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRule.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleVehicleType; +import com.ningdatech.carapi.sys.entity.enumeration.RuleOperationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Data +@TableName("nd_coding_rule") +@ApiModel(value = "CodingRule对象", description = "") +public class CodingRule implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + /** + * {@link RuleOperationTypeEnum} + */ + @ApiModelProperty("加分减分") + private String ruleOperationType; + + /** + * {@link CodingRuleVehicleType} + */ + @ApiModelProperty("车辆类型") + private String vehicleType; + + /** + * {@link CodingRuleBehaviorTypeEnum} + */ + @ApiModelProperty("行为类型") + private String behaviorType; + + @ApiModelProperty("操作分数") + private Integer operationScore; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRuleInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRuleInfo.java new file mode 100644 index 0000000..f0b16a9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CodingRuleInfo.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.sys.entity; + +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import com.ningdatech.carapi.sys.entity.enumeration.RuleOperationTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liuxinxin + * @date 2022/10/24 下午3:05 + */ +@Data +@ApiModel("规则") +public class CodingRuleInfo { + + @ApiModelProperty("加分减分") + @NotNull + private RuleOperationTypeEnum ruleOperationType; + + @ApiModelProperty("行为类型") + @NotNull + private CodingRuleBehaviorTypeEnum codingRuleBehaviorType; + + @ApiModelProperty("操作分数") + @NotNull + private Integer operationScore; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Company.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Company.java new file mode 100644 index 0000000..532c007 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Company.java @@ -0,0 +1,252 @@ +package com.ningdatech.carapi.sys.entity; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +import java.time.LocalDateTime; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_company_info") +@ApiModel(value = "Company", description = "企业") +@AllArgsConstructor +@Builder +public class Company extends BaseEntity { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + @NotEmpty(message = "企业名称不能为空") + @Size(max = 30, message = "企业名称长度不能超过30") + @TableField(value = "name", condition = LIKE) + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + @TableField("vehicle_num") + private Long vehicleNum; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区id") + @TableField("region_id") + private Long regionId; + + /** + * 地区名 + */ + @ApiModelProperty(value = "地区名") + @TableField("region_name") + private String regionName; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + @TableField("operator_id") + private Long operatorId; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + @Size(max = 50, message = "传真长度不能超过50") + @TableField(value = "fax") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + @TableField(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + @Size(max = 200, message = "地址长度不能超过200") + @TableField(value = "address", condition = LIKE) + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + @Size(max = 200, message = "联系人长度不能超过200") + @TableField(value = "contact_person", condition = LIKE) + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + @Size(max = 50, message = "联系方式长度不能超过50") + @TableField(value = "contact_phone", condition = LIKE) + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + @Size(max = 200, message = "法人长度不能超过200") + @TableField(value = "legal_person", condition = LIKE) + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + @Size(max = 50, message = "法人联系电话长度不能超过50") + @TableField(value = "legal_person_phone", condition = LIKE) + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + @TableField("company_type") + private Integer companyType; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 200, message = "备注不能超过200") + @TableField(value = "remark", condition = LIKE) + private String remark; + + @ApiModelProperty(value = "营业执照编号") + @TableField(value = "business_license", condition = LIKE) + private String businessLicense; + + @ApiModelProperty(value = "企业简称") + @TableField(value = "sort_name", condition = LIKE) + private String sortName; + + @ApiModelProperty(value = "员工数量") + @TableField("employees_num") + private Long employeesNum; + + @ApiModelProperty(value = "开户银行") + @TableField(value = "bank_name", condition = LIKE) + private String bankName; + + @ApiModelProperty(value = "税号") + @TableField(value = "duty_paragraph", condition = LIKE) + private String dutyParagraph; + + @ApiModelProperty(value = "银行账户") + @TableField(value = "bank_card_no", condition = LIKE) + private String bankCardNo; + + @ApiModelProperty(value = "法人邮箱") + @TableField(value = "legal_person_email", condition = LIKE) + private String legalPersonEmail; + + @ApiModelProperty(value = "企业状态") + @TableField(value = "company_status") + private Integer companyStatus; + + @ApiModelProperty(value = "注册资金") + @TableField(value = "registered_capital", condition = LIKE) + private String registeredCapital; + + @ApiModelProperty(value = "车辆企业类型") + @TableField(value = "car_company_type", condition = LIKE) + private String carCompanyType; + + @ApiModelProperty(value = "失信情况") + @TableField(value = "black_list") + private Boolean blackList; + + @ApiModelProperty(value = "经度") + @TableField(value = "longitude", condition = LIKE) + private String longitude; + + @ApiModelProperty(value = "纬度") + @TableField(value = "latitude", condition = LIKE) + private String latitude; + + @ApiModelProperty(value = "原始数据公司id 导数据使用,项目中无使用场景") + @TableField(value = "firm_id") + private Long firmId; + + @ApiModelProperty(value = "在线车辆数") + @TableField(value = "online_vehicle_num") + private Long onlineVehicleNum; + + @ApiModelProperty(value = "离线车辆数") + @TableField(value = "offline_vehicle_num") + private Long offlineVehicleNum; + + @ApiModelProperty(value = "异常车辆数") + @TableField(value = "exception_vehicle_num") + private Long exceptionVehicleNum; + + @ApiModelProperty(value = "区县管理员审核状态") + @TableField(value = "region_audit_status") + private Integer regionAuditStatus; + + @ApiModelProperty(value = "市管理员审核状态") + @TableField(value = "city_audit_status") + private Integer cityAuditStatus; + + @ApiModelProperty(value = "区县审核人") + @TableField(value = "region_audit_by") + private Long regionAuditBy; + + @ApiModelProperty(value = "市散办审核人") + @TableField(value = "city_audit_by") + private Long cityAuditBy; + + @ApiModelProperty(value = "区县审核意见") + @TableField(value = "region_audit_mind") + private String regionAuditMind; + + @ApiModelProperty(value = "市散办审核意见") + @TableField(value = "city_audit_mind") + private String cityAuditMind; + + @ApiModelProperty(value = "区县审核时间") + @TableField(value = "region_audit_time") + private LocalDateTime regionAuditTime; + + @ApiModelProperty(value = "市散办审核时间") + @TableField(value = "city_audit_time") + private LocalDateTime cityAuditTime; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyJoin.java new file mode 100644 index 0000000..cc8c285 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyJoin.java @@ -0,0 +1,216 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_company_info") +@ApiModel(value = "Company", description = "企业") +@AllArgsConstructor +@Builder +public class CompanyJoin extends BaseEntity { + + @TableId(value = "id",type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + @NotEmpty(message = "企业名称不能为空") + @Size(max = 30, message = "企业名称长度不能超过30") + @TableField(value = "name", condition = LIKE) + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + @TableField("vehicle_num") + private Long vehicleNum; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区id") + @TableField("region_id") + private Long regionId; + + /** + * 地区 + */ + @ApiModelProperty(value = "地区") + @TableField(exist = false) + private String regionName; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + @TableField("operator_id") + private Long operatorId; + + /** + * 运营商 + */ + @ApiModelProperty(value = "运营商") +// @TableField(exist = false) + private String operatorName; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + @Size(max = 50, message = "传真长度不能超过50") + @TableField(value = "fax") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + @TableField(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + @Size(max = 200, message = "地址长度不能超过200") + @TableField(value = "address", condition = LIKE) + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + @Size(max = 200, message = "联系人长度不能超过200") + @TableField(value = "contact_person", condition = LIKE) + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + @Size(max = 50, message = "联系方式长度不能超过50") + @TableField(value = "contact_phone", condition = LIKE) + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + @Size(max = 200, message = "法人长度不能超过200") + @TableField(value = "legal_person", condition = LIKE) + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + @Size(max = 50, message = "法人联系电话长度不能超过50") + @TableField(value = "legal_person_phone", condition = LIKE) + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + @TableField("company_type") + private Integer companyType; + + /** + * 公司类型名 + */ + @ApiModelProperty(value = "公司类型名") + @TableField(exist = false) + private String companyTypeName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 200, message = "备注不能超过200") + @TableField(value = "remark", condition = LIKE) + private String remark; + + @ApiModelProperty(value = "营业执照编号") + @TableField(value = "business_license", condition = LIKE) + private String businessLicense; + + @ApiModelProperty(value = "企业简称") + @TableField(value = "sort_name", condition = LIKE) + private String sortName; + + @ApiModelProperty(value = "员工数量") + @TableField("employees_num") + private Integer employeesNum; + + @ApiModelProperty(value = "开户银行") + @TableField(value = "bank_name", condition = LIKE) + private String bankName; + + @ApiModelProperty(value = "税号") + @TableField(value = "duty_paragraph", condition = LIKE) + private String dutyParagraph; + + @ApiModelProperty(value = "银行账户") + @TableField(value = "bank_card_no", condition = LIKE) + private String bankCardNo; + + @ApiModelProperty(value = "法人邮箱") + @TableField(value = "legal_person_email", condition = LIKE) + private String legalPersonEmail; + + @ApiModelProperty(value = "企业状态") + @TableField(value = "company_status") + private Integer companyStatus; + + @ApiModelProperty(value = "注册资金") + @TableField(value = "registered_capital", condition = LIKE) + private String registeredCapital; + + @ApiModelProperty(value = "车辆企业类型") + @TableField(value = "car_company_type", condition = LIKE) + private String carCompanyType; + + @ApiModelProperty(value = "失信情况") + @TableField(value = "black_list") + private Boolean blackList; + + @ApiModelProperty(value = "经度") + @TableField(value = "longitude", condition = LIKE) + private String longitude; + + @ApiModelProperty(value = "纬度") + @TableField(value = "latitude", condition = LIKE) + private String latitude; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyType.java new file mode 100644 index 0000000..7608038 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyType.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import java.io.Serializable; +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + * @Classname CompanyType + * @Description + * @Date 2022/11/2 13:54 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("nd_company_type") +@ApiModel(value = "CompanyType", description = "企业类型") +@AllArgsConstructor +@Builder +public class CompanyType implements Serializable { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业类型名称") + @TableField(value = "name", condition = LIKE) + private String name; + + /** + * 父节点 + */ + @ApiModelProperty(value = "父节点") + @TableField(value = "pid") + private Long pid; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyTypeRelated.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyTypeRelated.java new file mode 100644 index 0000000..dbebbe3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/CompanyTypeRelated.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import java.io.Serializable; + +/** + * @Classname CompanyTypeRelated + * @Description + * @Date 2022/11/2 13:54 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("nd_company_type_related") +@ApiModel(value = "CompanyTypeRelated", description = "企业类型关系表") +@AllArgsConstructor +@Builder +public class CompanyTypeRelated implements Serializable { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "企业ID") + @TableField(value = "company_id") + private Long companyId; + + @ApiModelProperty(value = "类型的id") + @TableField(value = "company_type_id") + private Long companyTypeId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ExamRule.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ExamRule.java new file mode 100644 index 0000000..dad0bf5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ExamRule.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.driver.constant.QuestionTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Data +@TableName("nd_exam_rule") +@ApiModel(value = "ExamRule对象", description = "") +public class ExamRule implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + private Long updateBy; + + @ApiModelProperty("每题分数") + private Integer perQuestionScore; + + /** + * {@link QuestionTypeEnum} + */ + @ApiModelProperty("题目类型") + private String questionType; + + @ApiModelProperty("题目需要数量") + private Integer questionCnt; + + @ApiModelProperty("所属区域") + private Long regionId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Menu.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Menu.java new file mode 100644 index 0000000..d8f4a25 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Menu.java @@ -0,0 +1,88 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 菜单 + *

+ * + * @author PoffyZhang + * @since 2022-9-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_menu") +@ApiModel(value = "Menu", description = "菜单") +@AllArgsConstructor +public class Menu extends TreeEntity { + + private static final long serialVersionUID = 1L; + + /** + * 权限" + */ + @ApiModelProperty(value = "权限") + @Size(max = 200, message = "权限长度不能超过200") + @TableField(value = "permission", condition = LIKE) + private String permission; + /** + * 类型;[0-菜单 1-目录 2-按钮] + */ + @ApiModelProperty(value = "类型") + @TableField(value = "type") + private Integer type; + + /** + * 组件 + */ + @ApiModelProperty(value = "组件") + @Size(max = 255, message = "组件长度不能超过255") + @TableField(value = "component", condition = LIKE) + private String component; + + /** + * 菜单图标 + */ + @ApiModelProperty(value = "菜单图标") + @Size(max = 255, message = "菜单图标长度不能超过255") + @TableField(value = "icon", condition = LIKE) + private String icon; + + /** + * 子菜单数目 + */ + @ApiModelProperty(value = "是否隐藏") + @TableField(value = "`hidden`") + private Integer hidden; + + /** + * activeMenu + */ + @ApiModelProperty(value = "activeMenu") + @TableField(value = "`active_menu`") + private String activeMenu; + + + /** + * 跳转 + */ + @ApiModelProperty(value = "跳转") + @TableField(value = "redirect") + private String redirect; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/MetaApply.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/MetaApply.java new file mode 100644 index 0000000..6a2320c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/MetaApply.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Liuxinxin + * @since 2022-10-15 + */ +@TableName("nd_meta_apply") +@Data +@ApiModel(value = "MetaApply对象", description = "") +public class MetaApply implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + @ApiModelProperty("审核记录所属用户id") + private Long userId; + + @ApiModelProperty("审核类型") + private String applyType; + + @ApiModelProperty("审核状态") + private String applyStatus; + + @ApiModelProperty("发起审核时间") + private LocalDateTime applyTime; + + @ApiModelProperty("审核时间") + private LocalDateTime reviewTime; + + @ApiModelProperty("审核意见") + private String auditOpinion; + + @ApiModelProperty("审核员id") + private Long approverUserId; + + @ApiModelProperty("审核员姓名(冗余字段)") + private String approver; + + @ApiModelProperty("发起审核人id") + private Long applicantId; + + @ApiModelProperty("发起审核人姓名") + private String applicant; + + @ApiModelProperty("额外材料") + private String extraMaterial; + + @ApiModelProperty("是否展示") + private String displayEnable; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("公司ID") + private Long companyId; + + @ApiModelProperty("申请类型") + private Integer applicantType; + + @ApiModelProperty("意向跳槽企业ID") + private Long jobChangeCompanyId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Operator.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Operator.java new file mode 100644 index 0000000..2548c8b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Operator.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_operator_info") +@ApiModel(value = "Operator", description = "运营商") +@AllArgsConstructor +@Builder +public class Operator extends BaseEntity { + + @TableId(value = "id",type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 运营商名称 + */ + @ApiModelProperty(value = "运营商名称") + @NotEmpty(message = "运营商名称不能为空") + @Size(max = 50, message = "运营商名称长度不能超过50") + @TableField(value = "name", condition = LIKE) + private String name; + + /** + * 运营商备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 250, message = "备注长度不能超过250") + @TableField(value = "remark", condition = LIKE) + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/OperatorRegionHead.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/OperatorRegionHead.java new file mode 100644 index 0000000..51f972a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/OperatorRegionHead.java @@ -0,0 +1,83 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 运营商区域负责人 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_operator_region_head") +@ApiModel(value = "OperatorRegionHead", description = "运营商区域负责人") +@AllArgsConstructor +@Builder +public class OperatorRegionHead extends BaseEntity { + + @TableId(value = "id",type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 区域负责人 + */ + @ApiModelProperty(value = "区域负责人") + @NotEmpty(message = "区域负责人不能为空") + @Size(max = 50, message = "区域负责人长度不能超过50") + @TableField(value = "regional_head", condition = LIKE) + private String regionalHead; + + /** + * 区域id + */ + @ApiModelProperty(value = "区域id") + @TableField(value = "region_id") + private Long regionId; + + /** + * 区域名字 + */ + @ApiModelProperty(value = "区域名") + @TableField(exist = false) + private String regionName; + + /** + *运营商ID + */ + @ApiModelProperty(value = "运营商ID") + @TableField(value = "operator_id") + private Long operatorId; + + /** + * 联系电话 + */ + @ApiModelProperty(value = "联系电话") + @Size(max = 20, message = "联系电话长度不能超过20") + @TableField(value = "mobile", condition = LIKE) + private String mobile; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Region.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Region.java new file mode 100644 index 0000000..8e25382 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Region.java @@ -0,0 +1,52 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * Region - 地域实体 + *

+ * + * @author WendyYang + * @since 10:33 2022/10/12 + */ +@Data +@TableName("nd_region") +public class Region implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String regionCode; + + private String name; + + private Integer level; + + private String govUnit; + + private String parentCode; + + private Long parentId; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long createBy; + + private Long updateBy; + + private Boolean deleted; + + private String mapData; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Resource.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Resource.java new file mode 100644 index 0000000..37762e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Resource.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 资源 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("c_resource") +@ApiModel(value = "Resource", description = "资源") +@AllArgsConstructor +public class Resource extends BaseEntity { + + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 编码 + */ + @ApiModelProperty(value = "编码") + @Size(max = 500, message = "编码长度不能超过500") + @TableField(value = "code", condition = LIKE) + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Size(max = 255, message = "名称长度不能超过255") + @TableField(value = "name", condition = LIKE) + private String name; + + /** + * 菜单ID + * #c_menu + */ + @ApiModelProperty(value = "菜单ID") + @TableField("menu_id") + private Long menuId; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 255, message = "描述长度不能超过255") + @TableField(value = "describe_", condition = LIKE) + private String describe; + + /** + * 内置 + */ + @ApiModelProperty(value = "内置") + @TableField("readonly_") + private Boolean readonly; + + + @Builder + public Resource(Long id, Long createdBy, LocalDateTime createTime, Long updatedBy, LocalDateTime updateTime, + String code, String name, Long menuId, String describe, Boolean readonly) { + this.id = id; + this.createBy = createdBy; + this.createOn = createTime; + this.updateBy = updatedBy; + this.updateOn = updateTime; + this.code = code; + this.name = name; + this.menuId = menuId; + this.describe = describe; + this.readonly = readonly; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Role.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Role.java new file mode 100644 index 0000000..14308e1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/Role.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 角色 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_role") +@ApiModel(value = "Role", description = "角色") +@AllArgsConstructor +public class Role extends BaseEntity { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Size(max = 30, message = "名称长度不能超过30") + @TableField(value = "name", condition = LIKE) + private String name; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 100, message = "描述长度不能超过100") + @TableField(value = "describe_", condition = LIKE) + private String describe; + + /** + * 数据范围 + */ + @ApiModelProperty(value = "数据范围 1全部 2本区域 3本区域以及下区域 4本公司") + private Integer dataScope; + + @ApiModelProperty("角色排序") + private Integer sort; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleAuthority.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleAuthority.java new file mode 100644 index 0000000..dcdd630 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleAuthority.java @@ -0,0 +1,76 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import com.ningdatech.carapi.sys.entity.enumeration.AuthorizeType; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 角色的资源 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_role_authority") +@ApiModel(value = "RoleAuthority", description = "角色的资源") +@AllArgsConstructor +public class RoleAuthority extends BaseEntity { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 资源id + * #c_resource #c_menu + */ + @ApiModelProperty(value = "资源id") + @NotNull(message = "资源id不能为空") + @TableField("authority_id") + private Long authorityId; + + /** + * 权限类型 + * #AuthorizeType{MENU:菜单;RESOURCE:资源;} + */ + @ApiModelProperty(value = "权限类型") + @NotNull(message = "权限类型不能为空") + @TableField("authority_type") + private AuthorizeType authorityType; + + /** + * 角色id + * #c_role + */ + @ApiModelProperty(value = "角色id") + @NotNull(message = "角色id不能为空") + @TableField("role_id") + private Long roleId; + + + @Builder + public RoleAuthority(Long id, LocalDateTime createTime, Long createdBy, + Long authorityId, AuthorizeType authorityType, Long roleId) { + this.id = id; + this.createOn = createTime; + this.createBy = createdBy; + this.authorityId = authorityId; + this.authorityType = authorityType; + this.roleId = roleId; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleMenu.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleMenu.java new file mode 100644 index 0000000..5c1761e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/RoleMenu.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-11-11 + */ +@TableName("nd_role_menu") +@Data +@ApiModel(value = "RoleMenu对象", description = "") +@AllArgsConstructor +@NoArgsConstructor +public class RoleMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("menu_id") + private Long menuId; + + @ApiModelProperty("role_id") + private Long roleId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ScoreDeductionRule.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ScoreDeductionRule.java new file mode 100644 index 0000000..ae76bfd --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/ScoreDeductionRule.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.sys.entity; + +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleVehicleType; +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/24 下午3:23 + */ +@ApiModel("扣分规则") +@Data +public class ScoreDeductionRule { + private CodingRuleVehicleType vehicleType; + private List codingRuleInfoList; +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/TreeEntity.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/TreeEntity.java new file mode 100644 index 0000000..4a02141 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/TreeEntity.java @@ -0,0 +1,131 @@ +package com.ningdatech.carapi.sys.entity; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + * 包括id、create_time、created_by、updated_by、update_time、label、parent_id、sort_value 字段的表继承的树形实体 + * + * @author PoffyZhang + * @since 2022/09/30 + */ +@Getter +@Setter +@Accessors(chain = true) +@ToString(callSuper = true) +public class TreeEntity, T extends Serializable> extends BaseEntity { + + @TableId(value = "id", type = IdType.AUTO) + protected Long id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Size(max = 255, message = "名称长度不能超过255") + @TableField(value = "name", condition = LIKE) + protected String name; + + /** + * 菜单标题 + */ + @ApiModelProperty(value = "菜单标题") + @NotEmpty(message = "菜单标题不能为空") + @Size(max = 255, message = "菜单标题长度不能超过255") + @TableField(value = "title", condition = LIKE) + protected String title; + + /** + * 父菜单ID + */ + @ApiModelProperty(value = "父ID") + @TableField(value = "pid") + protected Long pid; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序号") + @TableField(value = "sort") + protected Integer sort; + + /** + * 顶层菜单 + */ + @ApiModelProperty(value = "顶层菜单") + @TableField(exist = false) + protected String topMenu; + + /** + * 路径 + */ + @ApiModelProperty(value = "路径") + @Size(max = 255, message = "路径长度不能超过255") + @TableField(value = "path", condition = LIKE) + protected String path; + + + @ApiModelProperty(value = "子节点", hidden = true) + @TableField(exist = false) + protected Set children; + + + /** + * 层级 + */ + @ApiModelProperty(value = "层级") + @TableField(exist = false) + protected Integer level = 1; + + + /** + * 初始化子类 + */ + @JsonIgnore + public void initChildren() { + if (getChildren() == null) { + Comparator> comparator = Comparator.comparing(w -> ObjectUtil.defaultIfNull(w.getSort(), 0)); + comparator = comparator.thenComparing(TreeEntity::getId); + this.setChildren(new TreeSet<>(comparator)); + } + } + + @JsonIgnore + public void addChildren(E child) { + initChildren(); + children.add(child); + } + + public Integer getSize() { + if (CollUtil.isNotEmpty(getChildren())) { + return getChildren().size(); + } + return 0; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/UserRole.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/UserRole.java new file mode 100644 index 0000000..e8a0f41 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/UserRole.java @@ -0,0 +1,63 @@ +package com.ningdatech.carapi.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 角色分配 + * 账号角色绑定 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("nd_user_role") +@ApiModel(value = "UserRole", description = "角色分配") +public class UserRole { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 角色ID + * #c_role + */ + @ApiModelProperty(value = "角色ID") + @NotNull(message = "角色ID不能为空") + @TableField("role_id") + private Long roleId; + + /** + * 用户ID + * #c_user + */ + @ApiModelProperty(value = "用户ID") + @NotNull(message = "用户ID不能为空") + @TableField("user_id") + private Long userId; + + + @Builder + public UserRole(Long roleId, Long userId) { + this.roleId = roleId; + this.userId = userId; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/constant/ImportTemplateConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/constant/ImportTemplateConstant.java new file mode 100644 index 0000000..0e995ae --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/constant/ImportTemplateConstant.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.sys.entity.constant; + +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; + +import java.util.*; + +/** + *

+ * ImportTemplateEnumConstant + *

+ * + * @author WendyYang + * @since 20:11 2022/11/4 + */ +public class ImportTemplateConstant { + + public static final List VEHICLE_VIOLATION_COL_LIST = Arrays.asList("序号","城市","区(县)","企业名称","车牌号","车架号","行驶里程", "总累计违章次数", "万公里违章次数", "风险评估","备注"); + + public static final List VEHICLE_ACCIDENT_COL_LIST = Arrays.asList("序号","城市","区(县)","企业名称","车牌号","车架号","行驶里程", "总累计出险次数", "万公里出险次数", "风险评估","备注"); + + public static final List VEHICLE_OVER_SPEED_COL_LIST = Arrays.asList("序号","城市","区(县)","企业名称","车牌号","车架号","行驶里程", "总累计超速次数", "万公里超速次数", "风险评估","备注"); + + private static final List LAB_WORKER_CERTIFICATE = Arrays.asList("企业完整名称", "姓名", "性别", "身份证号码", "证照编号", "有效开始日期", "有效结束日期", "备注"); + + private static final List LAB_ACCEPTANCE_CERTIFICATE = Arrays.asList("证书编号", "企业完整名称", "备案项目", "执行标准", "发证机关", "发证日期", "备注", "换证日期"); + + // private fileout final List LAB_ACCEPTANCE_CERTIFICATE = Arrays.asList("证书编号", "企业名称", "备案项目", "生产能力", "执行标准", "有限期限", "发证机关", "发证日期", "备注", "换证日期"); + + public static final List VEHICLE_OUT_DANGER_COL_LIST = Arrays.asList("序号","所属区域","车牌号", "保險公司", "企业名称", "事故地点", "事故时间","受伤人数","死亡人数","理赔金额"); + + public static final List DRIVER_ARCHIVES_COL_LIST = Arrays.asList("姓名","性别","身份证号(必填)","出生年月","籍贯","手机号码","健康状况","住址","驾驶证号","准驾车型","驾驶证初次申领时间","拟驾车型","违法违规信息"); + + private static final Map> IMPORT_TEMPLATE_MAP; + + static { + IMPORT_TEMPLATE_MAP = new HashMap<>(ImportTemplateEnum.values().length); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.VEHICLE_ACCIDENT, VEHICLE_ACCIDENT_COL_LIST); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.VEHICLE_VIOLATION, VEHICLE_VIOLATION_COL_LIST); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.VEHICLE_OVER_SPEED, VEHICLE_OVER_SPEED_COL_LIST); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.LAB_WORKER_CERTIFICATE_QUA, LAB_WORKER_CERTIFICATE); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.LAB_WORKER_CERTIFICATE_EDU, LAB_WORKER_CERTIFICATE); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.LAB_ACCEPTANCE_CERTIFICATE, LAB_ACCEPTANCE_CERTIFICATE); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.INSURE_OUT_DANGER, VEHICLE_OUT_DANGER_COL_LIST); + IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.DRIVER_ARCHIVES,DRIVER_ARCHIVES_COL_LIST); + } + + public static List getTemplateTitle(ImportTemplateEnum template) { + return IMPORT_TEMPLATE_MAP.getOrDefault(template, Collections.emptyList()); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeCodeDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeCodeDTO.java new file mode 100644 index 0000000..7098536 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeCodeDTO.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + *

+ * 级联字典实体 + *

+ * + * @author PoffyZhang + * @since 2023/5/11 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(value = "CascadeCodeDTO", description = "用于级联返回") +public class CascadeCodeDTO { + + public static CascadeCodeDTO of(String code, String name) { + return new CascadeCodeDTO(code, name, null); + } + + public static CascadeCodeDTO of(String code, String name, List list) { + return new CascadeCodeDTO(code, name, list); + } + + private String code; + + private String name; + + private List children; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeDTO.java new file mode 100644 index 0000000..f4360d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CascadeDTO.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import lombok.*; +import lombok.experimental.Accessors; + +import java.util.Collections; +import java.util.List; + +/** + * @Classname CascadeDTO + * @Description + * @Date 2022/11/2 13:50 + * @Created by PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CascadeDTO", description = "用于级联返回") +public class CascadeDTO { + + public static CascadeDTO of(Long id,String name,List list){ + return new CascadeDTO(id,name,list); + } + + private Long id; + + private String name; + + private List children; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyDTO.java new file mode 100644 index 0000000..d0deb48 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyDTO.java @@ -0,0 +1,134 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 值对象 + * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "CompanyDTO", description = "企业") +@AllArgsConstructor +@Builder +public class CompanyDTO extends BaseEntity { + + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + private Long vehicleNum; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区id") + private Long regionId; + + /** + * 地区 + */ + @ApiModelProperty(value = "地区") + private String regionName; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + private Long operatorId; + + /** + * 运营商 + */ + @ApiModelProperty(value = "运营商") + private String operatorName; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + private Integer companyType; + + /** + * 公司类型名 + */ + @ApiModelProperty(value = "公司类型名") + private String companyTypeName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + @ApiModelProperty("经度") + private String longitude; + + @ApiModelProperty("维度") + private String latitude; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyPageQuery.java new file mode 100644 index 0000000..4b3d360 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyPageQuery.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import java.io.Serializable; +import java.util.List; + +import com.ningdatech.basic.model.PagePo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CompanyPageQuery", description = "企业") +public class CompanyPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称 模糊查询") + private String name; + + /** + * 所属区域id + */ + @ApiModelProperty(value = "所属区域id") + private Long regionId; + + /** + * 运营商 + */ + @ApiModelProperty(value = "运营商名字模糊查询") + private String operatorName; + + @ApiModelProperty(value = "是否失信") + private Boolean blackList; + + @ApiModelProperty(value = "公司类型 0管理企业 1生产企业 2物流企业 3其他") + private Integer companyType; + + @ApiModelProperty(value = "公司类型 0管理企业 1生产企业 2物流企业 3其他") + private List companyTypeList; + + @ApiModelProperty(value = "生产企业类型 2预拌砂浆生产企业 3预拌混凝土生产企业 4水泥生产企业") + private Integer productCompanyType; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyQueryDTO.java new file mode 100644 index 0000000..3c7d77c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyQueryDTO.java @@ -0,0 +1,146 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import java.io.Serializable; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CompanyQueryDTO", description = "企业") +public class CompanyQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + private Long vehicleNum; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区ID") + private Long regionId; + + /** + * 地区 + */ + @ApiModelProperty(value = "地区") + private String regionName; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + private Long operatorId; + + /** + * 运营商 + */ + @ApiModelProperty(value = "运营商") + private String operatorName; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + private Integer companyType; + + /** + * 公司类型名 + */ + @ApiModelProperty(value = "公司类型名") + private String companyTypeName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 企业类型 + */ + @ApiModelProperty(value = "企业类型") + private List enterpriseTypes; + private String enterpriseTypesName; + + @ApiModelProperty(value = "营业执照编号") + private String businessLicense; + + @ApiModelProperty(value = "经度") + private String longitude; + + @ApiModelProperty(value = "纬度") + private String latitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanySaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanySaveDTO.java new file mode 100644 index 0000000..fcfc270 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanySaveDTO.java @@ -0,0 +1,125 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CompanySaveDTO", description = "企业") +public class CompanySaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + @NotEmpty(message = "请输入企业名称!") + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + private Long vehicleNum; + + /** + * 地区id + */ + @ApiModelProperty(value = "地区id") + @NotNull(message = "请选择地区!") + private Long regionId; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") +// @NotNull(message = "请选择运营商!") + private Long operatorId; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + private Integer companyType; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + @ApiModelProperty(value = "生产企业类型") + private List enterpriseTypes; + + @ApiModelProperty(value = "营业执照编号") + private String businessLicense; + + @ApiModelProperty(value = "经度") + private String longitude; + + @ApiModelProperty(value = "纬度") + private String latitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyUpdateDTO.java new file mode 100644 index 0000000..1b02dde --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/CompanyUpdateDTO.java @@ -0,0 +1,131 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "CompanyUpdateDTO", description = "企业") +public class CompanyUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + @NotNull(message = "请传id") + private Long id; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + private Long vehicleNum; + + /** + * 地区id + */ + @ApiModelProperty(value = "地区id") + private Long regionId; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + private Long operatorId; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + private Integer companyType; + + /** + * 公司类型名 + */ + @ApiModelProperty(value = "公司类型名") + private String companyTypeName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + @ApiModelProperty(value = "生产企业类型") + private List enterpriseTypes; + + @ApiModelProperty(value = "营业执照编号") + private String businessLicense; + + @ApiModelProperty(value = "经度") + private String longitude; + + @ApiModelProperty(value = "纬度") + private String latitude; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/GlobalUserPageDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/GlobalUserPageDTO.java new file mode 100644 index 0000000..92bb2c5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/GlobalUserPageDTO.java @@ -0,0 +1,65 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 全局账号 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "GlobalUserSaveDTO", description = "全局账号") +public class GlobalUserPageDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ApiModelProperty(value = "租户编号") + @NotEmpty(message = "租户编号不能为空") + @Size(max = 10, message = "租户编号长度不能超过10") + private String tenantCode; + /** + * 账号 + */ + @ApiModelProperty(value = "账号") + @NotEmpty(message = "账号不能为空") + @Size(max = 30, message = "账号长度不能超过30") + private String account; + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + @Size(max = 20, message = "手机长度不能超过20") + private String mobile; + /** + * 姓名 + */ + @ApiModelProperty(value = "姓名") + @Size(max = 50, message = "姓名长度不能超过20") + private String name; + /** + * 邮箱 + */ + @ApiModelProperty(value = "邮箱") + @Size(max = 255, message = "邮箱长度不能超过255") + private String email; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuQueryDTO.java new file mode 100644 index 0000000..e630ea4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuQueryDTO.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 实体类 + * 菜单 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "MenuQueryDTO", description = "菜单") +public class MenuQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + private String name; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题") + private String title; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * 页面路径 + */ + @ApiModelProperty(value = "页面路径") + private String path; + + /** + * 图标 + */ + @ApiModelProperty(value = "图标") + private String icon; + + /** + * 组件 + */ + @ApiModelProperty(value = "组件") + private String component; + + /** + * 权限 + */ + @ApiModelProperty(value = "权限") + private String permission; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序") + private Integer sort; + + /** + * 父菜单ID + */ + @ApiModelProperty(value = "父菜单ID") + private Long pid; + + /** + * activeMenu + */ + @ApiModelProperty(value = "activeMenu") + private String activeMenu; + + /** + * 跳转 + */ + @ApiModelProperty(value = "跳转") + private String redirect; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuSaveDTO.java new file mode 100644 index 0000000..51e1354 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuSaveDTO.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 菜单 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "MenuSaveDTO", description = "菜单") +public class MenuSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + private String name; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题") + @NotEmpty(message = "请输入菜单标题") + private String title; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + @NotNull(message = "请选择类型") + private Integer type; + + /** + * 页面路径 + */ + @ApiModelProperty(value = "页面路径") + private String path; + + /** + * 图标 + */ + @ApiModelProperty(value = "图标") + private String icon; + + /** + * 组件 + */ + @ApiModelProperty(value = "组件") + private String component; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序") + private Integer sort; + + /** + * 父菜单ID + */ + @ApiModelProperty(value = "父菜单ID") + private Long pid; + + /** + * 是否隐藏 0不隐藏 1隐藏 + */ + @ApiModelProperty(value = "是否隐藏") + private Integer hidden; + + /** + * activeMenu + */ + @ApiModelProperty(value = "activeMenu") + private String activeMenu; + + /** + * 跳转 + */ + @ApiModelProperty(value = "跳转") + private String redirect; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuUpdateDTO.java new file mode 100644 index 0000000..e1ce2c0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/MenuUpdateDTO.java @@ -0,0 +1,101 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 菜单 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "MenuUpdateDTO", description = "菜单") +public class MenuUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + @NotNull(message = "请传id") + private Long id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + private String name; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题") + private String title; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * 页面路径 + */ + @ApiModelProperty(value = "页面路径") + private String path; + + /** + * 图标 + */ + @ApiModelProperty(value = "图标") + private String icon; + + /** + * 组件 + */ + @ApiModelProperty(value = "组件") + private String component; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序") + private Integer sort; + + /** + * 父菜单ID + */ + @ApiModelProperty(value = "父菜单ID") + private Long pid; + + /** + * 是否隐藏 0不隐藏 1隐藏 + */ + @ApiModelProperty(value = "是否隐藏") + private Integer hidden; + + /** + * activeMenu + */ + @ApiModelProperty(value = "activeMenu") + private String activeMenu; + + /** + * 跳转 + */ + @ApiModelProperty(value = "跳转") + private String redirect; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorPageQuery.java new file mode 100644 index 0000000..26a6c2d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorPageQuery.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "OperatorPageQuery", description = "运营商") +public class OperatorPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 运营商名称 + */ + @ApiModelProperty(value = "运营商名称") + private String name; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorQueryDTO.java new file mode 100644 index 0000000..04de177 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorQueryDTO.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "OperatorQueryDTO", description = "运营商") +public class OperatorQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 运营商名称 + */ + @ApiModelProperty(value = "运营商名称") + private String name; + + /** + * 运营商备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 区域负责人 + */ + @ApiModelProperty(value = "区域负责人") + private List operatorRegionHeads; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime createOn; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorRegionHeadSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorRegionHeadSaveDTO.java new file mode 100644 index 0000000..1f04c1d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorRegionHeadSaveDTO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "OperatorRegionHeadSaveDTO", description = "运营商") +public class OperatorRegionHeadSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 区域负责人 + */ + @ApiModelProperty(value = "区域负责人") + private String regionalHead; + + /** + * 区域id + */ + @ApiModelProperty(value = "区域id") + private Long regionId; + + /** + *联系电话 + */ + @ApiModelProperty(value = "联系电话") + private String mobile; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorSaveDTO.java new file mode 100644 index 0000000..3a57ef6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorSaveDTO.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "OperatorSaveDTO", description = "运营商") +public class OperatorSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 运营商名称 + */ + @ApiModelProperty(value = "运营商名称") + @NotEmpty(message = "请输入运营商名称!") + private String name; + + /** + * 运营商备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 运营商区域负责人 + */ + @ApiModelProperty(value = "运营商区域负责人") + private List operatorRegionHeads; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorUpdateDTO.java new file mode 100644 index 0000000..e3df750 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/OperatorUpdateDTO.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "OperatorUpdateDTO", description = "运营商") +public class OperatorUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + @NotNull(message = "请传id") + private Long id; + + /** + * 运营商名称 + */ + @ApiModelProperty(value = "运营商名称") + private String name; + + /** + * 运营商备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 运营商区域负责人 + */ + @ApiModelProperty(value = "运营商区域负责人") + private List operatorRegionHeads; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/PageParamsDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/PageParamsDTO.java new file mode 100644 index 0000000..cca5197 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/PageParamsDTO.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.util.HashMap; +import java.util.Map; + +/** + * 分页参数 + * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@ApiModel(value = "PageParams", description = "分页参数") +public class PageParamsDTO { + + @NotNull(message = "查询对象model不能为空") + @ApiModelProperty(value = "查询参数", required = true) + private T model; + + @ApiModelProperty(value = "页面大小", example = "10") + private Long size = 10L; + + @ApiModelProperty(value = "当前页", example = "1") + private Long current = 1L; + + @ApiModelProperty(value = "排序规则, 默认descending", allowableValues = "descending,ascending", example = "descending") + private String order = "descending"; + + @ApiModelProperty("扩展参数") + private Map extra = new HashMap<>(16); + + + public PageParamsDTO(long current, long size) { + this.size = size; + this.current = current; + } + + /** + * 构建分页对象 + * + * @return 分页对象 + */ + @JsonIgnore + public IPage buildPage() { + PageParamsDTO params = this; + return new Page<>(params.getCurrent(), params.getSize()); + } + + /** + * 计算当前分页偏移量 + */ + @JsonIgnore + public long offset() { + long current = this.current; + if (current <= 1L) { + return 0L; + } + return (current - 1) * this.size; + } + + @JsonIgnore + public PageParamsDTO put(String key, Object value) { + if (this.extra == null) { + this.extra = new HashMap<>(16); + } + this.extra.put(key, value); + return this; + } + + @JsonIgnore + public PageParamsDTO putAll(Map extra) { + if (this.extra == null) { + this.extra = new HashMap<>(16); + } + this.extra.putAll(extra); + return this; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionDTO.java new file mode 100644 index 0000000..ee4fd63 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionDTO.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Tolerate; + +/** + * @author liuxinxin + * @date 2022/7/22 上午9:12 + */ +@Data +@Builder +public class RegionDTO { + + @Tolerate + public RegionDTO() { + } + + /** + * 区域码 + */ + private String regionCode; + + /** + * 地区名 + */ + private String regionName; + + /** + * 地区级别 + */ + private Integer regionLevel; + + /** + * 地区父级code 当parent_code 为 -1 时为顶级区域 + */ + private String parentCode; + + /** + * 唯一编码:regionCode##regionName##regionLevel + */ + private String unionCode; + + private Long id; + + private String mapData; + + private Boolean deleted; + + private String govUnit; + + private Long parentId; + + public void unionCode() { + this.unionCode = String.format("%s##%s##%s", this.regionCode, this.regionName, this.regionLevel); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionInfo.java new file mode 100644 index 0000000..059723b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionInfo.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/9 上午10:46 + */ +@Data +@ApiModel(description = "区域信息") +public class RegionInfo { + + @ApiModelProperty("区域code") + private String regionCode; + + @ApiModelProperty("区域级别") + private Integer regionLevel; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionMapKey.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionMapKey.java new file mode 100644 index 0000000..c97565a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionMapKey.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import lombok.Data; + +import java.util.Objects; + +/** + * @author liuxinxin + * @date 2022/7/22 上午10:07 + */ +@Data +public class RegionMapKey { + + /** + * 区域码 + */ + private String regionCode; + /** + * 地区级别 + */ + private Integer regionLevel; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RegionMapKey key = (RegionMapKey) o; + return regionCode.equals(key.getRegionCode()) && regionLevel.equals(key.getRegionLevel()); + } + + @Override + public int hashCode() { + return Objects.hash(regionCode, regionLevel); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionTreeDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionTreeDTO.java new file mode 100644 index 0000000..1109ae4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RegionTreeDTO.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/7/22 上午9:08 + */ +@Data +public class RegionTreeDTO { + + /** + * 区域码 + */ + private String regionCode; + + /** + * 地区名 + */ + private String name; + + /** + * 地区级别 + */ + private Integer level; + + /** + * 地区父级code 当parent_code 为 -1 时为顶级区域 + */ + private String parentCode; + + private String unionCode; + + private List children; + + private Long id; + + private String mapData; + + private Boolean deleted; + + private String govUnit; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceQueryDTO.java new file mode 100644 index 0000000..451eb92 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceQueryDTO.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.sys.entity.dto; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 资源 查询DTO + * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(value = "ResourceQueryDTO", description = "资源查询") +public class ResourceQueryDTO { + + /** + * 父资源id, 用于查询按钮 + */ + @ApiModelProperty(value = "菜单id", notes = "指定菜单id") + private Long menuId; + /** + * 登录人用户id + */ + @ApiModelProperty(value = "指定用户id", notes = "指定用户id,前端不传则自动获取") + private Long userId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceSaveDTO.java new file mode 100644 index 0000000..bb19287 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceSaveDTO.java @@ -0,0 +1,63 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 资源 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "ResourceSaveDTO", description = "资源") +public class ResourceSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编码 + */ + @ApiModelProperty(value = "编码") + @Size(max = 500, message = "编码长度不能超过500") + private String code; + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Size(max = 255, message = "名称长度不能超过255") + private String name; + /** + * 菜单ID + * #c_menu + */ + @ApiModelProperty(value = "菜单ID") + private Long menuId; + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 255, message = "描述长度不能超过255") + private String describe; + /** + * 内置 + */ + @ApiModelProperty(value = "内置") + private Boolean readonly; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceUpdateDTO.java new file mode 100644 index 0000000..0fcbb95 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/ResourceUpdateDTO.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.core.conditions.update.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + *

+ * 实体类 + * 资源 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "ResourceUpdateDTO", description = "资源") +public class ResourceUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "主键") + @NotNull(message = "id不能为空", groups = Update.class) + private Long id; + + /** + * 编码 + */ + @ApiModelProperty(value = "编码") + @Size(max = 500, message = "编码长度不能超过500") + private String code; + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Size(max = 255, message = "名称长度不能超过255") + private String name; + /** + * 菜单ID + * #c_menu + */ + @ApiModelProperty(value = "菜单ID") + private Long menuId; + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 255, message = "描述长度不能超过255") + private String describe; + /** + * 内置 + */ + @ApiModelProperty(value = "内置") + private Boolean readonly; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleAuthoritySaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleAuthoritySaveDTO.java new file mode 100644 index 0000000..a5e6b5a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleAuthoritySaveDTO.java @@ -0,0 +1,53 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 角色的资源 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "RoleAuthoritySaveDTO", description = "角色的资源") +public class RoleAuthoritySaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 菜单ID + * #c_menu + */ + @ApiModelProperty(value = "资源ID") + private List menuIdList; + + /** + * 资源id + * #c_resource + */ + private List resourceIdList; + + /** + * 角色id + * #c_role + */ + @ApiModelProperty(value = "角色id") + @NotNull(message = "角色id不能为空") + private Long roleId; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RolePageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RolePageQuery.java new file mode 100644 index 0000000..f7d91bf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RolePageQuery.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 实体类 + * 角色 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "RolePageQuery", description = "角色") +public class RolePageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + private String name; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleQueryDTO.java new file mode 100644 index 0000000..797b7b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleQueryDTO.java @@ -0,0 +1,49 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 角色 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "RoleQueryDTO", description = "角色") +public class RoleQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + @ApiModelProperty(value = "ID") + private Long id; + + /** + * 角色名称 + */ + @ApiModelProperty(value = "角色名称") + private String name; + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String describe; + + /** + * 数据范围 + */ + @ApiModelProperty(value = "数据范围") + private Integer dataScope; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleSaveDTO.java new file mode 100644 index 0000000..67ec975 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleSaveDTO.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 角色 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "RoleSaveDTO", description = "角色") +public class RoleSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Size(max = 50, message = "名称长度不能超过50") + private String name; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 200, message = "描述长度不能超过200") + private String describe; + + /** + * 数据范围 + */ + @ApiModelProperty(value = "数据范围 1全部 2本区域 3本区域以及下区域 4本公司") + @NotNull(message = "请选择数据范围") + private Integer dataScope; + + + /** + * 菜单id + */ + @ApiModelProperty(value = "菜单id") + private List menuIds; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUpdateDTO.java new file mode 100644 index 0000000..29eb666 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUpdateDTO.java @@ -0,0 +1,64 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.core.conditions.update.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 角色 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "RoleUpdateDTO", description = "角色") +public class RoleUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "主键") + @NotNull(message = "id不能为空", groups = Update.class) + private Long id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + @Size(max = 50, message = "名称长度不能超过30") + private String name; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 200, message = "描述长度不能超过200") + private String describe; + + /** + * 数据范围 + */ + @ApiModelProperty(value = "数据范围 1全部 2本区域 3本区域以及下区域 4本公司") + private Integer dataScope; + + /** + * 菜单id + */ + @ApiModelProperty(value = "菜单id") + private List menuIds; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUserSaveVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUserSaveVO.java new file mode 100644 index 0000000..10ab420 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/RoleUserSaveVO.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 角色下的员工 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "RoleUserSaveVO", description = "给角色分配员工") +public class RoleUserSaveVO implements Serializable { + + private static final long serialVersionUID = 1L; + @ApiModelProperty(value = "绑定或取消") + @NotNull(message = "请填写绑定或取消参数") + private Boolean flag; + /** + * 角色;#c_role + */ + @ApiModelProperty(value = "角色") + @NotNull(message = "请选择角色") + private Long roleId; + /** + * 用户;#c_user + */ + @ApiModelProperty(value = "用户") + @Size(min = 1, message = "请选择用户") + private List userIdList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserPageQuery.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserPageQuery.java new file mode 100644 index 0000000..f09ca8a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserPageQuery.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.ningdatech.basic.model.PagePo; +import com.ningdatech.basic.model.PageVo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 用户 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "UserPageQuery", description = "用户") +public class UserPageQuery extends PagePo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + private String username; + + /** + * 登录帐号 + */ + @ApiModelProperty(value = "登录帐号") + private String account; + + /** + * 用户角色id + */ + @ApiModelProperty(value = "用户角色id") + private Long roleId; + + /** + * 所属企业 + */ + @ApiModelProperty(value = "所属企业") + private String companyName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserQueryDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserQueryDTO.java new file mode 100644 index 0000000..aec07f1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserQueryDTO.java @@ -0,0 +1,132 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 用户 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "UserQueryDTO", description = "用户") +public class UserQueryDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 账号 + */ + @ApiModelProperty(value = "账号") + private String account; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + private String username; + + /** + * 角色 + */ + @ApiModelProperty(value = "角色") + private Long role; + + /** + * 角色名称 + */ + @ApiModelProperty(value = "角色名称") + private String roleName; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + private Long companyId; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String companyName; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + private Long industry; + + /** + * 行业名称 + */ + @ApiModelProperty(value = "行业名称") + private String industryName; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + private String mobile; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 最后登录时间 + */ + @ApiModelProperty(value = "最后登录时间") + private LocalDateTime lastLoginTime; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + private String sectionOffice; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称") + private String nickName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserRoleSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserRoleSaveDTO.java new file mode 100644 index 0000000..e2122cc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserRoleSaveDTO.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 实体类 + * 角色分配 + * 账号角色绑定 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "UserRoleSaveDTO", description = "角色分配 账号角色绑定") +public class UserRoleSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 角色ID + * #c_role + */ + @ApiModelProperty(value = "角色ID") + @NotNull(message = "请选择角色") + private Long roleId; + /** + * 用户ID + * #c_user + */ + @ApiModelProperty(value = "用户ID") + private List userIdList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserSaveDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserSaveDTO.java new file mode 100644 index 0000000..f033bcb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserSaveDTO.java @@ -0,0 +1,111 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 用户 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "UserSaveDTO", description = "用户") +public class UserSaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 账号 + */ + @ApiModelProperty(value = "账号") + @NotEmpty(message = "请输入账号!") + @Size(max = 50, message = "账号长度不能超过30") + private String account; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + @NotEmpty(message = "请输入用户姓名!") + @Size(max = 50, message = "用户姓名长度不能超过50") + private String username; + + /** + * 角色 + */ + @ApiModelProperty(value = "角色") + @NotNull(message = "请选择角色") + private Long role; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + @NotNull(message = "请选择企业") + private Long companyId; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + private Long industry; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + @NotBlank(message = "手机号不能为空") + @Size(max = 20, message = "手机长度不能超过20") + private String mobile; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + @NotEmpty(message = "密码不能为空") + @Size(max = 50, message = "密码长度不能超过64") + private String password; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + @Size(max = 50, message = "职位长度不能超过50") + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + @Size(max = 50, message = "科室长度不能超过50") + private String sectionOffice; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 200, message = "备注不能超过200") + private String remark; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserUpdateDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserUpdateDTO.java new file mode 100644 index 0000000..63cc9f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/dto/UserUpdateDTO.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.sys.entity.dto; + +import com.baomidou.mybatisplus.core.conditions.update.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 实体类 + * 用户 + *

+ * + * @author PoffyZhang + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder +@ApiModel(value = "UserUpdateDTO", description = "用户") +public class UserUpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + @NotNull(message = "id不能为空") + private Long id; + + /** + * 账号 + */ + @ApiModelProperty(value = "账号") + @Size(max = 50, message = "账号长度不能超过30") + private String account; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + @Size(max = 50, message = "密码长度不能超过50") + private String password; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + @Size(max = 50, message = "用户姓名长度不能超过50") + private String username; + + /** + * 角色 + */ + @ApiModelProperty(value = "角色") + private Long role; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + private Long companyId; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + private Long industry; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + @Size(max = 20, message = "手机长度不能超过20") + private String mobile; + + /** + * 最后登录时间 + */ + @ApiModelProperty(value = "最后登录时间") + private LocalDateTime lastLoginTime; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + @Size(max = 50, message = "职位长度不能超过50") + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + @Size(max = 50, message = "科室长度不能超过50") + private String sectionOffice; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 200, message = "备注不能超过200") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/AuthorizeType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/AuthorizeType.java new file mode 100644 index 0000000..e0ec9a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/AuthorizeType.java @@ -0,0 +1,61 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.stream.Stream; + +/** + *

+ * 实体注释中生成的类型枚举 + * 角色的资源 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "AuthorizeType", description = "权限类型-枚举") +public enum AuthorizeType { + + /** + * MENU="菜单" + */ + MENU("菜单"), + DATA("数据"), + /** + * RESOURCE="资源" + */ + RESOURCE("资源"), + ; + + @ApiModelProperty(value = "描述") + private String desc; + + + /** + * 根据当前枚举的name匹配 + */ + public static AuthorizeType match(String val, AuthorizeType def) { + return Stream.of(values()).parallel().filter(item -> item.name().equalsIgnoreCase(val)).findAny().orElse(def); + } + + public static AuthorizeType get(String val) { + return match(val, null); + } + + public boolean eq(AuthorizeType val) { + return val != null && getCode().equals(val.name()); + } + + @ApiModelProperty(value = "编码", allowableValues = "MENU,RESOURCE", example = "MENU") + public String getCode() { + return this.name(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/BooleanDisplayEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/BooleanDisplayEnum.java new file mode 100644 index 0000000..3df3375 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/BooleanDisplayEnum.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/7/26 上午9:21 + */ +@AllArgsConstructor +@Getter +public enum BooleanDisplayEnum { + + /** + * true + */ + Y, + + /** + * false + */ + N; + + public static Boolean judgeBoolean(String key) { + return Y.name().equals(key); + } + + public static BooleanDisplayEnum judgeBoolean(Boolean key) { + return key ? Y : N; + } + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleBehaviorTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleBehaviorTypeEnum.java new file mode 100644 index 0000000..eb20651 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleBehaviorTypeEnum.java @@ -0,0 +1,144 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/20 上午11:31 + * 赋码规则行为类型 + */ +@AllArgsConstructor +@Getter +public enum CodingRuleBehaviorTypeEnum { + + /** + * 加分项 + */ + // 观看视频 + watch_video, + // 观看材料 + watch_profile, + // 完成考试 + complete_the_exam, + + /** + * 扣分项 + */ + + //驾驶员异常行为扣分 + //主动抓拍事件 + adas_initiative_capture_events, + + //前向碰撞报警 + forward_collision_warning, + + //车道偏离(左)报警 + lane_departure_left_warning, + + //车道偏离(右)报警 + lane_departure_right_warning, + + //频繁变道报警 + change_lanes_frequently_warning, + + //车距过近(前车)报警 + distance_too_close_warning, + + //行人碰撞报警 + pedestrian_collisions_warning, + + //不礼让行人 + no_comity_pedestrian, + + //道路标志识别事件 + road_sign_recognition_event, + + //道路标识超速报警 + road_signs_overspeed_warning, + + //路口快速通过报警 + crossroads_quickly_through_warning, + + //DSM主动抓拍事件 + dsm_initiative_capture_events, + + //探头遮挡报警 + probe_cover_alarm, + + //驾驶员人脸身份识别事件 + driver_face_identification_events, + + //换人驾驶报警 + substitution_driving_alarm, + + //超时驾驶报警 + driver_timeout_alarm, + + //疲劳驾驶报警 + fatigue_driving_alarm, + + //接打手持电话报警 + holding_a_call_alarm, + + //抽烟报警 + smoke_alarm, + + //分神驾驶报警 + distracted_driving_alarm, + + //驾驶员状态异常报警 + driver_abnormal_state_alarm, + + //未系安全带报警 + not_wearing_seatbelt_alarm, + + //驾驶员身份异常报警 + driver_abnormal_status_alarm, + + //后方接近报警 + close_behind_alarm, + + //左侧后方接近 + left_rear_near_alarm, + + //右侧后方接近报警 + right_rear_near_alarm, + + //死亡出险 + death_out_danger, + //受伤出险 + injured_out_danger, + //死亡事故 + death_accident, + //受伤事故 + injured_accident, + + //// 疲劳驾驶 + //fatigue_driving, + //// 接打电话 + //answer_and_make_calls, + //// 抽烟驾驶 + //smoking_driving, + //// 分神驾驶 + //distracted_driving, + //// 超速驾驶 + //overspeed_driving, + //// 闯禁行区域 + //breaking_the_forbidden_area, + //// 闯红灯 + //running_a_red_light, + //// 驾驶员异常 + //driver_abnormal, + //// 探头遮挡 + //probe_shielding, + //// 未系安全带 + //not_wearing_seat_belt, + //// 双手脱离方向盘 + //get_your_hands_off_the_steering_wheel, + //// 伤人事故 + //injuries, + //// 闯禁行时段 + //time_for_breaking_the_ban; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleVehicleType.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleVehicleType.java new file mode 100644 index 0000000..d2c3875 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/CodingRuleVehicleType.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +/** + * @author liuxinxin + * @date 2022/10/24 下午2:09 + * 赋码规则车辆类型 + */ +public enum CodingRuleVehicleType { + + // 散装水泥运输车 + BULK_CEMENT_TRUCK, + + // 预拌砂浆运输车 + READY_MIXED_MORTAR_TRUC, + + // 混凝土搅拌车 + MIXER, + + // 移动泵车 + KRHP + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/ImportTemplateEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/ImportTemplateEnum.java new file mode 100644 index 0000000..704baba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/ImportTemplateEnum.java @@ -0,0 +1,40 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import lombok.Getter; + +/** + *

+ * 导入模版枚举 + *

+ * + * @author WendyYang + * @since 2022-11-04 + */ +@Getter +public enum ImportTemplateEnum { + + /** + * 通用导入模版枚举 + */ + VEHICLE_ACCIDENT("车辆出险情况"), + + VEHICLE_VIOLATION("车辆违章情况"), + + VEHICLE_OVER_SPEED("车辆超速情况"), + + LAB_WORKER_CERTIFICATE_QUA("实验室人员从业资格证"), + LAB_WORKER_CERTIFICATE_EDU("实验室人员继续教育合格证"), + + LAB_ACCEPTANCE_CERTIFICATE("实验室验收合格证"), + + INSURE_OUT_DANGER("保险出险导入"), + + DRIVER_ARCHIVES("驾驶员档案导入"); + + private final String value; + + ImportTemplateEnum(String value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MenuTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MenuTypeEnum.java new file mode 100644 index 0000000..927b55c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MenuTypeEnum.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * 资源类型 + * + * @author PoffyZhang + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "MenuTypeEnum", description = "资源类型-枚举") +public enum MenuTypeEnum { + /** + * 菜单 + */ + MENU(0, "菜单"), + + /** + * 按钮 + */ + BUTTON(1, "按钮"); + + /** + * 资源类型 + */ + private Integer code; + + /** + * 资源描述 + */ + private String desc; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @ApiModelProperty(value = "编码", allowableValues = "0,1", example = "0") + public Integer getCode() { + return this.code; + } + + + public boolean eq(String val) { + return this.name().equals(val); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyStatusEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyStatusEnum.java new file mode 100644 index 0000000..89bc92a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyStatusEnum.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/15 下午2:37 + */ +@AllArgsConstructor +@Getter +public enum MetaApplyStatusEnum { + + /** + * 材料初审中 + */ + FIRST_TRIAL_UNDER_REVIEW, + + /** + * 材料复核中 + */ + REEXAMINATION_UNDER_REVIEW, + + + /** + * 材料初审通过 + */ + FIRST_TRIAL_APPROVED, + + /** + * 材料复核通过 + */ + REEXAMINATION_APPROVED, + + /** + * 材料初审驳回 + */ + FIRST_TRIAL_APPROVAL_REJECTION, + + /** + * 材料复核驳回 + */ + REEXAMINATION_APPROVAL_REJECTION + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyTypeEnum.java new file mode 100644 index 0000000..3842d4f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/MetaApplyTypeEnum.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author liuxinxin + * @date 2022/10/15 下午2:37 + */ +@AllArgsConstructor +@Getter +public enum MetaApplyTypeEnum { + + /** + * 初审审核 + */ + PRELIMINARY_REVIEW, + + /** + * 复审审核 + */ + IN_REVIEW +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RoleEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RoleEnum.java new file mode 100644 index 0000000..3c90bd4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RoleEnum.java @@ -0,0 +1,34 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +/** + * @author liuxinxin + * @date 2022/10/17 上午11:15 + */ + +@AllArgsConstructor +@Getter +public enum RoleEnum { + /** + * 駕駛員 + */ + DRIVER("DRIVER"); + + private final String key; + + public static boolean contains(String key) { + if (StringUtils.isBlank(key)) { + return false; + } + for (RoleEnum roleEnum : RoleEnum.values()) { + if (roleEnum.key.equals(key)) { + return true; + } + } + return false; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RuleOperationTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RuleOperationTypeEnum.java new file mode 100644 index 0000000..450f211 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/enumeration/RuleOperationTypeEnum.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.sys.entity.enumeration; + +/** + * @author liuxinxin + * @date 2022/10/24 下午2:03 + * 赋码规则 + */ + +public enum RuleOperationTypeEnum { + + // 加分 + bonus_points, + + // 减分 + score_deduction; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionDeleteReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionDeleteReq.java new file mode 100644 index 0000000..ba4a55e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionDeleteReq.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.sys.entity.req; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + *

+ * RegionDeleteReq + *

+ * + * @author WendyYang + * @since 14:37 2022/10/12 + */ +@Data +@ApiModel(description = "地区删除参数实体") +public class RegionDeleteReq { + + @ApiModelProperty("id") + @NotNull(message = "id不能为空") + private Long id; + + @ApiModelProperty("地区级别") + @NotNull(message = "地区级别不能为空") + private Integer level; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionTreeReq.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionTreeReq.java new file mode 100644 index 0000000..029dece --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/RegionTreeReq.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.sys.entity.req; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * RegionTreeReq + *

+ * + * @author WendyYang + * @since 20:12 2022/10/31 + */ +@Data +public class RegionTreeReq { + + /** + * 是否返回公司信息 + */ + private Boolean withCompany = false; + + /** + * 是否返回车牌号信息 + */ + private Boolean withCarNo = false; + + private Boolean withDevice = false; + + @ApiModelProperty("所选区域Id") + private Long regionId; + + @ApiModelProperty("所选区域Id列表") + private List regionIdList; + + @ApiModelProperty("查询车牌号") + private String carPlate; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/ReqCodingRulePO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/ReqCodingRulePO.java new file mode 100644 index 0000000..541ca0d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/req/ReqCodingRulePO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.sys.entity.req; + +import com.ningdatech.carapi.sys.entity.BonusPointsRule; +import com.ningdatech.carapi.sys.entity.ScoreDeductionRule; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/24 下午3:01 + */ +@Data +@ApiModel("赋码规则VO") +public class ReqCodingRulePO { + + @ApiModelProperty("加分规则") + public BonusPointsRule bonusPointsRule; + + @ApiModelProperty("减分规则") + public List scoreDeductionRuleList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarInfoVO.java new file mode 100644 index 0000000..68fabc2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarInfoVO.java @@ -0,0 +1,37 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.ToString; + +import java.util.List; +import java.util.Map; + +/** + *

+ * RegionTreeVO + *

+ * + * @author WendyYang + * @since 10:35 2022/10/12 + */ +@Data +@ToString(callSuper = true) +@ApiModel(value = "CarInfoVO", description = "车辆树状结构VO") +public class CarInfoVO { + + @ApiModelProperty("车辆所属企业ID") + private Long companyId; + + @ApiModelProperty("车牌号") + private String carPlate; + + @ApiModelProperty("车辆状态") + private Integer moving; + + @ApiModelProperty("车辆所属设备信息") + private Map> equipmentInfoMap; + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarVO.java new file mode 100644 index 0000000..fc15909 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CarVO.java @@ -0,0 +1,22 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author PoffyZhang + * @Classname CarVO + * @Description + * @Date 2022/12/5 15:22 + */ +@Data +public class CarVO { + @ApiModelProperty(value = "车牌号") + private String carPlate; + + @ApiModelProperty("车辆状态 0离线 1在线 2异常") + private Integer status; + + @ApiModelProperty("车辆是否行驶 0没有行驶 1行驶中") + private Integer moving; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyCarInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyCarInfoVO.java new file mode 100644 index 0000000..01a4444 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyCarInfoVO.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import java.util.List; +import java.util.Map; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.ToString; + +/** + *

+ * RegionTreeVO + *

+ * + * @author WendyYang + * @since 10:35 2022/10/12 + */ +@Data +@ToString(callSuper = true) +@ApiModel(value = "CompanyCarInfoVO", description = "企业车辆树状结构VO") +public class CompanyCarInfoVO { + + @ApiModelProperty("所选区域Id") + private Long regionId; + + @ApiModelProperty("企业信息列表") + private List companyList; + + @ApiModelProperty("企业下车辆信息") + private Map> carInfoMap; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyVO.java new file mode 100644 index 0000000..34ea016 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/CompanyVO.java @@ -0,0 +1,162 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import java.util.List; + +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "CompanyVO", description = "企业") +@AllArgsConstructor +@Builder +public class CompanyVO extends BaseEntity { + + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + private Long vehicleNum; + + private Long employeesNum; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区id") + private Long regionId; + + /** + * 地区 + */ + @ApiModelProperty(value = "地区") + private String regionName; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + private Long operatorId; + + /** + * 运营商 + */ + @ApiModelProperty(value = "运营商") + private String operatorName; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + private Integer companyType; + + /** + * 公司类型名 + */ + @ApiModelProperty(value = "公司类型名") + private String companyTypeName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 是否失信 + */ + @ApiModelProperty(value = "是否失信") + private Boolean blackList; + + /** + * 营业执照 + */ + @ApiModelProperty(value = "营业执照") + private String businessLicense; + + /** + * 企业类型ids + */ + @ApiModelProperty(value = "企业类型ids") + private List companyTypeIds; + + @ApiModelProperty(value = "经度") + private String longitude; + + @ApiModelProperty(value = "纬度") + private String latitude; + + @ApiModelProperty("企业风险等级") + private String dangerLevel; + + @ApiModelProperty("企业风险名称") + private String dangerLevelName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/EquipmentInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/EquipmentInfoVO.java new file mode 100644 index 0000000..316a4f3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/EquipmentInfoVO.java @@ -0,0 +1,33 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.ToString; + +/** + *

+ * RegionTreeVO + *

+ * + * @author WendyYang + * @since 10:35 2022/10/12 + */ +@Data +@ToString(callSuper = true) +@ApiModel(value = "EquipmentInfoVO", description = "车辆设备树状结构VO") +public class EquipmentInfoVO { + + @ApiModelProperty("设备所属车辆车牌号") + private String carPlate; + + @ApiModelProperty("设备视频状态") + private String videoStatus; + + @ApiModelProperty("设备ID") + private String deviceId; + + @ApiModelProperty("设备名称") + private String deviceName; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuResourceTreeVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuResourceTreeVO.java new file mode 100644 index 0000000..4210eba --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuResourceTreeVO.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.ningdatech.carapi.sys.entity.TreeEntity; +import com.ningdatech.carapi.sys.entity.enumeration.AuthorizeType; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.Size; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + * menuList + * 菜单资源树 + * + * @author PoffyZhang + */ +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class MenuResourceTreeVO extends TreeEntity { + + private AuthorizeType type; + private String code; + private String icon; + private Boolean isDef; + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + @Size(max = 200, message = "描述长度不能超过200") + @TableField(value = "describe_", condition = LIKE) + private String describe; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuRoleVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuRoleVO.java new file mode 100644 index 0000000..bde50af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuRoleVO.java @@ -0,0 +1,77 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.ningdatech.carapi.sys.entity.TreeEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 菜单 + *

+ * + * @author PoffyZhang + * @since 2022-9-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "RoleMenuVO", description = "菜单") +@AllArgsConstructor +public class MenuRoleVO extends TreeEntity { + + private static final long serialVersionUID = 1L; + + /** + * 权限" + */ + @ApiModelProperty(value = "权限") + private String permission; + /** + * 类型;[0-菜单 1-目录 2-按钮] + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * 组件 + */ + @ApiModelProperty(value = "组件") + private String component; + + /** + * 菜单图标 + */ + @ApiModelProperty(value = "菜单图标") + private String icon; + + /** + * 是否隐藏 + */ + @ApiModelProperty(value = "是否隐藏") + private Integer hidden; + + /** + * 是否有权限 + */ + @ApiModelProperty(value = "是否有权限 0没有 1有") + private Integer hasPermission = 0; + + /** + * activeMenu + */ + @ApiModelProperty(value = "activeMenu") + private String activeMenu; + + /** + * 跳转 + */ + @ApiModelProperty(value = "跳转") + @TableField(value = "redirect") + private String redirect; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuVO.java new file mode 100644 index 0000000..833aab5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/MenuVO.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 实体类 + * 菜单 + *

+ * + * @author PoffyZhang + * @since 2022-9-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "MenuVO", description = "菜单") +@AllArgsConstructor +@Builder +public class MenuVO extends TreeVO { + + private static final long serialVersionUID = 1L; + + /** + * 权限" + */ + @ApiModelProperty(value = "权限") + private String permission; + /** + * 类型;[0-菜单 1按钮] + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * 组件 + */ + @ApiModelProperty(value = "组件") + private String component; + + /** + * 菜单图标 + */ + @ApiModelProperty(value = "菜单图标") + private String icon; + + /** + * 子菜单数目 + */ + @ApiModelProperty(value = "是否隐藏") + private Integer hidden; + + /** + * activeMenu + */ + @ApiModelProperty(value = "activeMenu") + private String activeMenu; + + /** + * 跳转 + */ + @ApiModelProperty(value = "跳转") + @TableField(value = "redirect") + private String redirect; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/OperatorVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/OperatorVO.java new file mode 100644 index 0000000..e534b2f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/OperatorVO.java @@ -0,0 +1,62 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 运营商 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "Operator", description = "运营商") +@AllArgsConstructor +@Builder +public class OperatorVO extends BaseEntity { + + @TableId(value = "id",type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 运营商名称 + */ + @ApiModelProperty(value = "运营商名称") + private String name; + + /** + * 运营商备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 区域负责人 + */ + @ApiModelProperty(value = "区域负责人") + private List operatorRegionHeads; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionCompanyCarTreeVo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionCompanyCarTreeVo.java new file mode 100644 index 0000000..7e6fa6e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionCompanyCarTreeVo.java @@ -0,0 +1,50 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.ningdatech.basic.util.StrPool; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * BaseTreeVo + *

+ * + * @author WendyYang + * @since 15:39 2022/11/1 + */ +@Data +public class RegionCompanyCarTreeVo { + + public interface Type { + int REGION = 1; + int COMPANY = 2; + int CAR_NO = 3; + int CAR_VIDEO = 4; + } + + + private Long code; + + private String value; + + private Integer status; + + private Integer moving; + + private String unique; + + private Integer level; + + private Integer type; + private String videoStatus; + private String deviceId; + + private List children = new ArrayList<>(); + + public void setUnique() { + this.unique = this.code + StrPool.HASH + this.type; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeCompanyVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeCompanyVO.java new file mode 100644 index 0000000..c1fabe4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeCompanyVO.java @@ -0,0 +1,119 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 值对象 + * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-10-09 + */ +@Data +@ApiModel(value = "CompanyDTO", description = "企业") +public class RegionTreeCompanyVO { + + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String name; + + /** + * 车辆数 + */ + @ApiModelProperty(value = "车辆数") + private Long vehicleNum; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区id") + private Long regionId; + + /** + * 地区 + */ + @ApiModelProperty(value = "地区") + private String regionName; + + /** + * 运营商ID + */ + @ApiModelProperty(value = "运营商ID") + private Long operatorId; + + /** + * 运营商 + */ + @ApiModelProperty(value = "运营商") + private String operatorName; + + /** + * 传真 + */ + @ApiModelProperty(value = "传真") + private String fax; + + /** + * email + */ + @ApiModelProperty(value = "email") + private String email; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String address; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String contactPerson; + + /** + * 联系方式 + */ + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + /** + * 法人 + */ + @ApiModelProperty(value = "法人") + private String legalPerson; + + /** + * 法人联系电话 + */ + @ApiModelProperty(value = "法人联系电话") + private String legalPersonPhone; + + /** + * 公司类型 + */ + @ApiModelProperty(value = "公司类型") + private Integer companyType; + + /** + * 公司类型名 + */ + @ApiModelProperty(value = "公司类型名") + private String companyTypeName; + + @ApiModelProperty("车牌号集合") + private List carNoList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeVO.java new file mode 100644 index 0000000..3f4722e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RegionTreeVO.java @@ -0,0 +1,60 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.ToString; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + *

+ * RegionTreeVO + *

+ * + * @author WendyYang + * @since 10:35 2022/10/12 + */ +@Data +@ToString(callSuper = true) +@ApiModel(value = "RegionTreeVO", description = "区域树状结构VO") +public class RegionTreeVO { + + private Long id; + + @ApiModelProperty("区域码") + @NotBlank(message = "地区编码不能为空") + private String regionCode; + + @ApiModelProperty("地区名") + @NotBlank(message = "地区名称不能为空") + private String name; + + @ApiModelProperty("级别") + @NotNull(message = "级别不能为空") + private Integer level; + + @ApiModelProperty("区域级别") + @NotBlank(message = "区域级别不能为空") + private String govUnit; + + @ApiModelProperty("地区父级编码:-1为顶级区域") + @NotBlank(message = "地区父级编码不能为空") + private String parentCode; + + @ApiModelProperty("子区域") + private List children; + + @ApiModelProperty("唯一编码:regionCode##name##level") + private String unionCode; + + @ApiModelProperty("地图数据") + @NotBlank(message = "地图数据不能为空") + private String mapData; + + @ApiModelProperty("企业信息") + private List companyList; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/ResCodingRuleVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/ResCodingRuleVO.java new file mode 100644 index 0000000..fd6f066 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/ResCodingRuleVO.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.ningdatech.carapi.sys.entity.BonusPointsRule; +import com.ningdatech.carapi.sys.entity.ScoreDeductionRule; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/10/24 下午3:01 + */ +@Data +@ApiModel("赋码规则VO") +public class ResCodingRuleVO { + + @ApiModelProperty("加分规则") + public BonusPointsRule bonusPointsRule; + + @ApiModelProperty("减分规则") + public List scoreDeductionRuleList; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleMenuVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleMenuVO.java new file mode 100644 index 0000000..95dbc13 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleMenuVO.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author PoffyZhang + * @since 2022-11-11 + */ +@Data +@ApiModel(value = "RoleMenu对象", description = "") +public class RoleMenuVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("menu_id") + private Long menuId; + + @ApiModelProperty("role_id") + private Long roleId; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleVO.java new file mode 100644 index 0000000..38b0c9a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/RoleVO.java @@ -0,0 +1,67 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import com.ningdatech.carapi.sys.entity.Menu; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * 实体类 + * 角色 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "Role", description = "角色") +@AllArgsConstructor +@Builder +public class RoleVO extends BaseEntity { + + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + private String name; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String describe; + + /** + * 数据范围 + */ + @ApiModelProperty(value = "数据范围 1全部 2本区域 3本区域以及下区域 4本公司") + private Integer dataScope; + + /** + * 菜单 + */ + @ApiModelProperty(value = "菜单") + private List menu; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/TreeVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/TreeVO.java new file mode 100644 index 0000000..9b5a44a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/TreeVO.java @@ -0,0 +1,103 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + * 包括id、create_time、created_by、updated_by、update_time、label、parent_id、sort_value 字段的表继承的树形实体 + * + * @author PoffyZhang + * @since 2022/09/30 + */ +@Getter +@Setter +@Accessors(chain = true) +@ToString(callSuper = true) +public class TreeVO extends BaseEntity { + + protected Long id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + protected String name; + + /** + * 菜单标题 + */ + @ApiModelProperty(value = "菜单标题") + protected String title; + + /** + * 父菜单ID + */ + @ApiModelProperty(value = "父ID") + protected Long pid; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序号") + protected Integer sort; + + /** + * 顶层菜单 + */ + @ApiModelProperty(value = "顶层菜单") + protected String topMenu; + + /** + * 路径 + */ + @ApiModelProperty(value = "路径") + protected String path; + + + @ApiModelProperty(value = "子节点", hidden = true) + protected List children; + + /** + * 层级 + */ + @ApiModelProperty(value = "层级") + protected Integer level = 1; + + + /** + * 初始化子类 + */ + @JsonIgnore + public void initChildren() { + if (getChildren() == null) { + this.setChildren(new ArrayList<>()); + } + } + + @JsonIgnore + public void addChildren(E child) { + initChildren(); + children.add(child); + } + + @Override + public Object clone() throws CloneNotSupportedException{ + return super.clone(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/UserInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/UserInfoVO.java new file mode 100644 index 0000000..05b1131 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/entity/vo/UserInfoVO.java @@ -0,0 +1,120 @@ +package com.ningdatech.carapi.sys.entity.vo; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.ningdatech.carapi.common.base.BaseEntity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +/** + *

+ * + *

+ * + * @author Zpf + * @since 2022-10-17 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@AllArgsConstructor +@Builder +public class UserInfoVO extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 账号 + */ + @ApiModelProperty(value = "账号") + private String account; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + private String username; + + /** + * 角色 + */ + @ApiModelProperty(value = "角色") + private Long role; + + /** + * 角色名称 + */ + @ApiModelProperty(value = "角色名称") + private String roleName; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + private Long companyId; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String companyName; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + private Long industry; + + /** + * 行业名称 + */ + @ApiModelProperty(value = "行业名称") + private String industryName; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + private String mobile; + + /** + * 最后登录时间 + */ + @ApiModelProperty(value = "最后登录时间") + private LocalDateTime lastLoginTime; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + private String sectionOffice; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称") + private String nickName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 用户是否可登录 + */ + @ApiModelProperty(value = "用户是否可登录") + private Boolean canLogin; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/event/ImportDataEvent.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/event/ImportDataEvent.java new file mode 100644 index 0000000..be7770c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/event/ImportDataEvent.java @@ -0,0 +1,31 @@ +package com.ningdatech.carapi.sys.event; + +import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum; +import org.springframework.context.ApplicationEvent; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * ImportDataEvent - 模版数据导入事件 + *

+ * + * @author WendyYang + * @since 20:20 2022/11/4 + */ +public class ImportDataEvent extends ApplicationEvent { + + private ImportTemplateEnum template; + + public ImportDataEvent(MultipartFile source) { + super(source); + } + + public ImportTemplateEnum getTemplate() { + return template; + } + + public void setTemplate(ImportTemplateEnum template) { + this.template = template; + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/CompaniesCacheHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/CompaniesCacheHelper.java new file mode 100644 index 0000000..98ae80a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/CompaniesCacheHelper.java @@ -0,0 +1,196 @@ +package com.ningdatech.carapi.sys.helper; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.common.collect.Maps; +import com.ningdatech.carapi.sys.entity.CompanyJoin; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.service.CompanyJoinService; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * CompaniesCacheHelper + *

+ * + * @author PoffyZhang + * @since 09:01 2022/10/18 + */ +@Slf4j +@Component +public class CompaniesCacheHelper implements InitializingBean { + + private LoadingCache companyCache; + + // ================================================================================================================== + + private final CompanyJoinService companyService; + + @Resource + private RegionsCacheHelper regionsCacheHelper; + + private Map companyNameMap = Maps.newHashMap(); + + public CompaniesCacheHelper(CompanyJoinService companyService) { + this.companyService = companyService; + } + + @Override + public void afterPropertiesSet() { + companyCache = Caffeine.newBuilder() + // 需避免刷新过于频繁 + .refreshAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader() { + + @Override + public CompanyDTO load(@NonNull Long companyId) { + CompanyJoin company = companyService + .oneJoin(Wrappers.lambdaQuery(CompanyJoin.class).eq(CompanyJoin::getId, companyId)); + if (Objects.isNull(company)) { + log.info("加载企业信息失败: 企业{} 信息为空为空", companyId); + return null; + } + // 查询区域 + searchRegion(company); + return BeanUtil.copyProperties(company, CompanyDTO.class); + } + + @Override + public @NonNull Map loadAll(@NonNull Iterable keys) { + List companies = + companyService.listJoin(Wrappers.lambdaQuery(CompanyJoin.class).in(CompanyJoin::getId, keys)); + if (CollUtil.isEmpty(companies)) { + log.info("加载企业信息失败: 企业信息为空为空"); + return Collections.emptyMap(); + } + // 查询区域 + searchRegions(companies); + return companies.stream().map(c -> BeanUtil.copyProperties(c, CompanyDTO.class)) + .collect(Collectors.toMap(CompanyDTO::getId, Function.identity())); + } + + }); + + List companies = companyService.listJoin(Wrappers.lambdaQuery(CompanyJoin.class)); + if (CollUtil.isEmpty(companies)) { + log.info("加载企业信息失败: 企业为空"); + return; + } + // 查询区域 + searchRegions(companies); + companies.forEach(c -> { + CompanyDTO company = BeanUtil.copyProperties(c, CompanyDTO.class); + companyCache.put(company.getId(), company); + companyNameMap.put(company.getName(), company); + }); + } + + public Collection all() { + return companyCache.asMap().values(); + } + + private void searchRegions(List companyJoins) { + if (CollUtil.isEmpty(companyJoins)) { + return; + } + companyJoins.forEach(this::searchRegion); + } + + private void searchRegion(CompanyJoin company) { + if (Objects.isNull(company)) { + return; + } + if (Objects.nonNull(company.getRegionId())) { + List regions = + regionsCacheHelper.listParents(Long.valueOf(String.valueOf(company.getRegionId()))); + if (CollUtil.isNotEmpty(regions)) { + company.setRegionName(regions.stream().map(RegionDTO::getRegionName).collect(Collectors.joining("-"))); + } + } + } + + /** + * 获取当前企业信息 + * + * @param companyId + * 企业ID + * @return + */ + public CompanyDTO getById(Long companyId) { + CompanyDTO companyDTO = companyCache.get(companyId); + return Optional.ofNullable(companyDTO).orElse(new CompanyDTO()); + } + + public String getNameById(Long companyId) { + CompanyDTO dto = companyCache.get(companyId); + if (Objects.nonNull(dto)) { + return dto.getName(); + } + return StringUtils.EMPTY; + } + + public String getNameById(Long companyId, String oldName) { + CompanyDTO dto = companyCache.get(companyId); + if (Objects.nonNull(dto)) { + return dto.getName(); + } + return oldName; + } + + /** + * 获取当前企业信息 + * + * @param companyName + * 企业ID + * @return + */ + public CompanyDTO getByName(String companyName) { + return companyNameMap.get(companyName); + } + + /** + * 获取当前企业信息 + * + * @return + */ + public Map asMap() { + return companyCache.asMap(); + } + + public void refresh(Long id) { + companyCache.refresh(id); + CompanyDTO data = companyCache.get(id); + if (Objects.nonNull(data)) { + companyNameMap.put(data.getName(), data); + } + } + + public void refresh(List ids) { + if (CollUtil.isNotEmpty(ids)) { + ids.forEach(id -> { + companyCache.refresh(id); + CompanyDTO data = companyCache.get(id); + if (Objects.nonNull(data)) { + companyNameMap.put(data.getName(), data); + } + }); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/OperatorsCacheHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/OperatorsCacheHelper.java new file mode 100644 index 0000000..f1b6110 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/OperatorsCacheHelper.java @@ -0,0 +1,153 @@ +package com.ningdatech.carapi.sys.helper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.common.collect.Maps; +import com.ningdatech.carapi.sys.entity.Operator; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.manage.OperatorManage; +import com.ningdatech.carapi.sys.mapper.OperatorMapper; +import com.ningdatech.carapi.sys.service.OperatorService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + *

+ * OperatorsCacheHelper + *

+ * + * @author PoffyZhang + * @since 09:01 2022/11/29 + */ +@Slf4j +@Component +public class OperatorsCacheHelper implements InitializingBean { + + private LoadingCache operatorCache; + + //================================================================================================================== + + @Autowired + private OperatorMapper operatorMapper; + + + private Map operatorNameMap = Maps.newHashMap(); + + @Override + public void afterPropertiesSet() { + operatorCache = Caffeine.newBuilder() + //需避免刷新过于频繁 + .refreshAfterWrite(30, TimeUnit.MINUTES) + .maximumSize(500) + .build(new CacheLoader() { + + @Override + public OperatorQueryDTO load(Long operatorId) throws Exception { + Operator operator = operatorMapper.selectById(operatorId); + if(Objects.isNull(operator)){ + log.info("加载运营商信息失败: 运营商{} 信息为空为空",operatorId); + return null; + } + return BeanUtil.copyProperties(operator, OperatorQueryDTO.class); + } + + @Override + public Map loadAll(Iterable keys) throws Exception { + List operators = operatorMapper.selectList(Wrappers.lambdaQuery(Operator.class).in(Operator::getId,keys)); + if(CollUtil.isEmpty(operators)){ + log.info("加载运营商信息失败: 运营商信息为空为空"); + return Collections.emptyMap(); + } + Map map = operators.stream().map(c->BeanUtil.copyProperties(c, OperatorQueryDTO.class)) + .collect(Collectors.toMap(OperatorQueryDTO::getId,c -> c)); + return map; + } + }); + + List operators = operatorMapper.selectList(Wrappers.lambdaQuery(Operator.class)); + if(CollUtil.isEmpty(operators)){ + log.info("加载运营商信息失败: 运营商为空"); + return; + } + operators.stream().forEach(c -> { + OperatorQueryDTO operator = BeanUtil.copyProperties(c, OperatorQueryDTO.class); + operatorCache.put(operator.getId(),operator); + operatorNameMap.put(operator.getName(),operator); + }); + } + + public Collection all(){ + return operatorCache.asMap().values(); + } + + /** + * 获取当前运营商信息 + * @param id + * @return + */ + public OperatorQueryDTO getById(Long id) { + return operatorCache.get(id); + } + + public void refresh(Long id) { + operatorCache.refresh(id); + OperatorQueryDTO data = operatorCache.get(id); + if(Objects.nonNull(data)){ + operatorNameMap.put(data.getName(),data); + } + } + + public void refresh(List ids) { + if(CollUtil.isNotEmpty(ids)){ + ids.forEach(id -> { + operatorCache.refresh(id); + OperatorQueryDTO data = operatorCache.get(id); + if(Objects.nonNull(data)){ + operatorNameMap.put(data.getName(),data); + } + }); + } + } + + /** + * 获取当前运营商名字 + * @param id + * @return + */ + public String getNameById(Long id) { + if(Objects.isNull(id)){ + return StringUtils.EMPTY; + } + if(Objects.nonNull(operatorCache.get(id))){ + return operatorCache.get(id).getName(); + } + return id + StringUtils.EMPTY; + } + + /** + * 获取当前运营商信息 + * @param name + * @return + */ + public OperatorQueryDTO getByName(String name) { + return operatorNameMap.get(name); + } + + /** + * 获取运营商信息s + * @return + */ + public Map asMap() { + return operatorCache.asMap(); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelper.java new file mode 100644 index 0000000..6fee621 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelper.java @@ -0,0 +1,439 @@ +package com.ningdatech.carapi.sys.helper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ArrayUtil; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.sys.contants.RegionContant; +import com.ningdatech.carapi.sys.convert.RegionConverter; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.service.IRegionService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + *

+ * RegionsCacheHelper + *

+ * + * @author WendyYang + * @since 12:12 2022/10/12 + */ +@Slf4j +@Component +public class RegionsCacheHelper implements InitializingBean { + + /** + * 当前支持最大层级 + */ + public static final int MAX_LEVEL = 3; + + public static final Long ROOT_PARENT_ID = 0L; + + public static final String ROOT_PARENT_CODE = "-1"; + + private LoadingCache regionsCache; + + private final Map regionCodeMapId = new ConcurrentHashMap<>(256); + private final Map regionsMap = new ConcurrentHashMap<>(256); + + //================================================================================================================== + + private final IRegionService regionService; + + public RegionsCacheHelper(IRegionService regionService) { + this.regionService = regionService; + } + + /** + * 刷新地域信息 + * + * @param regionId 地域编码 + **/ + public void refresh(Long regionId) { + log.info("刷新区域信息:{}", regionId); + regionsCache.refresh(regionId); + } + + public Long getIdByCode(String regionCode) { + if(StringUtils.isBlank(regionCode)){ + return 0L; + } + return regionCodeMapId.getOrDefault(regionCode, 0L); + } + + public void put(Long regionId, Region region) { + regionsCache.put(regionId, RegionConverter.toRegionDTO(region)); + } + + public RegionDTO getByRegionId(Long regionId) { + return regionsCache.get(regionId); + } + + @Override + public void afterPropertiesSet() { + regionsCache = Caffeine.newBuilder() + .refreshAfterWrite(7, TimeUnit.DAYS) + .build(key -> { + log.info("加载区域信息:regionLevel = {}", key); + // 查询全部 + Region region = regionService.getById(key); + if (Objects.isNull(region)) { + return null; + } + if (!region.getRegionCode().equals(region.getParentCode())) { + regionCodeMapId.put(region.getRegionCode(), region.getId()); + regionsMap.put(region.getId(), RegionConverter.toRegionDTO(region)); + } + return RegionConverter.toRegionDTO(region); + }); + warmUp(); + } + + /** + * 或许所有区域信息 + * + * @return 所有区域信息 + */ + public Collection getAll() { + return regionsCache.asMap().values(); + } + + public List listChildRegionId(Long regionId) { + return listChildRegionId(regionId, true, false); + } + + public List listChildRegionId(Long regionId, boolean containsSelf, boolean skipThisLevel) { + Map> groupByPid = CollUtils.group(getAll(), RegionDTO::getParentId); + List childIds = childrenId(regionId, groupByPid, skipThisLevel); + if (containsSelf) { + childIds.add(regionId); + } + return childIds; + } + + private List childrenId(Long regionId, Map> regionMap) { + return childrenId(regionId, regionMap, false); + } + + /** + * 获取当前区域所有下级区域 + * + * @param regionId 区域ID + * @param regionMap 区域信息 + * @param skipThisLevel 是否跳过本级 + * @return 子区域ID + * @author WendyYang + **/ + private List childrenId(Long regionId, Map> regionMap, boolean skipThisLevel) { + List childIds = new ArrayList<>(); + List children = regionMap.get(regionId); + if (children != null) { + children.forEach(w -> { + if (skipThisLevel && w.getRegionCode().equals(w.getParentCode())) { + return; + } + childIds.add(w.getId()); + childIds.addAll(childrenId(w.getId(), regionMap)); + }); + } + return childIds; + } + + /** + * 根据传入的地区ID获取所有上层地区集合 + * 按照level升序排列 + * + * @param regionId 地区ID + * @return 所有父级区域集合 + * @author WendyYang + **/ + public List listParents(Long regionId) { + List result = new ArrayList<>(); + RegionDTO region = regionsCache.get(regionId); + if (region != null) { + result.add(region); + if (region.getParentId() > 0) { + result.addAll(0, listParents(region.getParentId())); + } + } + return result; + } + + + private void warmUp() { + List regions = regionService.list(); + + for (Region region : regions) { + if (!region.getRegionCode().equals(region.getParentCode())) { + regionCodeMapId.put(region.getRegionCode(), region.getId()); + regionsMap.put(region.getId(), RegionConverter.toRegionDTO(region)); + } + } + + Map mapByRegionId = CollUtils.listToMap(regions, Region::getId, RegionConverter::toRegionDTO); + regionsCache.putAll(mapByRegionId); + } + + + /** + * 获取展示的区域名称 + */ + public String getDisplayName(Long regionId) { + if (Objects.isNull(regionId)) { + return StringUtils.EMPTY; + } + String displayRegionName = null; + List regions = listParents(regionId); + if (CollUtil.isNotEmpty(regions)) { + displayRegionName = CollUtils.join(regions, RegionDTO::getRegionName, StrPool.DASH); + } + return displayRegionName; + } + + /** + * 查询区域请使用{@link #listChildRegionId(Long)} + * + * @param regionCode 区域编码 + * @param regionLevel 区域级别 + * @return 子区域集合 + */ + @Deprecated + public List listChildRegionCode(String regionCode, int regionLevel) { + return Collections.emptyList(); + } + + /** + * 获取当前区域的下级区域信息 + * + * @param regionId 区域ID + * @param skipThisLevel 是否包含本级 + * @return 子区域map + */ + public Map> getChildrenMap(Long regionId, Boolean... skipThisLevel) { + boolean notSkip = ArrayUtil.isNotEmpty(skipThisLevel) ? skipThisLevel[0] : false; + Map> result = new TreeMap<>(Comparator.comparing(RegionDTO::getRegionCode)); + for (RegionDTO region : getAll()) { + if (notSkip && region.getRegionCode().equals(region.getParentCode())) { + continue; + } + if (region.getParentId().equals(regionId)) { + result.put(region, listChildRegionId(region.getId())); + } + } + return result; + } + + /** + * 获取当前区域的下一级区域ID集合 + * + * @param regionId + * @return + */ + public List listChild(Long regionId) { + List result = new ArrayList<>(); + for (RegionDTO region : getAll()) { + if (region.getParentId().equals(regionId) && region.getDeleted() == false) { + result.add(region.getId()); + } + } + return result; + } + + /** + * 获取当前区域的下一级区域集合 + * + * @param regionId / + * @return / + */ + public List listChildOnly(Long regionId) { + return listChildOnly(regionId, false); + } + + public List listChildOnly(Long regionId, boolean skipThisLevel) { + List result = new ArrayList<>(); + for (RegionDTO region : getAll()) { + if (skipThisLevel && region.getRegionCode().equals(region.getParentCode())) { + continue; + } + if (Objects.nonNull(regionId) && regionId.equals(region.getParentId()) && !region.getDeleted()) { + result.add(region); + } + } + if (!result.isEmpty()) { + result.sort(Comparator.comparing(RegionDTO::getRegionCode)); + } + return result; + } + + /** + * 去获取菜单 有权限判断 + * + * @param dataScope + * @param companiesCacheHelper + * @return + */ + public Collection getAllWithRole(Optional dataScope, CompaniesCacheHelper companiesCacheHelper) { + if (!dataScope.isPresent() || (CollUtil.isEmpty(dataScope.get().getRegionIds()) && + CollUtil.isEmpty(dataScope.get().getCompanyIds()))) { + return regionsCache.asMap().values(); + } + + List dataScopeRegionIds = dataScope.get().getRegionIds(); + + //1.企业逻辑 + if (CollUtil.isNotEmpty(dataScope.get().getCompanyIds())) { + //其实只有一个企业 + Long companyId = dataScope.get().getCompanyIds().get(0); + CompanyDTO company = companiesCacheHelper.getById(companyId); + dataScopeRegionIds = new ArrayList() { + { + this.add(company.getRegionId()); + } + }; + } + + Collection<@NonNull RegionDTO> regions = regionsCache.asMap().values(); + if (dataScopeRegionIds.size() == regions.size()) { + return regions; + } + + //2.区域逻辑 + List finalDataScopeRegionIds = dataScopeRegionIds; + AtomicInteger index = new AtomicInteger(0); + Collection res = regions.stream().filter(region -> finalDataScopeRegionIds.contains(region.getId())) + .map(region -> { + RegionDTO resDto = BeanUtil.copyProperties(region, RegionDTO.class); + if (0 == index.get()) { + processFirst(region, resDto); + } + index.incrementAndGet(); + return resDto; + }).collect(Collectors.toList()); + return res; + } + + /** + * 角色数据权限筛选后的菜单 最顶部的 要装饰上省市 目标实体 resDto + * + * @param region + * @param resDto + */ + private void processFirst(RegionDTO region, RegionDTO resDto) { + if (region.getRegionLevel().equals(RegionContant.SECOND_LEVEL)) { + resDto.setRegionName(regionsCache.get(region.getParentId()).getRegionName() + region.getRegionName()); + } else if (region.getRegionLevel().equals(RegionContant.THIRD_LEVEL)) { + RegionDTO parent = regionsCache.get(region.getParentId()); + RegionDTO grandParent = regionsCache.get(parent.getParentId()); + resDto.setRegionName(grandParent.getRegionName() + parent.getRegionName() + region.getRegionName()); + } + resDto.setParentId(RegionContant.EMPTY_PARENT_ID); + } + + /** + * 获取到 此区域ID的省份 + * + * @param regionId + * @return + */ + public String getProvince(Long regionId) { + if (Objects.isNull(regionId)) { + return StringUtils.EMPTY; + } + RegionDTO regionDto = this.getByRegionId(regionId); + if (Objects.isNull(regionDto)) { + return StringUtils.EMPTY; + } + if (regionDto.getRegionLevel().equals(RegionContant.THIRD_LEVEL)) { + RegionDTO parent = getByRegionId(regionDto.getParentId()); + if (Objects.isNull(parent)) { + return StringUtils.EMPTY; + } + RegionDTO parentD = getByRegionId(parent.getParentId()); + if (Objects.isNull(parentD)) { + return StringUtils.EMPTY; + } + return parentD.getRegionName(); + } else if (regionDto.getRegionLevel().equals(RegionContant.SECOND_LEVEL)) { + RegionDTO parent = getByRegionId(regionDto.getParentId()); + if (Objects.isNull(parent)) { + return StringUtils.EMPTY; + } + return parent.getRegionName(); + } else if (regionDto.getRegionLevel().equals(RegionContant.FIRST_LEVEL)) { + return regionDto.getRegionName(); + } + return StringUtils.EMPTY; + } + + /** + * 获取到 此区域ID的城市 + * + * @param regionId + * @return + */ + public String getCity(Long regionId) { + if (Objects.isNull(regionId)) { + return StringUtils.EMPTY; + } + RegionDTO regionDto = this.getByRegionId(regionId); + if (Objects.isNull(regionDto)) { + return StringUtils.EMPTY; + } + if (regionDto.getRegionLevel().equals(RegionContant.THIRD_LEVEL)) { + RegionDTO parent = getByRegionId(regionDto.getParentId()); + if (Objects.isNull(parent)) { + return StringUtils.EMPTY; + } + return parent.getRegionName(); + } else if (regionDto.getRegionLevel().equals(RegionContant.SECOND_LEVEL)) { + return regionDto.getRegionName(); + } + return StringUtils.EMPTY; + } + + /** + * 获取到 此区域ID的区县 + * + * @param regionId + * @return + */ + public String getDistinguish(Long regionId) { + if (Objects.isNull(regionId)) { + return StringUtils.EMPTY; + } + RegionDTO regionDto = this.getByRegionId(regionId); + if (Objects.isNull(regionDto)) { + return StringUtils.EMPTY; + } + if (regionDto.getRegionLevel().equals(RegionContant.THIRD_LEVEL)) { + return regionDto.getRegionName(); + } + return StringUtils.EMPTY; + } + + public List listByLevel(Integer level) { + if (Objects.isNull(level)) { + return Collections.emptyList(); + } + return regionsCache.asMap().values().stream() + .filter(r -> Objects.nonNull(r.getRegionLevel()) && level.equals(r.getRegionLevel()) && !r.getDeleted()) + .collect(Collectors.toList()); + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/UserCacheHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/UserCacheHelper.java new file mode 100644 index 0000000..b6ceac7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/UserCacheHelper.java @@ -0,0 +1,124 @@ +package com.ningdatech.carapi.sys.helper; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.common.collect.Maps; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.mapper.NdUserInfoMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + *

+ * UserCacheHelper + *

+ * + * @author PoffyZhang + * @since 09:01 2022/11/29 + */ +@Slf4j +@Component +public class UserCacheHelper implements InitializingBean { + + private LoadingCache userCache; + + //================================================================================================================== + + private Map userMap = Maps.newHashMap(); + + @Resource + private NdUserInfoMapper userInfoMapper; + + @Override + public void afterPropertiesSet() { + userCache = Caffeine.newBuilder() + // 需避免刷新过于频繁 + .refreshAfterWrite(10, TimeUnit.MINUTES) +// .maximumSize(50000) + .build(new CacheLoader() { + + @Override + public NdUserInfo load(Long id) throws Exception { + NdUserInfo user = userInfoMapper.selectById(id); + if(Objects.isNull(user)){ + log.info("加载用户信息失败: {}",id); + return null; + } + return user; + } + + @Override + public Map loadAll(Iterable keys) throws Exception { + List users = userInfoMapper.selectList(Wrappers.lambdaQuery(NdUserInfo.class).in(NdUserInfo::getId,keys)); + if(CollUtil.isEmpty(users)){ + log.info("加载用户信息失败: 信息为空"); + return Collections.emptyMap(); + } + Map map = users.stream() + .collect(Collectors.toMap(c -> c.getId(),c -> c)); + return map; + } + + + }); + + List users = userInfoMapper.selectList(Wrappers.lambdaQuery(NdUserInfo.class)); + if(CollUtil.isEmpty(users)){ + log.info("加载用户信息失败: 为空"); + return; + } + users.stream().forEach(u -> { + userCache.put(u.getId(),u); + userMap.put(u.getId(),u); + }); + } + + public Collection all(){ + return userCache.asMap().values(); + } + + /** + * 获取信息 + * @param id + * @return + */ + public NdUserInfo getById(Long id) { + if(Objects.isNull(id)){ + return null; + } + return userCache.get(id); + } + + /** + * 获取当前信息 + * @return + */ + public Map asMap() { + return userCache.asMap(); + } + + public void refresh(Long id) { + userCache.refresh(id); + NdUserInfo userInfo = userCache.get(id); + if(Objects.nonNull(userInfo)){ + userMap.put(userInfo.getId(),userInfo); + } + } + + public void refresh(List ids) { + if(CollUtil.isNotEmpty(ids)){ + ids.forEach(id -> { + refresh(id); + }); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/VehiclesCacheHelper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/VehiclesCacheHelper.java new file mode 100644 index 0000000..6121bfa --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/helper/VehiclesCacheHelper.java @@ -0,0 +1,145 @@ +package com.ningdatech.carapi.sys.helper; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.common.collect.Maps; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + *

+ * VehiclesCacheHelper + *

+ * + * @author PoffyZhang + * @since 09:01 2022/11/29 + */ +@Slf4j +@Component +public class VehiclesCacheHelper implements InitializingBean { + + private LoadingCache vehicleCache; + + //================================================================================================================== + + private Map vehicleMap = Maps.newHashMap(); + private Map carPlateMap = Maps.newHashMap(); + + @Resource + private VehicleBaseInfoMapper vehicleBaseInfoMapper; + + @Override + public void afterPropertiesSet() { + vehicleCache = Caffeine.newBuilder() + // 需避免刷新过于频繁 + .refreshAfterWrite(10, TimeUnit.MINUTES) +// .maximumSize(50000) + .build(new CacheLoader() { + + @Override + public NdVehicleBaseInfo load(Long id) throws Exception { + NdVehicleBaseInfo vehicle = vehicleBaseInfoMapper.selectById(id); + if(Objects.isNull(vehicle)){ + log.info("加载车辆信息失败: 车辆{} 信息为空为空",id); + return null; + } + return vehicle; + } + + @Override + public Map loadAll(Iterable keys) throws Exception { + List vehicles = vehicleBaseInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).in(NdVehicleBaseInfo::getId,keys)); + if(CollUtil.isEmpty(vehicles)){ + log.info("加载车辆信息失败: 车辆信息为空为空"); + return Collections.emptyMap(); + } + Map map = vehicles.stream() + .collect(Collectors.toMap(c -> c.getId(),c -> c)); + return map; + } + + + }); + + List vehicles = vehicleBaseInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)); + if(CollUtil.isEmpty(vehicles)){ + log.info("加载车辆信息失败: 车辆为空"); + return; + } + vehicles.stream().forEach(v -> { + vehicleCache.put(v.getId(),v); + vehicleMap.put(v.getCompanyId() + v.getCarPlate(),v); + carPlateMap.put(v.getCarPlate(),v); + }); + } + + public Collection all(){ + return vehicleCache.asMap().values(); + } + + /** + * 获取当前车辆信息 + * @param id + * @return + */ + public NdVehicleBaseInfo getById(Long id) { + return vehicleCache.get(id); + } + + /** + * 获取当前车辆信息 企业ID和车牌号 + * @param companyCarPlate + * @return + */ + public NdVehicleBaseInfo getByCompanyCarPlate(String companyCarPlate) { + return vehicleMap.get(companyCarPlate); + } + public NdVehicleBaseInfo getByCarPlate(String carPlate) { + return carPlateMap.get(carPlate); + } + + public Boolean isExits(String carPlate) { + return carPlateMap.containsKey(carPlate); + } + + /** + * 获取当前车辆信息 + * @return + */ + public Map asMap() { + return vehicleCache.asMap(); + } + + public void refresh(Long id) { + vehicleCache.refresh(id); + NdVehicleBaseInfo vehicleBaseInfo = vehicleCache.get(id); + if(Objects.nonNull(vehicleBaseInfo)){ + vehicleMap.put(vehicleBaseInfo.getCompanyId() + vehicleBaseInfo.getCarPlate(),vehicleBaseInfo); + carPlateMap.put(vehicleBaseInfo.getCarPlate(),vehicleBaseInfo); + } + } + + public void refresh(List ids) { + if(CollUtil.isNotEmpty(ids)){ + ids.forEach(id -> { + vehicleCache.refresh(id); + NdVehicleBaseInfo vehicleBaseInfo = vehicleCache.get(id); + if(Objects.nonNull(vehicleBaseInfo)){ + vehicleMap.put(vehicleBaseInfo.getCompanyId() + vehicleBaseInfo.getCarPlate(),vehicleBaseInfo); + carPlateMap.put(vehicleBaseInfo.getCarPlate(),vehicleBaseInfo); + } + }); + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CodingRuleManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CodingRuleManage.java new file mode 100644 index 0000000..467a0fc --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CodingRuleManage.java @@ -0,0 +1,135 @@ +package com.ningdatech.carapi.sys.manage; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.sys.entity.BonusPointsRule; +import com.ningdatech.carapi.sys.entity.CodingRule; +import com.ningdatech.carapi.sys.entity.CodingRuleInfo; +import com.ningdatech.carapi.sys.entity.ScoreDeductionRule; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum; +import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleVehicleType; +import com.ningdatech.carapi.sys.entity.enumeration.RuleOperationTypeEnum; +import com.ningdatech.carapi.sys.entity.req.ReqCodingRulePO; +import com.ningdatech.carapi.sys.entity.vo.ResCodingRuleVO; +import com.ningdatech.carapi.sys.service.ICodingRuleService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.collection.CollectionUtil; +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/24 下午2:01 + */ +@Component +@RequiredArgsConstructor +public class CodingRuleManage { + + private final ICodingRuleService iCodingRuleService; + + public ResCodingRuleVO getCodingRule() { + ResCodingRuleVO resCodingRuleVO = new ResCodingRuleVO(); + + List codingRuleList = iCodingRuleService.list(); + Map> operationCodingRuleMap = codingRuleList.stream().collect(Collectors.groupingBy(CodingRule::getRuleOperationType)); + // 装配加分规则 + List codingRuleInfoList = new ArrayList<>(); + List bonusPointsCodingRuleList = operationCodingRuleMap.get(RuleOperationTypeEnum.bonus_points.name()); + if (CollectionUtil.isNotEmpty(bonusPointsCodingRuleList)) { + for (CodingRule codingRule : bonusPointsCodingRuleList) { + CodingRuleInfo codingRuleInfo = new CodingRuleInfo(); + codingRuleInfo.setRuleOperationType(RuleOperationTypeEnum.valueOf(codingRule.getRuleOperationType())); + codingRuleInfo.setOperationScore(codingRule.getOperationScore()); + codingRuleInfo.setCodingRuleBehaviorType(CodingRuleBehaviorTypeEnum.valueOf(codingRule.getBehaviorType())); + codingRuleInfoList.add(codingRuleInfo); + } + } + BonusPointsRule bonusPointsRule = new BonusPointsRule(); + bonusPointsRule.setCodingRuleInfoList(codingRuleInfoList); + resCodingRuleVO.setBonusPointsRule(bonusPointsRule); + + // 装配扣分规则 + List scoreDeductionCodingRuleList = operationCodingRuleMap.get(RuleOperationTypeEnum.score_deduction.name()); + + List scoreDeductionRuleList = new ArrayList<>(); + if (CollectionUtil.isNotEmpty(scoreDeductionCodingRuleList)) { + Map> vehicleMap = scoreDeductionCodingRuleList.stream() + .collect(Collectors.groupingBy(CodingRule::getVehicleType)); + for (String vehicleTypeStr : vehicleMap.keySet()) { + ScoreDeductionRule scoreDeductionRule = new ScoreDeductionRule(); + scoreDeductionRule.setVehicleType(CodingRuleVehicleType.valueOf(vehicleTypeStr)); + List vehicleTypeCodingRuleInfoList = new ArrayList<>(); + + List vehicleCodingRuleList = vehicleMap.get(vehicleTypeStr); + if (CollectionUtil.isNotEmpty(vehicleCodingRuleList)) { + for (CodingRule codingRule : vehicleCodingRuleList) { + CodingRuleInfo codingRuleInfo = new CodingRuleInfo(); + codingRuleInfo.setRuleOperationType(RuleOperationTypeEnum.valueOf(codingRule.getRuleOperationType())); + codingRuleInfo.setOperationScore(codingRule.getOperationScore()); + codingRuleInfo.setCodingRuleBehaviorType(CodingRuleBehaviorTypeEnum.valueOf(codingRule.getBehaviorType())); + vehicleTypeCodingRuleInfoList.add(codingRuleInfo); + } + } + scoreDeductionRule.setCodingRuleInfoList(vehicleTypeCodingRuleInfoList); + scoreDeductionRuleList.add(scoreDeductionRule); + } + } + resCodingRuleVO.setScoreDeductionRuleList(scoreDeductionRuleList); + return resCodingRuleVO; + } + + @Transactional(rollbackFor = Exception.class) + public void saveCodingRule(ReqCodingRulePO request) { + Long userId = LoginUserUtil.getUserId(); + BonusPointsRule bonusPointsRule = request.getBonusPointsRule(); + List scoreDeductionRuleList = request.getScoreDeductionRuleList(); + // 保存加分规则 + List bonusPointsRuleInfoList = bonusPointsRule.getCodingRuleInfoList(); + for (CodingRuleInfo bonusPointsRuleInfo : bonusPointsRuleInfoList) { + CodingRule codingRule = iCodingRuleService.getOne(Wrappers.lambdaQuery(CodingRule.class) + .eq(CodingRule::getBehaviorType, bonusPointsRuleInfo.getCodingRuleBehaviorType().name())); + if (Objects.isNull(codingRule)) { + codingRule = new CodingRule(); + codingRule.setCreateOn(LocalDateTime.now()); + codingRule.setCreateBy(userId); + } + codingRule.setUpdateOn(LocalDateTime.now()); + codingRule.setOperationScore(bonusPointsRuleInfo.getOperationScore()); + codingRule.setRuleOperationType(bonusPointsRuleInfo.getRuleOperationType().name()); + codingRule.setBehaviorType(bonusPointsRuleInfo.getCodingRuleBehaviorType().name()); + iCodingRuleService.saveOrUpdate(codingRule); + } + + // 保存扣分规则 + for (ScoreDeductionRule scoreDeductionRule : scoreDeductionRuleList) { + CodingRuleVehicleType vehicleType = scoreDeductionRule.getVehicleType(); + List codingRuleInfoList = scoreDeductionRule.getCodingRuleInfoList(); + for (CodingRuleInfo codingRuleInfo : codingRuleInfoList) { + CodingRule codingRule = iCodingRuleService.getOne(Wrappers.lambdaQuery(CodingRule.class) + .eq(CodingRule::getBehaviorType, codingRuleInfo.getCodingRuleBehaviorType().name()) + .eq(CodingRule::getVehicleType, vehicleType.name())); + + if (Objects.isNull(codingRule)) { + codingRule = new CodingRule(); + codingRule.setCreateOn(LocalDateTime.now()); + codingRule.setCreateBy(userId); + codingRule.setVehicleType(vehicleType.name()); + } + codingRule.setUpdateOn(LocalDateTime.now()); + codingRule.setOperationScore(codingRuleInfo.getOperationScore()); + codingRule.setRuleOperationType(codingRuleInfo.getRuleOperationType().name()); + codingRule.setBehaviorType(codingRuleInfo.getCodingRuleBehaviorType().name()); + iCodingRuleService.saveOrUpdate(codingRule); + } + } + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CompanyManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CompanyManage.java new file mode 100644 index 0000000..29fc3d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/CompanyManage.java @@ -0,0 +1,499 @@ +package com.ningdatech.carapi.sys.manage; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.ningdatech.carapi.company.enumeration.CompanyCreditLevelEnum; +import com.ningdatech.carapi.company.enumeration.CompanyTypeEnum; +import com.ningdatech.carapi.company.enumeration.ProductCompanyType; +import com.ningdatech.carapi.company.service.INdCompanyCreditLevelService; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.CompanyType; +import com.ningdatech.carapi.sys.entity.CompanyTypeRelated; +import com.ningdatech.carapi.sys.entity.dto.*; +import com.ningdatech.carapi.sys.entity.vo.CompanyVO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.CompanyTypeRelatedService; +import com.ningdatech.carapi.sys.service.CompanyTypeService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.http.HttpStatus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname CompanyManage + * @Description + * @Date 2022/10/12 11:26 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class CompanyManage { + + private final CompanyService companyService; + private final RegionsCacheHelper regionsCacheHelper; + + private final CompanyTypeService companyTypeService; + private final CompanyTypeRelatedService companyTypeRelatedService; + + private final CompaniesCacheHelper companiesCacheHelper; + private final IDriverInfoService driverInfoService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final INdCompanyCreditLevelService companyCreditLevelService; + private final INdUserInfoService userInfoService; + private final INdUserAuthService userAuthService; + + /** + * 公司列表查询 + * @param companyPageQuery + * @return + */ + public PageVo queryList(CompanyPageQuery companyPageQuery) { + Integer pageNumber = companyPageQuery.getPageNumber(); + Integer pageSize = companyPageQuery.getPageSize(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + // 未传入筛选条件时,筛选掉管理企业 + if (CollUtil.isEmpty(companyPageQuery.getCompanyTypeList())) { + companyPageQuery.setCompanyTypeList(Lists.newArrayList(1, 2, 3)); + } + ((CompanyManage)AopContext.currentProxy()).buildQueryWrapper(wrapper, companyPageQuery); + + // 获取所有符合传入条件的企业列表 + List companyList = companyService.list(wrapper); + + // 筛选出非管理企业的企业(根据传入的企业类型可筛选出生产企业、物流企业、其他企业) + List companyIdList = companyList.stream().map(Company::getId).collect(Collectors.toList()); + + Map> listMap = companyCreditLevelService.list().stream() + .filter(c -> companyIdList.contains(c.getCompanyId())) + .collect(Collectors.groupingBy(NdCompanyCreditLevel::getCompanyId)); + + Map> companyTypeRelatedMap = companyTypeRelatedService.list().stream() + .collect(Collectors.groupingBy(CompanyTypeRelated::getCompanyId)); + + List dataList = Lists.newArrayList(); + Integer companyType = companyPageQuery.getCompanyType(); + Integer productCompanyType = companyPageQuery.getProductCompanyType(); + // 如果是生产企业列表具体生产企业类型的筛选 + if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(companyType) + && Objects.nonNull(productCompanyType)){ + // 关联表中筛选出对应类型的生产企业 + List relatedCompanyIds = companyTypeRelatedService.list(Wrappers.lambdaQuery(CompanyTypeRelated.class) + .in(CompanyTypeRelated::getCompanyId, companyIdList) + .eq(CompanyTypeRelated::getCompanyTypeId, productCompanyType)) + .stream().map(CompanyTypeRelated::getCompanyId).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(relatedCompanyIds)) { + dataList = companyList.stream() + .filter(c -> relatedCompanyIds.contains(c.getId())) + .collect(Collectors.toList()); + } + }else { + // 非生产企业类型的列表筛选,就根据企业类型返回对应的数据 + dataList = companyList; + } + + List data = CollUtils.convert(dataList, c -> { + CompanyVO vo = new CompanyVO(); + BeanUtils.copyProperties(c, vo); + CodeUtil.searchRegionName(vo); + // 根据企业ID获取企业信用等级 + Long companyId = c.getId(); + List creditLevelList = listMap.get(companyId); + if (CollUtil.isNotEmpty(creditLevelList)) { + // 过滤出当前时间年份的信用等级 + String year = String.valueOf(LocalDateTime.now().getYear()); + List levels = + creditLevelList.stream().filter(d -> year.equals(d.getYear())).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(levels)) { + NdCompanyCreditLevel creditLevel = levels.get(0); + vo.setDangerLevel(creditLevel.getLevel()); + vo.setDangerLevelName(CompanyCreditLevelEnum.getDescByCode(creditLevel.getLevel())); + } + } else { + log.info("该企业{}不在企业信用等级列表中", companyId); + // 默认赋红码 + vo.setDangerLevel(CompanyCreditLevelEnum.E.getCode()); + vo.setDangerLevelName(CompanyCreditLevelEnum.E.getDesc()); + } + + // 如果是生产企业类型列表,要展示具体的生产企业类型 + if (Objects.nonNull(vo.getCompanyType())) { + if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(vo.getCompanyType())) { + List relatedList = companyTypeRelatedMap.get(vo.getId()); + if (CollUtil.isNotEmpty(relatedList)) { + List nameList = relatedList.stream() + .map(r -> ProductCompanyType.getDescByCode(r.getCompanyTypeId())) + .collect(Collectors.toList()); + String typeName = nameList.stream().collect(Collectors.joining(StrPool.COMMA)); + vo.setCompanyTypeName(typeName); + } + } else { + vo.setCompanyTypeName(CompanyTypeEnum.getDescByCode(vo.getCompanyType())); + } + } + return vo; + }); + + // 分页 + List vos = data.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize).collect(Collectors.toList()); + + return PageVo.of(vos, data.size()); + } + + /** + * 查询详情 + * @param id + * @return + */ + public CompanyQueryDTO getDetails(Long id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + CompanyManage context = (CompanyManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + Company company = companyService.getOne(wrapper); + if (Objects.isNull(company)){ + return null; + } + //Company company = companyService.getById(id); + + CompanyQueryDTO query = BeanUtil.toBean(company, CompanyQueryDTO.class); + query.setCompanyTypeName(CompanyTypeEnum.getDescByCode(company.getCompanyType())); + //查询区域 + CodeUtil.searchRegionName(query); + //查询企业类型 + List companyTypeRelateds = searchEnterpriseType(query.getId()); + if(CollUtil.isNotEmpty(companyTypeRelateds)){ + query.setEnterpriseTypes(companyTypeRelateds.stream().map(CompanyTypeRelated::getCompanyTypeId).collect(Collectors.toList())); + query.setEnterpriseTypesName(companyTypeRelateds.stream().map(r -> { + Long companyTypeId = r.getCompanyTypeId(); + CompanyType companyType = companyTypeService.getById(companyTypeId); + return Objects.nonNull(companyType) ? companyType.getName() : StringUtils.EMPTY; + }).filter(StringUtils::isNotBlank).collect(Collectors.joining(StrPool.COMMA))); + } + return query; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(Company::getId,id); + } + + /** + * 查询 此企业的类型 + * @param companyId + */ + public List searchEnterpriseType(Long companyId) { + return companyTypeRelatedService.list(Wrappers.lambdaQuery(CompanyTypeRelated.class).eq(CompanyTypeRelated::getCompanyId, companyId)); + } + + /** + * 企业类型 + * @return + */ + public List queryCompanyTypes() { + List companyTypes = companyTypeService.list(); + + return buildCompanyChildren(companyTypes); + } + + private List buildCompanyChildren(List companyTypes) { + if(CollUtil.isEmpty(companyTypes)){ + return Collections.emptyList(); + } + List res = Lists.newArrayList(); + + for(CompanyType companyType: companyTypes){ + // 获取生产企业的子菜单 + if(companyType.getPid().equals(Long.valueOf(CompanyTypeEnum.PRODUCT_BU.getCode()))){ + CascadeDTO cascade = CascadeDTO.of(companyType.getId(), companyType.getName(),null); + res.add(cascade); + } + } + + return res; + } + + + /** + * 处理地区 + * @param wrapper + * @param companyPageQuery + */ + @BuildChildrenRegionWrapper + @LambdaDataScope(type = LambdaDataScopeTypeEnum.COMPANY_TABLE) + public void buildQueryWrapper(LambdaQueryWrapper wrapper, CompanyPageQuery companyPageQuery) { + wrapper.like(StringUtils.isNotBlank(companyPageQuery.getName()),Company::getName, companyPageQuery.getName()) + .eq(Objects.nonNull(companyPageQuery.getBlackList()),Company::getBlackList,companyPageQuery.getBlackList()) + // 根据传入的企业类型获取相对应的企业(信息管理列表要筛选掉管理企业) + .in(CollUtil.isNotEmpty(companyPageQuery.getCompanyTypeList()),Company::getCompanyType,companyPageQuery.getCompanyTypeList()) + .eq(Objects.nonNull(companyPageQuery.getCompanyType()),Company::getCompanyType, companyPageQuery.getCompanyType()) + //// 区县、市散办审核通过的企业才展示 + //.eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_SUCESS.getCode()) + //.eq(Company::getCityAuditStatus,AuditStateEnum.AUDIT_SUCESS.getCode()) + .orderBy(Boolean.TRUE,Boolean.TRUE,Company::getName); + } + + /** + * 使用企业列表查询 + * @param wrapper + * @param companyPageQuery + */ + public void buildUseQueryWrapper(LambdaQueryWrapper wrapper, CompanyPageQuery companyPageQuery) { + wrapper.like(StringUtils.isNotBlank(companyPageQuery.getName()),Company::getName, companyPageQuery.getName()) + .eq(Objects.nonNull(companyPageQuery.getBlackList()),Company::getBlackList,companyPageQuery.getBlackList()) + // 根据传入的企业类型获取相对应的企业(信息管理列表要筛选掉管理企业) + .in(CollUtil.isNotEmpty(companyPageQuery.getCompanyTypeList()),Company::getCompanyType,companyPageQuery.getCompanyTypeList()) + .eq(Objects.nonNull(companyPageQuery.getCompanyType()),Company::getCompanyType, companyPageQuery.getCompanyType()) + .orderBy(Boolean.TRUE,Boolean.TRUE,Company::getName); + } + + /** + * 获取企业ids 用区域ids + * @param regionIds + * @return + */ + public List getIdsByRegionIds(List regionIds) { + List regionArr = Lists.newArrayList(); + + if (CollUtil.isEmpty(regionIds)) { + return Collections.emptyList(); + } + + regionIds.stream().forEach(regionId -> { + List regions = regionsCacheHelper.listChildRegionId(regionId); + if (CollUtil.isNotEmpty(regions)) { + regionArr.addAll(regions); + } + }); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + wrapper.in(Company::getRegionId, regionArr); + List companies = companyService.list(wrapper); + + if (CollUtil.isEmpty(companies)) { + return Collections.emptyList(); + } + + return companies.stream().map(Company::getId).collect(Collectors.toList()); + } + + public Company save(CompanySaveDTO data, Long userId) { + Company company = companyService.save(data, userId); + companiesCacheHelper.refresh(company.getId()); + return company; + } + + public Company update(CompanyUpdateDTO data, Long userId) { + Company old = companyService.getById(data.getId()); + if (Objects.isNull(old)) { + throw new BaseUncheckedException(HttpStatus.HTTP_OK, String.format("修改企业{} 不存在", data.getId())); + } + if (StringUtils.isNotBlank(data.getName())) { + Assert.isFalse(companyService.check(data.getName(), old.getId()), "企业名{} 已经存在", + data.getName()); + } + Company company = companyService.update(data, userId); + companiesCacheHelper.refresh(company.getId()); + + // 更新企业登录账号所关联的企业法人、法人手机号、登录账号(企业名称)等信息 + // 根据企业名称和企业ID获取原来企业信息员的用户信息 + NdUserInfo companyUserInfo = userInfoService.getOne(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getCompanyId, old.getId()) + .eq(NdUserInfo::getUsername, old.getName())); + if (Objects.nonNull(companyUserInfo)) { + // 更新了企业名称、法人联系电话 + companyUserInfo.setUsername(data.getName()); + companyUserInfo.setMobile(data.getLegalPersonPhone()); + try { + userInfoService.updateById(companyUserInfo); + } catch (Exception e) { + throw new BizException("该法人手机号绑定的用户已存在!"); + } + // 更新登录账号为修改后的企业名称 + Long companyUserId = companyUserInfo.getId(); + NdUserAuth companyUserAuth = userAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getUserId, companyUserId)); + companyUserAuth.setIdentifier(companyUserInfo.getUsername()); + userAuthService.updateById(companyUserAuth); + } + + List enterpriseTypes = data.getEnterpriseTypes(); + if (CollUtil.isNotEmpty(enterpriseTypes)){ + // 先删除原来关联的信息,再保存 + companyTypeRelatedService.remove(Wrappers.lambdaQuery(CompanyTypeRelated.class) + .eq(CompanyTypeRelated::getCompanyId,company.getId())); + for (Long enterpriseType : enterpriseTypes) { + CompanyTypeRelated companyTypeRelated = new CompanyTypeRelated(); + companyTypeRelated.setCompanyId(company.getId()); + companyTypeRelated.setCompanyTypeId(enterpriseType); + companyTypeRelatedService.save(companyTypeRelated); + } + } + + // 查询出驾驶员档案中所属公司为该企业的所有驾驶员 + List driverInfoList = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getCompanyId, company.getId())); + driverInfoList.forEach(driverInfo -> driverInfo.setRegionId(data.getRegionId())); + // 更新驾驶员档案信息中所属公司为该企业的所属区域 + driverInfoService.updateBatchById(driverInfoList); + // 查询出车辆档案信息中所属公司为该企业的所有车辆 + List ndVehicleBaseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCompanyId, company.getId())); + ndVehicleBaseInfoList.forEach(v -> { + v.setRegionId(data.getRegionId()); + v.setRegionName(regionsCacheHelper.getDisplayName(data.getRegionId())); + }); + // 更新车辆档案信息中所属公司为该企业的所属区域 + vehicleBaseInfoService.updateBatchById(ndVehicleBaseInfoList); + return company; + } + + public Boolean removeByIdWithCache(List ids) { + List list = Lists.newArrayList(); + CompanyManage context = (CompanyManage) AopContext.currentProxy(); + for (Long id : ids) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + context.buildQuery(wrapper, id); + Company company = companyService.getOne(wrapper); + if (Objects.nonNull(company)) { + list.add(company.getId()); + } + } + Boolean res = companyService.removeByIdWithCache(list); + companiesCacheHelper.refresh(list); + return res; + } + + public PageVo queryUseCompanyList(CompanyPageQuery companyPageQuery) { + Integer pageNumber = companyPageQuery.getPageNumber(); + Integer pageSize = companyPageQuery.getPageSize(); + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + // 未传入筛选条件时,筛选掉管理企业 + if (CollUtil.isEmpty(companyPageQuery.getCompanyTypeList())) { + companyPageQuery.setCompanyTypeList(Lists.newArrayList(1, 2, 3)); + } + buildUseQueryWrapper(wrapper, companyPageQuery); + + // 获取所有符合传入条件的企业列表 + List companyList = companyService.list(wrapper); + + // 筛选出非管理企业的企业(根据传入的企业类型可筛选出生产企业、物流企业、其他企业) + List companyIdList = companyList.stream().map(Company::getId).collect(Collectors.toList()); + + Map> listMap = companyCreditLevelService.list().stream() + .filter(c -> companyIdList.contains(c.getCompanyId())) + .collect(Collectors.groupingBy(NdCompanyCreditLevel::getCompanyId)); + + Map> companyTypeRelatedMap = companyTypeRelatedService.list().stream() + .collect(Collectors.groupingBy(CompanyTypeRelated::getCompanyId)); + + List dataList = Lists.newArrayList(); + Integer companyType = companyPageQuery.getCompanyType(); + Integer productCompanyType = companyPageQuery.getProductCompanyType(); + // 如果是生产企业列表具体生产企业类型的筛选 + if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(companyType) + && Objects.nonNull(productCompanyType)){ + // 关联表中筛选出对应类型的生产企业 + List relatedCompanyIds = companyTypeRelatedService.list(Wrappers.lambdaQuery(CompanyTypeRelated.class) + .in(CompanyTypeRelated::getCompanyId, companyIdList) + .eq(CompanyTypeRelated::getCompanyTypeId, productCompanyType)) + .stream().map(CompanyTypeRelated::getCompanyId).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(relatedCompanyIds)) { + dataList = companyList.stream() + .filter(c -> relatedCompanyIds.contains(c.getId())) + .collect(Collectors.toList()); + } + }else { + // 非生产企业类型的列表筛选,就根据企业类型返回对应的数据 + dataList = companyList; + } + + List data = CollUtils.convert(dataList, c -> { + CompanyVO vo = new CompanyVO(); + BeanUtils.copyProperties(c, vo); + CodeUtil.searchRegionName(vo); + // 根据企业ID获取企业信用等级 + Long companyId = c.getId(); + List creditLevelList = listMap.get(companyId); + if (CollUtil.isNotEmpty(creditLevelList)) { + // 过滤出当前时间年份的信用等级 + String year = String.valueOf(LocalDateTime.now().getYear()); + List levels = + creditLevelList.stream().filter(d -> year.equals(d.getYear())).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(levels)) { + NdCompanyCreditLevel creditLevel = levels.get(0); + vo.setDangerLevel(creditLevel.getLevel()); + vo.setDangerLevelName(CompanyCreditLevelEnum.getDescByCode(creditLevel.getLevel())); + } + } else { + log.info("该企业{}不在企业信用等级列表中", companyId); + // 默认赋红码 + vo.setDangerLevel(CompanyCreditLevelEnum.E.getCode()); + vo.setDangerLevelName(CompanyCreditLevelEnum.E.getDesc()); + } + + // 如果是生产企业类型列表,要展示具体的生产企业类型 + if (Objects.nonNull(vo.getCompanyType())) { + if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(vo.getCompanyType())) { + List relatedList = companyTypeRelatedMap.get(vo.getId()); + if (CollUtil.isNotEmpty(relatedList)) { + List nameList = relatedList.stream() + .map(r -> ProductCompanyType.getDescByCode(r.getCompanyTypeId())) + .collect(Collectors.toList()); + String typeName = nameList.stream().collect(Collectors.joining(StrPool.COMMA)); + vo.setCompanyTypeName(typeName); + } + } else { + vo.setCompanyTypeName(CompanyTypeEnum.getDescByCode(vo.getCompanyType())); + } + } + return vo; + }); + + // 分页 + List vos = data.stream() + .skip((long) (pageNumber - 1) * pageSize) + .limit(pageSize).collect(Collectors.toList()); + + return PageVo.of(vos, data.size()); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/MenuManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/MenuManage.java new file mode 100644 index 0000000..61233e6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/MenuManage.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.sys.manage; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.vo.MenuRoleVO; +import com.ningdatech.carapi.sys.service.IRoleMenuService; +import com.ningdatech.carapi.sys.utils.TreeUtil; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Classname MenuManage + * @Description + * @Date 2022/11/12 11:26 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +public class MenuManage { + private final IRoleMenuService roleMenuService; + + public List buildUserMenu(List list, UserInfoDetails loginUser) { + if (Objects.isNull(loginUser) || Objects.isNull(loginUser.getRoleId())) { + return Collections.emptyList(); + } + //查出当前用户的角色菜单 + List roleMenus = roleMenuService.list(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, loginUser.getRoleId())); + //单一用户 menuId应该是唯一的 可以做成map + Map roleMenuMap = CollUtils.listToMap(roleMenus,r -> r.getMenuId()); + List menuRoles = CollUtils.convert(list, w -> BeanUtil.copyProperties(w, MenuRoleVO.class)); + return TreeUtil.buildUserTree(menuRoles, roleMenuMap); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/OperatorManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/OperatorManage.java new file mode 100644 index 0000000..7033465 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/OperatorManage.java @@ -0,0 +1,125 @@ +package com.ningdatech.carapi.sys.manage; + +import java.util.List; +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.industry.service.IOperatorIndexScoreInfoService; +import com.ningdatech.carapi.sys.entity.Operator; +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import com.ningdatech.carapi.sys.entity.dto.OperatorPageQuery; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.entity.vo.OperatorVO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.service.IOperatorScoreInfoService; +import com.ningdatech.carapi.sys.service.OperatorRegionHeadService; +import com.ningdatech.carapi.sys.service.OperatorService; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname OperatorManage + * @Description + * @Date 2022/10/12 11:26 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class OperatorManage { + + private final OperatorService operatorService; + private final OperatorRegionHeadService operatorRegionHeadService; + private final IOperatorScoreInfoService operatorScoreInfoService; + + private final IOperatorIndexScoreInfoService operatorIndexScoreInfoService; + private final OperatorsCacheHelper operatorsCacheHelper; + + /** + * 查询列表 + * @param operatorPageQuery + * @return + */ + public PageVo queryList(OperatorPageQuery operatorPageQuery) { + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + Page page = operatorPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Operator.class); + wrapper.like(StringUtils.isNotBlank(operatorPageQuery.getName()), Operator::getName, operatorPageQuery.getName()) + .eq(Operator::getId,operatorId) + .orderBy(Boolean.TRUE, Boolean.FALSE, Operator::getUpdateOn); + operatorService.page(page, wrapper); + List data = CollUtils.convert(page.getRecords(), c -> BeanUtil.copyProperties(c, OperatorVO.class)); + return PageVo.of(data, page.getTotal()); + }else { + Page page = operatorPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Operator.class); + wrapper.like(StringUtils.isNotBlank(operatorPageQuery.getName()), Operator::getName, operatorPageQuery.getName()) + .orderBy(Boolean.TRUE, Boolean.FALSE, Operator::getUpdateOn); + operatorService.page(page, wrapper); + List data = CollUtils.convert(page.getRecords(), c -> BeanUtil.copyProperties(c, OperatorVO.class)); + return PageVo.of(data, page.getTotal()); + } + } + + + /** + * 查询详情 + * @param id + * @return + */ + public OperatorQueryDTO getDetails(Long id) { + Operator operator = operatorService.getById(id); + OperatorQueryDTO query = BeanUtil.toBean(operator, OperatorQueryDTO.class); + fillRegionHead(query); + return query; + } + + /** + * 放入区域负责人 + * @param query + */ + public void fillRegionHead(OperatorQueryDTO query) { + if(Objects.nonNull(query)){ + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(OperatorRegionHead.class); + List regionHeads = getOperatorRegionHeads(query, wrapper); + CodeUtil.searchRegionNames(regionHeads); + query.setOperatorRegionHeads(regionHeads); + } + } + + public List getOperatorRegionHeads(OperatorQueryDTO query, LambdaQueryWrapper wrapper) { + OperatorManage context = (OperatorManage) AopContext.currentProxy(); + context.buildQuery(wrapper, query.getId()); + List regionHeads = operatorRegionHeadService.list(wrapper); + return regionHeads; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.in(OperatorRegionHead::getOperatorId, id); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RegionManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RegionManage.java new file mode 100644 index 0000000..f5a9af9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RegionManage.java @@ -0,0 +1,663 @@ +package com.ningdatech.carapi.sys.manage; + +import static com.ningdatech.carapi.sys.helper.RegionsCacheHelper.ROOT_PARENT_ID; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.tuple.Pair; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.equipment.manage.VehicleEquipmentManage; +import com.ningdatech.carapi.car.equipment.model.DataAccessDevices; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo; +import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentPageQuery; +import com.ningdatech.carapi.car.equipment.model.vo.VehicleEquipmentVO; +import com.ningdatech.carapi.car.equipment.service.IDataAccessDevicesService; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentChannelsService; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.ningdatech.carapi.car.equipment.service.IVehicleEquipmentNoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.DeletedEnum; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.constant.VehicleEquipFuncEnum; +import com.ningdatech.carapi.company.enumeration.CompanyTypeEnum; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeContext; +import com.ningdatech.carapi.sys.convert.RegionConverter; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.entity.req.RegionTreeReq; +import com.ningdatech.carapi.sys.entity.vo.*; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.IRegionService; +import com.ningdatech.carapi.sys.utils.DataScopeCacheFilterUtil; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.map.MapUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * RegionManage + *

+ * + * @author WendyYang + * @since 10:39 2022/10/12 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class RegionManage { + + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + private final IRegionService regionService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final VehicleEquipmentManage equipmentManage; + private final INdVehicleEquipmentInfoService vehicleEquipmentInfoService; + private final IDataAccessDevicesService dataAccessDevicesService; + private final INdVehicleEquipmentChannelsService vehicleEquipmentChannelsService; + private final CompanyService companyService; + private final OperatorsCacheHelper operatorsCacheHelper; + private final IVehicleEquipmentNoService vehicleEquipmentNoService; + + public List getRegionTree(RegionTreeReq req) { + Map> companyMap = null; + Map> carNoGroup = null; + Optional dataScope = DataScopeContext.getDataScope(LoginUserUtil.loginUserDetail().getDataScope()); + if (req != null) { + if (req.getWithCarNo() || req.getWithCompany()) { + companyMap = companiesCacheHelper.all().stream() + .map(w -> BeanUtil.copyProperties(w, RegionTreeCompanyVO.class)) + .filter(c -> DataScopeCacheFilterUtil.dataScopeFilter(c, dataScope)) + .collect(Collectors.groupingBy(RegionTreeCompanyVO::getRegionId)); + } + if (req.getWithCarNo()) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + //数据权限 + ((RegionManage) AopContext.currentProxy()).wrapperDataScope(wrapper); + carNoGroup = vehicleBaseInfoService.list(wrapper) + .stream() + .collect(Collectors.groupingBy(NdVehicleBaseInfo::getCompanyId, + Collectors.mapping(car -> convertCar(car), Collectors.toList()))); + } + } + Map> regionMap = CollUtils.group(regionsCacheHelper.getAllWithRole(dataScope, companiesCacheHelper), RegionDTO::getParentId); + return RegionConverter.toRegionTree(ROOT_PARENT_ID, regionMap, false, carNoGroup, companyMap); + } + + public List getRegionCompanyCarNoTree(RegionTreeReq req) { + Map> companyMap = null; + Map>> carNoGroup = null; + Optional dataScope = DataScopeContext.getDataScope(LoginUserUtil.loginUserDetail().getDataScope()); + if (req != null) { + if (req.getWithCarNo() || req.getWithCompany()) { + companyMap = companiesCacheHelper.all().stream() + .map(w -> BeanUtil.copyProperties(w, RegionTreeCompanyVO.class)) + .filter(c -> DataScopeCacheFilterUtil.dataScopeFilter(c, dataScope)) + // 过滤掉管理企业 + .filter(c -> !CompanyTypeEnum.MANAGE_BU.getCode().equals(c.getCompanyType())) + .filter(item -> Objects.nonNull(item.getRegionId())) + .collect(Collectors.groupingBy(RegionTreeCompanyVO::getRegionId)); + } + if (req.getWithCarNo()) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + //数据权限 + ((RegionManage) AopContext.currentProxy()).wrapperDataScope(wrapper); + if(req.getWithDevice()){ + List withDeviceCars = null; + VehicleEquipmentPageQuery vehicleEquipmentPageQuery = new VehicleEquipmentPageQuery(); + vehicleEquipmentPageQuery.setPageNumber(1); + vehicleEquipmentPageQuery.setPageSize(200000); + PageVo ePage = equipmentManage.queryAdded(vehicleEquipmentPageQuery); + if(ePage.getTotal() > 0L){ + withDeviceCars = ePage.getRecords().stream().map(VehicleEquipmentVO::getCarPlate).collect(Collectors.toList()); + if(CollUtil.isNotEmpty(withDeviceCars)){ + wrapper.in(NdVehicleBaseInfo::getCarPlate,withDeviceCars); + } + } + } + carNoGroup = vehicleBaseInfoService.list(wrapper) + .stream() + .collect(Collectors.groupingBy(NdVehicleBaseInfo::getCompanyId, + Collectors.mapping(w -> Pair.of(w.getId(), convertCar(w)), Collectors.toList()))); + } + } + Map> regionMap = CollUtils.group(regionsCacheHelper.getAllWithRole(dataScope, companiesCacheHelper), RegionDTO::getParentId); + // 以车牌号分组,获取所有视频设备信息 + Map> equipmentMap = vehicleEquipmentInfoService.list().stream() + .filter(c -> VehicleEquipFuncEnum.video.name().equals(c.getEquipmentFunction())) + .collect(Collectors.groupingBy(NdVehicleEquipmentInfo::getCarPlate)); + // 获取设备的开启状态信息 + Map devicesMap = dataAccessDevicesService.list().stream() + .collect(Collectors.toMap(c -> c.getPlatformId() + c.getDeviceId(), c -> c)); + + // 获取设备通道信息 + Map channelsMap = vehicleEquipmentChannelsService.list().stream() + .collect(Collectors.toMap(NdVehicleEquipmentChannels::getEquipmentId, e -> e)); + return RegionConverter.toRegionCompanyCarNoTree(ROOT_PARENT_ID, regionMap, false, carNoGroup, companyMap,devicesMap,equipmentMap,channelsMap); + } + + @LambdaDataScope + public LambdaQueryWrapper wrapperDataScope(LambdaQueryWrapper wrapper) { + return wrapper.select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getStatus,NdVehicleBaseInfo::getMoving, NdVehicleBaseInfo::getCompanyId) + .eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()); + } + + + public LambdaQueryWrapper buildRegionWrapper(LambdaQueryWrapper wrapper) { + return wrapper.select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getStatus,NdVehicleBaseInfo::getMoving, NdVehicleBaseInfo::getCompanyId) + .eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()); + } + + public synchronized void saveOrUpdate(RegionTreeVO req) { + if (req.getId() == null) { + if (req.getLevel() > RegionsCacheHelper.MAX_LEVEL) { + throw new BizException("暂不支持添加第四级区域"); + } + if (req.getParentCode().equals(RegionsCacheHelper.ROOT_PARENT_CODE)) { + boolean exists = regionService.getBaseMapper().exists(Wrappers.lambdaQuery(Region.class) + .eq(Region::getParentCode, req.getParentCode()) + .eq(Region::getDeleted, false)); + Assert.isFalse(exists, "顶级区域已存在"); + } + } + LambdaQueryWrapper query = Wrappers.lambdaQuery(Region.class) + .eq(Region::getRegionCode, req.getRegionCode()) + .last("limit 1"); + Region region = regionService.getOne(query); + if (region != null) { + if (!region.getRegionCode().equals(req.getParentCode())) { + if (req.getId() == null || !req.getId().equals(region.getId())) { + throw new BizException("地区编码已存在"); + } + } + } + Long parentId = 0L; + if (req.getLevel() > 1) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Region.class) + .eq(Region::getRegionCode, req.getParentCode()) + .eq(Region::getLevel, req.getLevel() - 1); + Region parent = regionService.getOne(wrapper); + parentId = parent.getId(); + } + Region regionNew = BeanUtil.copyProperties(req, Region.class); + regionNew.setDeleted(false); + regionNew.setParentId(parentId); + regionNew.setUpdateBy(LoginUserUtil.getUserId()); + regionNew.setUpdateOn(LocalDateTime.now()); + if (req.getId() == null) { + regionNew.setCreateBy(regionNew.getUpdateBy()); + regionNew.setCreateOn(regionNew.getUpdateOn()); + } + if (regionService.saveOrUpdate(regionNew)) { + regionsCacheHelper.refresh(regionNew.getId()); + } + } + + public void remove(Long id, Integer level) { + LambdaUpdateWrapper updater = Wrappers.lambdaUpdate(Region.class) + .set(Region::getDeleted, true) + .eq(Region::getDeleted, false) + .eq(Region::getId, id); + if (regionService.update(updater)) { + regionsCacheHelper.refresh(id); + } + } + + private CarVO convertCar(NdVehicleBaseInfo car) { + CarVO res = new CarVO(); + res.setCarPlate(car.getCarPlate()); + res.setStatus(car.getStatus()); + res.setMoving(car.getMoving()); + return res; + } + + public List getRegionInfo() { + + Map regionInfoMap = regionService.list().stream().collect(Collectors.toMap(Region::getId, RegionConverter::toRegionDTO)); + Collection<@NonNull RegionDTO> regions = regionInfoMap.values(); + Map> regionMap = CollUtils.group(regions, RegionDTO::getParentId); + return RegionConverter.toRegionTree(ROOT_PARENT_ID, regionMap, false, null, null); + } + + public CompanyCarInfoVO getCompanyCarInfo(RegionTreeReq req) { + + // 按照登录用户,如果是运营商账号登录,删选出该运营商关联的车辆信息 + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + Long roleId = userDetail.getRoleId(); + + Long regionId = req.getRegionId(); + String carPlate = req.getCarPlate(); + CompanyCarInfoVO companyCarInfoVo = new CompanyCarInfoVO(); + + StopWatch stopWatch = new StopWatch(); + StopWatch stopWatch2 = new StopWatch(); + StopWatch stopWatch3 = new StopWatch(); + StopWatch stopWatch4 = new StopWatch(); + + // 0.09 + Map> companyCarMap = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(Objects.nonNull(regionId),NdVehicleBaseInfo::getRegionId,regionId)).stream() + .filter(v -> Objects.nonNull(v.getCompanyId())) + .collect(Collectors.groupingBy(NdVehicleBaseInfo::getCompanyId)); + + // 0.046 + Map carStatusMap = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(Objects.nonNull(regionId),NdVehicleBaseInfo::getRegionId,regionId) + .eq(NdVehicleBaseInfo::getDeleted,DeletedEnum.NO_DELETED.getCode()) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode()) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getMoving)) + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getMoving)); + + + //// 0.5 + //stopWatch.start(); + //// 以车牌号分组,获取所有视频设备信息 + //Map> equipmentMap = vehicleEquipmentInfoService.list(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) + // .select(NdVehicleEquipmentInfo::getVehicleId, NdVehicleEquipmentInfo::getId,NdVehicleEquipmentInfo::getEquipmentNo,NdVehicleEquipmentInfo::getPlatformId) + // .eq(NdVehicleEquipmentInfo::getEquipmentFunction,VehicleEquipFuncEnum.video.name())) + // .stream() + // .collect(Collectors.groupingBy(NdVehicleEquipmentInfo::getVehicleId)); + //stopWatch.stop(); + //log.info("设备信息查询 耗时 {}s", stopWatch.getTotalTimeSeconds()); + //// 获取设备的开启状态信息 + //// 0.6 + //stopWatch2.start(); + //Map devicesMap = dataAccessDevicesService.list(Wrappers.lambdaQuery(DataAccessDevices.class) + // .select(DataAccessDevices::getPlatformId,DataAccessDevices::getDeviceId,DataAccessDevices::getStatus)).stream() + // .collect(Collectors.toMap(c -> c.getPlatformId() + c.getDeviceId(), DataAccessDevices::getStatus)); + //stopWatch2.stop(); + //log.info("设备在线信息查询 耗时 {}s", stopWatch2.getTotalTimeSeconds()); + //// 获取设备通道信息 + //// 0.98 + //stopWatch3.start(); + //Map channelsMap = vehicleEquipmentChannelsService.list().stream().filter(v -> Objects.nonNull(v.getName())) + // .collect(Collectors.toMap(NdVehicleEquipmentChannels::getEquipmentId, NdVehicleEquipmentChannels::getName)); + //stopWatch3.stop(); + //log.info("设备通道信息查询 耗时 {}s", stopWatch2.getTotalTimeSeconds()); + + Map> carEquipmentNoMap = vehicleEquipmentNoService.list().stream() + .collect(Collectors.groupingBy(VehicleEquipmentNo::getCarPlate)); + + // 直接查询车牌号 + if (Objects.nonNull(carPlate)){ + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoService.getOne(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate, carPlate)); + if (Objects.nonNull(vehicleBaseInfo)) { + Long baseInfoRegionId = vehicleBaseInfo.getRegionId(); + Long vehicleId = vehicleBaseInfo.getId(); + if (Objects.nonNull(baseInfoRegionId)) { + companyCarInfoVo.setRegionId(baseInfoRegionId); + List companyVos = Lists.newArrayList(); + CompanyVO companyVo = new CompanyVO(); + CompanyDTO companyDto = companiesCacheHelper.getById(vehicleBaseInfo.getCompanyId()); + if (Objects.isNull(companyDto)){ + throw new BizException("查询车辆所属企业不存在!"); + } + companyVo.setId(companyDto.getId()); + companyVo.setName(companyDto.getName()); + companyVo.setRegionId(companyDto.getRegionId()); + companyVos.add(companyVo); + companyCarInfoVo.setCompanyList(companyVos); + List carInfoList = Lists.newArrayList(); + HashMap> carInfoMap = MapUtil.newHashMap(); + CarInfoVO carInfoVo = new CarInfoVO(); + carInfoVo.setCompanyId(vehicleBaseInfo.getCompanyId()); + carInfoVo.setCarPlate(carPlate); + carInfoVo.setMoving(vehicleBaseInfo.getMoving()); + + List vehicleEquipmentNos = carEquipmentNoMap.get(carPlate); + HashMap> equipmentInfoMap = MapUtil.newHashMap(); + if (CollUtil.isNotEmpty(vehicleEquipmentNos)) { + List equipmentInfoList = Lists.newArrayList(); + for (VehicleEquipmentNo equipmentInfo : vehicleEquipmentNos) { + EquipmentInfoVO equipmentInfoVo = new EquipmentInfoVO(); + equipmentInfoVo.setCarPlate(carPlate); + equipmentInfoVo.setDeviceId(equipmentInfo.getDeviceId()); + equipmentInfoVo.setDeviceName(equipmentInfo.getDeviceName()); + String videoStatus = equipmentInfo.getStatus(); + if (Objects.nonNull(videoStatus)) { + equipmentInfoVo.setVideoStatus(videoStatus); + }else { + equipmentInfoVo.setVideoStatus("OFF"); + } + equipmentInfoList.add(equipmentInfoVo); + } + equipmentInfoMap.put(carPlate,equipmentInfoList); + } + carInfoVo.setEquipmentInfoMap(equipmentInfoMap); + carInfoList.add(carInfoVo); + carInfoMap.put(companyDto.getId(),carInfoList); + companyCarInfoVo.setCarInfoMap(carInfoMap); + return companyCarInfoVo; + } + }else { + throw new BizException("查询车辆不存在!"); + } + + } + + //// 直接查询车牌号 + //if (Objects.nonNull(carPlate)){ + // NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoService.getOne(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + // .eq(NdVehicleBaseInfo::getCarPlate, carPlate)); + // if (Objects.nonNull(vehicleBaseInfo)) { + // Long baseInfoRegionId = vehicleBaseInfo.getRegionId(); + // Long vehicleId = vehicleBaseInfo.getId(); + // if (Objects.nonNull(baseInfoRegionId)) { + // companyCarInfoVo.setRegionId(baseInfoRegionId); + // List companyVos = Lists.newArrayList(); + // CompanyVO companyVo = new CompanyVO(); + // CompanyDTO companyDto = companiesCacheHelper.getById(vehicleBaseInfo.getCompanyId()); + // if (Objects.isNull(companyDto)){ + // throw new BizException("查询车辆所属企业不存在!"); + // } + // companyVo.setId(companyDto.getId()); + // companyVo.setName(companyDto.getName()); + // companyVo.setRegionId(companyDto.getRegionId()); + // companyVos.add(companyVo); + // companyCarInfoVo.setCompanyList(companyVos); + // List carInfoList = Lists.newArrayList(); + // HashMap> carInfoMap = MapUtil.newHashMap(); + // CarInfoVO carInfoVo = new CarInfoVO(); + // carInfoVo.setCompanyId(vehicleBaseInfo.getCompanyId()); + // carInfoVo.setCarPlate(carPlate); + // carInfoVo.setMoving(vehicleBaseInfo.getMoving()); + // List equipmentInfos = equipmentMap.get(vehicleId); + // HashMap> equipmentInfoMap = MapUtil.newHashMap(); + // if (CollUtil.isNotEmpty(equipmentInfos)) { + // List equipmentInfoList = Lists.newArrayList(); + // for (NdVehicleEquipmentInfo equipmentInfo : equipmentInfos) { + // EquipmentInfoVO equipmentInfoVo = new EquipmentInfoVO(); + // equipmentInfoVo.setCarPlate(carPlate); + // equipmentInfoVo.setDeviceId(equipmentInfo.getEquipmentNo()); + // String deviceName = channelsMap.get(equipmentInfo.getId()); + // equipmentInfoVo.setDeviceName(deviceName); + // String videoStatus = devicesMap.get(equipmentInfo.getPlatformId() + equipmentInfo.getEquipmentNo()); + // if (Objects.nonNull(videoStatus)) { + // equipmentInfoVo.setVideoStatus(videoStatus); + // }else { + // equipmentInfoVo.setVideoStatus("OFF"); + // } + // equipmentInfoList.add(equipmentInfoVo); + // } + // equipmentInfoMap.put(carPlate,equipmentInfoList); + // } + // carInfoVo.setEquipmentInfoMap(equipmentInfoMap); + // carInfoList.add(carInfoVo); + // carInfoMap.put(companyDto.getId(),carInfoList); + // companyCarInfoVo.setCarInfoMap(carInfoMap); + // return companyCarInfoVo; + // } + // }else { + // throw new BizException("查询车辆不存在!"); + // } + // + //} + + HashMap> carInfoMap = MapUtil.newHashMap(); + // 获取单个区域的数据 + if (CollUtil.isEmpty(req.getRegionIdList())) { + List companyVoList = Lists.newArrayList(); + List companyList = Lists.newArrayList(); + // 如果登录用户是企业用户 + if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + Long companyId = userDetail.getCompanyId(); + String companyName = userDetail.getCompanyName(); + Long regId = userDetail.getRegionId(); + CompanyVO companyVo = new CompanyVO(); + companyVo.setId(companyId); + companyVo.setName(companyName); + companyVo.setRegionId(regId); + companyVoList.add(companyVo); + companyList.add(companyService.getById(companyId)); + }else { + // 获取该区域下的所有企业 + companyList = companyService.list(Wrappers.lambdaQuery(Company.class) + .in(Company::getCompanyType, Lists.newArrayList(1, 2, 3)) + .eq(Company::getRegionId, regionId)); + companyVoList = companyList.stream().map(c -> { + CompanyVO companyVo = new CompanyVO(); + companyVo.setId(c.getId()); + companyVo.setName(c.getName()); + companyVo.setRegionId(c.getRegionId()); + return companyVo; + }).collect(Collectors.toList()); + } + companyCarInfoVo.setCompanyList(companyVoList); + stopWatch4.start(); + for (Company company : companyList) { + List carInfoList = Lists.newArrayList(); + List vehicleBaseInfos = companyCarMap.get(company.getId()); + // 该企业下没有车,直接跳过 + if (CollUtil.isEmpty(vehicleBaseInfos)) { + continue; + } + // 如果登录用户是运营商,只过滤出运营商下的车辆 + if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String companyName = userDetail.getCompanyName(); + // 暂时控制运营商名称和运营商所在企业名称相同 + OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // 获取运营商id + Long operatorId = operatorQueryDTO.getId(); + vehicleBaseInfos = vehicleBaseInfos.stream().filter(v -> operatorId.equals(v.getOperatorId())) + .collect(Collectors.toList()); + } + // 如果登录用户是企业用户 + else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + wrapper.and(w -> w.eq(NdVehicleBaseInfo::getCompanyId, company.getId()).or().eq(NdVehicleBaseInfo::getUseCompanyId, company.getId())); + vehicleBaseInfos = vehicleBaseInfoService.list(wrapper); + } + for (NdVehicleBaseInfo vehicleBaseInfo : vehicleBaseInfos) { + String carNo = vehicleBaseInfo.getCarPlate(); + Long vehicleId = vehicleBaseInfo.getId(); + CarInfoVO carInfoVo = new CarInfoVO(); + carInfoVo.setCompanyId(company.getId()); + carInfoVo.setCarPlate(carNo); + Integer moving = carStatusMap.get(carNo); + carInfoVo.setMoving(moving); + List vehicleEquipmentNos = carEquipmentNoMap.get(carNo); + HashMap> equipmentInfoMap = MapUtil.newHashMap(); + if (CollUtil.isNotEmpty(vehicleEquipmentNos)) { + List equipmentInfoList = Lists.newArrayList(); + for (VehicleEquipmentNo equipmentInfo : vehicleEquipmentNos) { + EquipmentInfoVO equipmentInfoVo = new EquipmentInfoVO(); + equipmentInfoVo.setCarPlate(carNo); + equipmentInfoVo.setDeviceId(equipmentInfo.getDeviceId()); + equipmentInfoVo.setDeviceName(equipmentInfo.getDeviceName()); + String videoStatus = equipmentInfo.getStatus(); + if (Objects.nonNull(videoStatus)) { + equipmentInfoVo.setVideoStatus(videoStatus); + } else { + equipmentInfoVo.setVideoStatus("OFF"); + } + equipmentInfoList.add(equipmentInfoVo); + } + equipmentInfoMap.put(carNo, equipmentInfoList); + carInfoVo.setEquipmentInfoMap(equipmentInfoMap); + } + carInfoList.add(carInfoVo); + carInfoMap.put(company.getId(), carInfoList); + } + } + stopWatch4.stop(); + log.info("装配车辆信息 耗时 {}s", stopWatch2.getTotalTimeSeconds()); + + }else { + // 获取多个区域的企业数据 + List companyList = companyService.list(Wrappers.lambdaQuery(Company.class) + .in(Company::getCompanyType, Lists.newArrayList(1, 2, 3)) + .in(Company::getRegionId, req.getRegionIdList())); + List companyVoList = companyList.stream().map(c -> { + CompanyVO companyVo = new CompanyVO(); + companyVo.setId(c.getId()); + companyVo.setName(c.getName()); + companyVo.setRegionId(c.getRegionId()); + return companyVo; + }).collect(Collectors.toList()); + companyCarInfoVo.setCompanyList(companyVoList); + } + + + //// 获取单个区域的数据 + //if (CollUtil.isEmpty(req.getRegionIdList())) { + // List companyVoList = Lists.newArrayList(); + // List companyList = Lists.newArrayList(); + // // 如果登录用户是企业用户 + // if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + // Long companyId = userDetail.getCompanyId(); + // String companyName = userDetail.getCompanyName(); + // Long regId = userDetail.getRegionId(); + // CompanyVO companyVo = new CompanyVO(); + // companyVo.setId(companyId); + // companyVo.setName(companyName); + // companyVo.setRegionId(regId); + // companyVoList.add(companyVo); + // companyList.add(companyService.getById(companyId)); + // }else { + // // 获取该区域下的所有企业 + // companyList = companyService.list(Wrappers.lambdaQuery(Company.class) + // .in(Company::getCompanyType, Lists.newArrayList(1, 2, 3)) + // .eq(Company::getRegionId, regionId)); + // companyVoList = companyList.stream().map(c -> { + // CompanyVO companyVo = new CompanyVO(); + // companyVo.setId(c.getId()); + // companyVo.setName(c.getName()); + // companyVo.setRegionId(c.getRegionId()); + // return companyVo; + // }).collect(Collectors.toList()); + // } + // companyCarInfoVo.setCompanyList(companyVoList); + // stopWatch4.start(); + // for (Company company : companyList) { + // List carInfoList = Lists.newArrayList(); + // List vehicleBaseInfos = companyCarMap.get(company.getId()); + // // 该企业下没有车,直接跳过 + // if (CollUtil.isEmpty(vehicleBaseInfos)) { + // continue; + // } + // // 如果登录用户是运营商,只过滤出运营商下的车辆 + // if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + // String companyName = userDetail.getCompanyName(); + // // 暂时控制运营商名称和运营商所在企业名称相同 + // OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName); + // // 获取运营商id + // Long operatorId = operatorQueryDTO.getId(); + // vehicleBaseInfos = vehicleBaseInfos.stream().filter(v -> operatorId.equals(v.getOperatorId())) + // .collect(Collectors.toList()); + // } + // // 如果登录用户是企业用户 + // else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + // LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + // wrapper.and(w -> w.eq(NdVehicleBaseInfo::getCompanyId, company.getId()).or().eq(NdVehicleBaseInfo::getUseCompanyId, company.getId())); + // vehicleBaseInfos = vehicleBaseInfoService.list(wrapper); + // } + // for (NdVehicleBaseInfo vehicleBaseInfo : vehicleBaseInfos) { + // String carNo = vehicleBaseInfo.getCarPlate(); + // Long vehicleId = vehicleBaseInfo.getId(); + // CarInfoVO carInfoVo = new CarInfoVO(); + // carInfoVo.setCompanyId(company.getId()); + // carInfoVo.setCarPlate(carNo); + // Integer moving = carStatusMap.get(carNo); + // carInfoVo.setMoving(moving); + // List equipmentInfos = equipmentMap.get(vehicleId); + // HashMap> equipmentInfoMap = MapUtil.newHashMap(); + // if (CollUtil.isNotEmpty(equipmentInfos)) { + // List equipmentInfoList = Lists.newArrayList(); + // for (NdVehicleEquipmentInfo equipmentInfo : equipmentInfos) { + // EquipmentInfoVO equipmentInfoVo = new EquipmentInfoVO(); + // equipmentInfoVo.setCarPlate(carNo); + // equipmentInfoVo.setDeviceId(equipmentInfo.getEquipmentNo()); + // String deviceName = channelsMap.get(equipmentInfo.getId()); + // equipmentInfoVo.setDeviceName(deviceName); + // String videoStatus = + // devicesMap.get(equipmentInfo.getPlatformId() + equipmentInfo.getEquipmentNo()); + // if (Objects.nonNull(videoStatus)) { + // equipmentInfoVo.setVideoStatus(videoStatus); + // } else { + // equipmentInfoVo.setVideoStatus("OFF"); + // } + // equipmentInfoList.add(equipmentInfoVo); + // } + // equipmentInfoMap.put(carNo, equipmentInfoList); + // carInfoVo.setEquipmentInfoMap(equipmentInfoMap); + // } + // carInfoList.add(carInfoVo); + // carInfoMap.put(company.getId(), carInfoList); + // } + // } + // stopWatch4.stop(); + // log.info("装配车辆信息 耗时 {}s", stopWatch2.getTotalTimeSeconds()); + // + //}else { + // // 获取多个区域的企业数据 + // List companyList = companyService.list(Wrappers.lambdaQuery(Company.class) + // .in(Company::getCompanyType, Lists.newArrayList(1, 2, 3)) + // .in(Company::getRegionId, req.getRegionIdList())); + // List companyVoList = companyList.stream().map(c -> { + // CompanyVO companyVo = new CompanyVO(); + // companyVo.setId(c.getId()); + // companyVo.setName(c.getName()); + // companyVo.setRegionId(c.getRegionId()); + // return companyVo; + // }).collect(Collectors.toList()); + // companyCarInfoVo.setCompanyList(companyVoList); + //} + + companyCarInfoVo.setCarInfoMap(carInfoMap); + companyCarInfoVo.setRegionId(regionId); + return companyCarInfoVo; + } + + public List getRegionCompanyTree(RegionTreeReq req) { + + Map> companyMap = null; + Optional dataScope = DataScopeContext.getDataScope(LoginUserUtil.loginUserDetail().getDataScope()); + if (req != null) { + if (req.getWithCompany()) { + companyMap = companiesCacheHelper.all().stream() + .map(w -> BeanUtil.copyProperties(w, RegionTreeCompanyVO.class)) + .filter(c -> DataScopeCacheFilterUtil.dataScopeFilter(c, dataScope)) + // 过滤掉管理企业 + .filter(c -> !CompanyTypeEnum.MANAGE_BU.getCode().equals(c.getCompanyType())) + .filter(item -> Objects.nonNull(item.getRegionId())) + .collect(Collectors.groupingBy(RegionTreeCompanyVO::getRegionId)); + } + } + Map> regionMap = CollUtils.group(regionsCacheHelper.getAllWithRole(dataScope, companiesCacheHelper), RegionDTO::getParentId); + + return RegionConverter.toRegionCompanyCarNoTree(ROOT_PARENT_ID, regionMap, false, null, companyMap,null,null,null); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RoleManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RoleManage.java new file mode 100644 index 0000000..c46e0f6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/RoleManage.java @@ -0,0 +1,92 @@ +package com.ningdatech.carapi.sys.manage; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeContext; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.dto.RolePageQuery; +import com.ningdatech.carapi.sys.entity.vo.MenuRoleVO; +import com.ningdatech.carapi.sys.entity.vo.RoleVO; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.sys.service.IRoleMenuService; +import com.ningdatech.carapi.sys.service.MenuService; +import com.ningdatech.carapi.sys.service.RoleService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import lombok.RequiredArgsConstructor; + +/** + * @Classname UserRepository + * @Description + * @Date 2022/10/12 11:26 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +public class RoleManage { + + private final UserManage userManage; + private final RoleService roleService; + private final MenuService menuService; + + private final IRoleMenuService roleMenuService; + + public PageVo queryList(RolePageQuery rolePageQuery) { + Page page = rolePageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Role.class); + searchList(page, wrapper, rolePageQuery); + List data = CollUtils.convert(page.getRecords(), w -> BeanUtil.copyProperties(w, RoleVO.class)); + return PageVo.of(data, page.getTotal()); + } + + public void searchList(Page page, LambdaQueryWrapper wrapper, RolePageQuery rolePageQuery) { + wrapper.like(StringUtils.isNotBlank(rolePageQuery.getName()), Role::getName, rolePageQuery.getName()) + .orderByAsc(Role::getSort); + roleService.page(page, wrapper); + } + + public Optional getCurrentUserDataScoper() { + UserInfoVO userInfoVO = userManage.queryDetails(LoginUserUtil.getUserId()); + //即便是多个 暂时取一个 + if (Objects.isNull(userInfoVO) || Objects.isNull(userInfoVO.getRole())) { + return Optional.empty(); + } + Role role = roleService.getById(userInfoVO.getRole()); + if (Objects.isNull(role) || Objects.isNull(role.getDataScope())) { + return Optional.empty(); + } + return DataScopeContext.getDataScope(role.getDataScope()); + } + + public void buildMenu(RoleVO query) { + //改成直接返回有权限的 + List list = menuService.list(Wrappers.lambdaQuery(Menu.class).orderByAsc(Menu::getSort)); + List roleMenus = roleMenuService.list(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, query.getId())); +// List menuRoleVOS = CollUtils.convert(list, w -> BeanUtil.copyProperties(w,MenuRoleVO.class)); +// List menus = TreeUtil.buildTree(menuRoleVOS,roleMenus); + List menus = list.stream().map(menu -> { + for (RoleMenu roleMenu : roleMenus) { + if (roleMenu.getMenuId().equals(menu.getId())) { + return BeanUtil.copyProperties(menu, MenuRoleVO.class); + } + } + return null; + }).filter(Objects::nonNull).collect(Collectors.toList()); + query.setMenu(menus); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/UserManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/UserManage.java new file mode 100644 index 0000000..ad45639 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/manage/UserManage.java @@ -0,0 +1,354 @@ +package com.ningdatech.carapi.sys.manage; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.basic.util.NdJsonUtil; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.DriverRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverStatusEnum; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationTypeEnum; +import com.ningdatech.carapi.driver.constant.UserCanLoginEnum; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.entity.TrainingRegistrationReview; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.driver.service.ITrainingRegistrationReviewService; +import com.ningdatech.carapi.sys.convert.UserAuthConverter; +import com.ningdatech.carapi.sys.convert.UserRoleConverter; +import com.ningdatech.carapi.sys.entity.MetaApply; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.UserPageQuery; +import com.ningdatech.carapi.sys.entity.dto.UserSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.UserUpdateDTO; +import com.ningdatech.carapi.sys.entity.enumeration.BooleanDisplayEnum; +import com.ningdatech.carapi.sys.entity.enumeration.MetaApplyStatusEnum; +import com.ningdatech.carapi.sys.entity.enumeration.MetaApplyTypeEnum; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.service.IMetaApplyService; +import com.ningdatech.carapi.sys.service.RoleService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.entity.NdUserInfoJoin; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoJoinService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.DesensitizedUtil; +import lombok.RequiredArgsConstructor; + +/** + * @Classname UserRepository + * @Description + * @Date 2022/10/12 11:26 + * @Created by PoffyZhang + */ +@Component +@RequiredArgsConstructor +public class UserManage { + private final INdUserInfoService userInfoService; + private final INdUserInfoJoinService userInfoJoinService; + private final INdUserAuthService userAuthService; + private final UserRoleService userRoleService; + private final RoleService roleService; + private final INdUserInfoService userService; + private final CompaniesCacheHelper companiesCacheHelper; + private final IDriverInfoService driverInfoService; + private final IMetaApplyService iMetaApplyService; + private final ITrainingRegistrationReviewService iTrainingRegistrationReviewService; + private final INdUserInfoService ndUserInfoService; + + public PageVo queryUserList(UserPageQuery userPageQuery){ + Page page = userPageQuery.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdUserInfoJoin.class); + wrapper.like(StringUtils.isNotBlank(userPageQuery.getUsername()),NdUserInfoJoin::getUsername, userPageQuery.getUsername()) + .like(StringUtils.isNotBlank(userPageQuery.getAccount()),NdUserInfoJoin::getAccount, userPageQuery.getAccount()) + .in(Objects.nonNull(userPageQuery.getRoleId()),NdUserInfoJoin::getRoleId, userPageQuery.getRoleId()) + .eq(Boolean.TRUE,NdUserInfoJoin::getCanLogin,UserCanLoginEnum.CAN_LOGIN.getCode()) + .like(StringUtils.isNotBlank(userPageQuery.getCompanyName()),NdUserInfoJoin::getCompanyName, userPageQuery.getCompanyName()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdUserInfoJoin::getUpdateOn); + userInfoJoinService.pageJoin(page, wrapper); + List data = CollUtils.convert(page.getRecords(), w -> BeanUtil.copyProperties(w, UserInfoVO.class)); + // 查出可登录的帐号 + List resVos = searchAuth(data); + // 查出角色名 + searchRoleName(resVos); + return PageVo.of(resVos, page.getTotal()); + } + + public UserInfoVO queryDetails(Long id) { + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdUserInfo.class); + UserManage context = (UserManage) AopContext.currentProxy(); + context.buildQuery(wrapper, id); + NdUserInfo user = userInfoService.getOne(wrapper); + if (Objects.isNull(user)) { + return null; + } + + UserInfoVO query = BeanUtil.toBean(user, UserInfoVO.class); + //查出帐号 + searchAuth(query); + //查出角色 + searchRoleName(query); + return query; + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_COMPANY) + public void buildQuery(LambdaQueryWrapper wrapper, Long id) { + wrapper.eq(NdUserInfo::getId,id); + } + + private List searchAuth(List userInfos) { + List results = null; + if(CollUtil.isEmpty(userInfos)){ + return Collections.emptyList(); + } + //查出帐号 + List userIds = userInfos.stream().map(UserInfoVO::getId).collect(Collectors.toList()); + Map userRoleMap = userRoleService.list(Wrappers.lambdaQuery(UserRole.class).in(UserRole::getUserId, userIds)) + .stream().collect(Collectors.toMap(UserRole::getUserId, r -> r)); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdUserAuth.class); + wrapper.in(NdUserAuth::getUserId, userIds); + List auths = userAuthService.list(wrapper); + if(CollUtil.isNotEmpty(auths)){ + results = userInfos.stream() + .map(user -> { + UserInfoVO vo = UserAuthConverter.convert(user, auths); + // 如果用户角色不为企业和运营商,需对账号(手机号)进行脱敏 + Long userId = user.getId(); + UserRole userRole = userRoleMap.get(userId); + if (Objects.nonNull(userRole)) { + Long roleId = userRole.getRoleId(); + if (!UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId) && + !UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) { + String account = user.getAccount(); + String encryptPhone = DesensitizedUtil.mobilePhone(account); + vo.setAccount(encryptPhone); + } + } + return vo; + }) + .collect(Collectors.toList()); + } + return results; + } + + private void searchRoleName(List userInfos) { + if(CollUtil.isEmpty(userInfos)){ + return; + } + //查出角色名 + List userIds = userInfos.stream().map(UserInfoVO::getId).collect(Collectors.toList()); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(UserRole.class); + wrapper.in(UserRole::getUserId, userIds); + List userRoles = userRoleService.list(wrapper); + if(CollUtil.isEmpty(userRoles)){ + return; + } + List roleIds = userRoles.stream() + .map(UserRole::getRoleId) + .distinct() + .collect(Collectors.toList()); + List roles = roleService.listByIds(roleIds); + if(CollUtil.isNotEmpty(roles)){ + userInfos.stream() + .map(user -> UserRoleConverter.convert(user,userRoles,roles)) + .collect(Collectors.toList()); + } + } + + private void searchAuth(UserInfoVO user) { + if(Objects.isNull(user)){ + return; + } + //查出帐号 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdUserAuth.class); + wrapper.in(NdUserAuth::getUserId, user.getId()); + List auths = userAuthService.list(wrapper); + if(CollUtil.isNotEmpty(auths)){ + UserAuthConverter.convert(user,auths); + } + } + + private void searchRoleName(UserInfoVO user) { + if(Objects.isNull(user)){ + return; + } + //查出角色名 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(UserRole.class); + wrapper.in(UserRole::getUserId, user.getId()); + List userRoles = userRoleService.list(wrapper); + if(CollUtil.isEmpty(userRoles)){ + return; + } + List roleIds = userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList()); + List roles = roleService.listByIds(roleIds); + if(CollUtil.isNotEmpty(roles)){ + UserRoleConverter.convert(user,userRoles,roles); + } + } + + public void save(UserSaveDTO data, Long userId) { + // 创建系统用户信息 + userService.save(data, LoginUserUtil.getUserId()); + // 当新增用户角色为驾驶员时,新增驾驶员档案信息,并默认驾驶员材料复审通过(该驾驶员可参加培训考试) + Long roleId = data.getRole(); + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)){ + // 获取对应的驾驶员用户信息 + NdUserInfo ndUserInfo = userInfoService.getOne(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getMobile, data.getMobile())); + // 将该驾驶员用户设置为不可登录状态 + ndUserInfo.setCanLogin(UserCanLoginEnum.CAN_NOT_LOGIN.getCode()); + // 更新信息 + ndUserInfoService.updateById(ndUserInfo); + DriverInfo driverInfo = new DriverInfo(); + driverInfo.setDriverName(data.getUsername()); + driverInfo.setCompanyId(data.getCompanyId()); + CompanyDTO companyDTO = companiesCacheHelper.getById(data.getCompanyId()); + driverInfo.setCompanyName(companyDTO.getName()); + driverInfo.setPhoneNo(data.getMobile()); + driverInfo.setUserId(ndUserInfo.getId()); + driverInfo.setDriverStatus(DriverStatusEnum.induction.name()); + driverInfo.setDriverRegistrationStatus(DriverRegistrationStatusEnum.exam_training_stage.name()); + driverInfo.setInductionTime(LocalDateTime.now()); + driverInfo.setCreateOn(LocalDateTime.now()); + driverInfo.setUpdateOn(LocalDateTime.now()); + driverInfoService.save(driverInfo); + + // 创建空的取证培训初审、复审审核记录 + Long driverId = driverInfo.getId(); + // 获取录入用户信息 + UserInfoDetails loginUser = LoginUserUtil.loginUserDetail(); + // 补充初审审核信息 + MetaApply metaApply = new MetaApply(); + assemblyMetaApplyInfo(ndUserInfo, driverId, loginUser, metaApply); + metaApply.setApplyType(MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()); + metaApply.setApplyStatus(MetaApplyStatusEnum.FIRST_TRIAL_APPROVED.name()); + iMetaApplyService.save(metaApply); + + // 补充驾驶员报名初审审核表信息 + TrainingRegistrationReview trainingRegistrationReviewSaveRecord = new TrainingRegistrationReview(); + assemblyTrainingRegistrationReviewInfo(data, ndUserInfo, companyDTO, driverId, loginUser, metaApply, trainingRegistrationReviewSaveRecord); + trainingRegistrationReviewSaveRecord.setMetaApplyType(MetaApplyTypeEnum.PRELIMINARY_REVIEW.name()); + trainingRegistrationReviewSaveRecord.setRegistrationType(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name()); + trainingRegistrationReviewSaveRecord.setApprovalStatus(MetaApplyStatusEnum.FIRST_TRIAL_APPROVED.name()); + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord); + + // 补充复审审核信息 + MetaApply inReviewMetaApply = new MetaApply(); + assemblyMetaApplyInfo(ndUserInfo, driverId, loginUser, inReviewMetaApply); + inReviewMetaApply.setApplyType(MetaApplyTypeEnum.IN_REVIEW.name()); + inReviewMetaApply.setApplyStatus(MetaApplyStatusEnum.REEXAMINATION_APPROVED.name()); + iMetaApplyService.save(inReviewMetaApply); + + // 补充驾驶员报名复审审核表信息 + TrainingRegistrationReview trainingRegistrationReviewSaveRecord2 = new TrainingRegistrationReview(); + assemblyTrainingRegistrationReviewInfo(data, ndUserInfo, companyDTO, driverId, loginUser, inReviewMetaApply, trainingRegistrationReviewSaveRecord2); + trainingRegistrationReviewSaveRecord2.setPreliminaryReviewAssociatedId(trainingRegistrationReviewSaveRecord.getId()); + trainingRegistrationReviewSaveRecord2.setMetaApplyType(MetaApplyTypeEnum.IN_REVIEW.name()); + trainingRegistrationReviewSaveRecord2.setRegistrationType(TrainingRegistrationTypeEnum.FORENSIC_REGISTRATION.name()); + trainingRegistrationReviewSaveRecord2.setApprovalStatus(MetaApplyStatusEnum.REEXAMINATION_APPROVED.name()); + iTrainingRegistrationReviewService.save(trainingRegistrationReviewSaveRecord2); + + } + } + + private void assemblyTrainingRegistrationReviewInfo(UserSaveDTO data, NdUserInfo ndUserInfo, CompanyDTO companyDTO, Long driverId, UserInfoDetails loginUser, MetaApply inReviewMetaApply, TrainingRegistrationReview trainingRegistrationReviewSaveRecord2) { + trainingRegistrationReviewSaveRecord2.setMetaApplyId(inReviewMetaApply.getId()); + trainingRegistrationReviewSaveRecord2.setCompanyId(data.getCompanyId()); + trainingRegistrationReviewSaveRecord2.setCompanyName(companyDTO.getName()); + trainingRegistrationReviewSaveRecord2.setRegionId(companyDTO.getRegionId()); + trainingRegistrationReviewSaveRecord2.setDriverUserId(ndUserInfo.getId()); + trainingRegistrationReviewSaveRecord2.setDriverId(driverId); + trainingRegistrationReviewSaveRecord2.setDriverName(data.getUsername()); + trainingRegistrationReviewSaveRecord2.setDriverPhoneNo(data.getMobile()); + trainingRegistrationReviewSaveRecord2.setCreateBy(loginUser.getUserId()); + trainingRegistrationReviewSaveRecord2.setCreateOn(LocalDateTime.now()); + trainingRegistrationReviewSaveRecord2.setUpdateOn(LocalDateTime.now()); + } + + private void assemblyMetaApplyInfo(NdUserInfo ndUserInfo, Long driverId, UserInfoDetails loginUser, MetaApply metaApply) { + metaApply.setCreateOn(LocalDateTime.now()); + metaApply.setUpdateOn(LocalDateTime.now()); + metaApply.setUserId(ndUserInfo.getId()); + metaApply.setApplyTime(LocalDateTime.now()); + metaApply.setApplicantId(loginUser.getUserId()); + metaApply.setApplicant(loginUser.getNickName()); + metaApply.setRegionId(loginUser.getRegionId()); + metaApply.setCompanyId(loginUser.getCompanyId()); + JSONObject extraMaterial = new JSONObject(); + extraMaterial.put("driverInfoId", driverId); + metaApply.setExtraMaterial(NdJsonUtil.toJson(extraMaterial)); + metaApply.setDisplayEnable(BooleanDisplayEnum.Y.name()); + } + + public void update(UserUpdateDTO data, Long userId) { + Long roleId = data.getRole(); + // 当编辑用户角色为驾驶员时,更新驾驶员档案信息 + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)){ + Long userInfoId = data.getId(); + DriverInfo driverInfo = driverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class).eq(DriverInfo::getUserId, userInfoId)); + if(Objects.nonNull(driverInfo)){ + driverInfo.setDriverName(data.getUsername()); + CompanyDTO companyDTO = companiesCacheHelper.getById(data.getCompanyId()); + driverInfo.setCompanyName(companyDTO.getName()); + driverInfo.setCompanyId(data.getCompanyId()); + driverInfo.setPhoneNo(data.getMobile()); + driverInfoService.updateById(driverInfo); + } + } + userService.update(data, LoginUserUtil.getUserId()); + } + + public Boolean remove(List ids) { + + ids.forEach(userId ->{ + UserRole userRole = userRoleService.getOne(Wrappers.lambdaQuery(UserRole.class) + .eq(UserRole::getUserId, userId)); + Long roleId = userRole.getRoleId(); + // 当删除用户角色为驾驶员时,删除驾驶员档案信息 + if (UserRoleTypeEnum.DRIVER_ROLE_ID.getId().equals(roleId)){ + driverInfoService.remove(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getUserId,userId)); + } + }); + + UserManage context = (UserManage) AopContext.currentProxy(); + List list = Lists.newArrayList(); + for (Long id : ids) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(NdUserInfo.class); + context.buildQuery(wrapper, id); + NdUserInfo userInfo = userService.getOne(wrapper); + if (Objects.nonNull(userInfo)) { + list.add(userInfo.getId()); + } + } + + return userService.removeByIdWithCache(list); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.java new file mode 100644 index 0000000..ec8ee88 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.ningdatech.carapi.sys.entity.CodingRule; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +public interface CodingRuleMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.xml new file mode 100644 index 0000000..41aa5e5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CodingRuleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyJoinMapper.java new file mode 100644 index 0000000..b4e2735 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyJoinMapper.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.sys.entity.CompanyJoin; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * Mapper 接口 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface CompanyJoinMapper extends BaseMapper { + String QUERY_SQL = "SELECT c.*, o.name as operator_name FROM nd_company_info AS c " + + "LEFT JOIN nd_operator_info AS o ON c.operator_id = o.id "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoin(Page page, @Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + List listJoin(@Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + CompanyJoin oneJoin(@Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.java new file mode 100644 index 0000000..6d61b31 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.sys.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.sys.entity.Company; + +/** + *

+ * Mapper 接口 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface CompanyMapper extends BaseMapper { + + Page pageVehicleNum(Page page,@Param("param") RptOtherParamDTO param); + + List countByRegion(@Param("param") DataScreenParam param); + + List countEnterpriseType(@Param("param") DataScreenParam param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.xml new file mode 100644 index 0000000..f55efe7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyMapper.xml @@ -0,0 +1,106 @@ + + + + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeMapper.java new file mode 100644 index 0000000..35ccdc1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.CompanyType; +import org.springframework.stereotype.Repository; + +/** + *

+ * Mapper 接口 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface CompanyTypeMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeRelatedMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeRelatedMapper.java new file mode 100644 index 0000000..bc1536b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/CompanyTypeRelatedMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.CompanyTypeRelated; +import org.springframework.stereotype.Repository; + +/** + *

+ * Mapper 接口 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface CompanyTypeRelatedMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.java new file mode 100644 index 0000000..692793e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.ningdatech.carapi.sys.entity.ExamRule; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +public interface ExamRuleMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.xml new file mode 100644 index 0000000..eed86b5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ExamRuleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.java new file mode 100644 index 0000000..79aab08 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.java @@ -0,0 +1,29 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.Menu; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * Mapper 接口 + * 菜单 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface MenuMapper extends BaseMapper { + + /** + * 查询用户可用菜单 + * + * @param userId 用户id + * @return 菜单 + */ + List findVisibleMenu(@Param("userId") Long userId); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.xml new file mode 100644 index 0000000..e171881 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MenuMapper.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id,label,sort_value,parent_id,created_by,create_time,updated_by,update_time, tree_grade, tree_path, + describe_, is_general, path, component, state, icon, group_, readonly_, resource_type, is_def, custom_class, data_scope + + + + + + id, label, path, component, state, sort_value, icon, group_, parent_id, resource_type, tree_grade, tree_path + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.java new file mode 100644 index 0000000..3b00f3c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.ningdatech.carapi.sys.entity.MetaApply; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Liuxinxin + * @since 2022-10-15 + */ +public interface MetaApplyMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.xml new file mode 100644 index 0000000..04bb05d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/MetaApplyMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.java new file mode 100644 index 0000000..050aec3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.Operator; +import org.springframework.stereotype.Repository; + +/** + *

+ * Mapper 接口 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface OperatorMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.xml new file mode 100644 index 0000000..90a5b0d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.java new file mode 100644 index 0000000..2464895 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.java @@ -0,0 +1,18 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import org.springframework.stereotype.Repository; + +/** + *

+ * Mapper 接口 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface OperatorRegionHeadMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.xml new file mode 100644 index 0000000..130d85b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorRegionHeadMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.java new file mode 100644 index 0000000..308f4a3 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.ningdatech.carapi.industry.entity.OperatorScoreInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author CMM + * @since 2023-01-04 + */ +public interface OperatorScoreInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.xml new file mode 100644 index 0000000..a4d4aa4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/OperatorScoreInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.java new file mode 100644 index 0000000..caafa0d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.ningdatech.carapi.sys.entity.Region; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-10-08 + */ +public interface RegionMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.xml new file mode 100644 index 0000000..388ab2c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RegionMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.java new file mode 100644 index 0000000..f3f2ba6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.Resource; +import com.ningdatech.carapi.sys.entity.dto.ResourceQueryDTO; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * Mapper 接口 + * 资源 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface ResourceMapper extends BaseMapper { + /** + * 查询 拥有的资源 + * + * @param resource 查询参数 + * @return 可用资源 + */ + List findVisibleResource(ResourceQueryDTO resource); + + /** + * 根据唯一索引 保存或修改资源 + * + * @param resource 资源 + * @return 操作条数 + */ + int saveOrUpdateUnique(Resource resource); + + /** + * 根据资源id查询菜单id + * + * @param resourceIdList 资源id + * @return 菜单id + */ + List findMenuIdByResourceId(@Param("resourceIdList") List resourceIdList); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.xml new file mode 100644 index 0000000..5c565eb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/ResourceMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + id,created_by,create_time,updated_by,update_time, + code, name, menu_id, describe_, readonly_ + + + + + + + insert into c_resource ( id, created_by, create_time, updated_by, update_time, + code, name, menu_id, describe_) + values (#{id,jdbcType=BIGINT}, #{createUser,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP},#{updateUser,jdbcType=BIGINT}, #{updateTime,jdbcType=TIMESTAMP}, + #{code,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{menuId,jdbcType=BIGINT}, #{tags,jdbcType=VARCHAR}, #{describe,jdbcType=VARCHAR} ) + ON DUPLICATE KEY UPDATE + name = #{name,jdbcType=VARCHAR}, + describe_ = #{describe,jdbcType=VARCHAR}, + updated_by = #{updateUser,jdbcType=BIGINT}, + update_time = #{updateTime,jdbcType=TIMESTAMP} + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.java new file mode 100644 index 0000000..9d6cdf9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.RoleAuthority; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * Mapper 接口 + * 角色的资源 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface RoleAuthorityMapper extends BaseMapper { + + /** + * 根据用户-角色-数据权限关系,查询可用的数据权限ID + *

+ * 角色被禁用后,用户不在拥有此角色的权限 + * + * @param userId 用户ID + * @param category 角色类别 + * @return + */ + List selectDataScopeIdFromRoleByUserId(@Param("userId") Long userId, @Param("category") String category); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.xml new file mode 100644 index 0000000..6836f5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleAuthorityMapper.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.java new file mode 100644 index 0000000..cbf1a72 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.Role; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * Mapper 接口 + * 角色 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface RoleMapper extends BaseMapper { + /** + * 查询用户拥有的角色 + * + * @param userId 用户id + * @return 角色 + */ + List findRoleByUserId(@Param("userId") Long userId); + + /** + * 根据角色编码查询用户ID + * + * @param codes 角色编码 + * @return 用户id + */ + List findUserIdByCode(@Param("codes") String[] codes); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.xml new file mode 100644 index 0000000..e58ef95 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMapper.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + id,created_by,create_time,updated_by,update_time, category, + name, code, describe_, state, readonly_ + + + + + r.id, r.name, r.code, r.describe_, r.state, r.readonly_, r.category + + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.java new file mode 100644 index 0000000..5345160 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-11-11 + */ +public interface RoleMenuMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.xml new file mode 100644 index 0000000..e4122a5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/RoleMenuMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.java new file mode 100644 index 0000000..6fed11f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ningdatech.carapi.sys.entity.UserRole; +import org.springframework.stereotype.Repository; + +/** + *

+ * Mapper 接口 + * 角色分配 + * 账号角色绑定 + *

+ * + * @author PoffyZhang + */ +@Repository +public interface UserRoleMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.xml new file mode 100644 index 0000000..5a8cdb6 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/mapper/UserRoleMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyJoinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyJoinService.java new file mode 100644 index 0000000..4ba9efe --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyJoinService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.CompanyJoin; + +import java.util.List; + +/** + *

+ * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface CompanyJoinService extends IService { + Page pageJoin(Page page, LambdaQueryWrapper wrapper); + + List listJoin(LambdaQueryWrapper wrapper); + + CompanyJoin oneJoin(LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyService.java new file mode 100644 index 0000000..0bcef97 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyService.java @@ -0,0 +1,73 @@ +package com.ningdatech.carapi.sys.service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.safe.model.dto.SecurityHonestyPageQuery; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.dto.CompanySaveDTO; +import com.ningdatech.carapi.sys.entity.dto.CompanyUpdateDTO; + +/** + *

+ * 企业 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface CompanyService extends IService { + + + /** + * 根据ID删除 + * + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 保存企业 + * + * @param data 企业 + * @param userId 用户id + */ + Company save(CompanySaveDTO data, Long userId); + + /** + * 修改 + * + * @param data 企业 + * @param userId 用户id + */ + Company update(CompanyUpdateDTO data, Long userId); + + Boolean check(String name); + + Boolean check(String name, Long id); + + Map listCompanyByIds(Collection ids); + + List listCompanyByCompanyNames(Collection names); + + Company getCompanyByCompanyNames(String companyName); + + List findCompanyIdsByRegionId(DataScreenParam param); + + Page pageVehicleNum(Page page, RptOtherParamDTO param); + + List countByRegion(DataScreenParam param); + + List countEnterpriseType(DataScreenParam param); + + Page pageDataScope(Page page, LambdaQueryWrapper wrapper, SecurityHonestyPageQuery param); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeRelatedService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeRelatedService.java new file mode 100644 index 0000000..e0fdd73 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeRelatedService.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.CompanyTypeRelated; + +/** + *

+ * 企业类型关系 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface CompanyTypeRelatedService extends IService { + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeService.java new file mode 100644 index 0000000..5ccee9a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/CompanyTypeService.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.CompanyType; + +/** + *

+ * 企业类型 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface CompanyTypeService extends IService { + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ICodingRuleService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ICodingRuleService.java new file mode 100644 index 0000000..67e18ab --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ICodingRuleService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.service; + +import com.ningdatech.carapi.sys.entity.CodingRule; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +public interface ICodingRuleService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IExamRuleService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IExamRuleService.java new file mode 100644 index 0000000..369505c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IExamRuleService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.service; + +import com.ningdatech.carapi.sys.entity.ExamRule; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +public interface IExamRuleService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IMetaApplyService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IMetaApplyService.java new file mode 100644 index 0000000..256ed9f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IMetaApplyService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.service; + +import com.ningdatech.carapi.sys.entity.MetaApply; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Liuxinxin + * @since 2022-10-15 + */ +public interface IMetaApplyService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IOperatorScoreInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IOperatorScoreInfoService.java new file mode 100644 index 0000000..f2cd26c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IOperatorScoreInfoService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.service; + +import com.ningdatech.carapi.industry.entity.OperatorScoreInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author CMM + * @since 2023-01-04 + */ +public interface IOperatorScoreInfoService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRegionService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRegionService.java new file mode 100644 index 0000000..aa2516f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRegionService.java @@ -0,0 +1,51 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; + +import java.util.List; + +/** + *

+ * 地域管理 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-10-08 + */ +public interface IRegionService extends IService { + + /** + * 查询所有区域 + * + * @return 所有区域 + */ + List queryAll(); + + /** + * 查询大于等与该级别的所有区域 + * + * @param regionLevel + * @return 区域集合 + */ + List listGeLevel(int regionLevel); + + /** + * 是否为父节点 + * + * @param regionId 区域ID + * @return boolean + **/ + boolean isParentRegion(Long regionId); + + /** + * 获取当前区域的本级 + * + * @param parentId 区域ID + * @param regionCode 区域code + * @return 区域ID + **/ + Long getRegionIdByParentIdWithSameRegionCode(Long parentId, String regionCode); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRoleMenuService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRoleMenuService.java new file mode 100644 index 0000000..c607c9f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/IRoleMenuService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.sys.service; + +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author PoffyZhang + * @since 2022-11-11 + */ +public interface IRoleMenuService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/MenuService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/MenuService.java new file mode 100644 index 0000000..c8e7010 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/MenuService.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.dto.MenuSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.MenuUpdateDTO; +import com.ningdatech.carapi.sys.entity.vo.MenuResourceTreeVO; + +import java.util.List; + +/** + *

+ * 业务接口 + * 菜单 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface MenuService extends IService { + + /** + * 根据ID删除 + * + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 修改菜单 + * + * @param menu 菜单 + * @return 是否成功 + */ + boolean update(MenuUpdateDTO menu, Long userId); + + /** + * 保存菜单 + * + * @param menu 菜单 + * @return 是否成功 + */ + boolean save(MenuSaveDTO menu, Long userId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorRegionHeadService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorRegionHeadService.java new file mode 100644 index 0000000..cc71b75 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorRegionHeadService.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import com.ningdatech.carapi.sys.entity.dto.OperatorRegionHeadSaveDTO; + +import java.util.List; + +/** + *

+ * 运营商区域负责人 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface OperatorRegionHeadService extends IService { + + + /** + * 根据ID删除 + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 根据运营商ID删除区域负责人 + * @param operatorId + * @return 是否成功 + */ + boolean removeByRegionId(Long operatorId); + + /** + * 保存企业 + * + * @param datas 运营商区域负责人 + * @param userId 用户id + */ + void saveBatch(List datas,Long operatorId, Long userId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorService.java new file mode 100644 index 0000000..1f45bbb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/OperatorService.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.Operator; +import com.ningdatech.carapi.sys.entity.dto.OperatorSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorUpdateDTO; + +import java.util.List; + +/** + *

+ * 运营商 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface OperatorService extends IService { + + + /** + * 根据ID删除 + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 保存企业 + * + * @param data 运营商 + * @param userId 用户id + */ + void save(OperatorSaveDTO data, Long userId); + + /** + * 修改 + * + * @param data 运营商 + * @param userId 用户id + */ + void update(OperatorUpdateDTO data, Long userId); + + Boolean check(String name); + Boolean check(String name, Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ResourceService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ResourceService.java new file mode 100644 index 0000000..96128bb --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/ResourceService.java @@ -0,0 +1,58 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.Resource; + +import java.util.List; + +/** + *

+ * 业务接口 + * 资源 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface ResourceService extends IService { + + /** + * 根据ID删除 + * + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 保存 + * + * @param resource 资源 + * @return 是否成功 + */ + boolean saveWithCache(Resource resource); + + + /** + * 根据菜单id删除资源 + * + * @param menuIds 菜单id + */ + void removeByMenuIdWithCache(List menuIds); + + /** + * 根据资源id 查询菜单id + * + * @param resourceIdList 资源id + * @return 菜单id + */ + List findMenuIdByResourceId(List resourceIdList); + + /** + * 检测资源编码是否可用 + * + * @param id 资源id + * @param code 资源编码 + */ + Boolean check(Long id, String code); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleAuthorityService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleAuthorityService.java new file mode 100644 index 0000000..4bfbd74 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleAuthorityService.java @@ -0,0 +1,71 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.RoleAuthority; +import com.ningdatech.carapi.sys.entity.dto.RoleAuthoritySaveDTO; +import com.ningdatech.carapi.sys.entity.dto.RoleUserSaveVO; +import com.ningdatech.carapi.sys.entity.dto.UserRoleSaveDTO; + +import java.util.List; + +/** + *

+ * 业务接口 + * 角色的资源 + *

+ * + * @author PoffyZhang + */ +public interface RoleAuthorityService extends IService { + /** + * 根据用户-角色-数据权限关系,查询可用的数据权限ID + *

+ * 角色被禁用后,用户不在拥有此角色的权限 + * + * @param userId 用户ID + * @param category 角色类别 + * @return + */ + List selectDataScopeIdFromRoleByUserId(Long userId, String category); + + /** + * 给用户分配角色 + * + * @param userRole 用于角色 + * @return 是否成功 + */ + boolean saveUserRole(UserRoleSaveDTO userRole); + + /** + * 给角色绑定用户 + * + * @param roleUser 用于角色 + * @return 是否成功 + */ + List saveRoleUser(RoleUserSaveVO roleUser); + + /** + * 根据角色查找用户 + * + * @param roleId 角色ID + * @return + */ + List findUserIdByRoleId(Long roleId); + + /** + * 给角色重新分配 权限(资源/菜单) + * + * @param roleAuthoritySaveDTO 角色授权信息 + * @return 是否成功 + */ + boolean saveRoleAuthority(RoleAuthoritySaveDTO roleAuthoritySaveDTO); + + /** + * 根据权限id 删除 + * + * @param ids id + * @return 是否成功 + */ + boolean removeByAuthorityId(List ids); + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleService.java new file mode 100644 index 0000000..35960c2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/RoleService.java @@ -0,0 +1,78 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.dto.RoleSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.RoleUpdateDTO; + +import java.util.List; + +/** + *

+ * 业务接口 + * 角色 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface RoleService extends IService { + + + /** + * 根据ID删除 + * + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 判断用户是否 租户系统的超级管理员 + * + * @param code 角色编码 + * @return 是否成功 + */ + boolean isPtAdmin(String code); + + /** + * 查询用户拥有的角色 + * + * @param userId 用户id + * @return 角色 + */ + List findRoleByUserId(Long userId); + + /** + * 保存角色 + * + * @param data 角色 + * @param userId 用户id + */ + void saveRole(RoleSaveDTO data, Long userId); + + /** + * 修改 + * + * @param role 角色 + * @param userId 用户id + */ + void updateRole(RoleUpdateDTO role, Long userId); + + /** + * 根据角色编码查询用户ID + * + * @param codes 角色编码 + * @return 用户id + */ + List findUserIdByCode(String[] codes); + + /** + * 检测角色名重复 + * + * @param name + * @return 存在返回真 + */ + Boolean check(String name); + Boolean check(String name,Long id); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/UserRoleService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/UserRoleService.java new file mode 100644 index 0000000..3ebcc45 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/UserRoleService.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.UserRole; + +/** + *

+ * 业务接口 + * 角色分配 + * 账号角色绑定 + *

+ * + * @author PoffyZhang + */ +public interface UserRoleService extends IService { + /** + * 初始化超级管理员角色 权限 + * + * @param userId 用户id + * @return 是否正确 + */ + boolean initAdmin(Long userId); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CodingRuleServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CodingRuleServiceImpl.java new file mode 100644 index 0000000..7ab6e98 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CodingRuleServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.ningdatech.carapi.sys.entity.CodingRule; +import com.ningdatech.carapi.sys.mapper.CodingRuleMapper; +import com.ningdatech.carapi.sys.service.ICodingRuleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Service +public class CodingRuleServiceImpl extends ServiceImpl implements ICodingRuleService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyJoinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyJoinServiceImpl.java new file mode 100644 index 0000000..9d7dcbf --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyJoinServiceImpl.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.sys.entity.CompanyJoin; +import com.ningdatech.carapi.sys.mapper.CompanyJoinMapper; +import com.ningdatech.carapi.sys.service.CompanyJoinService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 业务实现类 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CompanyJoinServiceImpl extends ServiceImpl implements CompanyJoinService { + + private final CompanyJoinMapper companyJoinMapper; + + @Override + @LambdaDataScope(wrapperIndex = 1,type = LambdaDataScopeTypeEnum.COMPANY_TABLE) + public Page pageJoin(Page page, LambdaQueryWrapper wrapper) { + return companyJoinMapper.pageJoin(page,wrapper); + } + + @Override + public List listJoin(LambdaQueryWrapper wrapper){ + return companyJoinMapper.listJoin(wrapper); + } + + @Override + public CompanyJoin oneJoin(LambdaQueryWrapper wrapper) { + return companyJoinMapper.oneJoin(wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyServiceImpl.java new file mode 100644 index 0000000..426cb3c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyServiceImpl.java @@ -0,0 +1,346 @@ +package com.ningdatech.carapi.sys.service.impl; + +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam; +import com.ningdatech.carapi.car.rpt.model.dto.RptOtherParamDTO; +import com.ningdatech.carapi.car.rpt.model.po.RptOtherOnlineVehiclesPO; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity; +import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.company.entity.po.ResCompanyTotalPO; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.datascope.aop.XmlDataScope; +import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum; +import com.ningdatech.carapi.driver.constant.UserCanLoginEnum; +import com.ningdatech.carapi.safe.model.dto.SecurityHonestyPageQuery; +import com.ningdatech.carapi.sys.contants.UserLoginConstant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.CompanyType; +import com.ningdatech.carapi.sys.entity.CompanyTypeRelated; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.CompanySaveDTO; +import com.ningdatech.carapi.sys.entity.dto.CompanyUpdateDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.helper.UserCacheHelper; +import com.ningdatech.carapi.sys.mapper.CompanyMapper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.CompanyTypeRelatedService; +import com.ningdatech.carapi.sys.service.CompanyTypeService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.sys.utils.AuthCacheKeyUtils; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.mapper.NdUserInfoMapper; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 业务实现类 + * 企业 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CompanyServiceImpl extends ServiceImpl implements CompanyService { + + private final CompanyMapper companyMapper; + private final NdUserInfoMapper userInfoMapper; + + private final CompanyTypeService companyTypeService; + private final CompanyTypeRelatedService companyTypeRelatedService; + private final RegionsCacheHelper regionsCacheHelper; + private final CompaniesCacheHelper companiesCacheHelper; + private final INdUserInfoService userInfoService; + private final UserCacheHelper userCacheHelper; + private final PasswordEncoder passwordEncoder; + private final INdUserAuthService ndUserAuthService; + private final UserRoleService userRoleService; + private final IVehicleBaseInfoService vehicleBaseInfoService; + private final CachePlusOps cachePlusOps; + + /** + * + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + + // 获取企业名称 + List companyNameList = companyMapper.selectList(Wrappers.lambdaQuery(Company.class).in(Company::getId, ids)).stream() + .map(Company::getName).collect(Collectors.toList()); + // 删除企业 + boolean removeFlag = removeByIds(ids); + if(removeFlag){ + companiesCacheHelper.refresh(ids); + // 删除该企业用户及用户关联的角色、账号密码等信息 + List userInfos = userInfoService.list(Wrappers.lambdaQuery(NdUserInfo.class) + .in(NdUserInfo::getUsername, companyNameList)); + for (NdUserInfo userInfo : userInfos) { + Long id = userInfo.getId(); + UserRole userRole = userRoleService.getOne(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getUserId, id)); + if (Objects.nonNull(userRole)) { + Long roleId = userRole.getRoleId(); + if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) { + // 删除企业用户 + userInfoService.removeById(userInfo); + //删除关联表和缓存 + ndUserAuthService.remove(Wrappers.lambdaQuery(NdUserAuth.class).eq(NdUserAuth::getUserId, id)); + userRoleService.remove(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getUserId, id)); + cachePlusOps.del(AuthCacheKeyUtils.userResourceCacheKey(id)); + userCacheHelper.refresh(id); + } + } + } + + // 车辆关联的这些企业与区域信息置为空 + List vehicleBaseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .in(NdVehicleBaseInfo::getCompanyId, ids)); + + for (NdVehicleBaseInfo vehicleBaseInfo : vehicleBaseInfoList) { + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(NdVehicleBaseInfo.class); + updateWrapper.set(NdVehicleBaseInfo::getCompanyId,null) + .set(NdVehicleBaseInfo::getUseCompanyId,null) + .set(NdVehicleBaseInfo::getUseCompanyName,null) + .set(NdVehicleBaseInfo::getRegionId,null) + .set(NdVehicleBaseInfo::getRegionName,null) + .eq(NdVehicleBaseInfo::getCarPlate,vehicleBaseInfo.getCarPlate()); + vehicleBaseInfoService.update(updateWrapper); + } + } + + //删除前要判断是否企业下还有用户 + //ids.forEach(entId -> { + // if (userInfoMapper.selectCount(Wrappers.lambdaQuery(NdUserInfo.class).eq(NdUserInfo::getCompanyId, entId)) > 0) { + // throw new BaseUncheckedException(HttpStatus.HTTP_OK, "删除失败!企业下还有用户存在 {}", + // entId); + // } + //}); + + // 企业 + return removeFlag; + } + + + /** + * 保存用户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Company save(CompanySaveDTO data, Long userId) { + if (StrUtil.isNotBlank(data.getName()) + && check(data.getName())) { + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "企业名{} 已经存在", + data.getName()); + } + Company company = BeanUtil.toBean(data, Company.class); + + //创建人 最后修改人 + company.setCreateBy(userId); + company.setUpdateBy(userId); + company.setRegionName(regionsCacheHelper.getDisplayName(data.getRegionId())); + // 默认新增的企业为待审核 + company.setRegionAuditStatus(AuditStateEnum.AUDIT.getCode()); + company.setCityAuditStatus(AuditStateEnum.AUDIT.getCode()); + if(save(company)){ + companiesCacheHelper.refresh(company.getId()); + } + // 公司类型 + if (CollUtil.isNotEmpty(data.getEnterpriseTypes())) { + // 先删除原来关联的信息,再保存 + companyTypeRelatedService.remove(Wrappers.lambdaQuery(CompanyTypeRelated.class) + .eq(CompanyTypeRelated::getCompanyId,company.getId())); + for (Long enterpriseType : data.getEnterpriseTypes()) { + CompanyTypeRelated companyTypeRelated = new CompanyTypeRelated(); + companyTypeRelated.setCompanyId(company.getId()); + companyTypeRelated.setCompanyTypeId(enterpriseType); + companyTypeRelatedService.save(companyTypeRelated); + } + } + + // 新增企业后,直接创建企业信息员账号 + NdUserInfo user = new NdUserInfo(); + user.setUsername(company.getName()); + user.setCompanyId(company.getId()); + // 登录用户手机号使用企业法人电话 + user.setMobile(company.getLegalPersonPhone()); + user.setNickName(company.getName()); + user.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode()); + + //创建人 最后修改人 + user.setCreateBy(userId); + user.setUpdateBy(userId); + if (checkMobile(company)){ + throw new BizException("该法人手机号绑定的企业用户已存在,请更换法人手机号!"); + } + boolean save = userInfoService.save(user); + if(save){ + userCacheHelper.refresh(user.getId()); + } + + NdUserAuth userAuth = new NdUserAuth(); + userAuth.setUserId(user.getId()); + // 登录账号使用企业全称 + userAuth.setIdentifier(company.getName()); + // 初始密码使用123456Aa + userAuth.setCredential(passwordEncoder.encode(UserLoginConstant.LOGIN_PASSWORD)); + userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + ndUserAuthService.save(userAuth); + + UserRole userRole = new UserRole(); + userRole.setUserId(user.getId()); + // 用户角色设置为企业信息员 + userRole.setRoleId(UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId()); + userRoleService.save(userRole); + return company; + } + + private Boolean checkMobile(Company company) { + return userInfoService.count(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getMobile, company.getLegalPersonPhone())) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Company update(CompanyUpdateDTO data, Long userId) { + Company company = BeanUtil.toBean(data, Company.class); + //最后修改人 + company.setUpdateBy(userId); + company.setRegionName(regionsCacheHelper.getDisplayName(data.getRegionId())); + if(updateById(company)){ + companiesCacheHelper.refresh(company.getId()); + } + //公司类型 + if (CollUtil.isNotEmpty(data.getEnterpriseTypes())) { + companyTypeRelatedService.remove(Wrappers.lambdaQuery(CompanyTypeRelated.class).eq(CompanyTypeRelated::getCompanyId, company.getId())); + for (Long enterpriseType : data.getEnterpriseTypes()) { + CompanyType companyType = companyTypeService.getById(enterpriseType); + if (Objects.nonNull(companyType)) { + companyTypeRelatedService.save(new CompanyTypeRelated(null, company.getId(), companyType.getId())); + } + } + } + return company; + } + + @Override + public Boolean check(String name) { + return super.count(Wrappers.lambdaQuery(Company.class).eq(Company::getName, name)) > 0; + } + + @Override + public Boolean check(String name, Long id) { + return super.count(Wrappers.lambdaQuery(Company.class).ne(Company::getId, id) + .eq(Company::getName, name)) > 0; + } + + @Override + public Map listCompanyByIds(Collection ids) { + if (CollectionUtils.isEmpty(ids)) { + return Collections.emptyMap(); + } + List companyList = list(Wrappers.lambdaQuery(Company.class) + .in(Company::getId, ids)); + return CollUtils.listToMap(companyList, Company::getId); + } + + @Override + public List listCompanyByCompanyNames(Collection names) { + if (CollectionUtils.isEmpty(names)) { + return Collections.emptyList(); + } + LambdaQueryWrapper query = Wrappers.lambdaQuery(Company.class); + query.in(Company::getName, names); + return list(query); + } + + @Override + public Company getCompanyByCompanyNames(String companyName) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(Company.class); + query.eq(Company::getName, companyName); + return getOne(query); + } + + @Override + public List findCompanyIdsByRegionId(DataScreenParam param) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Company.class); + CompanyServiceImpl context = (CompanyServiceImpl)AopContext.currentProxy(); + List list = context.searchCompanyIdsByRegionId(wrapper,param); + return list.stream().map(v -> String.valueOf(v.getId())).collect(Collectors.toList()); + } + + @Override + @XmlDataScope(entityIndex = 1) + @BuildChildrenRegionEntity(entityIndex = 1) + public Page pageVehicleNum(Page page, RptOtherParamDTO param) { + CodeUtil.buildRegionLevel(param); + return companyMapper.pageVehicleNum(page,param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List countByRegion(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return companyMapper.countByRegion(param); + } + + @Override + @XmlDataScope + @BuildChildrenRegionEntity + public List countEnterpriseType(DataScreenParam param) { + CodeUtil.buildRegionLevel(param); + return companyMapper.countEnterpriseType(param); + } + + @Override + @LambdaDataScope(wrapperIndex = 1) + @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2) + public Page pageDataScope(Page page, LambdaQueryWrapper wrapper, SecurityHonestyPageQuery param) { + return page(page,wrapper); + } + + @LambdaDataScope(type = LambdaDataScopeTypeEnum.COMPANY_TABLE) + @BuildChildrenRegionWrapper + public List searchCompanyIdsByRegionId(LambdaQueryWrapper wrapper, DataScreenParam param) { + log.info(param.toString()); + return list(wrapper); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeRelatedServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeRelatedServiceImpl.java new file mode 100644 index 0000000..d0f0b6c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeRelatedServiceImpl.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.sys.entity.CompanyTypeRelated; +import com.ningdatech.carapi.sys.mapper.CompanyTypeRelatedMapper; +import com.ningdatech.carapi.sys.service.CompanyTypeRelatedService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 业务实现类 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CompanyTypeRelatedServiceImpl extends ServiceImpl implements CompanyTypeRelatedService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeServiceImpl.java new file mode 100644 index 0000000..3094f3c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/CompanyTypeServiceImpl.java @@ -0,0 +1,23 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.carapi.sys.entity.CompanyType; +import com.ningdatech.carapi.sys.mapper.CompanyTypeMapper; +import com.ningdatech.carapi.sys.service.CompanyTypeService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 业务实现类 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CompanyTypeServiceImpl extends ServiceImpl implements CompanyTypeService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ExamRuleServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ExamRuleServiceImpl.java new file mode 100644 index 0000000..983b898 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ExamRuleServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.ningdatech.carapi.sys.entity.ExamRule; +import com.ningdatech.carapi.sys.mapper.ExamRuleMapper; +import com.ningdatech.carapi.sys.service.IExamRuleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-20 + */ +@Service +public class ExamRuleServiceImpl extends ServiceImpl implements IExamRuleService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MenuServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MenuServiceImpl.java new file mode 100644 index 0000000..e324197 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MenuServiceImpl.java @@ -0,0 +1,182 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.basic.util.ValidatorUtil; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.dto.MenuSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.MenuUpdateDTO; +import com.ningdatech.carapi.sys.entity.enumeration.MenuTypeEnum; +import com.ningdatech.carapi.sys.mapper.MenuMapper; +import com.ningdatech.carapi.sys.service.MenuService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static com.ningdatech.basic.util.StrPool.DEF_PARENT_ID; + + +/** + *

+ * 业务实现类 + * 菜单 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MenuServiceImpl extends ServiceImpl implements MenuService { + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + + List lastIds = Lists.newArrayList(); + lastIds.addAll(ids); + + //子菜单id + subMenus(ids,lastIds); + + boolean result = this.removeByIds(lastIds); + return result; + } + + private void subMenus(List ids, List lastIds) { + if(CollUtil.isEmpty(ids)){ + return; + } + + ids.forEach(id -> { + List subMenus = list(Wrappers.lambdaQuery(Menu.class).eq(Menu::getPid, id)); + if(CollUtil.isNotEmpty(subMenus)){ + //添加子菜单ID + List subIds = subMenus.stream().map(Menu::getId).collect(Collectors.toList()); + lastIds.addAll(subIds); + //递归 + subMenus(subIds,lastIds); + } + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(MenuUpdateDTO data, Long userId) { + if (MenuTypeEnum.MENU.getCode().equals(data.getType())) { + if(StrUtil.isBlank(data.getPath())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【地址栏路径】不能为空"); + } + if(StrUtil.isBlank(data.getComponent())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【页面路径】不能为空"); + } + if (!ValidatorUtil.isUrl(data.getPath())) { + if(checkPath(data.getId(), data.getPath())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,"【地址栏路径】:{}重复", data.getPath()); + } + } + } + Menu old = getById(data); + if(Objects.isNull(old)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,"您修改的菜单已不存在"); + } + Menu menu = BeanUtil.toBean(data, Menu.class); + menu.setUpdateBy(userId); + return this.updateById(menu); + } + + public Boolean checkPath(Long id, String path) { + return baseMapper.selectCount(Wrappers.lambdaQuery(Menu.class).ne(Menu::getId, id).eq(Menu::getPath, path)) > 0; + } + + public Boolean checkTitle(Long id, String title) { + return baseMapper.selectCount(Wrappers.lambdaQuery(Menu.class).ne(Menu::getId, id) + .in(Menu::getType, MenuTypeEnum.MENU.getCode()).eq(Menu::getTitle, title)) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean save(MenuSaveDTO data, Long userId) { + if (MenuTypeEnum.MENU.getCode().equals(data.getType())) { + if(StrUtil.isBlank(data.getPath())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【地址栏路径】不能为空"); + } + if(StrUtil.isBlank(data.getComponent())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【页面路径】不能为空"); + } + if (!ValidatorUtil.isUrl(data.getPath())) { + if(checkPath(null, data.getPath())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,"【地址栏路径】:{}重复", data.getPath()); + } + } + } + data.setPid(Convert.toLong(data.getPid(), DEF_PARENT_ID)); + + Menu menu = BeanUtil.toBean(data, Menu.class); + menu.setCreateBy(userId); + menu.setUpdateBy(userId); + save(menu); + return Boolean.TRUE; + } + + private void checkGeneral(Menu data, boolean isUpdate) { +// if (data.getIsGeneral() == null) { +// return; +// } +// +// if (data.getIsGeneral()) { +// // isGeneral 子节点 改成是,父节点全是 +// if (!TreeUtil.isRoot(data.getParentId())) { +// Menu parent = getById(data.getParentId()); +// Assert.notNull(parent, "父节点不存在"); +// Assert.isTrue(parent.getIsGeneral(), "请先将父节点{} “公共资源”字段修改为:“是”,在修改本节点", parent.getLabel()); +// } +// return; +// } + +// if (isUpdate) { +// // isGeneral 父节点 改成否,子节点全否 +// List childrenList = findChildrenByParentId(data.getId()); +// if (CollUtil.isNotEmpty(childrenList)) { +// childrenList.forEach(item -> { +// Assert.isFalse(item.getIsGeneral(), String.format("请先将子节点%s “公共资源”字段修改为:“否”,在修改本节点", item.getLabel())); +// }); +// } +// } + } + + public List findChildrenByParentId(Long pid) { + if(Objects.isNull(pid)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "pid 不能为空"); + } + return list(Wrappers.lambdaQuery(Menu.class).in(Menu::getPid, pid).orderByAsc(Menu::getSort)); + } + + private void fill(Menu resource) { + if (resource.getPid() == null || resource.getPid() <= 0) { + resource.setPid(DefValConstants.PARENT_ID); + } else { + Menu parent = getById(resource.getPid()); + if(Objects.isNull(parent)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "请正确填写父级"); + } + } + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MetaApplyServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MetaApplyServiceImpl.java new file mode 100644 index 0000000..a910486 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/MetaApplyServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.ningdatech.carapi.sys.entity.MetaApply; +import com.ningdatech.carapi.sys.mapper.MetaApplyMapper; +import com.ningdatech.carapi.sys.service.IMetaApplyService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Liuxinxin + * @since 2022-10-15 + */ +@Service +public class MetaApplyServiceImpl extends ServiceImpl implements IMetaApplyService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorRegionHeadServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorRegionHeadServiceImpl.java new file mode 100644 index 0000000..fb0dc4c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorRegionHeadServiceImpl.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Maps; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import com.ningdatech.carapi.sys.entity.dto.OperatorRegionHeadSaveDTO; +import com.ningdatech.carapi.sys.mapper.OperatorRegionHeadMapper; +import com.ningdatech.carapi.sys.service.OperatorRegionHeadService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + *

+ * 业务实现类 + * 运营商区域负责人 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class OperatorRegionHeadServiceImpl extends ServiceImpl + implements OperatorRegionHeadService { + + private final CachePlusOps cachePlusOps; + private final OperatorRegionHeadMapper operatorRegionHeadMapper; + + /** + * + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + // 运营商 + boolean removeFlag = removeByIds(ids); + + return removeFlag; + } + + @Override + public boolean removeByRegionId(Long operatorId) { + if (Objects.isNull(operatorId)) { + return Boolean.FALSE; + } + + Map columnsMap = Maps.newHashMap(); + columnsMap.put("operator_id",operatorId); + removeByMap(columnsMap); + + return Boolean.TRUE; + } + + + /** + * 保存用户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void saveBatch(List datas,Long operatorId, Long userId) { + if(CollUtil.isEmpty(datas)){ + return; + } + datas.forEach(data -> { + OperatorRegionHead operatorRegionHead = BeanUtil.toBean(data, OperatorRegionHead.class); + operatorRegionHead.setOperatorId(operatorId); + //创建人 最后修改人 + operatorRegionHead.setCreateBy(userId); + operatorRegionHead.setUpdateBy(userId); + save(operatorRegionHead); + }); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorScoreInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorScoreInfoServiceImpl.java new file mode 100644 index 0000000..0befff4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorScoreInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.ningdatech.carapi.industry.entity.OperatorScoreInfo; +import com.ningdatech.carapi.sys.mapper.OperatorScoreInfoMapper; +import com.ningdatech.carapi.sys.service.IOperatorScoreInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author CMM + * @since 2023-01-04 + */ +@Service +public class OperatorScoreInfoServiceImpl extends ServiceImpl implements IOperatorScoreInfoService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorServiceImpl.java new file mode 100644 index 0000000..2f07159 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/OperatorServiceImpl.java @@ -0,0 +1,128 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.sys.entity.Operator; +import com.ningdatech.carapi.sys.entity.OperatorRegionHead; +import com.ningdatech.carapi.sys.entity.dto.OperatorSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.OperatorUpdateDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.mapper.OperatorMapper; +import com.ningdatech.carapi.sys.service.OperatorRegionHeadService; +import com.ningdatech.carapi.sys.service.OperatorService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +/** + *

+ * 业务实现类 + * 运营商 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class OperatorServiceImpl extends ServiceImpl implements OperatorService { + + private final CachePlusOps cachePlusOps; + private final OperatorMapper operatorMapper; + private final OperatorRegionHeadService operatorRegionHeadService; + + private final OperatorsCacheHelper operatorsCacheHelper; + + /** + * + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + // 运营商 + boolean removeFlag = removeByIds(ids); + operatorsCacheHelper.refresh(ids); + //删除区域负责人 + operatorRegionHeadService.remove(Wrappers.lambdaQuery(OperatorRegionHead.class) + .in(OperatorRegionHead::getOperatorId, ids)); + return removeFlag; + } + + + /** + * 保存用户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void save(OperatorSaveDTO data, Long userId) { + if(StrUtil.isNotBlank(data.getName()) + && check(data.getName())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "运营商{} 已经存在", + data.getName()); + } + Operator operator = BeanUtil.toBean(data, Operator.class); + //创建人 最后修改人 + operator.setCreateBy(userId); + operator.setUpdateBy(userId); + if(save(operator)){ + operatorsCacheHelper.refresh(operator.getId()); + } + if(CollUtil.isNotEmpty(data.getOperatorRegionHeads())){ + //先删除 再批量添加 + operatorRegionHeadService.removeByRegionId(operator.getId()); + operatorRegionHeadService.saveBatch(data.getOperatorRegionHeads(),operator.getId(),userId); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(OperatorUpdateDTO data, Long userId) { + Operator old = operatorMapper.selectById(data.getId()); + if(Objects.isNull(old)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,String.format("修改运营商{} 不存在",data.getId())); + } + + if(StringUtils.isNotBlank(data.getName())){ + Assert.isFalse(check(data.getName(),old.getId()), "运营商名{} 已经存在", + data.getName()); + } + + Operator operator = BeanUtil.toBean(data, Operator.class); + //最后修改人 + operator.setUpdateBy(userId); + if(updateById(operator)){ + operatorsCacheHelper.refresh(operator.getId()); + } + if(CollUtil.isNotEmpty(data.getOperatorRegionHeads())){ + //先删除 再批量添加 + operatorRegionHeadService.removeByRegionId(operator.getId()); + operatorRegionHeadService.saveBatch(data.getOperatorRegionHeads(),operator.getId(),userId); + } + } + + @Override + public Boolean check(String name) { + return super.count(Wrappers.lambdaQuery(Operator.class).eq(Operator::getName, name)) > 0; + } + + @Override + public Boolean check(String name,Long id) { + return super.count(Wrappers.lambdaQuery(Operator.class).ne(Operator::getId,id) + .eq(Operator::getName, name)) > 0; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RegionServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RegionServiceImpl.java new file mode 100644 index 0000000..8dafb2b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RegionServiceImpl.java @@ -0,0 +1,56 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.carapi.sys.convert.RegionConverter; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.mapper.RegionMapper; +import com.ningdatech.carapi.sys.service.IRegionService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-10-08 + */ +@Service +public class RegionServiceImpl extends ServiceImpl implements IRegionService { + + @Override + public List queryAll() { + List allRegions = this.lambdaQuery().ne(Region::getId, -1).list(); + return CollUtils.convert(allRegions, RegionConverter::toRegionDTO); + } + + @Override + public List listGeLevel(int regionLevel) { + List regionsByLevel = lambdaQuery().ne(Region::getId, -1) + .le(Region::getLevel, regionLevel).list(); + return CollUtils.convert(regionsByLevel, RegionConverter::toRegionDTO); + } + + @Override + public boolean isParentRegion(Long regionId) { + return baseMapper.exists(Wrappers.lambdaQuery(Region.class) + .eq(Region::getParentId, regionId) + .eq(Region::getDeleted, false)); + } + + @Override + public Long getRegionIdByParentIdWithSameRegionCode(Long parentId, String regionCode) { + return baseMapper.selectOne(Wrappers.lambdaQuery(Region.class) + .eq(Region::getParentId, parentId) + .eq(Region::getRegionCode, regionCode) + .eq(Region::getDeleted, false)) + .getId(); + } + + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ResourceServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ResourceServiceImpl.java new file mode 100644 index 0000000..d4542d1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/ResourceServiceImpl.java @@ -0,0 +1,85 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.carapi.sys.entity.Resource; +import com.ningdatech.carapi.sys.mapper.ResourceMapper; +import com.ningdatech.carapi.sys.service.ResourceService; +import com.ningdatech.carapi.sys.service.RoleAuthorityService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 业务实现类 + * 资源 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class ResourceServiceImpl extends ServiceImpl implements ResourceService { + + private final RoleAuthorityService roleAuthorityService; + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + boolean result = this.removeByIds(ids); + + // 删除角色的权限 + roleAuthorityService.removeByAuthorityId(ids); + return result; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeByMenuIdWithCache(List menuIds) { + List resources = super.list(Wrappers.lambdaQuery(Resource.class).in(Resource::getMenuId, menuIds)); + if (resources.isEmpty()) { + return; + } + List resourceIdList = resources.stream().mapToLong(Resource::getId).boxed().collect(Collectors.toList()); + this.removeByIds(resourceIdList); + + List allIds = CollUtil.newArrayList(menuIds); + allIds.addAll(resourceIdList); + // 删除角色的权限 + roleAuthorityService.removeByAuthorityId(allIds); + } + + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean saveWithCache(Resource resource) { + resource.setCode(StrUtil.blankToDefault(resource.getCode(), RandomUtil.randomString(8))); + if (check(null, resource.getCode())) { + throw new BaseUncheckedException(HttpStatus.HTTP_BAD_REQUEST,String.format("编码[%s]重复", resource.getCode())); + } + + this.save(resource); + return true; + } + + @Override + public List findMenuIdByResourceId(List resourceIdList) { + return baseMapper.findMenuIdByResourceId(resourceIdList); + } + + @Override + public Boolean check(Long id, String code) { + return super.count(Wrappers.lambdaQuery(Resource.class).ne(Resource::getId, id).eq(Resource::getCode, code)) > 0; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleAuthorityServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleAuthorityServiceImpl.java new file mode 100644 index 0000000..699433d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleAuthorityServiceImpl.java @@ -0,0 +1,192 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Assert; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.sys.entity.RoleAuthority; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.RoleAuthoritySaveDTO; +import com.ningdatech.carapi.sys.entity.dto.RoleUserSaveVO; +import com.ningdatech.carapi.sys.entity.dto.UserRoleSaveDTO; +import com.ningdatech.carapi.sys.entity.enumeration.AuthorizeType; +import com.ningdatech.carapi.sys.mapper.ResourceMapper; +import com.ningdatech.carapi.sys.mapper.RoleAuthorityMapper; +import com.ningdatech.carapi.sys.service.RoleAuthorityService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.sys.utils.AuthCacheKeyUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 业务实现类 + * 角色的资源 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class RoleAuthorityServiceImpl extends ServiceImpl implements RoleAuthorityService { + + private final UserRoleService userRoleService; + private final ResourceMapper resourceMapper; + private final CachePlusOps cachePlusOps; + + @Override + public List selectDataScopeIdFromRoleByUserId(Long userId, String category) { + return baseMapper.selectDataScopeIdFromRoleByUserId(userId, category); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public List saveRoleUser(RoleUserSaveVO saveVO) { + Assert.notEmpty(saveVO.getUserIdList(), "请选择用户"); + if (saveVO.getFlag() == null) { + saveVO.setFlag(true); + } + + userRoleService.remove(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getRoleId, saveVO.getRoleId()).in(UserRole::getUserId, saveVO.getUserIdList())); + if (saveVO.getFlag()) { + List list = saveVO.getUserIdList().stream().map(employeeId -> + UserRole.builder().userId(employeeId).roleId(saveVO.getRoleId()).build()).collect(Collectors.toList()); + userRoleService.saveBatch(list); + } + return findUserIdByRoleId(saveVO.getRoleId()); + } + + @Override + public List findUserIdByRoleId(Long roleId) { + return userRoleService.listObjs(Wrappers.lambdaQuery(UserRole.class) + .select(UserRole::getUserId).eq(UserRole::getRoleId, roleId), + Convert::toLong); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean saveUserRole(UserRoleSaveDTO userRole) { + List oldUserRoleList = userRoleService.list(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getRoleId, userRole.getRoleId())); + userRoleService.remove(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getRoleId, userRole.getRoleId())); + + Set delIdList = new HashSet<>(); + if (CollUtil.isNotEmpty(userRole.getUserIdList())) { + List list = userRole.getUserIdList() + .stream() + .map(userId -> UserRole.builder() + .userId(userId) + .roleId(userRole.getRoleId()) + .build()) + .collect(Collectors.toList()); + userRoleService.saveBatch(list); + delIdList.addAll(userRole.getUserIdList()); + } + + /* 角色A -> u1 u2 + 修改成 + 角色A -> u3 u2 + 所以, 应该清除 u1、u2、u3 的角色、菜单、资源 + */ + + if (!oldUserRoleList.isEmpty()) { + delIdList.addAll(oldUserRoleList.stream().map(UserRole::getUserId).collect(Collectors.toSet())); + } + delUserAuthority(delIdList); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean saveRoleAuthority(RoleAuthoritySaveDTO dto) { + Assert.notNull(dto.getRoleId(), "请选择角色"); + + //删除角色和资源的关联 + super.remove(Wrappers.lambdaQuery(RoleAuthority.class).eq(RoleAuthority::getRoleId, dto.getRoleId())); + + List list = new ArrayList<>(); + if (dto.getResourceIdList() != null && !dto.getResourceIdList().isEmpty()) { + List menuIdList = resourceMapper.findMenuIdByResourceId(dto.getResourceIdList()); + if (dto.getMenuIdList() == null || dto.getMenuIdList().isEmpty()) { + dto.setMenuIdList(menuIdList); + } else { + dto.getMenuIdList().addAll(menuIdList); + } + + //保存授予的资源resourceMapper + List resourceList = new HashSet<>(dto.getResourceIdList()) + .stream() + .map(resourceId -> RoleAuthority.builder() + .authorityType(AuthorizeType.RESOURCE) + .authorityId(resourceId) + .roleId(dto.getRoleId()) + .build()) + .collect(Collectors.toList()); + list.addAll(resourceList); + } + if (dto.getMenuIdList() != null && !dto.getMenuIdList().isEmpty()) { + //保存授予的菜单 + List menuList = new HashSet<>(dto.getMenuIdList()) + .stream() + .map(menuId -> RoleAuthority.builder() + .authorityType(AuthorizeType.MENU) + .authorityId(menuId) + .roleId(dto.getRoleId()) + .build()) + .collect(Collectors.toList()); + list.addAll(menuList); + } + super.saveBatch(list); + + // 角色下的所有用户 + List userIdList = userRoleService.listObjs( + Wrappers.lambdaQuery(UserRole.class) + .select(UserRole::getUserId) + .eq(UserRole::getRoleId, dto.getRoleId()), + Convert::toLong); + + delUserAuthority(userIdList); + cachePlusOps.del(AuthCacheKeyUtils.roleResourceCacheKey(dto.getRoleId())); + cachePlusOps.del(AuthCacheKeyUtils.roleResourceCacheKey((dto.getRoleId()))); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByAuthorityId(List ids) { + List roleIds = listObjs( + Wrappers.lambdaQuery(RoleAuthority.class) + .select(RoleAuthority::getRoleId) + .in(RoleAuthority::getAuthorityId, ids), + Convert::toLong); + + if (!roleIds.isEmpty()) { + remove(Wrappers.lambdaQuery(RoleAuthority.class).in(RoleAuthority::getAuthorityId, ids)); + List userIdList = userRoleService.listObjs( + Wrappers.lambdaQuery(UserRole.class).select(UserRole::getUserId).in(UserRole::getRoleId, roleIds), + Convert::toLong); + + delUserAuthority(userIdList); + roleIds.forEach(roleId -> { + cachePlusOps.del(AuthCacheKeyUtils.roleResourceCacheKey(roleId)); + cachePlusOps.del(AuthCacheKeyUtils.roleMenuCacheKey(roleId)); + }); + } + return true; + } + + private void delUserAuthority(Collection collections) { + collections.forEach(userId -> { + cachePlusOps.del(AuthCacheKeyUtils.userResourceCacheKey(userId)); + cachePlusOps.del(AuthCacheKeyUtils.userMenuCacheKey(userId)); + cachePlusOps.del(AuthCacheKeyUtils.userRoleCacheKey(userId)); + }); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleMenuServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleMenuServiceImpl.java new file mode 100644 index 0000000..1453392 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleMenuServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.sys.service.impl; + +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.mapper.RoleMenuMapper; +import com.ningdatech.carapi.sys.service.IRoleMenuService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author PoffyZhang + * @since 2022-11-11 + */ +@Service +public class RoleMenuServiceImpl extends ServiceImpl implements IRoleMenuService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..9b5da73 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/RoleServiceImpl.java @@ -0,0 +1,207 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.sys.entity.Menu; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.RoleSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.RoleUpdateDTO; +import com.ningdatech.carapi.sys.mapper.RoleMapper; +import com.ningdatech.carapi.sys.service.*; +import com.ningdatech.carapi.sys.utils.AuthCacheKeyUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 业务实现类 + * 角色 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class RoleServiceImpl extends ServiceImpl implements RoleService { + private final RoleAuthorityService roleAuthorityService; + private final UserRoleService userRoleService; + private final RoleMapper roleMapper; + + private final CachePlusOps cachePlusOps; + + private final IRoleMenuService roleMenuService; + + private final MenuService menuService; + + private static final String SUPER_ADMIN = "SUPER_ADMIN"; + + @Override + public boolean isPtAdmin(String code) { + return SUPER_ADMIN.equals(code); + } + + + /** + * 删除角色时,需要级联删除跟角色相关的一切资源: + * 1,角色本身 + * 2,角色-组织: + * 3,角色-权限(菜单和按钮): + * 4,角色-用户:角色拥有的用户 + * 5,用户-权限: + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + + if(userRoleService.count(Wrappers.lambdaQuery(UserRole.class).select(UserRole::getUserId) + .in(UserRole::getRoleId, ids)) > 0){ + throw new BizException(ExceptionCode.OPERATION_EX.getCode(), "该角色下还有用户 不能随意删除!"); + } + + // 角色 + boolean removeFlag = removeByIds(ids); + + //角色拥有的用户 + userRoleService.remove(Wrappers.lambdaQuery(UserRole.class).in(UserRole::getRoleId, ids)); + if(removeFlag){ + // 角色绑定了那些用户 + if(roleMenuService.remove(Wrappers.lambdaQuery(RoleMenu.class).in(RoleMenu::getRoleId, ids))){ + return Boolean.TRUE; + } + } + return removeFlag; + } + + /** + * 1、根据 {tenant}:USER_ROLE:{userId} 查询用户拥有的角色ID集合 + * 2、缓存中有,则根据角色ID集合查询 角色集合 + * 3、缓存中有查不到,则从DB查询,并写入缓存, 立即返回 + * + * @param userId 用户id + */ + @Override + public List findRoleByUserId(Long userId) { + String cacheKey = AuthCacheKeyUtils.userRoleCacheKey(userId); + List roleList = new ArrayList<>(); + List list = (List) cachePlusOps.get(cacheKey); + if (list == null) { + roleList.addAll(baseMapper.findRoleByUserId(userId)); + list = roleList.stream().map(Role::getId).collect(Collectors.toList()); + } + if (roleList.isEmpty()) { + return listByIds(list); + } + return roleList; + } + + /** + * 1,保存角色 + * 2,保存 与组织的关系 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void saveRole(RoleSaveDTO data, Long userId) { + if(StrUtil.isNotBlank(data.getName()) && check(data.getName())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "角色名称{} 已存在", data.getName()); + } + Role role = BeanUtil.toBean(data, Role.class); + role.setCreateBy(userId); + role.setUpdateBy(userId); + save(role); + saveRoleMenu(data.getMenuIds(),role.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateRole(RoleUpdateDTO data, Long userId) { + Role roleOld = roleMapper.selectById(data.getId()); + if(Objects.isNull(roleOld)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,String.format("修改用户%d 为空",data.getId())); + } + + if(StringUtils.isNotBlank(data.getName())){ + Assert.isFalse(check(data.getName(),roleOld.getId()), "角色名{} 已经存在", + data.getName()); + } + Role role = BeanUtil.toBean(data, Role.class); + role.setUpdateBy(userId); + updateById(role); + saveRoleMenu(data.getMenuIds(),role.getId()); + + cachePlusOps.del(AuthCacheKeyUtils.userResourceCacheKey(userId)); + } + + @Override + public List findUserIdByCode(String[] codes) { + return baseMapper.findUserIdByCode(codes); + } + + @Override + public Boolean check(String name) { + return super.count(Wrappers.lambdaQuery(Role.class).eq(Role::getName, name)) > 0; + } + + @Override + public Boolean check(String name,Long id) { + return super.count(Wrappers.lambdaQuery(Role.class).ne(Role::getId,id) + .eq(Role::getName, name)) > 0; + } + + private void saveRoleMenu(List menuIds, Long roleId) { + if(CollUtil.isNotEmpty(menuIds)){ + roleMenuService.remove(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, roleId)); + Set toAddMenus = new HashSet<>(); + for(Long menuId : menuIds){ + Menu menu = menuService.getById(menuId); + if(Objects.isNull(menu)){ + continue; + } + RoleMenu roleMenu = new RoleMenu(null,menuId,roleId); + toAddMenus.add(roleMenu); + //父级菜单 +// addParent(toAddMenus,menu,roleId); + } + if(CollUtil.isNotEmpty(toAddMenus)){ + roleMenuService.saveBatch(toAddMenus); + } + } + } + + private void addParent(Set toAddMenus, Menu menu,Long roleId) { + if(Objects.isNull(menu.getPid()) || menu.getPid().equals(0)){ + return; + } + Menu parant = menuService.getById(menu.getPid()); + if(Objects.isNull(parant)){ + return; + } + RoleMenu roleMenu = new RoleMenu(null,parant.getId(),roleId); + toAddMenus.add(roleMenu); + addParent(toAddMenus,parant,roleId); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/UserRoleServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..f82345e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/service/impl/UserRoleServiceImpl.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.sys.service.impl; + +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.mapper.RoleMapper; +import com.ningdatech.carapi.sys.mapper.UserRoleMapper; +import com.ningdatech.carapi.sys.service.UserRoleService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 业务实现类 + * 角色分配 + * 账号角色绑定 + *

+ * + * @author PoffyZhang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class UserRoleServiceImpl extends ServiceImpl implements UserRoleService { + + private static final String INIT_ROLE_CODE = "SUPER_ADMIN"; + + private final RoleMapper roleMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean initAdmin(Long userId) { + Role role = roleMapper.selectOne(Wrappers.lambdaQuery(Role.class).eq(Role::getName, INIT_ROLE_CODE)); + if (role == null) { + throw new BaseUncheckedException(HttpStatus.HTTP_OK,String.format("初始化用户角色失败, 无法查询到内置角色:%s", INIT_ROLE_CODE)); + } + UserRole userRole = UserRole.builder() + .userId(userId).roleId(role.getId()) + .build(); + + return super.save(userRole); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/AuthCacheKeyUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/AuthCacheKeyUtils.java new file mode 100644 index 0000000..1673aa0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/AuthCacheKeyUtils.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.sys.utils; + +/** + *

+ * AuthCacheKeyUtils + *

+ * + * @author PoffyZhang + */ +public class AuthCacheKeyUtils { + + private static final String USER_RESOURCE_CKP = "user_resource:"; + private static final String USER_MENU_CKP = "user_menu:"; + private static final String USER_ROLE_CKP = "user_role:"; + private static final String ROLE_RESOURCE_CKP = "role_resource:"; + private static final String ROLE_MENU_CKP = "role_menu:"; + + public static String roleResourceCacheKey(Long roleId) { + return ROLE_RESOURCE_CKP + roleId; + } + + public static String roleMenuCacheKey(Long roleId) { + return ROLE_MENU_CKP + roleId; + } + + public static String userResourceCacheKey(Long userId) { + return USER_RESOURCE_CKP + userId; + } + + public static String userMenuCacheKey(Long userId) { + return USER_MENU_CKP + userId; + } + + public static String userRoleCacheKey(Long userId) { + return USER_ROLE_CKP + userId; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/DataScopeCacheFilterUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/DataScopeCacheFilterUtil.java new file mode 100644 index 0000000..76f78f2 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/DataScopeCacheFilterUtil.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.sys.utils; + +import cn.hutool.core.collection.CollUtil; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.sys.entity.vo.RegionTreeCompanyVO; + +import java.util.Optional; + +/** + * @Classname DataScopeCacheFilterUtil + * @Description + * @Date 2022/11/21 16:48 + * @Created by PoffyZhang + */ +public class DataScopeCacheFilterUtil { + + public static boolean dataScopeFilter(NdVehicleBaseInfo v, Optional dataScope) { + if(!dataScope.isPresent()){ + return Boolean.TRUE; + } + + if(CollUtil.isNotEmpty(dataScope.get().getRegionIds())){ + if(dataScope.get().getRegionIds().contains(v.getRegionId())){ + return Boolean.TRUE; + } + return Boolean.FALSE; + }else if(CollUtil.isNotEmpty(dataScope.get().getCompanyIds())){ + if(dataScope.get().getCompanyIds().contains(v.getId())){ + return Boolean.TRUE; + } + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + public static boolean dataScopeFilter(RegionTreeCompanyVO v, Optional dataScope) { + if(!dataScope.isPresent()){ + return Boolean.TRUE; + } + + if(CollUtil.isNotEmpty(dataScope.get().getRegionIds())){ + if(dataScope.get().getRegionIds().contains(v.getRegionId())){ + return Boolean.TRUE; + } + return Boolean.FALSE; + }else if(CollUtil.isNotEmpty(dataScope.get().getCompanyIds())){ + if(dataScope.get().getCompanyIds().contains(v.getId())){ + return Boolean.TRUE; + } + return Boolean.FALSE; + } + return Boolean.TRUE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/HttpUtils.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/HttpUtils.java new file mode 100644 index 0000000..4a83978 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/HttpUtils.java @@ -0,0 +1,310 @@ +package com.ningdatech.carapi.sys.utils; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class HttpUtils { + /** + * get + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/TreeUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/TreeUtil.java new file mode 100644 index 0000000..7a2f60a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/sys/utils/TreeUtil.java @@ -0,0 +1,318 @@ +package com.ningdatech.carapi.sys.utils; + +import cn.hutool.core.collection.CollUtil; +import com.google.common.collect.Maps; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.sys.entity.RoleMenu; +import com.ningdatech.carapi.sys.entity.TreeEntity; +import com.ningdatech.carapi.sys.entity.vo.MenuRoleVO; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * list列表 转换成tree列表 + * + * @author PoffyZhang + */ +public final class TreeUtil { + private TreeUtil() { + } + + /** + * 判断id是否为根节点 + * + * @param id + * @return + */ + public static boolean isRoot(Long id) { + return id == null || StrPool.DEF_PARENT_ID.equals(id); + } + + + public static String getTreePath(String parentTreePath, Long parentId) { + return StrPool.COMMA + parentId + parentTreePath; + } + + /** + * 构建Tree结构 + * + * @param treeList 待转换的集合 + * @return 树结构 + */ + public static > List buildTree(List treeList) { + if (CollUtil.isEmpty(treeList)) { + return treeList; + } + //记录自己是自己的父节点的id集合 + List selfIdEqSelfParent = new ArrayList<>(); + + // 遍历两次 + foreachNodes(treeList, selfIdEqSelfParent); + foreachNodesWithTopMenu(treeList); + + // 找出根节点集合 + List trees = new ArrayList<>(); + + List allIds = treeList.stream().map(node -> node.getId()).collect(Collectors.toList()); + for (E baseNode : treeList) { + if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) { + baseNode.setPid(null); + baseNode.setTopMenu(baseNode.getName()); + trees.add(baseNode); + } + } + return trees; + } + + /** + * 构建Tree结构 + * + * @param treeList 待转换的集合 + * @param title 菜单名 + * @return 树结构 + */ + public static > List buildTree(List treeList, String title) { + if (CollUtil.isEmpty(treeList)) { + return treeList; + } + //记录自己是自己的父节点的id集合 + List selfIdEqSelfParent = new ArrayList<>(); + + // 遍历两次 + foreachNodes(treeList, selfIdEqSelfParent); + foreachNodesWithTopMenu(treeList); + + // 找出根节点集合 + List trees = new ArrayList<>(); + + List allIds = treeList.stream().map(node -> node.getId()).collect(Collectors.toList()); + for (E baseNode : treeList) { + if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) { + baseNode.setPid(null); + baseNode.setTopMenu(baseNode.getName()); + trees.add(baseNode); + } + } +// checkTitle(trees,title); + return trees; + } + + private static > + void foreachNodes(List treeList, List selfIdEqSelfParent) { + for (E parent : treeList) { + Serializable id = parent.getId(); + for (E children : treeList) { + if (parent != children) { + //parent != children 这个来判断自己的孩子不允许是自己,因为有时候,根节点的parent会被设置成为自己 + if (id.equals(children.getPid())) { + parent.initChildren(); + if (0L == parent.getPid()) { + children.setTopMenu(parent.getName()); + children.setLevel(2); + } else { + children.setTopMenu(parent.getTopMenu()); + children.setLevel(parent.getLevel() + 1); + } + parent.getChildren().add(children); + } + } else if (id.equals(parent.getPid())) { + selfIdEqSelfParent.add(id); + } + } + } + } + + private static > void foreachNodesWithTopMenu(List treeList) { + for (E parent : treeList) { + Serializable id = parent.getId(); + for (E children : treeList) { + if (parent != children) { + if (id.equals(children.getPid())) { + if (0L == parent.getPid()) { + children.setTopMenu(parent.getName()); + children.setLevel(2); + } else { + children.setTopMenu(parent.getTopMenu()); + children.setLevel(parent.getLevel() + 1); + } + } + } + } + } + } + + /** + * 生成当前用户的菜单列表 + * + * @param treeList + * @param roleMenuMap + * @return + */ + public static List buildUserTree(List treeList, Map roleMenuMap) { + if (CollUtil.isEmpty(treeList)) { + return Collections.emptyList(); + } + //记录自己是自己的父节点的id集合 + List selfIdEqSelfParent = new ArrayList<>(); + + // 遍历两次 + foreachNodesCheckRole(treeList, selfIdEqSelfParent, roleMenuMap); + foreachNodesWithTopMenu(treeList); + + // 找出根节点集合 + List trees = new ArrayList<>(); + + List allIds = treeList.stream().map(TreeEntity::getId).collect(Collectors.toList()); + for (MenuRoleVO baseNode : treeList) { + if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) { + baseNode.setPid(null); + if (roleMenuMap.containsKey(baseNode.getId())) { + baseNode.setTopMenu(baseNode.getName()); + checkRedirect(baseNode); + trees.add(baseNode); + } else { + if (baseNode.getSize() > 0) { + baseNode.setTopMenu(baseNode.getName()); + checkRedirect(baseNode); + trees.add(baseNode); + } + } + } + } + return trees; + } + + //判断角色权限用 不用父级 + private static void foreachNodesCheckRoleWithoutParent(List treeList, List selfIdEqSelfParent, Map roleMenuMap) { + for (MenuRoleVO parent : treeList) { + Serializable id = parent.getId(); + for (MenuRoleVO children : treeList) { + if (parent != children) { + //parent != children 这个来判断自己的孩子不允许是自己,因为有时候,根节点的parent会被设置成为自己 + if (id.equals(children.getPid())) { + parent.initChildren(); + + if (!roleMenuMap.containsKey(children.getId())) { + continue; + } + + if (0L == parent.getPid()) { + children.setTopMenu(parent.getName()); + children.setLevel(2); + } else { + children.setTopMenu(parent.getTopMenu()); + children.setLevel(parent.getLevel() + 1); + } + parent.getChildren().add(children); + } + } else if (id.equals(parent.getPid())) { + selfIdEqSelfParent.add(id); + } + + if (roleMenuMap.containsKey(children.getId())) { + children.setHasPermission(1); + } + } + } + } + + //判断当前登录权限用 + private static void foreachNodesCheckRole(List treeList, List selfIdEqSelfParent, Map roleMenuMap) { + for (MenuRoleVO parent : treeList) { + Serializable id = parent.getId(); + for (MenuRoleVO children : treeList) { + if (parent != children) { + //parent != children 这个来判断自己的孩子不允许是自己,因为有时候,根节点的parent会被设置成为自己 + if (id.equals(children.getPid())) { + parent.initChildren(); + + if (!roleMenuMap.containsKey(children.getId())) { + continue; + } + + if (0L == parent.getPid()) { + children.setTopMenu(parent.getName()); + children.setLevel(2); + } else { + children.setTopMenu(parent.getTopMenu()); + children.setLevel(parent.getLevel() + 1); + } + parent.getChildren().add(children); + } + } else if (id.equals(parent.getPid())) { + selfIdEqSelfParent.add(id); + } + } + + //1层 2层 再加一下 + for (MenuRoleVO children : treeList) { + if (parent != children) { + if (id.equals(children.getPid())) { + + if (parent.getChildren().contains(children) || + children.getSize() == 0) { + continue; + } + + if (0L == parent.getPid()) { + children.setTopMenu(parent.getName()); + children.setLevel(2); + } else { + children.setTopMenu(parent.getTopMenu()); + children.setLevel(parent.getLevel() + 1); + } + parent.getChildren().add(children); + } + } + } + } + } + + /** + * 动态判断redirect + * + * @param baseNode + */ + private static void checkRedirect(MenuRoleVO baseNode) { + checkMenuRedirect(baseNode, baseNode.getChildren()); + } + + /** + * 判断菜单是否需要跳转 + * + * @param baseNode / + * @param menus / + * @return / + */ + private static Boolean checkMenuRedirect(MenuRoleVO baseNode, Set menus) { + if (baseNode.getSize() > 0) { + for (MenuRoleVO menu : menus) { + //如果是大屏类型的 2层-3层 直接跳转 + if (menu.getPath().endsWith("Datav")) { + baseNode.setRedirect(menu.getComponent()); + return Boolean.TRUE; + } + + //如果是不隐藏 和 没有子菜单 跳转 + if (menu.getSize() == 0 && 0 == menu.getHidden()) { + baseNode.setRedirect(menu.getComponent()); + return Boolean.TRUE; + } + } + + //一轮没有合适的菜单 去三级菜单找 + for (MenuRoleVO menu : menus) { + if (menu.getSize() > 0) { + if (checkMenuRedirect(baseNode, menu.getChildren())) { + return Boolean.TRUE; + } + } + } + } + + return Boolean.FALSE; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserAuthController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserAuthController.java new file mode 100644 index 0000000..09521a1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserAuthController.java @@ -0,0 +1,95 @@ +package com.ningdatech.carapi.user.controller; + +import java.io.IOException; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ningdatech.basic.model.ApiResponse; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.user.security.auth.constant.SessionTimeConstant; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * @author LiuXinXin + * @date 2022/9/29 下午3:26 + */ + +@RestController +@RequestMapping("/api/v1/user/auth") +@Api(tags = {"用户鉴权-相关接口"}) +@RequiredArgsConstructor +public class UserAuthController { + + private final ObjectMapper objectMapper; + + @Value("${login.public-key}") + private String publicKey; + + //@PostMapping(value = "/login/password", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + //@ApiOperation(value = "账号密码的登陆方式") + //@ApiImplicitParams({ + // @ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "form", dataType = "String"), + // @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "form", dataType = "String")}) + //public void loginByUsernameAndPassword(@RequestParam("username") String username, + // @RequestParam("password") String password) { + // // 不实现任何内容,只是为了出api文档 + //} + + @PostMapping(value = "/login/password", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + @ApiOperation(value = "账号密码验证码的登陆方式") + @ApiImplicitParams({ + @ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "form", dataType = "String"), + @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "form", dataType = "String"), + @ApiImplicitParam(name = "verificationCode",value = "验证码",required = true,paramType = "form",dataType = "String")}) + public void loginByUsernameAndPasswordAndVerificationCode(@RequestParam("username") String username, + @RequestParam("password") String password,@RequestParam("verificationCode") String verificationCode) { + // 不实现任何内容,只是为了出api文档 + } + + /** + * 当需要身份认证时,跳转到这里 + * + * @param response + * @return + * @throws IOException + */ + @RequestMapping("/auth-require") + @CrossOrigin(originPatterns = "*", allowCredentials = "true", maxAge = 3600) + public void requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(401); + response.getWriter().write(objectMapper.writeValueAsString( + ApiResponse.of(401, "用户未登录", null))); + } + + @RequestMapping("/invalid-session") + @CrossOrigin(originPatterns = "*", allowCredentials = "true", maxAge = 3600) + public void invalidSession(HttpServletRequest request, HttpServletResponse response) throws IOException { + response.setContentType("application/json;charset=UTF-8"); + Cookie cookie = new Cookie(CommonConstant.COOKIE_KEY, null); + String cookiePath = request.getContextPath() + "/"; + cookie.setPath(cookiePath); + cookie.setMaxAge(SessionTimeConstant.SESSION_TIME_SECONDS); + response.addCookie(cookie); + response.setStatus(401); + response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.of(401, "用户未登录", null))); + } + + @ApiOperation(value = "获取登录信息加密公钥", notes = "获取登录信息加密公钥") + @GetMapping("/get-public-key") + public String getPublicKey(){ + return publicKey; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserInfoController.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserInfoController.java new file mode 100644 index 0000000..e63e6b8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/controller/UserInfoController.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.user.controller; + +import com.ningdatech.carapi.user.manage.UserInfoManage; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author liuxinxin + * @date 2022/10/24 下午2:14 + */ + +@RestController +@RequestMapping("/api/v1/user/info") +@Api(tags = {"用户信息-相关接口"}) +@RequiredArgsConstructor +public class UserInfoController { + private final UserInfoManage userInfoManage; + + + @ApiOperation(value = "获取用户基本信息") + @PostMapping("/get/basic-info") + public UserBasicInfoVO getUserBasicInfo() { + return userInfoManage.getUserBasicInfo(); + } + + @ApiOperation(value = "创建企业信息员账号信息") + @GetMapping("/create/companyUser") + public String createCompanyUser() { + return userInfoManage.createCompanyUser(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserAuth.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserAuth.java new file mode 100644 index 0000000..6f22724 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserAuth.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.user.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author LiuXinXin + * @since 2022-09-30 + */ +@TableName("nd_user_auth") +@Data +public class NdUserAuth implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private LocalDateTime createOn; + + private LocalDateTime updateOn; + + private Long userId; + + private String authType; + + private String identifier; + + private String credential; + + private Boolean isAvailable; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfo.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfo.java new file mode 100644 index 0000000..0b31e5c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfo.java @@ -0,0 +1,128 @@ +package com.ningdatech.carapi.user.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_user_info") +@ApiModel(value = "User", description = "用户") +@AllArgsConstructor +@Builder +public class NdUserInfo extends BaseEntity implements Serializable { + + @TableId(value = "id",type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + @NotEmpty(message = "用户姓名不能为空") + @Size(max = 50, message = "用户姓名长度不能超过50") + @TableField(value = "username", condition = LIKE) + private String username; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + @TableField("company_id") + private Long companyId; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + @TableField("industry") + private Long industry; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + @Size(max = 20, message = "手机长度不能超过20") + @TableField(value = "mobile", condition = LIKE) + private String mobile; + + /** + * 最后登录时间 + */ + @ApiModelProperty(value = "最后登录时间") + @TableField("last_login_time") + private LocalDateTime lastLoginTime; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + @Size(max = 50, message = "职位长度不能超过50") + @TableField(value = "position", condition = LIKE) + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + @Size(max = 50, message = "科室长度不能超过50") + @TableField(value = "section_office", condition = LIKE) + private String sectionOffice; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称") + @Size(max = 50, message = "昵称长度不能超过50") + @TableField(value = "nick_name", condition = LIKE) + private String nickName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 200, message = "备注不能超过200") + @TableField(value = "remark", condition = LIKE) + private String remark; + + /** + * 用户是否可登录 + */ + @ApiModelProperty(value = "用户是否可登录") + @TableField("can_login") + private Integer canLogin; + + /** + * 用户登录验证码 + */ + @ApiModelProperty(value = "用户登录验证码") + @TableField("verification_code") + private String verificationCode; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfoJoin.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfoJoin.java new file mode 100644 index 0000000..db6ec7b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/NdUserInfoJoin.java @@ -0,0 +1,148 @@ +package com.ningdatech.carapi.user.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nd_user_info") +@ApiModel(value = "User", description = "用户") +@AllArgsConstructor +@Builder +public class NdUserInfoJoin extends BaseEntity implements Serializable { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + @NotEmpty(message = "用户姓名不能为空") + @Size(max = 50, message = "用户姓名长度不能超过50") + @TableField(value = "username", condition = LIKE) + private String username; + + /** + * 帐号 + */ + @ApiModelProperty(value = "帐号") +// @TableField(exist = false) + private String account; + + /** + * 角色ID + */ + @ApiModelProperty(value = "角色ID") +// @TableField(exist = false) + private Long roleId; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + @TableField("company_id") + private Long companyId; + + /** + * 区域id + */ + @ApiModelProperty(value = "区域id") + @TableField("region_id") + private Long regionId; + + /** + * 企业名称 + */ + @ApiModelProperty(value = "企业名称") + private String companyName; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + @TableField("industry") + private Long industry; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + @Size(max = 20, message = "手机长度不能超过20") + @TableField(value = "mobile", condition = LIKE) + private String mobile; + + /** + * 最后登录时间 + */ + @ApiModelProperty(value = "最后登录时间") + @TableField("last_login_time") + private LocalDateTime lastLoginTime; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + @Size(max = 50, message = "职位长度不能超过50") + @TableField(value = "position", condition = LIKE) + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + @Size(max = 50, message = "科室长度不能超过50") + @TableField(value = "section_office", condition = LIKE) + private String sectionOffice; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称") + @Size(max = 50, message = "昵称长度不能超过50") + @TableField(value = "nick_name", condition = LIKE) + private String nickName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + @Size(max = 200, message = "备注不能超过200") + @TableField(value = "remark", condition = LIKE) + private String remark; + + /** + * 用户是否可登录 + */ + @ApiModelProperty(value = "用户是否可登录") + @TableField("can_login") + private Integer canLogin; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/ReqCreateAccountPO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/ReqCreateAccountPO.java new file mode 100644 index 0000000..27b1159 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/entity/ReqCreateAccountPO.java @@ -0,0 +1,48 @@ +package com.ningdatech.carapi.user.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/9 上午9:31 + */ +@Data +@ApiModel(description = "新建账号入参") +public class ReqCreateAccountPO { + + @ApiModelProperty("用户姓名") + private String nickName; + + @ApiModelProperty("所属企业") + private String companyName; + + @ApiModelProperty("所属企业唯一标识") + private String companyId; + + @ApiModelProperty("公司行业") + private String corporateIndustry; + + @ApiModelProperty("用户角色") + private String role; + + @ApiModelProperty("登陆账号") + private String userName; + + @ApiModelProperty("登陆密码") + private String password; + + @ApiModelProperty("职位") + private String position; + + @ApiModelProperty("科室") + private String department; + + @ApiModelProperty("手机号码") + private String phoneNo; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/manage/UserInfoManage.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/manage/UserInfoManage.java new file mode 100644 index 0000000..c5cc3f1 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/manage/UserInfoManage.java @@ -0,0 +1,113 @@ +package com.ningdatech.carapi.user.manage; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.company.enumeration.CompanyTypeEnum; +import com.ningdatech.carapi.datascope.model.DataScopeDto; +import com.ningdatech.carapi.datascope.provider.DataScopeContext; +import com.ningdatech.carapi.driver.constant.UserCanLoginEnum; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.model.vo.UserBasicInfoVO; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.ningdatech.carapi.user.util.LoginUserUtil; + +import lombok.RequiredArgsConstructor; + +/** + * @author liuxinxin + * @date 2022/10/24 下午2:15 + */ +@Component +@RequiredArgsConstructor +public class UserInfoManage { + + private final IDriverInfoService iDriverInfoService; + + private final CompanyService companyService; + + private final INdUserInfoService userInfoService; + + private final PasswordEncoder passwordEncoder; + private final INdUserAuthService ndUserAuthService; + private final UserRoleService userRoleService; + + public UserBasicInfoVO getUserBasicInfo() { + UserBasicInfoVO userBasicInfoVO = new UserBasicInfoVO(); + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + Long userId = user.getUserId(); + Long roleId = user.getRoleId(); + Optional dataScope = DataScopeContext.getDataScope(user.getDataScope()); + if(dataScope.isPresent()){ + userBasicInfoVO.setMaxRegion(dataScope.get().getMaxRegion()); + } + userBasicInfoVO.setNickName(user.getNickName()); + // 获取驾驶员信息 + DriverInfo driverInfo = iDriverInfoService.getOne(Wrappers.lambdaQuery(DriverInfo.class) + .eq(DriverInfo::getUserId, userId)); + if (Objects.nonNull(driverInfo)) { + userBasicInfoVO.setDriverId(driverInfo.getId()); + } + userBasicInfoVO.setUserId(userId); + userBasicInfoVO.setRoleId(roleId); + userBasicInfoVO.setCompanyId(user.getCompanyId()); + userBasicInfoVO.setCompanyName(user.getCompanyName()); + userBasicInfoVO.setRegionId(user.getRegionId()); + userBasicInfoVO.setRegionName(user.getRegionName()); + + return userBasicInfoVO; + } + + public String createCompanyUser() { + // 创建各企业企业信息员账号 + Map companyMap = companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + List companyList = companyService.list().stream().filter(c -> c.getCompanyType().equals(CompanyTypeEnum.PRODUCT_BU.getCode()) + || c.getCompanyType().equals(CompanyTypeEnum.LOGISTICS_BU.getCode()) + || c.getCompanyType().equals(CompanyTypeEnum.OTHER.getCode())).collect(Collectors.toList()); + for (Company company : companyList) { + Long companyId = company.getId(); + Company companyInfo = companyMap.get(companyId); + NdUserInfo userInfo = new NdUserInfo(); + userInfo.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode()); + userInfo.setUsername(companyInfo.getName()); + userInfo.setCompanyId(companyId); + userInfo.setCreateOn(LocalDateTime.now()); + userInfo.setUpdateOn(LocalDateTime.now()); + userInfoService.save(userInfo); + + Long userId = userInfo.getId(); + NdUserAuth userAuth = new NdUserAuth(); + userAuth.setUserId(userId); + userAuth.setIdentifier(companyInfo.getName()); + userAuth.setCredential(passwordEncoder.encode("123456Aa")); + userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + userAuth.setIsAvailable(true); + ndUserAuthService.save(userAuth); + + UserRole userRole = new UserRole(); + userRole.setUserId(userId); + userRole.setRoleId(UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId()); + userRoleService.save(userRole); + } + return "创建完成"; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.java new file mode 100644 index 0000000..6a7af5d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.user.mapper; + +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +public interface NdUserAuthMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.xml new file mode 100644 index 0000000..fd275df --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserAuthMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoJoinMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoJoinMapper.java new file mode 100644 index 0000000..05a4805 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoJoinMapper.java @@ -0,0 +1,32 @@ +package com.ningdatech.carapi.user.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.user.entity.NdUserInfoJoin; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface NdUserInfoJoinMapper extends BaseMapper { + + String QUERY_SQL = "SELECT u.*, c.name as company_name,c.region_id, " + + " a.identifier as account,ur.role_id FROM nd_user_info AS u " + + " LEFT JOIN nd_company_info AS c ON u.company_id = c.id " + + " LEFT JOIN nd_user_role AS ur ON u.id = ur.user_id " + + " LEFT JOIN nd_user_auth AS a ON u.id = a.user_id "; + String WRAPPER_SQL = "SELECT * from ( " + QUERY_SQL + " ) AS q ${ew.customSqlSegment}"; + + @Select(WRAPPER_SQL) + Page pageJoin(Page page, @Param("ew") LambdaQueryWrapper wrapper); + + @Select(WRAPPER_SQL) + NdUserInfoJoin oneJoin(@Param("ew") LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.java new file mode 100644 index 0000000..3b59e62 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.user.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.sys.entity.dto.GlobalUserPageDTO; +import com.ningdatech.carapi.sys.entity.dto.PageParamsDTO; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author PoffyZhang + * @since 2022-09-30 + */ +public interface NdUserInfoMapper extends BaseMapper { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.xml b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.xml new file mode 100644 index 0000000..88751b5 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/mapper/NdUserInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/NdUserInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/NdUserInfoVO.java new file mode 100644 index 0000000..4b2fb97 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/NdUserInfoVO.java @@ -0,0 +1,99 @@ +package com.ningdatech.carapi.user.model.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ningdatech.carapi.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.LocalDateTime; + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +/** + *

+ * + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +@Data +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@ApiModel(value = "User", description = "用户") +@AllArgsConstructor +@Builder +public class NdUserInfoVO extends BaseEntity implements Serializable { + + @TableId(value = "id",type = IdType.AUTO) + private Long id; + + private static final long serialVersionUID = 1L; + + /** + * 用户姓名 + */ + @ApiModelProperty(value = "用户姓名") + private String username; + + /** + * 企业 + */ + @ApiModelProperty(value = "企业id") + private Long companyId; + + /** + * 公司行业 + */ + @ApiModelProperty(value = "行业id") + private Long industry; + + /** + * 手机 + */ + @ApiModelProperty(value = "手机") + private String mobile; + + /** + * 最后登录时间 + */ + @ApiModelProperty(value = "最后登录时间") + private LocalDateTime lastLoginTime; + + /** + * 职位 + */ + @ApiModelProperty(value = "职位") + private String position; + + /** + * 科室 + */ + @ApiModelProperty(value = "科室") + private String sectionOffice; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称") + private String nickName; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + @ApiModelProperty(value = "数据范围") + private Integer dataScope; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/UserBasicInfoVO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/UserBasicInfoVO.java new file mode 100644 index 0000000..42c4ae4 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/model/vo/UserBasicInfoVO.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.user.model.vo; + +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liuxinxin + * @date 2022/10/24 下午2:21 + */ +@ApiModel("用户基础信息VO") +@Data +public class UserBasicInfoVO { + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("角色id") + private Long roleId; + + @ApiModelProperty("用户昵称") + private String nickName; + + @ApiModelProperty("驾驶员id(只有驾驶员信息时才有)") + private Long driverId; + + @ApiModelProperty("企业ID") + private Long companyId; + + @ApiModelProperty("企业名称") + private String companyName; + + @ApiModelProperty("区域ID") + private Long regionId; + + @ApiModelProperty("区域名称") + private String regionName; + + @ApiModelProperty("该用户所能看到的最大区域 权限") + private RegionDTO maxRegion; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthProperties.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthProperties.java new file mode 100644 index 0000000..465814d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthProperties.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.user.security.auth; + +import com.ningdatech.basic.factory.PropertySourceFactory; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @Author LiuXinXin + * @Date 2020/8/1 6:06 下午 + * @Version 1.0 + **/ +@Configuration +@PropertySource(value = "classpath:security/auth-${spring.profiles.active}.yml" + , encoding = "utf-8", factory = PropertySourceFactory.class) +@ConfigurationProperties(prefix = "security.auth") +@Component +@Data +public class AuthProperties { + + private String authRequireUrl; + + private String invalidSessionUrl; + + private String passwordLoginUrl; + + private String logoutUrl; + + private List ignoreAuthUrls; + + private List ignoreCsrfUrls; + + public String[] getIgnoreAuthUrlsArray() { + String[] stringArray = new String[ignoreAuthUrls.size()]; + return ignoreAuthUrls.toArray(stringArray); + } + + public String[] getIgnoreCsrfUrlsArray() { + String[] stringArray = new String[ignoreCsrfUrls.size()]; + return ignoreCsrfUrls.toArray(stringArray); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthenticationBeanConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthenticationBeanConfig.java new file mode 100644 index 0000000..c276b0f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/AuthenticationBeanConfig.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.user.security.auth; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * @Author LiuXinXin + * @Date 2020/7/28 1:00 下午 + * @Version 1.0 + **/ +@Configuration +public class AuthenticationBeanConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SessionRegistry sessionRegistry() { + return new SessionRegistryImpl(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/WebSecurityConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/WebSecurityConfig.java new file mode 100644 index 0000000..bae5241 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/WebSecurityConfig.java @@ -0,0 +1,66 @@ +package com.ningdatech.carapi.user.security.auth; + +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.user.security.auth.handler.DefaultExpiredSessionStrategy; +import com.ningdatech.carapi.user.security.auth.password.UsernamePasswordAuthSecurityConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; + +/** + * @Author LiuXinXin + * @Date 2020/7/28 4:14 下午 + * @Version 1.0 + */ +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private AuthProperties authProperties; + + @Autowired + private UsernamePasswordAuthSecurityConfig usernamePasswordAuthSecurityConfig; + + @Autowired + @Qualifier(value = "defaultLogoutSuccessHandler") + private LogoutSuccessHandler logoutSuccessHandler; + + @Autowired + private DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.formLogin() + .loginPage(authProperties.getAuthRequireUrl()) + .and().apply(usernamePasswordAuthSecurityConfig) + .and() + .authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest() + .authenticated().and() + // 防止固定会话攻击,Spring security的默认配置就是如此: + // 登陆成功之后会创建一个新的会话,然后将旧的session信息复制到新的session中(客户端的sessionId变了) + .sessionManagement().invalidSessionUrl(authProperties.getInvalidSessionUrl()).sessionFixation() + .migrateSession() + // .invalidSessionStrategy(defaultInvalidSessionStrategy) + .maximumSessions(10) + .maxSessionsPreventsLogin(true) + .expiredSessionStrategy(defaultExpiredSessionStrategy) + .and().and() + .logout().logoutUrl(authProperties.getLogoutUrl()).logoutSuccessHandler(logoutSuccessHandler) + .deleteCookies(CommonConstant.COOKIE_KEY) + .and().headers().frameOptions().sameOrigin() + // .and() + // .cors().configurationSource(corsConfigurationSource()) + .and() + // .csrf().disable(); + // 开启csrf验证,需要前端同步传入token + //.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) + .csrf().csrfTokenRepository(new CookieCsrfTokenRepository()) + .ignoringAntMatchers(authProperties.getIgnoreCsrfUrlsArray()); + // http.anonymous().authenticationFilter(availableUserAuthenticationFilter); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/config/RedisSessionConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/config/RedisSessionConfig.java new file mode 100644 index 0000000..930f41f --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/config/RedisSessionConfig.java @@ -0,0 +1,57 @@ +package com.ningdatech.carapi.user.security.auth.config; + +import cn.hutool.core.util.StrUtil; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.common.constant.CommonConstant; +import com.ningdatech.carapi.user.security.auth.constant.SessionTimeConstant; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.data.redis.RedisIndexedSessionRepository; +import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; +import org.springframework.session.web.http.CookieHttpSessionIdResolver; +import org.springframework.session.web.http.DefaultCookieSerializer; + +/** + *

+ * 设置session的过期时间为一天 + *

+ * + * @Author LiuXinXin + * @Date 2020/7/29 9:46 上午 + * @Version 1.0 + **/ +@Configuration +@EnableRedisHttpSession( + maxInactiveIntervalInSeconds = RedisSessionConfig.SESSION_TIMEOUT, + redisNamespace = RedisSessionConfig.REDIS_NAMESPACE +) +public class RedisSessionConfig { + + static final int SESSION_TIMEOUT = 24 * 60 * 60 * 10; + + static final String REDIS_NAMESPACE = "#{redisSessionConfig.getRedisNamespace()}"; + + @Value("${nd.cache.def.keyPrefix:}") + private String keyPrefix; + + public String getRedisNamespace() { + return (StrUtil.isBlank(keyPrefix) ? StrPool.EMPTY : keyPrefix + StrPool.COLON) + RedisIndexedSessionRepository.DEFAULT_NAMESPACE; + } + + + @Bean + public CookieHttpSessionIdResolver sessionIdResolver() { + // 创建 CookieHttpSessionIdResolver 对象 + CookieHttpSessionIdResolver sessionIdResolver = new CookieHttpSessionIdResolver(); + + // 创建 DefaultCookieSerializer 对象 + DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); + + // 设置到 sessionIdResolver 中 + sessionIdResolver.setCookieSerializer(cookieSerializer); + cookieSerializer.setCookieName(CommonConstant.COOKIE_KEY); + cookieSerializer.setCookieMaxAge(SessionTimeConstant.SESSION_TIME_SECONDS); + return sessionIdResolver; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/AuthTypeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/AuthTypeEnum.java new file mode 100644 index 0000000..6d9c5b7 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/AuthTypeEnum.java @@ -0,0 +1,47 @@ +package com.ningdatech.carapi.user.security.auth.constant; + +/** + * @author LiuXinXin + * @date 2021/7/30 下午2:10 + */ + +public enum AuthTypeEnum { + + /** + * 手机 + 密码的认证方式 + */ + PHONE_PASSWORD("phone_password"), + + /** + * 子账号 账号 + 密码的认证方式 + */ + ACCOUNT_PASSWORD("account_password"); + + private final String key; + + AuthTypeEnum(String key) { + this.key = key; + } + + public static boolean contains(String key) { + for (AuthTypeEnum value : AuthTypeEnum.values()) { + if (key.equals(value.getKey())) { + return true; + } + } + return false; + } + + public String getKey() { + return key; + } + + public static AuthTypeEnum of(String key) { + for (AuthTypeEnum value : AuthTypeEnum.values()) { + if (key.equals(value.getKey())) { + return value; + } + } + throw new RuntimeException(String.format("invalid AuthTypeEnum = %s", key)); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/SessionTimeConstant.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/SessionTimeConstant.java new file mode 100644 index 0000000..be45f0d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/constant/SessionTimeConstant.java @@ -0,0 +1,12 @@ +package com.ningdatech.carapi.user.security.auth.constant; + +/** + * @Author LiuXinXin + * @Date 2022/2/17 12:59 上午 + * @Version 1.0 + **/ +public class SessionTimeConstant { + + public static final Integer SESSION_TIME_SECONDS = 24 * 60 * 60 * 10; + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/errorcode/AuthErrorCodeEnum.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/errorcode/AuthErrorCodeEnum.java new file mode 100644 index 0000000..df57286 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/errorcode/AuthErrorCodeEnum.java @@ -0,0 +1,36 @@ +package com.ningdatech.carapi.user.security.auth.errorcode; + + +import com.ningdatech.carapi.common.exception.AppErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author LiuXinXin + * @date 2021/7/30 上午10:59 + */ + +@AllArgsConstructor +@Getter +public enum AuthErrorCodeEnum { + /** + * 登录用户名 + */ + USERNAME_OR_PASSWORD_ERROR(AppErrorCode.AUTH.getCode() + "100000" + , "登陆时用户名或者密码错误"), + + ACCOUNT_ALREADY_EXIST_WHEN_REGISTER(AppErrorCode.AUTH.getCode() + "100001" + , "账号已经存在"), + + SESSION_EXPIRED(AppErrorCode.AUTH.getCode() + "100002" + ,"用户session过期,登陆状态失效"); + + + private final String code; + + private final String msg; + + public Integer getCode() { + return Integer.valueOf(code); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/facade/UserAuthLoginFacade.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/facade/UserAuthLoginFacade.java new file mode 100644 index 0000000..775f752 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/facade/UserAuthLoginFacade.java @@ -0,0 +1,55 @@ +package com.ningdatech.carapi.user.security.auth.facade; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.security.auth.model.dto.UserFullInfoDTO; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * @author LiuXinXin + * @date 2022/9/30 上午9:54 + */ +@Component +@RequiredArgsConstructor +public class UserAuthLoginFacade { + private final INdUserAuthService iNdUserAuthService; + private final INdUserInfoService iNdUserInfoService; + + private final CompaniesCacheHelper companiesCacheHelper; + + public UserFullInfoDTO queryUserInfoInPasswordAuth(String username) { + // 获取用户鉴权信息 + NdUserAuth userAuth = iNdUserAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getIdentifier, username) + .eq(NdUserAuth::getAuthType, AuthTypeEnum.ACCOUNT_PASSWORD.getKey())); + if (Objects.isNull(userAuth)) { + return null; + } + + // 获取用户详情信息 + NdUserInfo userInfo = iNdUserInfoService.getOne(Wrappers.lambdaQuery(NdUserInfo.class) + .eq(NdUserInfo::getId, userAuth.getUserId())); + UserFullInfoDTO userFullInfoDto = new UserFullInfoDTO(); + userFullInfoDto.setUserId(userInfo.getId()); + userFullInfoDto.setNickName(userInfo.getUsername()); + userFullInfoDto.setIdentifier(userAuth.getIdentifier()); + userFullInfoDto.setCredential(userAuth.getCredential()); + userFullInfoDto.setCompanyId(userInfo.getCompanyId()); + CompanyDTO company = companiesCacheHelper.getById(userInfo.getCompanyId()); + if(Objects.nonNull(company)){ + userFullInfoDto.setCompanyName(company.getName()); + userFullInfoDto.setRegionId(company.getRegionId()); + userFullInfoDto.setRegionName(company.getRegionName()); + } + return userFullInfoDto; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultExpiredSessionStrategy.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultExpiredSessionStrategy.java new file mode 100644 index 0000000..0d089b0 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultExpiredSessionStrategy.java @@ -0,0 +1,41 @@ +package com.ningdatech.carapi.user.security.auth.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ningdatech.basic.model.ApiResponse; +import com.ningdatech.carapi.user.security.auth.errorcode.AuthErrorCodeEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.web.session.SessionInformationExpiredEvent; +import org.springframework.security.web.session.SessionInformationExpiredStrategy; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @Author LiuXinXin + * @Date 2020/8/20 11:15 上午 + * @Version 1.0 + **/ +@Component +public class DefaultExpiredSessionStrategy implements SessionInformationExpiredStrategy { + + public static final Logger LOG = LoggerFactory.getLogger(DefaultExpiredSessionStrategy.class); + + @Autowired + private ObjectMapper objectMapper; + + @Override + public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent) + throws IOException, ServletException { + if (LOG.isInfoEnabled()) { + LOG.info("session已经过期"); + } + HttpServletResponse response = sessionInformationExpiredEvent.getResponse(); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString( + ApiResponse.of(AuthErrorCodeEnum.SESSION_EXPIRED.getCode(), AuthErrorCodeEnum.SESSION_EXPIRED.getMsg(), null))); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginFailureHandler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginFailureHandler.java new file mode 100644 index 0000000..a225d62 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginFailureHandler.java @@ -0,0 +1,46 @@ +package com.ningdatech.carapi.user.security.auth.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ningdatech.basic.model.ApiResponse; +import com.ningdatech.carapi.user.security.auth.errorcode.AuthErrorCodeEnum; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:32 下午 + * @Version 1.0 + **/ +@Component("defaultLoginFailureHandler") +public class DefaultLoginFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + response.setContentType("application/json;charset=UTF-8"); + int errorCode; + String errorMsg; + // 所有的认证异常都可以在这里添加,目前只支持用户名密码错误异常 + if (exception instanceof BadCredentialsException || exception instanceof UsernameNotFoundException) { + errorCode = AuthErrorCodeEnum.USERNAME_OR_PASSWORD_ERROR.getCode(); + errorMsg = "帐号密码错误"; + } else { + errorCode = ApiResponse.ERROR_CODE; + errorMsg = exception.getMessage(); + } + response.setStatus(400); + response.getWriter() + .write(objectMapper.writeValueAsString(ApiResponse.of(errorCode, errorMsg, null))); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginSuccessHandler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginSuccessHandler.java new file mode 100644 index 0000000..f156e0d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLoginSuccessHandler.java @@ -0,0 +1,38 @@ +package com.ningdatech.carapi.user.security.auth.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ningdatech.basic.model.ApiResponse; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:32 下午 + * @Version 1.0 + **/ +@Component("defaultLoginSuccessHandler") +@Primary +public class DefaultLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { + + @Autowired + private ObjectMapper objectMapper; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, ServletException { + response.setContentType("application/json;charset=UTF-8"); + //设置cookie + UserInfoDetails principal = (UserInfoDetails) authentication.getPrincipal(); + response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofSuccess())); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLogoutSuccessHandler.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLogoutSuccessHandler.java new file mode 100644 index 0000000..07791e9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/handler/DefaultLogoutSuccessHandler.java @@ -0,0 +1,28 @@ +package com.ningdatech.carapi.user.security.auth.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ningdatech.basic.model.ApiResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 默认的退出成功处理器 + */ +@Component("defaultLogoutSuccessHandler") +public class DefaultLogoutSuccessHandler implements LogoutSuccessHandler { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException { + // 退出成功后返回 和前端约定的Json + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofSuccess())); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/UserInfoDetails.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/UserInfoDetails.java new file mode 100644 index 0000000..4b7653b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/UserInfoDetails.java @@ -0,0 +1,69 @@ +package com.ningdatech.carapi.user.security.auth.model; + +import com.ningdatech.basic.auth.AbstractLoginUser; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author LiuXinXin + * @date 2022/8/1 下午3:32 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class UserInfoDetails extends AbstractLoginUser implements UserDetails { + + private static final long serialVersionUID = 1L; + + private String nickName; + + private String password; + + private List roleList; + + private Integer dataScope; + + private Long roleId; + + private Long companyId; + + private String companyName; + + private Long regionId; + + private String regionName; + + /** + * 获取用户权限 + */ + @Override + public Collection getAuthorities() { + return new ArrayList<>(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/dto/UserFullInfoDTO.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/dto/UserFullInfoDTO.java new file mode 100644 index 0000000..b1c614c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/model/dto/UserFullInfoDTO.java @@ -0,0 +1,30 @@ +package com.ningdatech.carapi.user.security.auth.model.dto; + +import lombok.Data; + +/** + * @author LiuXinXin + * @date 2022/9/30 上午10:10 + */ +@Data +public class UserFullInfoDTO { + + /** + * userId + */ + private Long userId; + + private String nickName; + + private String identifier; + + private String credential; + + private Long companyId; + + private String companyName; + + private Long regionId; + + private String regionName; +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/PasswordLoginUserDetailServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/PasswordLoginUserDetailServiceImpl.java new file mode 100644 index 0000000..5325dd9 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/PasswordLoginUserDetailServiceImpl.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.user.security.auth.password; + +import java.util.ArrayList; +import java.util.Objects; + +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import com.ningdatech.carapi.common.helper.UserInfoHelper; +import com.ningdatech.carapi.sys.entity.Role; +import com.ningdatech.carapi.sys.entity.vo.UserInfoVO; +import com.ningdatech.carapi.sys.manage.UserManage; +import com.ningdatech.carapi.sys.service.RoleService; +import com.ningdatech.carapi.user.security.auth.facade.UserAuthLoginFacade; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.carapi.user.security.auth.model.dto.UserFullInfoDTO; + +import lombok.RequiredArgsConstructor; + +/** + * @author LiuXinXin + * @date 2022/9/30 上午9:49 + */ + +@Service("passwordLoginUserDetailService") +@RequiredArgsConstructor +public class PasswordLoginUserDetailServiceImpl implements UserDetailsService { + + private final UserAuthLoginFacade userAuthLoginFacade; + private final UserManage userManage; + private final RoleService roleService; + private final UserInfoHelper userInfoHelper; + + @Override + public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UserFullInfoDTO userFullInfoDTO = userAuthLoginFacade.queryUserInfoInPasswordAuth(username); + if (Objects.isNull(userFullInfoDTO)) { + throw new UsernameNotFoundException(String.format("%s user not exist", username)); + } + + UserInfoDetails userInfoDetails = new UserInfoDetails(); + userInfoDetails.setUserId(userFullInfoDTO.getUserId()); + userInfoDetails.setNickName(userFullInfoDTO.getNickName()); + userInfoDetails.setUsername(userFullInfoDTO.getNickName()); + userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier()); + userInfoDetails.setPassword(userFullInfoDTO.getCredential()); + userInfoDetails.setCompanyId(userFullInfoDTO.getCompanyId()); + userInfoDetails.setCompanyName(userFullInfoDTO.getCompanyName()); + userInfoDetails.setRoleList(new ArrayList<>()); + userInfoDetails.setRegionId(userFullInfoDTO.getRegionId()); + userInfoDetails.setRegionName(userFullInfoDTO.getRegionName()); + + //UserInfoVO userInfoVO = userManage.queryDetails(userFullInfoDTO.getUserId()); + UserInfoVO userInfoVO = userInfoHelper.getUserDetailByUserId(userFullInfoDTO.getUserId()); + //即便是多个 暂时取一个 + if(Objects.isNull(userInfoVO) || Objects.isNull(userInfoVO.getRole())){ + return userInfoDetails; + } + userInfoDetails.setRoleId(userInfoVO.getRole()); + Role role = roleService.getById(userInfoVO.getRole()); + if(Objects.isNull(role) || Objects.isNull(role.getDataScope())){ + return userInfoDetails; + } + userInfoDetails.setDataScope(role.getDataScope()); + return userInfoDetails; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthFilter.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthFilter.java new file mode 100644 index 0000000..21ec46e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthFilter.java @@ -0,0 +1,87 @@ +package com.ningdatech.carapi.user.security.auth.password; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.RSA; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:46 下午 + * @Version 1.0 + **/ + +public class UsernamePasswordAuthFilter extends AbstractAuthenticationProcessingFilter { + + private String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAPhUV8sdOC5MB0m6qHAIJfI0vhkO+wZpO8srcmiMjbzCoaCSznlxZKLVv8MXMB5fgEHqTlrXThZlmCXHJRdZvIpBLNCYu5dd8T0NlmxuioiOVH3dU7Cd1a78B901oZ0NJ5TdcmtQQQQNIq/eKdeOpb+x9NGCLBy7vaOJtYYPTKQIDAQAB"; + + private String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIA+FRXyx04LkwHSbqocAgl8jS+GQ77Bmk7yytyaIyNvMKhoJLOeXFkotW/wxcwHl+AQepOWtdOFmWYJcclF1m8ikEs0Ji7l13xPQ2WbG6KiI5Ufd1TsJ3VrvwH3TWhnQ0nlN1ya1BBBA0ir94p146lv7H00YIsHLu9o4m1hg9MpAgMBAAECgYBdgueFNZ62/iGX9oXTbNDfcf7RZKoJcsq+PrRF3+83a2CjrCz2/MaCDPkgQwU4HWFVdS6sZ/z13Dla+hAKn+4X2v2pL3ryrcjlY35yreB6NlCjbsRbEACZEvhaps/taLu4IkZ/CQ6msCz8XHkBOMlWDF36kIxS3BFRmu3mWjHCcQJBAMAfZfKZxWX6lJBWLSy3QhV8jIo9+e+kk4VQRZUXgLJf1IwkxcHMmp4OSgcJp5do1YcoBlPQNdaWta0bt7TQL0cCQQCq4X+jc8Ikn/fxeeIpE75CqveHiF86KU7HKVfpjqiZATIeIbBe8eeC1pXlgX6TmMTWFQSRHWVzmVSwRaRhuYIPAkBd5jquksdu60T3MpdLtpm+5KvP2TCyFq7fRndrwhvtknbQtBxPdw/O1k8KF4bosp1CPKazCh12LxzGabikz+d7AkA0iKbo5UmmYNelEUeKQVuYu17l9/LuuoxRhlBUqVsDzu5NfSXvyobWHopuyGTVk33QIx4ITvVFmLoEhySGNrXZAkBktQR+kMStI0SlcMKYFKmQXu78W97p8soVvhP1AndvPiI9keO3UxO7cUjcPRROmcGUU39yGHYlJvu1Krj6+GI1"; + + private boolean postOnly = true; + + private final String SMS_VERIFICATION_CODE_FEILD = "verificationCode"; + + // ~ Constructors + // =================================================================================================== + + public UsernamePasswordAuthFilter(String processingUrl) { + super(new AntPathRequestMatcher(processingUrl, "POST")); + } + // ~ Methods + // ======================================================================================================== + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException { + + if (postOnly && !HttpMethod.POST.toString().equals(request.getMethod())) { + throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); + } + RSA rsa = new RSA(privateKey, publicKey); + String usernameParameter = "username"; + String username = request.getParameter(usernameParameter); + // 将获取到的经过RSA公钥加密后的用户名解密 + String userName = rsa.decryptStr(username, KeyType.PrivateKey); + + String passwordParameter = "password"; + String password = request.getParameter(passwordParameter); + // 将获取到的经过RSA公钥加密后的密码解密 + String pwd = rsa.decryptStr(password, KeyType.PrivateKey); + String verificationCode = request.getParameter(SMS_VERIFICATION_CODE_FEILD); + // 将获取到的经过RSA公钥加密后的验证码解密 + String verifyCode = rsa.decryptStr(verificationCode, KeyType.PrivateKey); + + if (StringUtils.isBlank(userName) || StringUtils.isBlank(pwd)) { + throw new UsernameNotFoundException("帐号密码不能为空!"); + } + userName = userName.trim(); + pwd = pwd.trim(); + verifyCode = verifyCode.trim(); + + try { + UsernamePasswordAuthToken authRequest = new UsernamePasswordAuthToken(userName, pwd, verifyCode); + // Allow subclasses to set the "details" property + setDetails(request, authRequest); + return this.getAuthenticationManager().authenticate(authRequest); + } catch (AuthenticationException e) { + throw e; + } catch (Exception e) { + throw new InternalAuthenticationServiceException(e.getMessage(), e); + } + } + + protected void setDetails(HttpServletRequest request, UsernamePasswordAuthToken authRequest) { + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthProvider.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthProvider.java new file mode 100644 index 0000000..587769a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthProvider.java @@ -0,0 +1,149 @@ +package com.ningdatech.carapi.user.security.auth.password; + +import java.util.Objects; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.sys.contants.UserLoginConstant; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:55 下午 + * @Version 1.0 + **/ +public class UsernamePasswordAuthProvider implements AuthenticationProvider { + + private UserDetailsService userDetailsService; + private PasswordEncoder passwordEncoder; + private INdUserInfoService ndUserInfoService; + + private INdUserAuthService ndUserAuthService; + + private CachePlusOps cachePlusOps; + + private Boolean smsCheck; + + public UsernamePasswordAuthProvider() { + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if (!(authentication instanceof UsernamePasswordAuthToken)) { + throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken"); + } + UsernamePasswordAuthToken authenticationToken = (UsernamePasswordAuthToken)authentication; + // 获取用户名信息 + String userName = (String) authenticationToken.getPrincipal(); + + //验证短信验证码 + if(smsCheck){ + smsCheck(authenticationToken, userName); + } + + UserDetails user = userDetailsService.loadUserByUsername((String)authenticationToken.getPrincipal()); + if (user == null) { + throw new InternalAuthenticationServiceException("获取不到用户信息!"); + } + additionalAuthenticationChecks(user, authenticationToken); + // 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 + return new UsernamePasswordAuthToken(user, user.getPassword(), user.getAuthorities(),null); + } + + private void smsCheck(UsernamePasswordAuthToken authenticationToken, String userName) { + String code = authenticationToken.getVerificationCode(); + + if (Objects.isNull(code)){ + throw new BizException("验证码未传!"); + } + code = code.trim(); + + // 将用户输入的验证码与redis中对应手机号的验证码做比较,判断验证码是否过期 + CacheKey key = new CacheKey(UserLoginConstant.RedisKey.USER_LOGIN + userName); + String verificationCode = cachePlusOps.get(key); + + if (Objects.isNull(verificationCode)){ + throw new BizException("验证码失效,请重新获取!"); + } + + if (!code.equals(verificationCode)){ + throw new BizException("验证码输入错误,请重新输入!"); + } + } + + protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthToken authentication) + throws AuthenticationException { + String presentedUsername = authentication.getPrincipal().toString(); + NdUserAuth userAuth = ndUserAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getIdentifier, presentedUsername)); + if (!userAuth.getIsAvailable()){ + throw new BizException("账号已被禁用,禁止登录!"); + } + + if (authentication.getCredentials() == null) { + throw new BadCredentialsException("login fail! password is null"); + } + String presentedPassword = authentication.getCredentials().toString(); + if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { + throw new BadCredentialsException("login fail! password is error"); + } + } + + @Override + public boolean supports(Class authentication) { + return UsernamePasswordAuthToken.class.isAssignableFrom(authentication); + } + + public void setUserDetailsService(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + public void setNdUserInfoService(INdUserInfoService ndUserInfoService) { + this.ndUserInfoService = ndUserInfoService; + } + + public void setCachePlusOps(CachePlusOps cachePlusOps) { + this.cachePlusOps = cachePlusOps; + } + + public INdUserInfoService getNdUserInfoService() { + return ndUserInfoService; + } + + public CachePlusOps getCachePlusOps() { + return cachePlusOps; + } + + public INdUserAuthService getNdUserAuthService() { + return ndUserAuthService; + } + + public void setNdUserAuthService(INdUserAuthService ndUserAuthService) { + this.ndUserAuthService = ndUserAuthService; + } + + public Boolean getSmsCheck() { + return smsCheck; + } + + public void setSmsCheck(Boolean smsCheck) { + this.smsCheck = smsCheck; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthSecurityConfig.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthSecurityConfig.java new file mode 100644 index 0000000..b108c3e --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthSecurityConfig.java @@ -0,0 +1,84 @@ +package com.ningdatech.carapi.user.security.auth.password; + +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.user.security.auth.AuthProperties; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.stereotype.Component; + +/** + * 账号密码登陆的认证配置 + */ +@Component +public class UsernamePasswordAuthSecurityConfig + extends SecurityConfigurerAdapter { + + @Autowired + @Qualifier(value = "defaultLoginSuccessHandler") + protected AuthenticationSuccessHandler defaultLoginSuccessHandler; + + @Autowired + @Qualifier(value = "defaultLoginFailureHandler") + protected AuthenticationFailureHandler defaultLoginFailureHandler; + + @Autowired + @Qualifier(value = "passwordLoginUserDetailService") + private UserDetailsService passwordLoginUserDetailService; + + @Autowired + private INdUserInfoService ndUserInfoService; + + @Autowired + private CachePlusOps cachePlusOps; + + @Autowired + private INdUserAuthService ndUserAuthService; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private AuthProperties authProperties; + + private AuthenticationManager authenticationManager; + + @Value("${login.sms-check}") + private boolean smsChcek; + + @Override + public void configure(HttpSecurity http) throws Exception { + UsernamePasswordAuthFilter usernamePasswordAuthFilter = + new UsernamePasswordAuthFilter(authProperties.getPasswordLoginUrl()); + authenticationManager = http.getSharedObject(AuthenticationManager.class); + usernamePasswordAuthFilter.setAuthenticationManager(authenticationManager); + usernamePasswordAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); + usernamePasswordAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); + + UsernamePasswordAuthProvider authenticationProvider = new UsernamePasswordAuthProvider(); + authenticationProvider.setUserDetailsService(passwordLoginUserDetailService); + authenticationProvider.setNdUserInfoService(ndUserInfoService); + authenticationProvider.setCachePlusOps(cachePlusOps); + authenticationProvider.setNdUserAuthService(ndUserAuthService); + authenticationProvider.setSmsCheck(smsChcek); + // 确保对密码进行加密的encoder和解密的encoder相同 + authenticationProvider.setPasswordEncoder(passwordEncoder); + http.authenticationProvider(authenticationProvider).addFilterAfter(usernamePasswordAuthFilter, + UsernamePasswordAuthenticationFilter.class); + } + + public AuthenticationManager getAuthenticationManager() { + return authenticationManager; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthToken.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthToken.java new file mode 100644 index 0000000..7505a5d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/security/auth/password/UsernamePasswordAuthToken.java @@ -0,0 +1,75 @@ +package com.ningdatech.carapi.user.security.auth.password; + +import java.util.Collection; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.SpringSecurityCoreVersion; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:52 下午 + * @Version 1.0 + **/ +public class UsernamePasswordAuthToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + private final Object principal; + + private final Object credentials; + + private final String verificationCode; + + /** + * This constructor can be safely used by any code that wishes to create a + * UsernamePasswordAuthenticationToken, as the {@link #isAuthenticated()} will return + * false. + */ + public UsernamePasswordAuthToken(String principal, String credentials, String verificationCode) { + super(null); + this.principal = principal; + this.credentials = credentials; + this.verificationCode = verificationCode; + setAuthenticated(false); + } + + public UsernamePasswordAuthToken(Object principal, Object credentials, + Collection authorities, String verificationCode) { + super(authorities); + this.principal = principal; + this.credentials = credentials; + this.verificationCode = verificationCode; + // must use super, as we override + super.setAuthenticated(true); + } + + public Object getCredentials() { + return this.credentials; + } + + @Override + public Object getPrincipal() { + return this.principal; + } + + public String getVerificationCode() { + return verificationCode; + } + + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + if (isAuthenticated) { + throw new IllegalArgumentException( + "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + } + super.setAuthenticated(false); + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + } + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserAuthService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserAuthService.java new file mode 100644 index 0000000..5e77a8a --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserAuthService.java @@ -0,0 +1,16 @@ +package com.ningdatech.carapi.user.service; + +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +public interface INdUserAuthService extends IService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoJoinService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoJoinService.java new file mode 100644 index 0000000..0304c2c --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoJoinService.java @@ -0,0 +1,24 @@ +package com.ningdatech.carapi.user.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.carapi.sys.entity.dto.UserSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.UserUpdateDTO; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.entity.NdUserInfoJoin; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +public interface INdUserInfoJoinService extends IService { + + Page pageJoin(Page page,LambdaQueryWrapper wrapper); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoService.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoService.java new file mode 100644 index 0000000..5b04cc8 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/INdUserInfoService.java @@ -0,0 +1,45 @@ +package com.ningdatech.carapi.user.service; + +import com.ningdatech.carapi.sys.entity.dto.UserSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.UserUpdateDTO; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +public interface INdUserInfoService extends IService { + + /** + * 根据ID删除 + * + * @param ids id + * @return 是否成功 + */ + boolean removeByIdWithCache(List ids); + + /** + * 保存用户 + * + * @param data 用户 + * @param userId 用户id + */ + void save(UserSaveDTO data, Long userId); + + /** + * 修改 + * + * @param data 用户 + * @param userId 用户id + */ + void update(UserUpdateDTO data, Long userId); + + Boolean check(String account,String mobile); +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserAuthServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserAuthServiceImpl.java new file mode 100644 index 0000000..3ad7f85 --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserAuthServiceImpl.java @@ -0,0 +1,20 @@ +package com.ningdatech.carapi.user.service.impl; + +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.mapper.NdUserAuthMapper; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +@Service +public class NdUserAuthServiceImpl extends ServiceImpl implements INdUserAuthService { + +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoJoinServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoJoinServiceImpl.java new file mode 100644 index 0000000..492fb5b --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoJoinServiceImpl.java @@ -0,0 +1,59 @@ +package com.ningdatech.carapi.user.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.datascope.aop.LambdaDataScope; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.UserSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.UserUpdateDTO; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.sys.utils.AuthCacheKeyUtils; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.entity.NdUserInfoJoin; +import com.ningdatech.carapi.user.mapper.NdUserInfoJoinMapper; +import com.ningdatech.carapi.user.mapper.NdUserInfoMapper; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoJoinService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class NdUserInfoJoinServiceImpl extends ServiceImpl + implements INdUserInfoJoinService { + + private final NdUserInfoJoinMapper userInfoJoinMapper; + + @Override + @LambdaDataScope(wrapperIndex = 1) + public Page pageJoin(Page page, LambdaQueryWrapper wrapper) { + return userInfoJoinMapper.pageJoin(page,wrapper); + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoServiceImpl.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoServiceImpl.java new file mode 100644 index 0000000..0b3383d --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/service/impl/NdUserInfoServiceImpl.java @@ -0,0 +1,196 @@ +package com.ningdatech.carapi.user.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BaseUncheckedException; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.exception.code.ExceptionCode; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.driver.constant.UserCanLoginEnum; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.UserSaveDTO; +import com.ningdatech.carapi.sys.entity.dto.UserUpdateDTO; +import com.ningdatech.carapi.sys.helper.UserCacheHelper; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.sys.utils.AuthCacheKeyUtils; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.mapper.NdUserInfoMapper; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +/** + *

+ * 服务实现类 + *

+ * + * @author LiuXinXin + * @since 2022-09-30 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class NdUserInfoServiceImpl extends ServiceImpl implements INdUserInfoService { + private final CachePlusOps cachePlusOps; + private final NdUserInfoMapper userMapper; + private final INdUserAuthService ndUserAuthService; + private final UserRoleService userRoleService; + private final PasswordEncoder passwordEncoder; + + private final UserCacheHelper userCacheHelper; + + private static final String SUPER_ADMIN = "SUPER_ADMIN"; + + /** + * 删除用户时,需要级联删除跟角色相关的一切资源: + * 1,角色本身 + * 2,角色-组织: + * 3,角色-权限(菜单和按钮): + * 4,角色-用户:角色拥有的用户 + * 5,用户-权限: + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdWithCache(List ids) { + if (ids.isEmpty()) { + return true; + } + // 用户 + boolean removeFlag = removeByIds(ids); + + //用户 + ids.forEach(userId -> { + //删除关联表和缓存 + ndUserAuthService.remove(Wrappers.lambdaQuery(NdUserAuth.class).eq(NdUserAuth::getUserId,userId)); + userRoleService.remove(Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getUserId,userId)); + cachePlusOps.del(AuthCacheKeyUtils.userResourceCacheKey(userId)); + userCacheHelper.refresh(userId); + }); + + return removeFlag; + } + + + /** + * 保存用户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void save(UserSaveDTO data, Long userId) { + if(StrUtil.isNotBlank(data.getAccount()) && StrUtil.isNotBlank(data.getMobile()) + && check(data.getAccount(),data.getMobile())){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK, "帐号{},或者手机号{} 输入有误或已经存在", + data.getAccount(),data.getMobile()); + } + + NdUserInfo user = BeanUtil.toBean(data, NdUserInfo.class); + //创建人 最后修改人 + user.setCreateBy(userId); + user.setUpdateBy(userId); + user.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode()); + if(save(user)){ + userCacheHelper.refresh(user.getId()); + } + + NdUserAuth userAuth = new NdUserAuth(); + userAuth.setUserId(user.getId()); + userAuth.setIdentifier(data.getAccount()); + userAuth.setCredential(passwordEncoder.encode(data.getPassword())); + userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + ndUserAuthService.save(userAuth); + + UserRole userRole = new UserRole(); + userRole.setUserId(user.getId()); + userRole.setRoleId(data.getRole()); + userRoleService.save(userRole); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(UserUpdateDTO data, Long userId) { + NdUserInfo userOld = userMapper.selectById(data.getId()); + if(Objects.isNull(userOld)){ + throw new BaseUncheckedException(HttpStatus.HTTP_OK,String.format("修改用户%d 为空",data.getId())); + } + + if(StringUtils.isNotBlank(data.getAccount())){ + Assert.isFalse(checkAccount(data.getAccount(),userOld.getId()), "帐号{} 已经存在",data.getAccount()); + } + + if(StringUtils.isNotBlank(data.getMobile())){ + Assert.isFalse(checkMobile(data.getMobile(),userOld.getId()), "手机号{} 已经存在",data.getMobile()); + } + + NdUserInfo user = BeanUtil.toBean(data, NdUserInfo.class); + //最后修改人 + user.setUpdateBy(userId); + if(updateById(user)){ + userCacheHelper.refresh(userId); + } + + if(StringUtils.isNotBlank(data.getAccount()) + || StringUtils.isNotBlank(data.getPassword())){ + NdUserAuth authOld = ndUserAuthService.getOne(Wrappers.lambdaQuery(NdUserAuth.class) + .eq(NdUserAuth::getUserId, user.getId())); + if(Objects.isNull(authOld)){ + //去新增个auth + if(StringUtils.isBlank(data.getAccount()) + || StringUtils.isBlank(data.getPassword())){ + throw new BizException(ExceptionCode.BASE_VALID_PARAM.getCode(),String.format("修改auth用户%d 号码密码必填",data.getId())); + } + NdUserAuth userAuth = new NdUserAuth(); + userAuth.setUserId(user.getId()); + userAuth.setIdentifier(data.getAccount()); + userAuth.setCredential(passwordEncoder.encode(data.getPassword())); + userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + ndUserAuthService.save(userAuth); + }else{ + if(StringUtils.isNotBlank(data.getAccount())){ + authOld.setIdentifier(data.getAccount()); + } + if(StringUtils.isNotBlank(data.getPassword())){ + authOld.setCredential(passwordEncoder.encode(data.getPassword())); + } + authOld.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + ndUserAuthService.updateById(authOld); + } + } + + if(Objects.nonNull(data.getRole())){ + userRoleService.remove(Wrappers.lambdaQuery(UserRole.class) + .eq(UserRole::getUserId, user.getId())); + UserRole userRole = new UserRole(); + userRole.setUserId(user.getId()); + userRole.setRoleId(data.getRole()); + userRoleService.save(userRole); + } + } + + @Override + public Boolean check(String account,String mobile) { + return ndUserAuthService.count(Wrappers.lambdaQuery(NdUserAuth.class).eq(NdUserAuth::getIdentifier, account)) > 0 || + super.count(Wrappers.lambdaQuery(NdUserInfo.class).eq(NdUserInfo::getMobile,mobile)) > 0; + } + + private Boolean checkMobile(String mobile,Long id) { + return super.count(Wrappers.lambdaQuery(NdUserInfo.class).ne(NdUserInfo::getId,id).eq(NdUserInfo::getMobile,mobile)) > 0; + } + private Boolean checkAccount(String account,Long id) { + return ndUserAuthService.count(Wrappers.lambdaQuery(NdUserAuth.class).ne(NdUserAuth::getUserId,id) + .eq(NdUserAuth::getIdentifier, account)) > 0; + } +} diff --git a/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/util/LoginUserUtil.java b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/util/LoginUserUtil.java new file mode 100644 index 0000000..8e274af --- /dev/null +++ b/ningda-yw-api/src/main/java/com/ningdatech/carapi/user/util/LoginUserUtil.java @@ -0,0 +1,17 @@ +package com.ningdatech.carapi.user.util; + +import com.ningdatech.basic.auth.AbstractLoginUserUtil; +import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails; + +/** + * @Author liuxinxin + * @Date 2022/9/30 12:26 下午 + * @Version 1.0 + **/ +public class LoginUserUtil extends AbstractLoginUserUtil { + + public static UserInfoDetails loginUserDetail() { + return getLoginUserPrincipal(); + } + +} diff --git a/ningda-yw-api/src/main/resources/application-dev.yml b/ningda-yw-api/src/main/resources/application-dev.yml new file mode 100644 index 0000000..5b10340 --- /dev/null +++ b/ningda-yw-api/src/main/resources/application-dev.yml @@ -0,0 +1,147 @@ +server: + port: 28088 + servlet: + context-path: /yw + session: + cookie: + http-only: true + tomcat: + connection-timeout: 600000 +logging: + config: classpath:logback-spring.xml + file: + path: logs +spring: + mvc: + pathmatch: + matching-strategy: ant_path_matcher + session: + store-type: redis + redis: + namespace: "spring:session" + redis: + timeout: 15000 + host: 47.98.125.47 + port: 26379 + database: 5 + password: Ndkj1234 + jedis: + pool: + max-active: 200 + max-idle: 500 + min-idle: 8 + max-wait: 10000 + application: + name: cm + jackson: + default-property-inclusion: non_null + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://47.98.125.47:3306/nd-yw-road?serverTimezone=Asia/Shanghai&characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false + username: root + password: NingdaKeji123! + hikari: + minimum-idle: 5 + maximum-pool-size: 50 + aop: + proxy-target-class: true + auto: true + mqtt: + url: tcp://202.107.206.254:1883 + username: artemis_22874416_1F3PANKD + password: GKIII7GJ + cleansession: false + clientid: 52dba0a1d3804a5e920afea8f8c06070 + timeout: 1000 + keepalive: 10 + completionTimeout: 3000 + default_topic: artemis/event_msa_alarm/5201154049/admin + servlet: + multipart: + max-file-size: 100MB + +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +swagger: + enabled: true +# redis相关配置 +nd: + cache: + type: REDIS + serializerType: ProtoStuff + cacheNullVal: true + def: + keyPrefix: cm + timeToLive: PT5M + + # 文件存储 + file: + storage-type: ALI_OSS + ali: + protocol: https:// + bucket: devplat + urlPrefix: oss-cn-hangzhou.aliyuncs.com + endpoint: oss-cn-hangzhou.aliyuncs.com + accessKeyId: LTAI4GL7uypycnBjiRn55rMG + accessKeySecret: qwYC7bW9bkStsko7qkLVnToAzj0Y98 + log: + enabled: true + type: DB +task: + host: iZbp13nwyvib53j4j1p2xoZ + switch: + is-open: false #开关 + corn: + task-corn: 0/30 * * * * ? #每隔30秒统计一次车辆在线数 + driver-abnormal-behavior-task-corn: 0 0/1 * * * ? #每隔1分钟更新一次驾驶员异常行为数据 + vehicle-status-task-corn: 0 0/1 * * * ? +sms: + user: hzndkj + siid: HZNDKJYXGS + secretKey: hzndkj12!@ + url: http://115.239.134.217/smsservice/httpservices/capService + interfaceKey: szc2_sms + transmitUrl: http://shuiniche.ningdatech.com/sms/open/api/sms/send-sms-code +car: + interfaceKey: szc2_car_position +open-api: + app-key-secret: + test: test +error-warn: + url: https://oapi.dingtalk.com/robot/send?access_token=bc6b4c0deb3299a045bc511b61cfb0bd516af0c1d1ca221e3bcc97b9d69c2637 +# 日志文件配置 +log: + path: ./logs + info: + file-size: 50MB + max-size: 5 + total-size: 200MB + error: + file-size: 10MB + max-size: 5 + total-size: 50MB + backup: + url: https://claqgz.zcom.gov.cn/cm/open/api/log/backup/download +# url: http://shuiniche.ningdatech.com/cm/open/api/log/backup/download + +login: + sms-check: false + public-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAPhUV8sdOC5MB0m6qHAIJfI0vhkO+wZpO8srcmiMjbzCoaCSznlxZKLVv8MXMB5fgEHqTlrXThZlmCXHJRdZvIpBLNCYu5dd8T0NlmxuioiOVH3dU7Cd1a78B901oZ0NJ5TdcmtQQQQNIq/eKdeOpb+x9NGCLBy7vaOJtYYPTKQIDAQAB + private-key: MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIA+FRXyx04LkwHSbqocAgl8jS+GQ77Bmk7yytyaIyNvMKhoJLOeXFkotW/wxcwHl+AQepOWtdOFmWYJcclF1m8ikEs0Ji7l13xPQ2WbG6KiI5Ufd1TsJ3VrvwH3TWhnQ0nlN1ya1BBBA0ir94p146lv7H00YIsHLu9o4m1hg9MpAgMBAAECgYBdgueFNZ62/iGX9oXTbNDfcf7RZKoJcsq+PrRF3+83a2CjrCz2/MaCDPkgQwU4HWFVdS6sZ/z13Dla+hAKn+4X2v2pL3ryrcjlY35yreB6NlCjbsRbEACZEvhaps/taLu4IkZ/CQ6msCz8XHkBOMlWDF36kIxS3BFRmu3mWjHCcQJBAMAfZfKZxWX6lJBWLSy3QhV8jIo9+e+kk4VQRZUXgLJf1IwkxcHMmp4OSgcJp5do1YcoBlPQNdaWta0bt7TQL0cCQQCq4X+jc8Ikn/fxeeIpE75CqveHiF86KU7HKVfpjqiZATIeIbBe8eeC1pXlgX6TmMTWFQSRHWVzmVSwRaRhuYIPAkBd5jquksdu60T3MpdLtpm+5KvP2TCyFq7fRndrwhvtknbQtBxPdw/O1k8KF4bosp1CPKazCh12LxzGabikz+d7AkA0iKbo5UmmYNelEUeKQVuYu17l9/LuuoxRhlBUqVsDzu5NfSXvyobWHopuyGTVk33QIx4ITvVFmLoEhySGNrXZAkBktQR+kMStI0SlcMKYFKmQXu78W97p8soVvhP1AndvPiI9keO3UxO7cUjcPRROmcGUU39yGHYlJvu1Krj6+GI1 +qyytz: + host: https://gyytz.market.alicloudapi.com + path: /sms/smsSend + appcode: daab49d0cf344614b174a9bf8303b4e2 + smsSignId: 2e65b1bb3d054466b82f0c9d125465e2 + templateId: 908e94ccf08b4476ba6c876d13f084ad +gps: + host: 120.26.44.207 +vedio: + host: 120.26.44.207 +send-urge-warn: + url: http://120.26.44.207:8092/warn/send_urge_warn \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/application-prod.yml b/ningda-yw-api/src/main/resources/application-prod.yml new file mode 100644 index 0000000..df0f7b6 --- /dev/null +++ b/ningda-yw-api/src/main/resources/application-prod.yml @@ -0,0 +1,175 @@ +server: + port: 28088 + servlet: + context-path: /yw + session: + cookie: + http-only: true + tomcat: + connection-timeout: 600000 +logging: + config: classpath:logback-spring.xml + file: + path: logs +spring: + mvc: + pathmatch: + matching-strategy: ant_path_matcher + session: + store-type: redis + redis: + namespace: "spring:session" + redis: + timeout: 15000 + host: r-i5c0beef0e0c5114.redis.rds.internet.cloud-inner.zj.gov.cn + port: 6379 + database: 0 + password: Sswt_8705 + jedis: + pool: + max-active: 200 + max-idle: 500 + min-idle: 8 + max-wait: 10000 + application: + name: cm + jackson: + default-property-inclusion: non_null + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://rm-i5c1i506lf32hy1ox.mysql.rds.internet.cloud-inner.zj.gov.cn/szsnc2?serverTimezone=Asia/Shanghai&characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false + username: u_snc2 + password: Sswt_8705 + hikari: + minimum-idle: 5 + maximum-pool-size: 1000 + connection-timeout: 6000 + idle-timeout: 600000 + max-lifetime: 1800000 + aop: + proxy-target-class: true + auto: true + + mqtt: + url: tcp://202.107.206.254:1883 + username: artemis_22874416_1F3PANKD + password: GKIII7GJ + cleansession: false + clientid: 52dba0a1d3804a5e920afea8f8c06070 + timeout: 1000 + keepalive: 10 + completionTimeout: 3000 + default_topic: artemis/event_msa_alarm/5201154049/admin + servlet: + multipart: + max-file-size: 100MB + +jwt: + header: Authorization + # 令牌前缀 + token-start-with: sfm + # 必须使用最少88位的Base64对该令牌进行编码 + base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= + # 令牌过期时间 此处单位/毫秒 ,默认4小时 + token-validity-in-seconds: 14400000 + # 在线用户key + online-key: sfm-online-token- + # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 + detect: 1800000 + # 续期时间范围,默认1小时,单位毫秒 + renew: 3600000 + +# 内存用户缓存配置 +user-cache: + # 最小回收数(当缓存数量达到此值时进行回收) + min-evictable-size: 512 + # 最小回收间隔 + min-evictable-interval: 1800000 + # 最小存活时间 (ms) + min-idle-time: 3600000 + +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +swagger: + enabled: true +# redis相关配置 +nd: + cache: + type: REDIS + serializerType: ProtoStuff + cacheNullVal: true + def: + keyPrefix: cm + timeToLive: PT5M + # 文件存储 + file: + storage-type: ALI_OSS + ali: + protocol: https:// + bucket: sanzhuangche2 + urlPrefix: oss-cn-hangzhou-zwynet-d01-a.internet.cloud-inner.zj.gov.cn + endpoint: oss-cn-hangzhou-zwynet-d01-a.internet.cloud-inner.zj.gov.cn + accessKeyId: oZFNfkh9YexqzTED + accessKeySecret: xewpDvACMzLQAGvY14fcXjkijBKSNH + log: + enabled: true + type: DB +task: + host: iZi5c01gdwbs8j8r0dzf8lZ + switch: + is-open: true #开关 + corn: + task-corn: 0/30 * * * * ? #每隔30秒统计一次车辆在线数 + driver-abnormal-behavior-task-corn: 0 0/1 * * * ? #每隔1分钟更新一次驾驶员异常行为数据 + vehicle-status-task-corn: 0 0/1 * * * ? +sms: + user: hzndkj + siid: HZNDKJYXGS + secretKey: hzndkj12!@ + url: http://115.239.134.217/smsservice/httpservices/capService + interfaceKey: szc2_sms + transmitUrl: http://shuiniche.ningdatech.com/sms/open/api/sms/send-sms-code +car: + interfaceKey: szc2_car_position +open-api: + app-key-secret: + test: test +error-warn: + url: https://oapi.dingtalk.com/robot/send?access_token=bc6b4c0deb3299a045bc511b61cfb0bd516af0c1d1ca221e3bcc97b9d69c2637 +# 日志文件配置 +log: + path: ./logs + info: + file-size: 50MB + max-size: 5 + total-size: 200MB + error: + file-size: 10MB + max-size: 5 + total-size: 50MB + backup: + url: https://claqgz.zcom.gov.cn/cm/open/api/log/backup/download +# url: http://shuiniche.ningdatech.com/cm/open/api/log/backup/download + +login: + sms-check: true + public-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAPhUV8sdOC5MB0m6qHAIJfI0vhkO+wZpO8srcmiMjbzCoaCSznlxZKLVv8MXMB5fgEHqTlrXThZlmCXHJRdZvIpBLNCYu5dd8T0NlmxuioiOVH3dU7Cd1a78B901oZ0NJ5TdcmtQQQQNIq/eKdeOpb+x9NGCLBy7vaOJtYYPTKQIDAQAB + private-key: MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIA+FRXyx04LkwHSbqocAgl8jS+GQ77Bmk7yytyaIyNvMKhoJLOeXFkotW/wxcwHl+AQepOWtdOFmWYJcclF1m8ikEs0Ji7l13xPQ2WbG6KiI5Ufd1TsJ3VrvwH3TWhnQ0nlN1ya1BBBA0ir94p146lv7H00YIsHLu9o4m1hg9MpAgMBAAECgYBdgueFNZ62/iGX9oXTbNDfcf7RZKoJcsq+PrRF3+83a2CjrCz2/MaCDPkgQwU4HWFVdS6sZ/z13Dla+hAKn+4X2v2pL3ryrcjlY35yreB6NlCjbsRbEACZEvhaps/taLu4IkZ/CQ6msCz8XHkBOMlWDF36kIxS3BFRmu3mWjHCcQJBAMAfZfKZxWX6lJBWLSy3QhV8jIo9+e+kk4VQRZUXgLJf1IwkxcHMmp4OSgcJp5do1YcoBlPQNdaWta0bt7TQL0cCQQCq4X+jc8Ikn/fxeeIpE75CqveHiF86KU7HKVfpjqiZATIeIbBe8eeC1pXlgX6TmMTWFQSRHWVzmVSwRaRhuYIPAkBd5jquksdu60T3MpdLtpm+5KvP2TCyFq7fRndrwhvtknbQtBxPdw/O1k8KF4bosp1CPKazCh12LxzGabikz+d7AkA0iKbo5UmmYNelEUeKQVuYu17l9/LuuoxRhlBUqVsDzu5NfSXvyobWHopuyGTVk33QIx4ITvVFmLoEhySGNrXZAkBktQR+kMStI0SlcMKYFKmQXu78W97p8soVvhP1AndvPiI9keO3UxO7cUjcPRROmcGUU39yGHYlJvu1Krj6+GI1 +qyytz: + host: https://gyytz.market.alicloudapi.com + path: /sms/smsSend + appcode: daab49d0cf344614b174a9bf8303b4e2 + smsSignId: 2e65b1bb3d054466b82f0c9d125465e2 + templateId: 908e94ccf08b4476ba6c876d13f084ad +gps: + host: 10.145.213.161 +vedio: + host: 10.145.213.162 +# 督办调用接口 +send-urge-warn: + url: http://10.145.213.161:8092/warn/send_urge_warn \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/application.yml b/ningda-yw-api/src/main/resources/application.yml new file mode 100644 index 0000000..3d7808a --- /dev/null +++ b/ningda-yw-api/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + profiles: + active: dev diff --git a/ningda-yw-api/src/main/resources/db/migration/V1.sql b/ningda-yw-api/src/main/resources/db/migration/V1.sql new file mode 100644 index 0000000..a167490 --- /dev/null +++ b/ningda-yw-api/src/main/resources/db/migration/V1.sql @@ -0,0 +1,230 @@ +CREATE TABLE `nd_company_product_manage` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `company_name` varchar(500) DEFAULT NULL COMMENT '企业名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `product_name` varchar(255) NOT NULL COMMENT '生产线名称', + `car_start_time` datetime DEFAULT NULL COMMENT '发车日期', + `equipment_status` varchar(255) NOT NULL COMMENT '设备状态', + `sum_product_count` int(12) DEFAULT NULL COMMENT '当天累计生产方量', + `real_product_count` int(12) DEFAULT NULL COMMENT '当天实际生产方量', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='公司生产管理'; + +CREATE TABLE `nd_company_quality_manage` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `file_time` datetime DEFAULT NULL COMMENT '通报年月', + `file_path` varchar(255) NOT NULL COMMENT '文件地址', + `file_name` varchar(255) DEFAULT NULL COMMENT '文件名称', + `download_count` int(12) DEFAULT NULL COMMENT '下载次数', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='质量通报'; + +CREATE TABLE `nd_company_security_product_duty` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `company_id` bigint(20) DEFAULT NULL COMMENT '企业id', + `company_name` varchar(255) DEFAULT NULL COMMENT '企业名称', + `file_path` varchar(255) DEFAULT NULL COMMENT '文件地址', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='安全生产责任体系'; + +CREATE TABLE `nd_company_security_product_regulations` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `regulations_name` varchar(255) DEFAULT NULL COMMENT '制度名称', + `competent_department` varchar(255) DEFAULT NULL COMMENT '主管部门', + `file_path` varchar(255) DEFAULT NULL COMMENT '文件地址', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='安全生产制度体系'; + +CREATE TABLE `nd_company_security_product_execute` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(255) DEFAULT NULL COMMENT '通报名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `file_path` varchar(255) DEFAULT NULL COMMENT '文件地址', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='安全生产制度执行'; + +CREATE TABLE `nd_company_credit_inside` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) DEFAULT NULL COMMENT '企业id', + `company_name` varchar(255) DEFAULT NULL COMMENT '企业名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `driver_id` bigint(20) DEFAULT NULL COMMENT '驾驶员id', + `driver_name` varchar(255) DEFAULT NULL COMMENT '驾驶员名称', + `type` varchar(255) DEFAULT NULL COMMENT '行政监管类别', + `car_no` varchar(255) DEFAULT NULL COMMENT '车牌号', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `check_time` datetime DEFAULT NULL COMMENT '检查日期', + `check_type` bit(1) NOT NULL COMMENT '检查类型(1-联合,0-内部)', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='内部/联合检查'; + +CREATE TABLE `nd_company_credit_deduct` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `company_name` varchar(255) DEFAULT NULL COMMENT '企业名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `type` varchar(255) DEFAULT NULL COMMENT '检查指标类型', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `check_time` datetime DEFAULT NULL COMMENT '检查日期', + `score` int(12) NOT NULL COMMENT '分值', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='平安办扣分'; + +CREATE TABLE `nd_company_credit_reward` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `company_name` varchar(255) DEFAULT NULL COMMENT '企业名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `content` varchar(2000) DEFAULT NULL COMMENT '嘉奖内容', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `reward_time` datetime DEFAULT NULL COMMENT '日期', + `reward_type` bit(1) NOT NULL COMMENT '嘉奖类型(1-行业标杆,0-政府)', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='政府/行业嘉奖'; + +CREATE TABLE `nd_company_credit_level` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `company_name` varchar(255) DEFAULT NULL COMMENT '企业名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `year` varchar(12) DEFAULT NULL COMMENT '年度', + `level` varchar(12) DEFAULT NULL COMMENT '信用等级', + `score` int(12) NOT NULL COMMENT '综合得分', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='信用等级'; + +CREATE TABLE `nd_company_black_list` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `company_name` varchar(500) DEFAULT NULL COMMENT '企业名称', + `region_id` bigint(20) DEFAULT NULL COMMENT '区域id', + `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', + `type` varchar(12) DEFAULT NULL COMMENT '失信类型', + `black_time` datetime DEFAULT NULL COMMENT '失信日期', + `site` varchar(500) DEFAULT NULL COMMENT '地点', + `content` text DEFAULT NULL COMMENT '描述', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='企业失信名单'; + +CREATE TABLE `nd_company_certificate` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `certificate_name` varchar(255) NOT NULL COMMENT '证书名称', + `certificate_content` varchar(1000) NOT NULL COMMENT '证书内容', + `deadline_time` datetime NOT NULL COMMENT '有效日期', + `certificate_path` varchar(255) NOT NULL COMMENT '证书路径', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='企业证书'; + +CREATE TABLE `nd_company_basic_credit` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `registered_capital` varchar(255) DEFAULT NULL COMMENT '注册资金', + `business_term` varchar(255) DEFAULT NULL COMMENT '营业期限', + `create_time` datetime DEFAULT NULL COMMENT '成立日期', + `evaluation_organization` varchar(255) DEFAULT NULL COMMENT '评价机构', + `website` varchar(255) DEFAULT NULL COMMENT '企业网址', + `nature_business` text DEFAULT NULL COMMENT '经营范围', + `business_license_path` varchar(255) DEFAULT NULL COMMENT '营业执照地址', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='企业基础信用信息'; + +CREATE TABLE `nd_company_common_credit` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `company_id` bigint(20) NOT NULL COMMENT '企业id', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `black_list` varchar(255) DEFAULT NULL COMMENT '失信情况(0-失信,1-否)', + `black_list_content` text DEFAULT NULL COMMENT '失信内容', + `dispute_content` text DEFAULT NULL COMMENT '纠纷内容', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_by` varchar(255) DEFAULT NULL COMMENT '修改人', + `create_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', + `update_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='企业公共信用信息'; + + +CREATE TABLE `nd_training_bonus_record` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '继续教育培训奖励表', + `create_on` datetime NOT NULL, + `update_on` datetime DEFAULT NULL, + `driver_id` bigint(20) DEFAULT NULL COMMENT '驾驶员id', + `user_id` bigint(20) DEFAULT NULL COMMENT '用户id', + `material_type` varchar(64) DEFAULT NULL COMMENT '材料类型', + `training_material_id` bigint(20) DEFAULT NULL COMMENT '培训材料id', + `training_organization_id` bigint(20) DEFAULT NULL COMMENT '培训组织id', + `behavior_type` varchar(64) DEFAULT NULL COMMENT '行为类型', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/db/migration/meta_region.sql b/ningda-yw-api/src/main/resources/db/migration/meta_region.sql new file mode 100644 index 0000000..9118b48 --- /dev/null +++ b/ningda-yw-api/src/main/resources/db/migration/meta_region.sql @@ -0,0 +1,157 @@ +/* + Navicat Premium Data Transfer + + Source Server : 宁达科技测试数据库 + Source Server Type : MySQL + Source Server Version : 50736 + Source Host : 47.98.125.47:3306 + Source Schema : nd_cement_truck_dev + + Target Server Type : MySQL + Target Server Version : 50736 + File Encoding : 65001 + + Date: 08/10/2022 13:41:13 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for meta_region +-- ---------------------------- +DROP TABLE IF EXISTS `meta_region`; +CREATE TABLE `meta_region` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `create_on` datetime DEFAULT NULL, + `update_on` datetime DEFAULT NULL, + `region_code` varchar(64) DEFAULT NULL, + `name` varchar(64) DEFAULT NULL, + `level` int(8) DEFAULT NULL, + `parent_code` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=117 DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of meta_region +-- ---------------------------- +BEGIN; +INSERT INTO `meta_region` VALUES (1, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330000', '省本级', 2, '330000'); +INSERT INTO `meta_region` VALUES (2, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330100', '杭州市', 2, '330000'); +INSERT INTO `meta_region` VALUES (3, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330100', '市本级', 3, '330100'); +INSERT INTO `meta_region` VALUES (4, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330102', '上城区', 3, '330100'); +INSERT INTO `meta_region` VALUES (5, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330103', '下城区', 3, '330100'); +INSERT INTO `meta_region` VALUES (6, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330104', '江干区', 3, '330100'); +INSERT INTO `meta_region` VALUES (7, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330105', '拱墅区', 3, '330100'); +INSERT INTO `meta_region` VALUES (8, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330106', '西湖区', 3, '330100'); +INSERT INTO `meta_region` VALUES (9, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330108', '滨江区', 3, '330100'); +INSERT INTO `meta_region` VALUES (10, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330109', '萧山区', 3, '330100'); +INSERT INTO `meta_region` VALUES (11, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330110', '余杭区', 3, '330100'); +INSERT INTO `meta_region` VALUES (12, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330111', '富阳区', 3, '330100'); +INSERT INTO `meta_region` VALUES (13, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330112', '临安区', 3, '330100'); +INSERT INTO `meta_region` VALUES (14, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330122', '桐庐县', 3, '330100'); +INSERT INTO `meta_region` VALUES (15, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330127', '淳安县', 3, '330100'); +INSERT INTO `meta_region` VALUES (16, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330182', '建德市', 3, '330100'); +INSERT INTO `meta_region` VALUES (17, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330113', '临平区', 3, '330100'); +INSERT INTO `meta_region` VALUES (18, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330114', '钱塘区', 3, '330100'); +INSERT INTO `meta_region` VALUES (19, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330200', '宁波市', 2, '330000'); +INSERT INTO `meta_region` VALUES (20, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330200', '市本级', 3, '330200'); +INSERT INTO `meta_region` VALUES (21, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330203', '海曙区', 3, '330200'); +INSERT INTO `meta_region` VALUES (22, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330205', '江北区', 3, '330200'); +INSERT INTO `meta_region` VALUES (23, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330206', '北仑区', 3, '330200'); +INSERT INTO `meta_region` VALUES (24, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330211', '镇海区', 3, '330200'); +INSERT INTO `meta_region` VALUES (25, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330212', '鄞州区', 3, '330200'); +INSERT INTO `meta_region` VALUES (26, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330213', '奉化区', 3, '330200'); +INSERT INTO `meta_region` VALUES (27, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330225', '象山县', 3, '330200'); +INSERT INTO `meta_region` VALUES (28, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330226', '宁海县', 3, '330200'); +INSERT INTO `meta_region` VALUES (29, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330281', '余姚市', 3, '330200'); +INSERT INTO `meta_region` VALUES (30, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330282', '慈溪市', 3, '330200'); +INSERT INTO `meta_region` VALUES (31, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330300', '温州市', 2, '330000'); +INSERT INTO `meta_region` VALUES (32, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330300', '市本级', 3, '330300'); +INSERT INTO `meta_region` VALUES (33, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330302', '鹿城区', 3, '330300'); +INSERT INTO `meta_region` VALUES (34, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330303', '龙湾区', 3, '330300'); +INSERT INTO `meta_region` VALUES (35, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330304', '瓯海区', 3, '330300'); +INSERT INTO `meta_region` VALUES (36, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330305', '洞头区', 3, '330300'); +INSERT INTO `meta_region` VALUES (37, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330324', '永嘉县', 3, '330300'); +INSERT INTO `meta_region` VALUES (38, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330326', '平阳县', 3, '330300'); +INSERT INTO `meta_region` VALUES (39, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330327', '苍南县', 3, '330300'); +INSERT INTO `meta_region` VALUES (40, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330328', '文成县', 3, '330300'); +INSERT INTO `meta_region` VALUES (41, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330329', '泰顺县', 3, '330300'); +INSERT INTO `meta_region` VALUES (42, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330381', '瑞安市', 3, '330300'); +INSERT INTO `meta_region` VALUES (43, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330382', '乐清市', 3, '330300'); +INSERT INTO `meta_region` VALUES (44, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330383', '龙港市', 3, '330300'); +INSERT INTO `meta_region` VALUES (45, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330400', '嘉兴市', 2, '330000'); +INSERT INTO `meta_region` VALUES (46, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330400', '市本级', 3, '330400'); +INSERT INTO `meta_region` VALUES (47, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330402', '南湖区', 3, '330400'); +INSERT INTO `meta_region` VALUES (48, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330411', '秀洲区', 3, '330400'); +INSERT INTO `meta_region` VALUES (49, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330421', '嘉善县', 3, '330400'); +INSERT INTO `meta_region` VALUES (50, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330424', '海盐县', 3, '330400'); +INSERT INTO `meta_region` VALUES (51, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330481', '海宁市', 3, '330400'); +INSERT INTO `meta_region` VALUES (52, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330482', '平湖市', 3, '330400'); +INSERT INTO `meta_region` VALUES (53, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330483', '桐乡市', 3, '330400'); +INSERT INTO `meta_region` VALUES (54, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330500', '湖州市', 2, '330000'); +INSERT INTO `meta_region` VALUES (55, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330500', '市本级', 3, '330500'); +INSERT INTO `meta_region` VALUES (56, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330502', '吴兴区', 3, '330500'); +INSERT INTO `meta_region` VALUES (57, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330503', '南浔区', 3, '330500'); +INSERT INTO `meta_region` VALUES (58, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330521', '德清县', 3, '330500'); +INSERT INTO `meta_region` VALUES (59, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330522', '长兴县', 3, '330500'); +INSERT INTO `meta_region` VALUES (60, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330523', '安吉县', 3, '330500'); +INSERT INTO `meta_region` VALUES (61, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330600', '绍兴市', 2, '330000'); +INSERT INTO `meta_region` VALUES (62, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330600', '市本级', 3, '330600'); +INSERT INTO `meta_region` VALUES (63, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330602', '越城区', 3, '330600'); +INSERT INTO `meta_region` VALUES (64, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330603', '柯桥区', 3, '330600'); +INSERT INTO `meta_region` VALUES (65, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330604', '上虞区', 3, '330600'); +INSERT INTO `meta_region` VALUES (66, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330624', '新昌县', 3, '330600'); +INSERT INTO `meta_region` VALUES (67, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330681', '诸暨市', 3, '330600'); +INSERT INTO `meta_region` VALUES (68, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330683', '嵊州市', 3, '330600'); +INSERT INTO `meta_region` VALUES (69, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330700', '金华市', 2, '330000'); +INSERT INTO `meta_region` VALUES (70, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330700', '市本级', 3, '330700'); +INSERT INTO `meta_region` VALUES (71, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330702', '婺城区', 3, '330700'); +INSERT INTO `meta_region` VALUES (72, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330703', '金东区', 3, '330700'); +INSERT INTO `meta_region` VALUES (73, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330723', '武义县', 3, '330700'); +INSERT INTO `meta_region` VALUES (74, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330726', '浦江县', 3, '330700'); +INSERT INTO `meta_region` VALUES (75, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330727', '磐安县', 3, '330700'); +INSERT INTO `meta_region` VALUES (76, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330781', '兰溪市', 3, '330700'); +INSERT INTO `meta_region` VALUES (77, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330782', '义乌市', 3, '330700'); +INSERT INTO `meta_region` VALUES (78, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330783', '东阳市', 3, '330700'); +INSERT INTO `meta_region` VALUES (79, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330784', '永康市', 3, '330700'); +INSERT INTO `meta_region` VALUES (80, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330800', '衢州市', 2, '330000'); +INSERT INTO `meta_region` VALUES (81, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330800', '市本级', 3, '330800'); +INSERT INTO `meta_region` VALUES (82, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330802', '柯城区', 3, '330800'); +INSERT INTO `meta_region` VALUES (83, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330803', '衢江区', 3, '330800'); +INSERT INTO `meta_region` VALUES (84, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330822', '常山县', 3, '330800'); +INSERT INTO `meta_region` VALUES (85, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330824', '开化县', 3, '330800'); +INSERT INTO `meta_region` VALUES (86, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330825', '龙游县', 3, '330800'); +INSERT INTO `meta_region` VALUES (87, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330881', '江山市', 3, '330800'); +INSERT INTO `meta_region` VALUES (88, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330900', '舟山市', 2, '330000'); +INSERT INTO `meta_region` VALUES (89, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330900', '市本级', 3, '330900'); +INSERT INTO `meta_region` VALUES (90, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330902', '定海区', 3, '330900'); +INSERT INTO `meta_region` VALUES (91, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330903', '普陀区', 3, '330900'); +INSERT INTO `meta_region` VALUES (92, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330921', '岱山县', 3, '330900'); +INSERT INTO `meta_region` VALUES (93, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330922', '嵊泗县', 3, '330900'); +INSERT INTO `meta_region` VALUES (94, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331000', '台州市', 2, '330000'); +INSERT INTO `meta_region` VALUES (95, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331000', '市本级', 3, '331000'); +INSERT INTO `meta_region` VALUES (96, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331002', '椒江区', 3, '331000'); +INSERT INTO `meta_region` VALUES (97, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331003', '黄岩区', 3, '331000'); +INSERT INTO `meta_region` VALUES (98, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331004', '路桥区', 3, '331000'); +INSERT INTO `meta_region` VALUES (99, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331022', '三门县', 3, '331000'); +INSERT INTO `meta_region` VALUES (100, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331023', '天台县', 3, '331000'); +INSERT INTO `meta_region` VALUES (101, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331024', '仙居县', 3, '331000'); +INSERT INTO `meta_region` VALUES (102, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331081', '温岭市', 3, '331000'); +INSERT INTO `meta_region` VALUES (103, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331082', '临海市', 3, '331000'); +INSERT INTO `meta_region` VALUES (104, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331083', '玉环市', 3, '331000'); +INSERT INTO `meta_region` VALUES (105, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331100', '丽水市', 2, '330000'); +INSERT INTO `meta_region` VALUES (106, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331100', '市本级', 3, '331100'); +INSERT INTO `meta_region` VALUES (107, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331102', '莲都区', 3, '331100'); +INSERT INTO `meta_region` VALUES (108, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331121', '青田县', 3, '331100'); +INSERT INTO `meta_region` VALUES (109, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331122', '缙云县', 3, '331100'); +INSERT INTO `meta_region` VALUES (110, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331123', '遂昌县', 3, '331100'); +INSERT INTO `meta_region` VALUES (111, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331124', '松阳县', 3, '331100'); +INSERT INTO `meta_region` VALUES (112, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331125', '云和县', 3, '331100'); +INSERT INTO `meta_region` VALUES (113, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331126', '庆元县', 3, '331100'); +INSERT INTO `meta_region` VALUES (114, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331127', '景宁畲族自治县', 3, '331100'); +INSERT INTO `meta_region` VALUES (115, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '331181', '龙泉市', 3, '331100'); +INSERT INTO `meta_region` VALUES (116, '2022-10-08 12:02:23', '2022-10-08 12:02:23', '330000', '浙江省', 1, '-1'); +COMMIT; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/ningda-yw-api/src/main/resources/integration/zwdd-dev.yml b/ningda-yw-api/src/main/resources/integration/zwdd-dev.yml new file mode 100644 index 0000000..775749e --- /dev/null +++ b/ningda-yw-api/src/main/resources/integration/zwdd-dev.yml @@ -0,0 +1,15 @@ +# 专有钉钉 +integration: + zwdd: + enabled: true + # 扫码 + app-auth-key: file-manage_dingoa-zte2LbiAfIj + app-auth-secret: H794aFZf271QbfUr50pbBpBTlXSrWIP71q9RTR34 + + #免登/获取信息 + app-key: file-manage-4Mjx9358wuxjyYFjY3 + app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O + + #专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729 + tenantId: 31141 + domain: openplatform.dg-work.cn \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/integration/zwdd-prod.yml b/ningda-yw-api/src/main/resources/integration/zwdd-prod.yml new file mode 100644 index 0000000..775749e --- /dev/null +++ b/ningda-yw-api/src/main/resources/integration/zwdd-prod.yml @@ -0,0 +1,15 @@ +# 专有钉钉 +integration: + zwdd: + enabled: true + # 扫码 + app-auth-key: file-manage_dingoa-zte2LbiAfIj + app-auth-secret: H794aFZf271QbfUr50pbBpBTlXSrWIP71q9RTR34 + + #免登/获取信息 + app-key: file-manage-4Mjx9358wuxjyYFjY3 + app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O + + #专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729 + tenantId: 31141 + domain: openplatform.dg-work.cn \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/irs/车牌号.xlsx b/ningda-yw-api/src/main/resources/irs/车牌号.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1443da47db15590de8ce7f7ba10687027ab343b3 GIT binary patch literal 38096 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 + + + + + + + + + + ${logPath}/info.log + + ${logPath}/info-%d{yyyyMMdd}-%i.log + + ${infoFileSize} + + ${infoMaxSize} + ${infoTotalSize} + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n + + + UTF-8 + + + + + + ERROR + + ${logPath}/error.log + + ${logPath}/error-%d{yyyyMMdd}-%i.log + + ${errorFileSize} + + ${errorMaxSize} + ${errorTotalSize} + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n + + + UTF-8 + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n + + UTF-8 + + + DEBUG + + + + + + + + + diff --git a/ningda-yw-api/src/main/resources/security/auth-dev.yml b/ningda-yw-api/src/main/resources/security/auth-dev.yml new file mode 100644 index 0000000..7aba25f --- /dev/null +++ b/ningda-yw-api/src/main/resources/security/auth-dev.yml @@ -0,0 +1,45 @@ +security: + auth: + auth-require-url: /api/v1/user/auth/auth-require + invalid-session-url: /api/v1/user/auth/invalid-session + password-login-url: /api/v1/user/auth/login/password + password-verificationCode-login-url: /api/v1/user/auth/login/password/verificationCode + logout-url: /api/v1/user/auth/logout + ignore-auth-urls: + - /v2/api-docs + - /swagger-ui.html + - /webjars/** + - /swagger-resources/** + - /webjars/ + - /api/v1/user/auth/register + - /api/v1/user/auth/auth-require + - /api/v1/user/auth/invalid-session + - /api/v1/user/auth/login/password + - /api/v1/user/auth/forget-password + - /api/v1/user/auth/get-public-key + - /doc.html + - /ok.html + - /open/api/** + ignore-csrf-urls: + - /api/v1/user/auth/** + - /v2/api-docs + - /swagger-ui.html + - /webjars/** + - /swagger-resources/** + - /webjars/ + - /doc.html + - /ok.html + - /api/v1/** + - /optLog/** + - /file/** + - /api/user/** + - /api/role/** + - /api/menu/** + - /api/company/** + - /api/operator/** + - /api/archives/** + - /api/safe/** + - /api/qrcode/** + - /api/industry/** + - /api/car-rpt/** + - /open/api/** \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/security/auth-prod.yml b/ningda-yw-api/src/main/resources/security/auth-prod.yml new file mode 100644 index 0000000..ac4ba41 --- /dev/null +++ b/ningda-yw-api/src/main/resources/security/auth-prod.yml @@ -0,0 +1,44 @@ +security: + auth: + auth-require-url: /api/v1/user/auth/auth-require + invalid-session-url: /api/v1/user/auth/invalid-session + password-login-url: /api/v1/user/auth/login/password + logout-url: /api/v1/user/auth/logout + ignore-auth-urls: + - /v2/api-docs + - /swagger-ui.html + - /webjars/** + - /swagger-resources/** + - /webjars/ + - /api/v1/user/auth/register + - /api/v1/user/auth/auth-require + - /api/v1/user/auth/invalid-session + - /api/v1/user/auth/login/password + - /api/v1/user/auth/forget-password + - /api/v1/user/auth/get-public-key + - /doc.html + - /ok.html + - /open/api/** + ignore-csrf-urls: + - /api/v1/user/auth/** + - /v2/api-docs + - /swagger-ui.html + - /webjars/** + - /swagger-resources/** + - /webjars/ + - /doc.html + - /ok.html + - /api/v1/** + - /optLog/** + - /file/** + - /api/user/** + - /api/role/** + - /api/menu/** + - /api/company/** + - /api/operator/** + - /api/archives/** + - /api/safe/** + - /api/qrcode/** + - /api/industry/** + - /api/car-rpt/** + - /open/api/** \ No newline at end of file diff --git a/ningda-yw-api/src/main/resources/template/散装水泥、预拌混凝土、干混砂浆物流装备统计年报表(空).xls b/ningda-yw-api/src/main/resources/template/散装水泥、预拌混凝土、干混砂浆物流装备统计年报表(空).xls new file mode 100644 index 0000000000000000000000000000000000000000..aa04800b5d95f81599d236c66c164656505ac719 GIT binary patch literal 23552 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 Z`&aRbk}Uks!HNwj0z-tz#nC+C{vYsXf{p+H literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/浙江省散装水泥中转库进出量快报.xls b/ningda-yw-api/src/main/resources/template/浙江省散装水泥中转库进出量快报.xls new file mode 100644 index 0000000000000000000000000000000000000000..e38b167dc6c06953232318d375107f84cd9dd049 GIT binary patch literal 10375 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 WM_wB0=VC>D>TQF0lCvOx#{EAOhwQHa literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/温州、台州、舟山市散装水泥使用量快报(空).xls b/ningda-yw-api/src/main/resources/template/温州、台州、舟山市散装水泥使用量快报(空).xls new file mode 100644 index 0000000000000000000000000000000000000000..41c173dce76908d3ec7ef7af3c19a8a818e34462 GIT binary patch literal 10280 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 N^I$O* literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/车辆事故数据(空).xlsx b/ningda-yw-api/src/main/resources/template/车辆事故数据(空).xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f67a030c6b01bab4d1dc8ae2f4e274237c4e14bc GIT binary patch literal 9861 zcma)CWmp_r(#Bl|g1fs0cXxMpcXtQ@2DjjZph<8D5HtjL4GszJ?(Td;vU??acc1V4 z=$`3*tE&4wUDc4Wn^+Ey@qu>cT&GcVtX-K+~DeEbhy!S2AAWMkx{c8Qb$#o#0ggbbX{*jw6V>syx*wSKm; zv-TKTy}~C1`D4LA`XFSP@tdx)wE+Arr=ei}x-QH%p4+T!MSlDD`R?)2y;TfnZ8uZ31E)3f$2gU zhmop~m=GKTX!>4N>l4(0^k!Kn;a~En#bMEtI^X zozr6#_8Gu6!7D2F5M++Rh~K^R#N?=RwlYjv}qGa1D=1m z8Zda-s?VfM6z;Mrl|U>t=qyV`O@Tx_+YbBS@cB_>zvn5*Tan6&LQ%3yfaJ)P_%ZAr z|L?pT7JPQ32l0*u;{C*+96w>tz|0OjoTxQXrL)MGn~T&ppOOk@&z-C1R@;Kd!3fWr*8 zcpPVnb%`NDcJ7NA>$i)GUHFtzpX7UM&Co=tw~dDyNW^Dg1=VM3?M%4J)x|9Ki!R0M z9JJ0vrzhG%Ns){dcV+N-mQN7FnVP!C?lFJ#-P#v=%}rQ)OkBTs_0R>(~Dsp_CW{37!F*!=hUNyZYhB+yAz4$J)Zr=SAQ!Vsp{=sYzKASmo%a@+AAqv zu)``(t2HW7?s@1#kSx#Nj;H(gnz>G07mn`Jxj$VS`*Er{d@kO5N2n!qk8_QrwmDna zIC<4}HyoB(;c;Ve3;xXQKL-{_5Vzj;KSRnt15kbeyqsL^+^j7u+d)I0%hn!mV60ZT$YJKB}n&R8XJ8*@am&Aqu?I;tj| z0FtOv$#J`UyKxlE8Q#C89LW?|3I0qb8nj0qj=?HtT@^W6kyBdA>I&?V2xilK1J{fm z^l6J&Xo#*Sr#ls}^Ey;i+?w8k=Yk*2NhU6IP*$}qE%}5%&U*u2DLHdlJn3`@F(7bz zBOR+xJN@+PyRnU|*=O?;ChAajN$∋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 literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/车辆事故数据.xlsx b/ningda-yw-api/src/main/resources/template/车辆事故数据.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5b38bca38136521e05f789738bd7c2d596abaeb1 GIT binary patch literal 10070 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 literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/运营商考核详情.docx b/ningda-yw-api/src/main/resources/template/运营商考核详情.docx new file mode 100644 index 0000000000000000000000000000000000000000..824422dce6b992aa488e07933331b175987a7d4c GIT binary patch literal 11492 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 R4&{ZG{PpF1dZKy-{SQ5+FN^>H literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/非禁现区域散装水泥销售使用情况统计年报表(空).xls b/ningda-yw-api/src/main/resources/template/非禁现区域散装水泥销售使用情况统计年报表(空).xls new file mode 100644 index 0000000000000000000000000000000000000000..d462edf623b88819eb55c60875a30fec4635663c GIT binary patch literal 22016 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 literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/main/resources/template/预拌砂浆生产及废弃物综合利用情况统计月报表(空).xls b/ningda-yw-api/src/main/resources/template/预拌砂浆生产及废弃物综合利用情况统计月报表(空).xls new file mode 100644 index 0000000000000000000000000000000000000000..fd7bc512e1741bdbe1ff5c0c7681cea2ac68abc1 GIT binary patch literal 23040 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 Rf#3sZ90EK6;Q#-*{|8&r@fZLA literal 0 HcmV?d00001 diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/AppTests.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/AppTests.java new file mode 100644 index 0000000..b98c838 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/AppTests.java @@ -0,0 +1,19 @@ +package com.ningdatech.carapi; + +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + *

+ * AppRunTests + *

+ * + * @author WendyYang + * @since 19:27 2022/5/10 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = App.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class AppTests { + +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/alarm/AlarmTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/alarm/AlarmTest.java new file mode 100644 index 0000000..8414a35 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/alarm/AlarmTest.java @@ -0,0 +1,164 @@ +package com.ningdatech.carapi.alarm; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarn; +import com.ningdatech.carapi.car.monitor.entity.DataAccessAlarmWarnFile; +import com.ningdatech.carapi.car.monitor.entity.VehicleSecurityMonitor; +import com.ningdatech.carapi.car.monitor.service.IDataAccessAlarmWarnFileService; +import com.ningdatech.carapi.car.monitor.service.IDataAccessAlarmWarnService; +import com.ningdatech.carapi.car.monitor.service.IVehicleSecurityMonitorService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.common.constant.BgTypeEnum; +import com.ningdatech.carapi.common.constant.DeletedEnum; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.common.util.CodeUtil; +import com.ningdatech.carapi.driver.constant.DriverAbnormalBehaviorAppendixTypeEnum; +import com.ningdatech.carapi.scheduler.contants.TaskContant; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.StopWatch; +import lombok.extern.slf4j.Slf4j; + +/** + * @author PoffyZhang + * @Classname AlarmTest + * @Description + * @Date 2022/12/15 18:11 + */ +@Slf4j +public class AlarmTest extends AppTests { + + @Resource + private IDataAccessAlarmWarnService dataAccessAlarmWarnService; + + @Resource + private IDataAccessAlarmWarnFileService dataAccessAlarmWarnFileService; + + @Resource + private VehiclesCacheHelper vehiclesCacheHelper; + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Resource + private IVehicleSecurityMonitorService vehicleSecurityMonitorService; + + @Test + public void test1(){ + Map online_index = stringRedisTemplate.opsForHash().entries("online_index"); + System.out.println(online_index); + } + + @Test + public void test(){ + log.info("========== 更新车辆安全监控数据 ==========任务开始"); + StopWatch stopWatch = StopWatch.create(StringUtils.EMPTY); + stopWatch.start(); + + List alarms = dataAccessAlarmWarnService.list(Wrappers.lambdaQuery(DataAccessAlarmWarn.class) + .eq(DataAccessAlarmWarn::getId,16078) + .isNotNull(DataAccessAlarmWarn::getBgType) + .orderBy(Boolean.TRUE,Boolean.TRUE,DataAccessAlarmWarn::getId)); + + if(CollUtil.isEmpty(alarms)){ + log.info("this time vehicle alarm size is empty"); + return; + } + + log.info("this time vehicle alarm size :{}",alarms.size()); + + //获取异常行为列表的所有报警唯一序号 + List alarmMsgSnList = alarms.stream().map(DataAccessAlarmWarn::getAlarmMsgSn).collect(Collectors.toList()); + List files = dataAccessAlarmWarnFileService.list(Wrappers.lambdaQuery(DataAccessAlarmWarnFile.class) + .in(DataAccessAlarmWarnFile::getAlarmMsgSn,alarmMsgSnList)); + for (DataAccessAlarmWarn alarm : alarms) { + NdVehicleBaseInfo car = vehiclesCacheHelper.getByCarPlate(alarm.getVehicleNo()); + if(Objects.isNull(car)){ + log.info("此条异常行为数据 系统里没有这辆车 {}", JSON.toJSONString(alarm)); + continue; + } + + VehicleSecurityMonitor monitor = new VehicleSecurityMonitor(); + List matchFiles = files.stream() + .filter(d -> Objects.nonNull(d.getAlarmMsgSn()) + && d.getAlarmMsgSn().equals(alarm.getAlarmMsgSn()) + && Objects.nonNull(d.getGnssCenterId()) + && d.getGnssCenterId().equals(alarm.getGnssCenterId())) + .collect(Collectors.toList()); + for (DataAccessAlarmWarnFile file : matchFiles) { + if (DriverAbnormalBehaviorAppendixTypeEnum.PICTURE.getCode().equals(file.getFileType())){ + monitor.setPictureUrl(StringUtils.isNotBlank(file.getFilePath()) ? file.getFilePath() : file.getSrcPath()); + } else if (DriverAbnormalBehaviorAppendixTypeEnum.VIDEO.getCode().equals(file.getFileType())){ + monitor.setVideoUrl(StringUtils.isNotBlank(file.getFilePath()) ? file.getFilePath() : file.getSrcPath()); + } + } + + String content = alarm.getContent(); + if(Objects.isNull(content) || !CodeUtil.getJSONType(content)){ + log.info("此条异常行为数据content内容有误 {}",JSON.toJSONString(alarm)); + continue; + } + + JSONObject jsonContent = JSON.parseObject(content); + JSONObject gpsJson = jsonContent.getJSONObject(TaskContant.DataField.GPS); + + if(Objects.isNull(gpsJson)){ + log.info("此条异常行为数据 GPS 内容有误 {}",JSON.toJSONString(alarm)); + continue; + } + + monitor.setLongitude(Optional.of(gpsJson.getBigDecimal(TaskContant.DataField.LONGITUDE)) + .map(c -> c.divide(TaskContant.Math.LONGITUDE_UNITS, BigDecimal.ROUND_HALF_EVEN,BigDecimal.ROUND_HALF_UP)).get()); + monitor.setLatitude(Optional.of(gpsJson.getBigDecimal(TaskContant.DataField.LATITUDE)) + .map(c -> c.divide(TaskContant.Math.LONGITUDE_UNITS,BigDecimal.ROUND_HALF_EVEN,BigDecimal.ROUND_HALF_UP)).get()); + + // 装配告警信息 + monitor.setCompanyId(car.getCompanyId()); + monitor.setRegionId(car.getRegionId()); + CodeUtil.searchCompanyNameAndRegionName(monitor); + monitor.setAlarmAddress(alarm.getAddress()); + monitor.setAlarmId(alarm.getAlarmMsgSn()); + monitor.setAlarmType(alarm.getBgType()); + monitor.setAlarmTypeName(BgTypeEnum.getDescByCode(alarm.getBgType())); + monitor.setCarPlate(alarm.getVehicleNo()); + monitor.setVehicleType(car.getVehicleType()); + monitor.setVehicleTypeName(VehicleTypeEnum.getDescByCode(car.getVehicleType())); + monitor.setAlarmTime(alarm.getStartTime()); + monitor.setAlarmLevel(alarm.getGrade()); + monitor.setOperatorId(alarm.getGnssCenterId()); + + VehicleSecurityMonitor one = vehicleSecurityMonitorService.getOne(Wrappers.lambdaQuery(VehicleSecurityMonitor.class) + .eq(VehicleSecurityMonitor::getDeleted, DeletedEnum.NO_DELETED) + .eq(VehicleSecurityMonitor::getAlarmId, alarm.getAlarmMsgSn()) + .eq(VehicleSecurityMonitor::getOperatorId,alarm.getGnssCenterId())); + if(Objects.nonNull(one)){ + monitor.setId(one.getId()); + } + + vehicleSecurityMonitorService.saveOrUpdate(monitor); + } + stopWatch.stop(); + log.info(stopWatch.getTotalTimeSeconds() + ":::"); + } + + +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/HmacAuthUtil.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/HmacAuthUtil.java new file mode 100644 index 0000000..7d1a837 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/HmacAuthUtil.java @@ -0,0 +1,89 @@ +package com.ningdatech.carapi.car; + + +import org.apache.commons.lang3.tuple.Pair; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.bind.DatatypeConverter; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author CMM + * @since 2023/06/27 13:01 + */ + +public class HmacAuthUtil { + /** + * 构造http请求 header + * + * @param url 请求url,全路径格式,比如:https://bcdsg.zj.gov.cn/api/p/v1/user.get + * @param requestMethod 请求方法,大写格式,如:GET, POST + * @param accessKey 应用的 AK + * @param secretKey 应用的 SK + * @return + */ + public static Map generateHeader(String url, String requestMethod, String accessKey, String secretKey) { + Map header = new HashMap<>(); + try { + DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = dateFormat.format(new Date()); + date = "Tue, 27 Jun 2023 05:02:23 GMT"; + URI uri = URI.create(url); + String canonicalQueryString = getCanonicalQueryString(uri.getQuery()); + String message = requestMethod.toUpperCase() + "\n" + uri.getPath() + "\n" + canonicalQueryString + "\n" + accessKey + "\n" + date + "\n"; + System.out.println(message); + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256")); + byte[] hash = mac.doFinal(message.getBytes()); + // to lowercase hexits + String hex = DatatypeConverter.printHexBinary(hash); + // to base64 + String sign = DatatypeConverter.printBase64Binary(hex.getBytes()); + header.put("X-BG-HMAC-SIGNATURE", sign); + header.put("X-BG-HMAC-ALGORITHM", "hmac-sha256"); + header.put("X-BG-HMAC-ACCESS-KEY", accessKey); + header.put("X-BG-DATE-TIME", date); + } catch (Exception e) { + throw new RuntimeException("generate jc brain header error", e); + } + return header; + } + + private static String getCanonicalQueryString(String query) { + if (query == null || query.trim().length() == 0) { + return ""; + } + List> queryParamList = new ArrayList<>(); + String[] params = query.split("&"); + for (String param : params) { + String[] keyValue = param.split("="); + Pair pair = Pair.of(keyValue[0], keyValue.length > 1 ? keyValue[1] : ""); + queryParamList.add(pair); + } + List> sortedParamList = queryParamList.stream().sorted(Comparator.comparing(param -> param.getKey() + "=" + Optional.ofNullable(param.getValue()).orElse(""))).collect(Collectors.toList()); + List> encodeParamList = new ArrayList<>(); + sortedParamList.forEach(param -> { + try { + String key = URLEncoder.encode(param.getKey(), "utf-8"); + String value = URLEncoder.encode(Optional.ofNullable(param.getValue()).orElse(""), "utf-8"); + encodeParamList.add(Pair.of(key, value)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("encoding error"); + } + }); + StringBuilder queryParamString = new StringBuilder(64); + for (Pair encodeParam : encodeParamList) { + queryParamString.append(encodeParam.getKey()).append("=").append(Optional.ofNullable(encodeParam.getValue()).orElse("")); + queryParamString.append("&"); + } + return queryParamString.substring(0, queryParamString.length() - 1); + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/RptTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/RptTest.java new file mode 100644 index 0000000..5864863 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/RptTest.java @@ -0,0 +1,109 @@ +package com.ningdatech.carapi.car; + +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import com.alibaba.fastjson.JSON; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; + +import lombok.RequiredArgsConstructor; + +/** + * 车辆报表 + * + * @author CMM + * @since 2023/06/25 16:41 + */ +@RequiredArgsConstructor +public class RptTest extends AppTests { + + private final IVehicleBaseInfoService vehicleBaseInfoService; + @Test + public void test() { + + // 假设有以下车辆的上线时间和下线时间 + Map vehicles = new HashMap<>(); + vehicles.put("车辆1", new LocalDate[]{LocalDate.of(2021, 1, 1), LocalDate.of(2021, 1, 10)}); // 上线时间为1月1日,下线时间为1月10日 + vehicles.put("车辆2", new LocalDate[]{LocalDate.of(2021, 1, 5), LocalDate.of(2021, 1, 15)}); // 上线时间为1月5日,下线时间为1月15日 + vehicles.put("车辆3", new LocalDate[]{LocalDate.of(2021, 1, 10), LocalDate.of(2021, 1, 20)}); // 上线时间为1月10日,下线时间为1月20日 + + // 统计每辆车当月某个时间段不上线的天数 + LocalDate startDate = LocalDate.of(2021, 1, 1); // 统计开始日期 + LocalDate endDate = LocalDate.of(2021, 1, 31); // 统计结束日期 + Map offlineDays = new HashMap<>(); + for (Map.Entry entry : vehicles.entrySet()) { + LocalDate[] dates = entry.getValue(); + LocalDate onlineDate = dates[0]; + LocalDate offlineDate = dates[1]; + long days = ChronoUnit.DAYS.between(startDate, endDate) + 1; // 当月总天数 + if (onlineDate.isAfter(endDate) || offlineDate.isBefore(startDate)) { // 车辆在统计时间段外上下线 + offlineDays.put(entry.getKey(), days); + } else { + if (onlineDate.isBefore(startDate)) { + onlineDate = startDate; + } + if (offlineDate.isAfter(endDate)) { + offlineDate = endDate; + } + long offline = ChronoUnit.DAYS.between(onlineDate, offlineDate) + 1; // 不上线天数 + offlineDays.put(entry.getKey(), days - offline); + } + } + + // 按不上线天数进行排序 + List> list = new ArrayList<>(offlineDays.entrySet()); + list.sort(Map.Entry.comparingByValue()); + + // 输出结果 + for (Map.Entry entry : list) { + System.out.println(entry.getKey() + ": " + entry.getValue() + "天"); + } + + } + + @Test + public void test2() { + + //DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + //dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + //String date = dateFormat.format(new Date()); + //System.out.println(date); + + + String method = "GET"; + String url = "https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020230427000001/irs-res-bill/report/pdfUrl?appCode=A330000100000202105002530"; + String appScret = "BCDSGS_4ab4235d26a9a357170a39f3a13fd68c"; + String appKey = "BCDSGA_d874c8e46b541eb4e8aac6510fd3351b"; + + Map header = HmacAuthUtil.generateHeader(url, method, appKey, appScret); + //请求头 + HttpHeaders headers = new HttpHeaders(); + + for(Map.Entry entry : header.entrySet()){ + headers.add(entry.getKey(), entry.getValue()); + } + + System.out.println(headers); + //封装请求头 + HttpEntity> formEntity = new HttpEntity>(headers); + + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity forEntity = restTemplate.exchange(url, HttpMethod.GET,formEntity, String.class); + + System.out.println(JSON.toJSONString(forEntity)); + + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/VehicleBaseInfoTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/VehicleBaseInfoTest.java new file mode 100644 index 0000000..1ddb9fb --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/car/VehicleBaseInfoTest.java @@ -0,0 +1,744 @@ +package com.ningdatech.carapi.car; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.redis.core.StringRedisTemplate; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesPageQuery; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.DeletedEnum; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusDayService; +import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusHourService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.Operator; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.IRegionService; +import com.ningdatech.carapi.sys.service.OperatorService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname InsureOutdangerTest + * @Description + * @Date 2022/12/22 10:47 + * @Created by PoffyZhang + */ +@Slf4j +public class VehicleBaseInfoTest extends AppTests { + + @Autowired + private CompanyService companyService; + @Autowired + private IVehicleBaseInfoService vehicleBaseInfoService; + @Autowired + private OperatorService operatorService; + @Autowired + private IRegionService regionService; + @Autowired + private RegionsCacheHelper regionCacheHelper; + @Autowired + private INdVehicleEquipmentInfoService vehicleEquipmentInfoService; + @Autowired + private IVehicleOnlineStatusHourService vehicleOnlineStatusHourService; + @Autowired + private IVehicleOnlineStatusDayService vehicleOnlineStatusDayService; + @Autowired + private ApplicationContext applicationContext; + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Test + public void test() throws FileNotFoundException { + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\车辆.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + HashSet carPlates = new HashSet<>(); + HashSet companySet = new HashSet<>(); + HashSet operatorSet = new HashSet<>(); + HashSet countySet = new HashSet<>(); + + // 根据企业名查询企业信息 + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + // 根据运营商名称查询运营商信息 + Map operatorMap = operatorService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + operatorSet.add(v.getName())) + .collect(Collectors.toMap(Operator::getName, v -> v)); + + // 根据区县名称获取区域ID + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + + NdVehicleBaseInfo vehicleBaseInfo = new NdVehicleBaseInfo(); + + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 企业名称 + String companyName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + Company companyInfo = companyNameMap.get(companyName); + // 区县 + String countyName = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + Region region = regionMap.get(countyName); + Long regionId = null; + if (Objects.nonNull(region)) { + regionId = region.getId(); + } + String displayName = regionCacheHelper.getDisplayName(regionId); + // 运营商 + String operatorName = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + Operator operator = operatorMap.get(operatorName); + Long operatorId = null; + if (Objects.nonNull(operator)) { + operatorId = operator.getId(); + } + + Long companyId = companyInfo.getId(); + if (Objects.nonNull(companyInfo)) { + // 获取最新一个公司信息 + companyId = companyInfo.getId(); + } else if (!StrPool.EMPTY.equals(companyName)) { + // 没有该公司信息,新增企业信息 + Company company = new Company(); + company.setRegionId(regionId); + company.setRegionName(displayName); + company.setOperatorId(operatorId); + company.setCompanyType(1); + company.setName(companyName); + company.setSortName(companyName); + company.setCompanyStatus(0); + companyService.save(company); + companyId = company.getId(); + // 更新map + companyNameMap.put(companyName,company); + } + vehicleBaseInfo.setCarPlate(carPlate); + vehicleBaseInfo.setOperatorId(operatorId); + vehicleBaseInfo.setRegionId(regionId); + vehicleBaseInfo.setRegionName(displayName); + vehicleBaseInfo.setCompanyId(companyId); + vehicleBaseInfo.setAuditState(2); + vehicleBaseInfo.setUpdateOn(LocalDateTime.now()); + vehicleBaseInfo.setCreateOn(LocalDateTime.now()); + vehicleBaseInfoService.save(vehicleBaseInfo); + System.out.println("准备更新 " + i + "条:" + JSON.toJSONString(vehicleBaseInfo)); + } + } + } + + @Test + public void testRegion(){ + RegionDTO regionDTO = regionCacheHelper.getByRegionId(6L); + String regionName = regionDTO.getRegionName(); + System.out.println(regionName); + } + + //public fileout void main(String[] args) { + // Date date = new Date(); + // System.out.println(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); + //} + + //这个下面是单独函数 + public static Workbook readExcel(InputStream is, String extString) { + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if (".xls".equals(extString)) { + return wb = new HSSFWorkbook(is); + } else if (".xlsx".equals(extString)) { + return wb = new XSSFWorkbook(is); + } else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } + + + @Test + public void test2() throws FileNotFoundException { + File f = new File("D:\\work\\file\\0510\\运营商车辆.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + HashSet carPlates = new HashSet<>(); + HashSet companySet = new HashSet<>(); + HashSet operatorSet = new HashSet<>(); + HashSet countySet = new HashSet<>(); + + int count = 0; + // 根据车牌号查询车辆信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getCarPlate()) && + carPlates.add(v.getCarPlate())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 根据企业名查询企业信息 + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + //获取最大列数 + List list = new ArrayList<>(); + for (int i = 1; i < rownum; i++) { + + NdVehicleBaseInfo vehicleBaseInfo = new NdVehicleBaseInfo(); + + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 企业名称 + String companyName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + // 企业信息不存在 + if (!companyNameMap.containsKey(companyName)){ + log.info("该车牌号:" + carPlate + "没有公司信息"); + Company com = new Company(); + com.setName(companyName); + com.setSortName(companyName); + com.setCompanyStatus(0); + companyService.save(com); + // 更新map + companyNameMap.put(companyName,com); + } + if (!vehicleBaseInfoMap.containsKey(carPlate)) { + Company company = companyNameMap.get(companyName); + vehicleBaseInfo.setCarPlate(carPlate); + vehicleBaseInfo.setCompanyId(company.getId()); + vehicleBaseInfo.setOperatorId(company.getOperatorId()); + vehicleBaseInfo.setRegionId(company.getRegionId()); + vehicleBaseInfo.setRegionName(company.getRegionName()); + vehicleBaseInfo.setAuditState(2); + list.add(vehicleBaseInfo); + count++; + } + } + System.out.println("新增的车辆数为:" + count); + HashSet set = new HashSet<>(); + List infos = + list.stream().filter(c -> set.add(c.getCarPlate())).collect(Collectors.toList()); + System.out.println("去重后的总数为:" + infos.size()); + vehicleBaseInfoService.saveOrUpdateBatch(infos); + System.out.println("更新完成"); + + } + + } + + @Test + public void test3() throws FileNotFoundException { + File f = new File("D:\\work\\file\\0510\\运营商车辆.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + HashSet companySet = new HashSet<>(); + + // 根据企业名查询企业信息 + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 企业名称 + String companyName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + // 企业信息不存在 + if (!companyNameMap.containsKey(companyName)){ + Company com = new Company(); + com.setName(companyName); + com.setSortName(companyName); + com.setCompanyStatus(0); + companyService.save(com); + } + + } + System.out.println("更新完成"); + + } + + } + + + + @Test + public void test4() throws FileNotFoundException { + File f = new File("D:\\work\\file\\0510\\运营商车辆.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + HashSet carPlates = new HashSet<>(); + HashSet companySet = new HashSet<>(); + + int count = 0; + // 根据车牌号查询车辆信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getCarPlate()) && + carPlates.add(v.getCarPlate())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 根据企业名查询企业信息 + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + //获取最大列数 + List list = new ArrayList<>(); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 企业名称 + String companyName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + if (vehicleBaseInfoMap.containsKey(carPlate)) { + NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate); + Company company = companyNameMap.get(companyName); + vehicleBaseInfo.setCompanyId(company.getId()); + list.add(vehicleBaseInfo); + count++; + } + } + System.out.println("新增的车辆数为:" + count); + HashSet set = new HashSet<>(); + List infos = + list.stream().filter(c -> set.add(c.getCarPlate())).collect(Collectors.toList()); + System.out.println("去重后的总数为:" + infos.size()); + vehicleBaseInfoService.saveOrUpdateBatch(infos); + System.out.println("更新完成"); + + } + + } + + + @Test + public void test5() throws FileNotFoundException { + File f = new File("D:\\work\\file\\0510\\缺区域2.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + HashSet carPlates = new HashSet<>(); + HashSet countySet = new HashSet<>(); + + int count = 0; + // 根据车牌号查询车辆信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getCarPlate()) && + carPlates.add(v.getCarPlate())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 根据区县名称获取区域ID + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + //获取最大列数 + List list = new ArrayList<>(); + for (int i = 1; i < rownum; i++) { + + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 区县 + String countyName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + Region region = regionMap.get(countyName); + Long regionId = null; + if (Objects.nonNull(region)) { + regionId = region.getId(); + } + String displayName = regionCacheHelper.getDisplayName(regionId); + if (carPlates.contains(carPlate)) { + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMap.get(carPlate); + baseInfo.setRegionId(regionId); + baseInfo.setRegionName(displayName); + count++; + list.add(baseInfo); + } + } + log.info("更新的车辆数量为:" + count); + vehicleBaseInfoService.saveOrUpdateBatch(list); + System.out.println("更新完成"); + } + } + + @Test + public void test6() throws FileNotFoundException { + File f = new File("D:\\work\\file\\0510\\车牌缺运营商.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + HashSet carPlates = new HashSet<>(); + HashSet companySet = new HashSet<>(); + HashSet operatorSet = new HashSet<>(); + HashSet countySet = new HashSet<>(); + + int count = 0; + // 根据车牌号查询车辆信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getCarPlate()) && + carPlates.add(v.getCarPlate())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 根据运营商名称查询运营商信息 + Map operatorMap = operatorService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + operatorSet.add(v.getName())) + .collect(Collectors.toMap(Operator::getName, v -> v)); + + //获取最大列数 + List list = new ArrayList<>(); + for (int i = 1; i < rownum; i++) { + + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 运营商 + String operatorName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + Operator operator = operatorMap.get(operatorName); + Long operatorId = null; + if (Objects.nonNull(operator)) { + operatorId = operator.getId(); + } + + if (carPlates.contains(carPlate)) { + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMap.get(carPlate); + baseInfo.setOperatorId(operatorId); + count++; + list.add(baseInfo); + } + } + log.info("更新的车辆数为:" + count); + vehicleBaseInfoService.saveOrUpdateBatch(list); + System.out.println("更新完成"); + } + } + + @Test + public void test7() throws FileNotFoundException { + File f = new File("D:\\work\\file\\0510\\缺企业.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + HashSet carPlates = new HashSet<>(); + HashSet companySet = new HashSet<>(); + + int count = 0; + // 根据车牌号查询车辆信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getCarPlate()) && + carPlates.add(v.getCarPlate())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 根据企业名查询企业信息 + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + //获取最大列数 + List list = new ArrayList<>(); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 企业名称 + String companyName = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + Company companyInfo = companyNameMap.get(companyName); + Long companyId = null; + if (Objects.nonNull(companyInfo)) { + // 获取最新一个公司信息 + companyId = companyInfo.getId(); + } + if (carPlates.contains(carPlate)) { + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMap.get(carPlate); + baseInfo.setCompanyId(companyId); + count++; + list.add(baseInfo); + } + } + log.info("更新的车辆数为:" + count); + vehicleBaseInfoService.saveOrUpdateBatch(list); + System.out.println("更新完成"); + } + } + + // 更新车辆设备表中车辆ID + @Test + public void test8(){ + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + List equipmentInfos = vehicleEquipmentInfoService.list(); + + for (NdVehicleEquipmentInfo equipmentInfo : equipmentInfos) { + String carPlate = equipmentInfo.getCarPlate(); + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMap.get(carPlate); + if (Objects.nonNull(baseInfo)) { + equipmentInfo.setVehicleId(baseInfo.getId()); + if (Objects.nonNull(baseInfo.getVehicleType())){ + equipmentInfo.setVehicleType(Long.valueOf(baseInfo.getVehicleType())); + } + vehicleEquipmentInfoService.updateById(equipmentInfo); + } + } + } + + // 更新车辆区域信息 + @Test + public void test9(){ + List baseInfos = vehicleBaseInfoService.list().stream() + .filter(v -> Objects.isNull(v.getRegionId())) + .collect(Collectors.toList()); + Map companyMap = companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + for (NdVehicleBaseInfo baseInfo : baseInfos) { + Long companyId = baseInfo.getCompanyId(); + Company company = companyMap.get(companyId); + Long regionId = company.getRegionId(); + String regionName = company.getRegionName(); + baseInfo.setRegionId(regionId); + baseInfo.setRegionName(regionName); + vehicleBaseInfoService.updateById(baseInfo); + } + } + + @Test + public void test10() throws FileNotFoundException { + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\车辆类型数据.xlsx"); + Workbook wb = readExcel(new FileInputStream(f), f.getName()); + Row row = null; + if (wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + HashSet carPlates = new HashSet<>(); + // 根据车牌号查询车辆信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getCarPlate()) && + carPlates.add(v.getCarPlate())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + //获取最大列数 + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 车辆类型 + String vehicleType = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + // 审核时间 + LocalDateTime dateTime = LocalDateTime.now(); + Cell cell = row.getCell(2); + if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) { + Date dateValue = cell.getDateCellValue(); + // 处理日期值 + dateTime = NdDateUtils.date2LocalDateTime(dateValue); + if (vehicleBaseInfoMap.containsKey(carPlate)) { + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMap.get(carPlate); + baseInfo.setAuditTime(dateTime); + vehicleBaseInfoService.updateById(baseInfo); + } + } + + } + } + } + + + private Long lastIndex = 626L; + private Integer lastCount = 626; + @Test + public void test11(){ + readLastIndex(); + System.out.println(lastIndex); + System.out.println(lastCount); + } + private void readLastIndex() { + File file = new File("C:\\Users\\CMM\\Desktop\\demo\\vehicleLicenseIndex.txt"); + try { + List dataList = FileUtil.readLines(file, StandardCharsets.UTF_8); + if (CollUtil.isNotEmpty(dataList) && dataList.size() == 2){ + lastIndex = Long.valueOf(dataList.get(0)); + lastCount = Integer.valueOf(dataList.get(1)); + } + } catch (Exception e) { + log.info("读取下标和车牌号失败!"); + } + } + + @Test + public void test12(){ + + LambdaQueryWrapper query = + Wrappers.lambdaQuery(NdVehicleBaseInfo.class).ge(NdVehicleBaseInfo::getId, 1000) + .lt(NdVehicleBaseInfo::getId, 1000 + 2900 - 1401 + 1) + .select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getId).isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + if (CollUtil.isNotEmpty(list)) { + List carPlateSet = list.stream() + .sorted(Comparator.comparing(NdVehicleBaseInfo::getId)) + .map(NdVehicleBaseInfo::getCarPlate) + .collect(Collectors.toList()); + String[] carPlates = carPlateSet.stream().toArray(String[]::new); + System.out.println(carPlates[1499]); + System.out.println(carPlates[0]); + } + } + + + @Test + public void test13(){ + Map infoMap = + vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getId,NdVehicleBaseInfo::getCarPlate)) + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getId, NdVehicleBaseInfo::getCarPlate)); + OptionalLong maxKey = infoMap.keySet().stream().mapToLong(Long::longValue).max(); + Long maxIndex = null; + if (maxKey.isPresent()){ + maxIndex = maxKey.getAsLong(); + } + // 校验下标对应的车牌号是否一致 + String carNo; + carNo = infoMap.get(lastIndex); + while (Objects.isNull(carNo)) { + log.info("车辆id{}不存在,请检查该车辆信息是否已经被删除!", lastIndex); + // 查找下一个车辆信息,直到车辆信息存在 + lastIndex++; + if (Objects.nonNull(maxIndex) && lastIndex.compareTo(maxIndex) > 0){ + log.info("系统中没有待查询的车牌号"); + return; + } + carNo = infoMap.get(lastIndex); + } + + // 从车辆信息表中从上次执行中断的下标获取一定数量的车牌号 + int cnt = 2950 - lastCount; + LambdaQueryWrapper query = + Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .ge(NdVehicleBaseInfo::getId, lastIndex) + .last("limit " + cnt) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId) + .isNotNull(NdVehicleBaseInfo::getCarPlate); + List list = vehicleBaseInfoService.list(query); + log.info("此次任务车辆数量为:" + list.size()); + + // 任务执行完毕后保存最终的数据下标 + TreeMap sortedMap = new TreeMap<>(infoMap); + Map.Entry higherEntry = sortedMap.higherEntry(lastIndex); + if (Objects.nonNull(higherEntry)){ + lastIndex = higherEntry.getKey(); + } + log.info("下个下标为:" + lastIndex); + } + + + @Test + public void test14(){ + VehicleArchivesPageQuery vehicleArchivesPageQuery = new VehicleArchivesPageQuery(); + LambdaQueryWrapper otherWrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class); + otherWrapper.eq(NdVehicleBaseInfo::getDeleted, DeletedEnum.NO_DELETED.getCode()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getCompanyId()),NdVehicleBaseInfo::getCompanyId,vehicleArchivesPageQuery.getCompanyId()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfo::getCarPlate, vehicleArchivesPageQuery.getCarPlate()) + .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getUseCompanyName()),NdVehicleBaseInfo::getUseCompanyName,vehicleArchivesPageQuery.getUseCompanyName()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfo::getVehicleType, vehicleArchivesPageQuery.getVehicleType()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleStatus()),NdVehicleBaseInfo::getVehicleStatus,vehicleArchivesPageQuery.getVehicleStatus()) + .eq(Objects.nonNull(vehicleArchivesPageQuery.getRegionId()),NdVehicleBaseInfo::getRegionId,vehicleArchivesPageQuery.getRegionId()) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfo::getUpdateOn); + List baseInfos = vehicleBaseInfoService.list(otherWrapper).stream().filter(v -> Objects.isNull(v.getCompanyId())).collect(Collectors.toList()); + log.info("数量为{}",baseInfos.size()); + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/company/CompanyInfoTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/company/CompanyInfoTest.java new file mode 100644 index 0000000..e52a41b --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/company/CompanyInfoTest.java @@ -0,0 +1,268 @@ +package com.ningdatech.carapi.company; + +import java.io.*; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alibaba.fastjson.JSON; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel; +import com.ningdatech.carapi.company.service.INdCompanyCreditLevelService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.CompanyTypeRelated; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.CompanyTypeRelatedService; +import com.ningdatech.carapi.sys.service.IRegionService; + +/** + * @Classname InsureOutdangerTest + * @Description + * @Date 2022/12/22 10:47 + * @Created by PoffyZhang + */ +public class CompanyInfoTest extends AppTests { + + @Autowired + private CompanyService companyService; + @Autowired + private IRegionService regionService; + + @Autowired + private RegionsCacheHelper regionsCacheHelper; + + @Autowired + private CompanyTypeRelatedService companyTypeRelatedService; + @Autowired + private INdCompanyCreditLevelService companyCreditLevelService; + + @Test + public void test() throws FileNotFoundException { + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\最新企业.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + + HashSet countySet = new HashSet<>(); + // 根据区县名称获取区域ID + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + Map companyMap = companyService.list().stream() + .collect(Collectors.toMap(Company::getName, v -> v)); + + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i countySet = new HashSet<>(); + // 根据公司名称获取公司ID + Map companyMap = companyService.list().stream() + .collect(Collectors.toMap(Company::getName, c -> c)); + + + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i companyList = companyService.list().stream().filter(c -> c.getCompanyType() != 0).collect(Collectors.toList()); + // 初始化所有企业2023年的的企业信用等级 + for (Company company : companyList) { + NdCompanyCreditLevel creditLevel = new NdCompanyCreditLevel(); + creditLevel.setCompanyId(company.getId()); + creditLevel.setCompanyName(company.getName()); + creditLevel.setRegionId(company.getRegionId()); + String regionName = regionsCacheHelper.getDisplayName(company.getRegionId()); + creditLevel.setRegionName(regionName); + creditLevel.setYear("2023"); + creditLevel.setScore(1000); + creditLevel.setLevel("A"); + creditLevel.setBasicCreditScore(120); + creditLevel.setCommonCreditScore(300); + creditLevel.setSafeProductCreditScore(240); + creditLevel.setIndustryRegulateCreditScore(240); + creditLevel.setIndustryHonorBonus(100); + creditLevel.setGovernmentAwardScore(50); + creditLevel.setIndustryBenchMarkScore(50); + companyCreditLevelService.save(creditLevel); + } + + } + + @Test + public void test4() throws FileNotFoundException { + File f = new File("D:\\work\\水泥车车辆数据\\丽水莲都区物流企业.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i companyMap = companyService.list().stream().collect(Collectors.toMap(Company::getName, c -> c)); + List insureInfoList = insureInfoService.list(); + List warnAnalysisCompanyList = analysisCompanyService.list(); + for (WarnAnalysisCompany warnAnalysisCompany : warnAnalysisCompanyList) { + String companyName = warnAnalysisCompany.getCompanyName(); + if (companyMap.containsKey(companyName)){ + Company company = companyMap.get(companyName); + warnAnalysisCompany.setCompanyId(company.getId()); + warnAnalysisCompany.setRegionId(company.getRegionId()); + analysisCompanyService.updateById(warnAnalysisCompany); + } + } + } + + @Test + public void test3() { + // 更新预警评估-保险机构信息中的企业和区域信息 + Map vehicleBaseInfoMap = vehicleBaseInfoService.list().stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + Map companyMap = companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + List insureInfos = insureInfoService.list(); + for (NdInsureInfo insureInfo : insureInfos) { + String carPlate = insureInfo.getCarPlate(); + NdVehicleBaseInfo baseInfo = vehicleBaseInfoMap.get(carPlate); + Long companyId = baseInfo.getCompanyId(); + Long regionId = baseInfo.getRegionId(); + String regionName = baseInfo.getRegionName(); + Company company = companyMap.get(companyId); + insureInfo.setCompanyId(companyId); + insureInfo.setRegionId(regionId); + insureInfo.setRegionName(regionName); + insureInfo.setCompanyName(company.getName()); + insureInfoService.updateById(insureInfo); + } + } + + @Test + public void test4() { + // 创建各市、区县散装中心管理企业 + List cityList = regionService.list() + .stream().filter(c -> (2 == c.getLevel() || 3 == c.getLevel()) + && !"市本级".equals(c.getName())) + .collect(Collectors.toList()); + for (Region region : cityList) { + Company company = new Company(); + String regionName = region.getName(); + Long regionId = region.getId(); + String companyName = regionName + "散装中心"; + company.setName(companyName); + company.setRegionId(regionId); + String displayName = regionsCacheHelper.getDisplayName(regionId); + company.setRegionName(displayName); + company.setCompanyType(CompanyTypeEnum.MANAGE_BU.getCode()); + company.setCreateOn(LocalDateTime.now()); + company.setUpdateOn(LocalDateTime.now()); + companyService.save(company); + } + } + + @Test + public void test5() { + // 创建各企业企业信息员账号 + Map companyMap = companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c)); + List companyList = companyService.list().stream().filter(c -> c.getCompanyType().equals(CompanyTypeEnum.PRODUCT_BU.getCode()) + || c.getCompanyType().equals(CompanyTypeEnum.LOGISTICS_BU.getCode()) + || c.getCompanyType().equals(CompanyTypeEnum.OTHER.getCode())).collect(Collectors.toList()); + for (Company company : companyList) { + Long companyId = company.getId(); + Company companyInfo = companyMap.get(companyId); + NdUserInfo userInfo = new NdUserInfo(); + userInfo.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode()); + userInfo.setUsername(companyInfo.getName()); + userInfo.setCompanyId(companyId); + userInfo.setCreateOn(LocalDateTime.now()); + userInfo.setUpdateOn(LocalDateTime.now()); + userInfoService.save(userInfo); + + Long userId = userInfo.getId(); + NdUserAuth userAuth = new NdUserAuth(); + userAuth.setUserId(userId); + userAuth.setIdentifier(companyInfo.getName()); + userAuth.setCredential(passwordEncoder.encode("123456Aa")); + userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey()); + userAuth.setIsAvailable(true); + ndUserAuthService.save(userAuth); + + UserRole userRole = new UserRole(); + userRole.setUserId(userId); + userRole.setRoleId(UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId()); + userRoleService.save(userRole); + } + } + + @Test + public void test2() throws FileNotFoundException { + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\水泥车企业类型细分.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + + HashSet countySet = new HashSet<>(); + // 根据公司名称获取公司ID + Map companyMap = companyService.list().stream() + .collect(Collectors.toMap(Company::getName, c -> c)); + + + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i driverInfos = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class) + .eq(Objects.nonNull(companyId), DriverInfo::getCompanyId, companyId) + .eq(Objects.nonNull(regionId), DriverInfo::getRegionId, regionId) + .eq(Objects.nonNull(companyName), DriverInfo::getCompanyName, companyName)); + + Assert.assertNotNull(driverInfos); + + for (DriverInfo driverInfo : driverInfos) { + + //保存培训组织基础信息 考试试卷 + TrainingOrganization saveRecord = new TrainingOrganization(); + saveRecord.setUpdateOn(LocalDateTime.now()); + saveRecord.setTrainingTopic("取证培训"); + saveRecord.setTrainingStartTime(LocalDateTime.of(2022,12,1,9,30)); + saveRecord.setTrainingEndTime(LocalDateTime.of(2022,12,15,18,30)); + saveRecord.setAddress("杭州"); + saveRecord.setTrainingMode(TrainingModeEnum.online.name()); + + saveRecord.setTrainingType(TrainingTypeEnum.forensic_registration_training.name()); + saveRecord.setContacts("宁达"); + saveRecord.setContactNumber("18556996666"); + + saveRecord.setTrainingStatus(TrainingStatusEnum.enable.name()); + saveRecord.setRemark("备注"); + saveRecord.setExamPaperId(18L); + saveRecord.setExamPaperName("取证培训试卷"); + saveRecord.setCreateBy(2L); + saveRecord.setCreateOn(LocalDateTime.now()); + saveRecord.setRegionId(regionId); + iTrainingOrganizationService.save(saveRecord); + + //保存培训人员 + TrainingOrganizationTrainer trainingOrganizationTrainer = new TrainingOrganizationTrainer(); + trainingOrganizationTrainer.setDriverId(driverInfo.getId()); + trainingOrganizationTrainer.setDriverName(driverInfo.getDriverName()); + trainingOrganizationTrainer.setCompanyId(driverInfo.getCompanyId()); + trainingOrganizationTrainer.setDriverUserId(driverInfo.getUserId()); + trainingOrganizationTrainer.setCompanyName(driverInfo.getCompanyName()); + trainingOrganizationTrainer.setCreateOn(LocalDateTime.now()); + trainingOrganizationTrainer.setUpdateOn(LocalDateTime.now()); + trainingOrganizationTrainer.setExamPaperId(18L); + trainingOrganizationTrainer.setExaminationStatus(ExaminationStatusEnum.examined.name()); + trainingOrganizationTrainer.setExamPaperName("取证培训试卷"); + trainingOrganizationTrainer.setExamRegistrationNo("abcdefg"); + trainingOrganizationTrainer.setTrainingOrganizationId(saveRecord.getId()); + iTrainingOrganizationTrainerService.save(trainingOrganizationTrainer); + + //保存考试记录 + ExamRecord saveExamRecord = new ExamRecord(); + saveExamRecord.setCreateBy(2L); + saveExamRecord.setCreateOn(LocalDateTime.now()); + saveExamRecord.setUpdateOn(LocalDateTime.now()); + saveExamRecord.setExamPaperId(18L); + saveExamRecord.setTrainingOrganizationId(saveRecord.getId()); + saveExamRecord.setExamType(TrainingTypeEnum.forensic_registration_training.name()); + iExamRecordService.save(saveExamRecord); + + //保存考试分数 + ExamRecordDetail examRecordDetail = new ExamRecordDetail(); + examRecordDetail.setDriverId(driverInfo.getId()); + examRecordDetail.setDriverUserId(driverInfo.getUserId()); + examRecordDetail.setDriverName(driverInfo.getDriverName()); + examRecordDetail.setCompanyName(driverInfo.getCompanyName()); + examRecordDetail.setCompanyId(driverInfo.getCompanyId()); + examRecordDetail.setScore(100); + examRecordDetail.setExamResult(ExamQualifiedEnum.qualified.name()); + examRecordDetail.setExamTime(LocalDateTime.of(2022,12,7,9,30)); + examRecordDetail.setRegionId(driverInfo.getRegionId()); + examRecordDetail.setExamType(TrainingTypeEnum.forensic_registration_training.name()); + examRecordDetail.setExamRecordId(saveExamRecord.getId()); + examRecordDetail.setCreateBy(2L); + examRecordDetail.setCreateOn(LocalDateTime.now()); + examRecordDetail.setUpdateOn(LocalDateTime.now()); + //初始化驾驶员星级 + StarManage starManage = new StarManage(); + starManage.setCurrentStar(5.0); + starManage.setDriverId(driverInfo.getId()); + starManage.setDriverName(driverInfo.getDriverName()); + starManage.setRegionId(driverInfo.getRegionId()); + starManage.setCompanyName(driverInfo.getCompanyName()); + starManage.setCompanyId(driverInfo.getCompanyId()); + starManage.setCreateOn(LocalDateTime.now()); + starManage.setUpdateOn(LocalDateTime.now()); + iStarManageService.save(starManage); + + TrainingOrganizationTrainer trainer = iTrainingOrganizationTrainerService.getOne(Wrappers.lambdaQuery(TrainingOrganizationTrainer.class) + .eq(Objects.nonNull(driverInfo), TrainingOrganizationTrainer::getDriverId, driverInfo.getId())); + + // 保存培训资料 + TrainingMaterialOverviewInfo trainingMaterialOverviewInfo = new TrainingMaterialOverviewInfo(); + List ruleSystemMaterialList = new ArrayList<>(); + TrainingMaterialInfo trainingMaterialInfo1 = new TrainingMaterialInfo(); + trainingMaterialInfo1.setTrainingMaterialId(1L); + trainingMaterialInfo1.setMaterialType(MaterialTypeEnum.rule_system); + trainingMaterialInfo1.setContent("1"); + trainingMaterialInfo1.setTitle("杭州市水泥车培训资料"); + ruleSystemMaterialList.add(trainingMaterialInfo1); + trainingMaterialOverviewInfo.setRuleSystemMaterialList(ruleSystemMaterialList); + + List policyDocumentsMaterialInfoList = new ArrayList<>(); + TrainingMaterialInfo trainingMaterialInfo2 = new TrainingMaterialInfo(); + trainingMaterialInfo2.setTrainingMaterialId(4L); + trainingMaterialInfo2.setMaterialType(MaterialTypeEnum.policy_documents); + trainingMaterialInfo2.setContent("1"); + trainingMaterialInfo2.setTitle("散办水泥车政策文件"); + ruleSystemMaterialList.add(trainingMaterialInfo2); + trainingMaterialOverviewInfo.setPolicyDocumentsMaterialInfoList(policyDocumentsMaterialInfoList); + + List safetyKnowledgeMaterialInfoList = new ArrayList<>(); + TrainingMaterialInfo trainingMaterialInfo3 = new TrainingMaterialInfo(); + trainingMaterialInfo3.setTrainingMaterialId(3L); + trainingMaterialInfo3.setMaterialType(MaterialTypeEnum.safety_knowledge); + trainingMaterialInfo3.setContent("资料2内容"); + trainingMaterialInfo3.setTitle("散办水泥车规则"); + safetyKnowledgeMaterialInfoList.add(trainingMaterialInfo3); + trainingMaterialOverviewInfo.setSafetyKnowledgeMaterialInfoList(safetyKnowledgeMaterialInfoList); + + List accidentCaseMaterialInfoList = new ArrayList<>(); + TrainingMaterialInfo trainingMaterialInfo4 = new TrainingMaterialInfo(); + trainingMaterialInfo4.setTrainingMaterialId(8L); + trainingMaterialInfo4.setMaterialType(MaterialTypeEnum.accident_case); + trainingMaterialInfo4.setContent("122222222"); + trainingMaterialInfo4.setTitle("浙江省2022年事故案例"); + safetyKnowledgeMaterialInfoList.add(trainingMaterialInfo4); + trainingMaterialOverviewInfo.setAccidentCaseMaterialInfoList(accidentCaseMaterialInfoList); + + List trainingVideoMaterialInfoList = new ArrayList<>(); + TrainingMaterialInfo trainingMaterialInfo5 = new TrainingMaterialInfo(); + trainingMaterialInfo5.setTrainingMaterialId(9L); + trainingMaterialInfo5.setMaterialType(MaterialTypeEnum.training_video); + trainingMaterialInfo5.setContent("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"); + trainingMaterialInfo5.setTitle("省交通局培训视频"); + safetyKnowledgeMaterialInfoList.add(trainingMaterialInfo5); + trainingMaterialOverviewInfo.setTrainingVideoMaterialInfoList(trainingVideoMaterialInfoList); + + List otherMaterialInfoList = new ArrayList<>(); + TrainingMaterialInfo trainingMaterialInfo6 = new TrainingMaterialInfo(); + trainingMaterialInfo6.setTrainingMaterialId(10L); + trainingMaterialInfo6.setMaterialType(MaterialTypeEnum.other); + trainingMaterialInfo6.setContent("21"); + trainingMaterialInfo6.setTitle("交通厅其他资料"); + safetyKnowledgeMaterialInfoList.add(trainingMaterialInfo6); + trainingMaterialOverviewInfo.setOtherMaterialInfoList(otherMaterialInfoList); + + List allList = trainingMaterialOverviewInfo.getAllList(); + List materialSaveRecordList = new ArrayList<>(); + for (TrainingMaterialInfo trainingMaterialInfo : allList) { + TrainingOrganizationMaterial materialSaveRecord = new TrainingOrganizationMaterial(); + materialSaveRecord.setCreateBy(2L); + materialSaveRecord.setCreateOn(LocalDateTime.now()); + materialSaveRecord.setUpdateOn(LocalDateTime.now()); + materialSaveRecord.setMaterialType(trainingMaterialInfo.getMaterialType().name()); + materialSaveRecord.setTrainingMaterialId(trainingMaterialInfo.getTrainingMaterialId()); + materialSaveRecord.setTrainingOrganizationId(trainer.getTrainingOrganizationId()); + materialSaveRecordList.add(materialSaveRecord); + } + iTrainingOrganizationMaterialService.saveBatch(materialSaveRecordList); + } + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverDataImportTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverDataImportTest.java new file mode 100644 index 0000000..01926b7 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverDataImportTest.java @@ -0,0 +1,864 @@ +package com.ningdatech.carapi.driver; + + +import java.io.*; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.crypto.password.PasswordEncoder; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.*; +import com.ningdatech.carapi.driver.constant.DriverRegistrationStatusEnum; +import com.ningdatech.carapi.driver.constant.DriverStatusEnum; +import com.ningdatech.carapi.driver.constant.TrainingRegistrationFlagEnum; +import com.ningdatech.carapi.driver.constant.UserCanLoginEnum; +import com.ningdatech.carapi.driver.entity.Certificate; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.entity.DriverScoreInfo; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.driver.service.IDriverScoreInfoService; +import com.ningdatech.carapi.sys.contants.UserLoginConstant; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.IRegionService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.RSA; +import lombok.extern.slf4j.Slf4j; + +/** + * @author liuxinxin + * @date 2022/11/10 下午5:30 + */ +@Slf4j +public class DriverDataImportTest extends AppTests { + @Autowired + private IDriverInfoService iDriverInfoService; + @Autowired + private CompanyService companyService; + @Autowired + private IRegionService regionService; + @Autowired + private RegionsCacheHelper regionCacheHelper; + @Autowired + private INdUserInfoService iNdUserInfoService; + @Autowired + private INdUserAuthService iNdUserAuthService; + @Autowired + private UserRoleService userRoleService; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private ICertificateService certificateService; + @Autowired + private IDriverScoreInfoService iDriverScoreInfoService; + @Autowired + private IVehicleBaseInfoService vehicleBaseInfoService; + @Autowired + private OperatorsCacheHelper operatorsCacheHelper; + + @Value("${login.public-key}") + private String publicKey; + + @Value("${login.private-key}") + private String privateKey; + + @Test + public void importData() { + +// try { +// Workbook wb; +// File file = new File("/Users/liuxinxin/Desktop/driver_data_20221111.xls"); +// InputStream is = Files.newInputStream(file.toPath()); +// wb = Workbook.getWorkbook(is); +// +// Sheet sheet = wb.getSheet(0); +// int row_total = sheet.getRows(); +// +// List saveRecordList = new ArrayList<>(); +// List firmIdList = new ArrayList<>(); +// for (int j = 0; j < row_total; j++) { +// if (j >= 1) { +// Cell[] cells = sheet.getRow(j); +// String firmId = cells[53].getContents(); +// if (StringUtils.isNotBlank(firmId)) { +// firmIdList.add(Long.parseLong(firmId)); +// } +// } +// } +// Assert.assertNotNull(firmIdList); +// firmIdList = firmIdList.stream().distinct().collect(Collectors.toList()); +// List companyList = companyService.list(new QueryWrapper() +// .in("firm_id", firmIdList)); +// Map companyMap = companyList.stream().collect(Collectors.toMap(Company::getFirmId, Function.identity())); +// +// +// for (int j = 0; j < row_total; j++) { +// if (j >= 1) { +// Cell[] cells = sheet.getRow(j); +// DriverInfo saveRecord = new DriverInfo(); +// saveRecord.setDriverName(cells[1].getContents()); +//// saveRecord.setAvatarFile(cells[1].getContents()); +// saveRecord.setGender("男".equals(cells[3].getContents()) ? 1 : 0); +// saveRecord.setIdCard(cells[5].getContents()); +// +//// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); +//// LocalDateTime birth= LocalDateTime.parse(cells[2].getContents(), DateTimeFormatter.ofPattern("yyyy-MM-dd")); +//// saveRecord.setBirth(birth); +// +// saveRecord.setNativePlace(cells[21].getContents()); +// +//// saveRecord.setNativePlaceRegionCode(cells[1].getContents()); +// saveRecord.setPhoneNo(cells[4].getContents()); +// +// saveRecord.setHealth("良好"); +// saveRecord.setAddress(cells[13].getContents()); +// +// saveRecord.setDriverLicenseNo(cells[6].getContents()); +// +// String licenseClass = cells[7].getContents(); +// +// if (StringUtils.isNotBlank(licenseClass) && licenseClass.length() >= 2) { +// licenseClass = licenseClass.substring(0, 2); +// saveRecord.setDriverLicenseType(licenseClass); +// +// } +//// saveRecord.setCompanyId(cells[1].getContents()); +//// saveRecord.setCompanyName(cells[1].getContents()); +// saveRecord.setCreateOn(LocalDateTime.now()); +// saveRecord.setUpdateOn(LocalDateTime.now()); +// saveRecord.setDriverStatus(DriverStatusEnum.induction.name()); +//// saveRecord.setUserId(cells[1].getContents()); +//// saveRecord.setRegionId(cells[1].getContents()); +// +// saveRecord.setDriverRegistrationStatus(DriverRegistrationStatusEnum.available.name()); +//// saveRecord.setIllegalAndIllegalInfo(cells[1].getContents()); +//// saveRecord.setInitialLicenseTime(cells[1].getContents()); +//// saveRecord.setQuitTime(cells[1].getContents()); +//// saveRecord.setInductionTime(cells[1].getContents()); +// +//// saveRecord.setReplacementRegistrationStatus(cells[1].getContents()); +//// saveRecord.setContinuingEducationStatus(cells[1].getContents()); +// System.out.println(saveRecord); +// +//// iDriverInfoService.save(saveRecord); +// +// String firmId = cells[53].getContents(); +// if (StringUtils.isNotBlank(firmId)) { +// Company company = companyMap.get(Long.parseLong(firmId)); +// if (Objects.nonNull(company)) { +// saveRecord.setCompanyName(company.getName()); +// saveRecord.setCompanyId(company.getId()); +// saveRecord.setRegionId(company.getRegionId()); +// } +// } +// saveRecordList.add(saveRecord); +// } +// } +// +// List> split = SplitListUtils.split(saveRecordList, 500); +// for (List saveRecordList1 : split) { +// iDriverInfoService.saveBatch(saveRecordList1); +// } +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (BiffException e) { +// e.printStackTrace(); +// } + } + + + @Test + public void test() throws FileNotFoundException { + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\宁波驾驶员数据.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\宁波驾驶员数据-8-2.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\湖州安吉驾驶员.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\嘉兴驾驶员\\嘉兴驾驶员数据.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\丽水驾驶员\\丽水驾驶员数据.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\温州驾驶员\\温州驾驶员数据.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\驾驶员模板.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\金华市驾驶员.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\浙江丽水嘉城混凝土有限公司上岗证.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\台州市驾驶员.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\舟山市驾驶员数据-第一批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\绍兴市驾驶员数据-第一批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\温州平阳驾驶员数据-第二批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州南浔区驾驶员数据-第二批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\丽水遂昌驾驶员数据-第二批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\杭州富阳驾驶员数据-第二批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\杭州淳安驾驶员数据-第三批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\丽水莲都驾驶员数据-第三批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\温州苍南驾驶员数据-第三批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州南浔驾驶员数据-第四批.xlsx"); + //--------------------------------------------------------------------------- + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州吴兴驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州长合驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州常山驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州江山驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州开化驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州龙游驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州衢江驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\丽水莲都斯通驾驶员数据-第二批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州衢江市本级驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\衢州柯城驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州安吉驾驶员数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\嘉兴平湖驾驶员数据-第四批.xlsx"); + //--------------------------------------------------------------------------- + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州德清驾驶员数据-第五批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\湖州德清驾驶员数据-第五批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\嘉兴经开区驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\嘉兴海盐县驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\嘉兴秀洲区驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\丽水市驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\台州市驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\温州龙港市驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\舟山定海区驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\舟山高新区驾驶员数据-第六批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\绍兴上虞驾驶员数据-第六批.xlsx"); + //--------------------------------------------------------------------------- + //File f = new File("D:\\work\\水泥车驾驶员数据\\台州市驾驶员数据-第一批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\舟山市驾驶员数据-第七批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\丽水松阳驾驶员数据-第七批.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\温州市驾驶员-第七批-2022-2023.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\温州市驾驶员-第七批-2020-2021.xlsx"); + //File f = new File("D:\\work\\水泥车驾驶员数据\\金华东阳驾驶员数据-第七批.xlsx"); + //--------------------------------------------------------------------------- + //File f = new File("D:\\work\\水泥车驾驶员数据\\杭州钱塘驾驶员数据-第八批.xlsx"); + File f = new File("D:\\work\\水泥车驾驶员数据\\丽水松阳驾驶员数据-第八批.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + // 根据企业名查询企业信息 + HashSet companySet = new HashSet<>(); + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + for (int i = 1; i arrayList = Lists.newArrayList(); + if (motorcycleTypeList.contains(StrPool.DASH)){ + String[] split = motorcycleTypeList.split(StrPool.DASH); + List strings = Arrays.asList(split); + String collect = strings.stream().map(s -> { + DriverVehicleTypeEnum vehicleTypeEnum = DriverVehicleTypeEnum.getEnum(s); + return vehicleTypeEnum.name(); + }).collect(Collectors.joining(StrPool.COMMA)); + arrayList.add(collect); + }else { + DriverVehicleTypeEnum vehicleTypeEnum = DriverVehicleTypeEnum.getEnum(motorcycleTypeList); + if (Objects.nonNull(vehicleTypeEnum)) { + arrayList.add(vehicleTypeEnum.name()); + } + } + driverInfo.setMotorcycleTypeList(JSONObject.toJSONString(arrayList)); + iDriverInfoService.saveOrUpdate(driverInfo); + System.out.println("准备插入 " + i + "条:" + JSON.toJSONString(driverInfo)); + + + //生成合格证信息 + Certificate certificate = new Certificate(); + + certificate.setDriverId(driverInfo.getId()); + certificate.setUserId(driverInfo.getUserId()); + certificate.setDriverName(driverInfo.getDriverName()); + certificate.setBirth(driverInfo.getBirth()); + certificate.setGender(driverInfo.getGender()); + certificate.setNativePlace(driverInfo.getNativePlace()); + certificate.setHealth(driverInfo.getHealth()); + certificate.setPhoneNo(driverInfo.getPhoneNo()); + certificate.setAddress(driverInfo.getAddress()); + certificate.setDriverLicenseType(driverInfo.getDriverLicenseType()); + certificate.setDriverLicenseNo(driverInfo.getDriverLicenseNo()); + // 合格证书编号 + certificate.setCertificateNo(certificateNo); + // 发证单位 + certificate.setIssuedBy(issuedBy); + if (Objects.nonNull(issueDate)) { + certificate.setIssueDate(issueDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); + } + if (Objects.nonNull(expiryDate)) { + certificate.setExpiryDate(expiryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); + } + certificate.setRemark(null); + certificate.setRegionId(driverInfo.getRegionId()); + certificate.setRegionName(regionName); + certificate.setCompanyId(driverInfo.getCompanyId()); + certificate.setCompanyName(driverInfo.getCompanyName()); + certificate.setCreateOn(LocalDateTime.now()); + certificate.setUpdateOn(LocalDateTime.now()); + certificate.setCreateBy(2L); + certificateService.save(certificate); + //生成上车分数信息 + DriverScoreInfo driverScoreInfo = new DriverScoreInfo(); + driverScoreInfo.setCreateOn(LocalDateTime.now()); + driverScoreInfo.setCreateBy(2L); + driverScoreInfo.setUserId(driverInfo.getUserId()); + driverScoreInfo.setDriverId(driverInfo.getId()); + driverScoreInfo.setDriverScore(60); + iDriverScoreInfoService.save(driverScoreInfo); + System.out.println("准备插入 " + i + "条合格证信息:" + JSON.toJSONString(certificate)); + } + } + log.info("重复的手机号对应的用户ID为{}",userList.toString()); + System.out.println(userList); + } + + @Test + public void test2() throws FileNotFoundException { + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\0729\\宁波车辆数据.xlsx"); + File f = new File("D:\\work\\水泥车车辆数据\\丽水经济技术开发区车辆数据.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + HashSet useComSet = new HashSet<>(); + HashSet comSet = new HashSet<>(); + HashSet carSet = new HashSet<>(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + // 根据企业名查询企业信息 + HashSet companySet = new HashSet<>(); + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + List baseInfos = vehicleBaseInfoService.list().stream() + .filter(v -> Objects.isNull(v.getCompanyId())).collect(Collectors.toList()); + + Map baseInfoMap = baseInfos.stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + for (int i = 1; i < rownum; i++) { + + NdVehicleBaseInfo vehicleBaseInfo = new NdVehicleBaseInfo(); + + row = sheet.getRow(i); + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 车辆类型 + String carType = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + // 运营商 + String operatorName = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 使用企业 + String useCompanyName = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 所属企业 + String companyName = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + NdVehicleBaseInfo baseInfo = baseInfoMap.get(carPlate); + // 车牌号在无所属企业中 + if (Objects.nonNull(baseInfo)){ + vehicleBaseInfo.setId(baseInfo.getId()); + vehicleBaseInfo.setVehicleType(baseInfo.getVehicleType()); + vehicleBaseInfo.setOperatorId(baseInfo.getOperatorId()); + } + vehicleBaseInfo.setCarPlate(carPlate); + if (StringUtils.isNotBlank(carType)) { + vehicleBaseInfo.setVehicleType(VehicleTypeEnum.getCodeByDesc(carType)); + } + if (StringUtils.isNotBlank(operatorName)) { + OperatorQueryDTO operatorDto = operatorsCacheHelper.getByName(operatorName); + vehicleBaseInfo.setOperatorId(operatorDto.getId()); + } + // 更新车辆数据 + Company company = companyNameMap.get(companyName); + vehicleBaseInfo.setRegionId(company.getRegionId()); + vehicleBaseInfo.setRegionName(regionCacheHelper.getDisplayName(company.getRegionId())); + vehicleBaseInfo.setCompanyId(company.getId()); + vehicleBaseInfo.setUseCompanyId(company.getId()); + vehicleBaseInfo.setUseCompanyName(company.getName()); + vehicleBaseInfo.setAuditState(AuditStateEnum.AUDIT_SUCCESS.getCode()); + vehicleBaseInfo.setVehicleStatus(CarStatusEnum.ENABLE.getCode()); + vehicleBaseInfoService.saveOrUpdate(vehicleBaseInfo); + System.out.println("准备插入 " + i + "条:" + JSON.toJSONString(vehicleBaseInfo)); + } + } + } + + @Test + public void test3() throws FileNotFoundException { + File f = new File("D:\\work\\水泥车车辆数据\\非所属企业车辆.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据企业名查询企业信息 + HashSet companySet = new HashSet<>(); + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + Map baseInfoMap = vehicleBaseInfoService.list().stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + List comList = Lists.newArrayList(); + List carList = Lists.newArrayList(); + for (int i = 1; i < rownum; i++) { + + row = sheet.getRow(i); + // 所属企业 + String companyName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + Company company = companyNameMap.get(companyName); + if (Objects.isNull(company)){ + log.info("企业:{} 不在系统中",companyName); + comList.add(companyName); + } + NdVehicleBaseInfo baseInfo = baseInfoMap.get(carPlate); + if (Objects.isNull(baseInfo)){ + log.info("车牌号:{} 不在系统中",carPlate); + carList.add(carPlate); + continue; + } + // 更新车辆信息 + // 如果车辆所在区域、所属企业和公司及所在区域相同,才更新 + Long regionId = baseInfo.getRegionId(); + Long companyId = baseInfo.getCompanyId(); + + Long companyRegionId = company.getRegionId(); + Long id = company.getId(); + + if (Objects.nonNull(regionId) && Objects.nonNull(companyId) + && regionId.equals(companyRegionId) && companyId.equals(id)) { + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(NdVehicleBaseInfo.class); + updateWrapper.set(NdVehicleBaseInfo::getCompanyId, null) + .set(NdVehicleBaseInfo::getUseCompanyId, null) + .set(NdVehicleBaseInfo::getUseCompanyName, null) + .set(NdVehicleBaseInfo::getRegionId, null) + .set(NdVehicleBaseInfo::getRegionName, null) + .eq(NdVehicleBaseInfo::getCarPlate, baseInfo.getCarPlate()); + vehicleBaseInfoService.update(updateWrapper); + System.out.println("准备更新 " + i + "条:" + JSON.toJSONString(baseInfo)); + } + } + } + } + + @Test + public void test4() throws FileNotFoundException { + //File f = new File("D:\\work\\水泥车车辆数据\\丽水中航混凝土有限公司车辆数据.xlsx"); + //File f = new File("D:\\work\\水泥车车辆数据\\丽水莲都区车辆数据-第二批.xlsx"); + //File f = new File("D:\\work\\水泥车车辆数据\\绍兴上虞区车辆数据-第四批.xlsx"); + //File f = new File("D:\\work\\水泥车车辆数据\\舟山定海车辆数据-第五批.xlsx"); + //File f = new File("D:\\work\\水泥车车辆数据\\绍兴柯桥车辆数据-第六批.xlsx"); + File f = new File("D:\\work\\水泥车车辆数据\\丽水松阳车辆数据-第六批.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + HashSet useComSet = new HashSet<>(); + HashSet comSet = new HashSet<>(); + HashSet carSet = new HashSet<>(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + // 根据企业名查询企业信息 + HashSet companySet = new HashSet<>(); + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + // 系统中已经存在的车辆(包括无所属企业的车辆) + List baseInfos = vehicleBaseInfoService.list(); + + Map baseInfoMap = baseInfos.stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + for (int i = 1; i < rownum; i++) { + + NdVehicleBaseInfo vehicleBaseInfo = new NdVehicleBaseInfo(); + + row = sheet.getRow(i); + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 车牌颜色 + String plateColor = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : StringUtils.EMPTY; + // 车辆类型 + String vehicleType = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 总质量 + String standardTonnage = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 发动机号 + String engineNo = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 底盘号 + String chassisNo = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 运营商 + String operatorName = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 责任驾驶员一 + String responsibleDriverFirst = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 责任驾驶员一 电话 + String responsibleDriverFirstMobile = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + // 排放标准 + String effluentDischargeStandard = Objects.nonNull(row.getCell(9)) ? row.getCell(9).toString() : StringUtils.EMPTY; + // 使用年限 + String usefulLife = Objects.nonNull(row.getCell(10)) ? row.getCell(10).toString() : StringUtils.EMPTY; + // 使用企业 + String useCompanyName = Objects.nonNull(row.getCell(11)) ? row.getCell(11).toString() : StringUtils.EMPTY; + // 所属企业 + String companyName = Objects.nonNull(row.getCell(12)) ? row.getCell(12).toString() : StringUtils.EMPTY; + // 自编号 + String selfNo = Objects.nonNull(row.getCell(13)) ? row.getCell(13).toString() : StringUtils.EMPTY; + // 整备质量 + String selfWeight = Objects.nonNull(row.getCell(14)) ? row.getCell(14).toString() : StringUtils.EMPTY; + NdVehicleBaseInfo baseInfo = baseInfoMap.get(carPlate); + // 车牌号在无所属企业中 + if (Objects.nonNull(baseInfo)){ + vehicleBaseInfo.setId(baseInfo.getId()); + } + vehicleBaseInfo.setCarPlate(carPlate); + vehicleBaseInfo.setPlateColor(plateColor); + if (StringUtils.isNotBlank(vehicleType)) { + vehicleBaseInfo.setVehicleType(VehicleTypeEnum.getCodeByDesc(vehicleType)); + } + vehicleBaseInfo.setStandardTonnage(Double.valueOf(standardTonnage)); + vehicleBaseInfo.setEngineNo(engineNo); + vehicleBaseInfo.setChassisNo(chassisNo); + OperatorQueryDTO operatorDto = operatorsCacheHelper.getByName(operatorName); + if (Objects.nonNull(operatorDto)) { + vehicleBaseInfo.setOperatorId(operatorDto.getId()); + } + vehicleBaseInfo.setResponsibleDriverFirst(responsibleDriverFirst); + vehicleBaseInfo.setResponsibleDriverFirstMobile(responsibleDriverFirstMobile); + vehicleBaseInfo.setEffluentDischargeStandard(effluentDischargeStandard); + if (StringUtils.isNotBlank(usefulLife)) { + Integer life = (int) Double.parseDouble(usefulLife); + vehicleBaseInfo.setUsefulLife(life); + } + if (StringUtils.isNotBlank(selfNo)) { + vehicleBaseInfo.setSelfNo(selfNo); + } + if (StringUtils.isNotBlank(selfWeight)) { + vehicleBaseInfo.setSelfWeight(Double.valueOf(selfWeight)); + } + // 更新车辆数据 + Company company = companyNameMap.get(companyName); + vehicleBaseInfo.setRegionId(company.getRegionId()); + vehicleBaseInfo.setRegionName(regionCacheHelper.getDisplayName(company.getRegionId())); + vehicleBaseInfo.setCompanyId(company.getId()); + vehicleBaseInfo.setUseCompanyId(company.getId()); + vehicleBaseInfo.setUseCompanyName(useCompanyName); + vehicleBaseInfo.setAuditState(AuditStateEnum.AUDIT_SUCCESS.getCode()); + vehicleBaseInfo.setVehicleStatus(CarStatusEnum.ENABLE.getCode()); + vehicleBaseInfoService.saveOrUpdate(vehicleBaseInfo); + System.out.println("准备插入 " + i + "条:" + JSON.toJSONString(vehicleBaseInfo)); + } + } + } + + @Test + public void test5(){ + //String username = "dImMTGYAPmUVoRZFly0RTadTvwASVSizaSuH9LFstFJb3t1Izz4HxlNUcE1x7VfwxJDHeWmQOL8Tl/KdWFZXC6lfyfoh1l4jEyInvgHIEBI9cHfxg14IcvCMZ/mEfdcn/BovjSc52vQuBy+EnD65zj6VUiCSJbssleqWjfSKWVc="; + String pwd = "ThcjwYO/IU1IKdQ5CivzyVreUBLXK79Qhe6DzEhjNWwOf3iGtz8yM0oUG8Ffhy2WqKEqXZ09vSBQm5uSY/U1Yyl2+j1NRIVAg3N5Q6n3nNV5lVFNSoCqhc8vGkRZArkOFJ1Pk5wDn45SHomB2LzKFiDUeckAkIR7RBKkVpfKFPQ="; + // 将获取到的经过RSA公钥加密后的用户名解密 + RSA rsa = new RSA(privateKey, publicKey); + + // 密码的密文先进行base64解码,之后再进行解密 + //String decryptStr = rsa.decryptStr(username, KeyType.PrivateKey); + String decryptStr = rsa.decryptStr(pwd, KeyType.PrivateKey); + //byte[] decrypt = rsa.decrypt(Base64.decode(username), KeyType.PrivateKey); + //String decryptStr = StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8); + + System.out.println("解密后的用户名为:" + decryptStr); + } + + @Test + public void test6() throws FileNotFoundException { + File f = new File("D:\\work\\水泥车安全通报\\事故车牌号.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + List carPlates = Lists.newArrayList(); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 车牌号 + String carPlate = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + StringBuilder sb = new StringBuilder(); + sb.append("\"" + carPlate + "\""); + String s = sb.toString(); + carPlates.add(s); + } + + String collect = carPlates.stream().collect(Collectors.joining(StrPool.COMMA)); + System.out.println(collect); + } + } + + @Test + public void test7(){ + // 获取系统车辆信息 + List baseInfos = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode()) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getVehicleType)); + if (CollUtil.isNotEmpty(baseInfos)) { + baseInfos.stream().filter(v -> StringUtils.isNotBlank(v.getCarPlate()) && Objects.nonNull(v.getVehicleType())) + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getVehicleType)); + } + } + + //这个下面是单独函数 + public static org.apache.poi.ss.usermodel.Workbook readExcel(InputStream is, String extString){ + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if(".xls".equals(extString)){ + return wb = new HSSFWorkbook(is); + }else if(".xlsx".equals(extString)){ + return wb = new XSSFWorkbook(is); + }else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } + + //public fileout void main(String[] args) { + // String a = "2023-02-06"; + // LocalDateTime birthTime = LocalDateTime.parse(a, DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + // System.out.println(birthTime); + //} + +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverStarDataImportTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverStarDataImportTest.java new file mode 100644 index 0000000..d233553 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/DriverStarDataImportTest.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.driver; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.driver.entity.DriverInfo; +import com.ningdatech.carapi.driver.entity.StarManage; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.driver.service.IStarManageService; +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author liuxinxin + * @date 2022/11/16 下午2:56 + */ + +class DriverStarDataImportTest extends AppTests { + + @Autowired + private IDriverInfoService iDriverInfoService; + + @Autowired + private IStarManageService iStarManageService; + + + @Test + void importData() throws Exception { +// long count = iDriverInfoService.count(Wrappers.lambdaQuery(DriverInfo.class) +// .isNotNull(DriverInfo::getCompanyId)); + int pageNumber = 1; + int pageSize = 500; + + while (true) { + Page page = iDriverInfoService.page(new Page<>(pageNumber, pageSize), Wrappers.lambdaQuery(DriverInfo.class) + .isNotNull(DriverInfo::getCompanyId).orderByAsc(DriverInfo::getId)); + if (page.getTotal() == 0) { + return; + } + pageNumber++; + List records = page.getRecords(); + List collect = records.stream().map(r -> { + StarManage starManage = new StarManage(); + starManage.setCreateOn(LocalDateTime.now()); + starManage.setUpdateOn(LocalDateTime.now()); + starManage.setDriverId(r.getId()); + starManage.setDriverName(r.getDriverName()); + starManage.setCompanyId(r.getCompanyId()); + starManage.setCompanyName(r.getCompanyName()); + starManage.setRegionId(r.getRegionId()); + starManage.setAccidentsCnt(0); + starManage.setInjuredCnt(0); + starManage.setInsuranceCnt(0); + starManage.setInjuredCnt(0); + starManage.setCurrentStar(5D); + starManage.setDeductStar(0D); + starManage.setAccidentsCnt(0); + return starManage; + }).collect(Collectors.toList()); + Assert.assertTrue(iStarManageService.saveBatch(collect)); + } + } + + +} \ No newline at end of file diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/SplitListUtils.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/SplitListUtils.java new file mode 100644 index 0000000..81c5e1d --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/driver/SplitListUtils.java @@ -0,0 +1,27 @@ +package com.ningdatech.carapi.driver; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author liuxinxin + * @date 2022/8/23 下午4:31 + */ + +public class SplitListUtils { + + public static List> split(List list, int groupSize) { + int length = list.size(); + // 计算可以分成多少组 + int num = (length + groupSize - 1) / groupSize; + List> newList = new ArrayList<>(num); + for (int i = 0; i < num; i++) { + // 开始位置 + int fromIndex = i * groupSize; + // 结束位置 + int toIndex = (i + 1) * groupSize < length ? (i + 1) * groupSize : length; + newList.add(list.subList(fromIndex, toIndex)); + } + return newList; + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/AliSmsTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/AliSmsTest.java new file mode 100644 index 0000000..d5db6a0 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/AliSmsTest.java @@ -0,0 +1,39 @@ +package com.ningdatech.carapi.loginbycode; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSONObject; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.ningdatech.carapi.loginbycode.utils.AliSmsUtil; + +/** + * @author CMM + * @since 2022/12/28 14:44 + */ + +public class AliSmsTest { + public static void main(String[] args) { + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + String sd = sdf.format(new Date()); + String phone = "********"; + String template = "********"; + String name = "********"; + Map map = new HashMap<>(4); + map.put("transportNo",name); + map.put("hour",sd); + // 对象转json + JSONObject jsonObject = (JSONObject) JSONObject.toJSON(map); + AliSmsUtil aliSmsUtil = new AliSmsUtil(); + // 发送短信 + SendSmsResponse sendSmsResponse = aliSmsUtil.sendSms(phone,jsonObject,template); + if("OK".equals(sendSmsResponse.getCode())){ + System.out.println("发送成功"); + }else { + System.out.println("发送失败"); + } + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/config/Config.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/config/Config.java new file mode 100644 index 0000000..bbda9ae --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/config/Config.java @@ -0,0 +1,35 @@ +package com.ningdatech.carapi.loginbycode.config; + +/** + * @author CMM + * @since 2022/12/28 14:00 + */ + +public class Config { + // 所有参数,可自定义根据需求,配置成application.properties 用@value()注入 + /** + * 产品名称: 云通信短信API产品,开发者无需替换 + */ + public static final String PRODUCT = "Dysmsapi"; + + /** + * 产品域名,开发者无需更换 + */ + public static final String DOMAIN = "dysmsapi.aliyuncs.com"; + + /** + * 开发者自己的AccessKeyID + */ + public static final String ACCESS_KEYID = "********"; + + /** + * 开发者自己的AccessKeySecret + */ + public static final String ACCESSKEY_SECRET = "********"; + + /** + * 短信签名--可在短信控制台中找到 + */ + public static final String SIGN = "****"; + +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/utils/AliSmsUtil.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/utils/AliSmsUtil.java new file mode 100644 index 0000000..b9b7836 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/loginbycode/utils/AliSmsUtil.java @@ -0,0 +1,106 @@ +package com.ningdatech.carapi.loginbycode.utils; + +import static com.ningdatech.carapi.loginbycode.config.Config.*; + +import com.alibaba.fastjson.JSONObject; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.FormatType; +import com.aliyuncs.http.MethodType; +import com.aliyuncs.profile.DefaultProfile; +import com.aliyuncs.profile.IClientProfile; + +/** + * @author ouj + * 版本: 阿里云云通信 + * jar包: aliyun-java-sdk-core and aliyun-java-sdk-dysmsapi + * 编码格式:UTF-8 + * 需要参数: 签名名称 / 模板code / RAM访问控制中的 AccessKeyID 和 AccessKeySecret + */ +public class AliSmsUtil { + + /** + * IAcsClient是aliyun-java-sdk-green的Java客户端。使用aliyun-java-sdk-green Java SDK发起请求前,您需要初始化一个IAcsClient实例,并根据需要修改IClientProfile的配置项。 + */ + public IAcsClient acsClient; + + /** + * 配置超时时间,初始化acsClient + * + * @return + * @throws + */ + public IAcsClient getInstant() throws ClientException { + if (acsClient == null) { + // 配置超时时间 + System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); + System.setProperty("sun.net.client.defaultReadTimeout", "10000"); + //初始化acsClient,暂不支持region化 + IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEYID, ACCESSKEY_SECRET); + DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", PRODUCT, DOMAIN); + return acsClient = new DefaultAcsClient(profile); + } + return acsClient; + } + + /** + * 创建短信发送请求 + * @param mobile 手机号 + * @param jsonObject json数据 + * @param templateCode 短信模板 + * @return + * @throws ClientException + */ + public SendSmsResponse getSmsCodeClient(String mobile, JSONObject jsonObject, String templateCode) throws ClientException { + //组装请求对象-具体描述见控制台-文档部分内容 + SendSmsRequest request = new SendSmsRequest(); + //修改数据提交方式 + request.setMethod(MethodType.POST); + //修改数据交互格式 + request.setAcceptFormat(FormatType.JSON); + //必填:待发送手机号 + request.setPhoneNumbers(mobile); + //必填:短信签名-可在短信控制台中找到 + request.setSignName(SIGN); + //必填:短信模板-可在短信控制台中找到 + request.setTemplateCode(templateCode); + //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为 + request.setTemplateParam(jsonObject.toString()); + + return getInstant().getAcsResponse(request); + } + + /** + * 发送短信 + * + * @param mobile 手机号码 + * @param jsonObject json数据 + * @param templateCode 短信模板 + * @return + */ + public SendSmsResponse sendSms(String mobile, JSONObject jsonObject, String templateCode) { + SendSmsResponse smsResponse = null; + try{ + smsResponse = getSmsCodeClient(mobile,jsonObject,templateCode); + } catch (ClientException e) { + e.printStackTrace(); + } + // 发生业务错误 + if ("isv.BUSINESS_LIMIT_CONTROL".equals(smsResponse.getCode())) { + String message = smsResponse.getMessage(); + String limitNum = message.substring(message.length() - 1); + if ("5".equals(limitNum)) { + // 此处可自定义业务异常 + throw new RuntimeException("获取次数已达上线,请过一小时再试"); + } else if (limitNum.equals("0")) { + throw new RuntimeException("获取次数已达上线,请明日再试"); + } else if (limitNum.equals("1")) { + throw new RuntimeException("获取次数已达上线,请过一分钟再试"); + } + } + return smsResponse; + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/open/OpenApiTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/open/OpenApiTest.java new file mode 100644 index 0000000..ba49bf3 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/open/OpenApiTest.java @@ -0,0 +1,294 @@ +package com.ningdatech.carapi.open; + +import java.sql.Timestamp; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.cache.redis.RedisOps; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.homepage.entity.model.OnlineNumCnt; +import com.ningdatech.carapi.irs.model.entity.VehicleAccidentIrsData; +import com.ningdatech.carapi.irs.service.IVehicleAccidentIrsDataService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @Classname OpenApiTest + * @Description + * @Date 2022/11/3 10:47 + * @Created by PoffyZhang + */ +@Slf4j +public class OpenApiTest extends AppTests { + + @Autowired + private IVehicleBaseInfoService vehicleBaseInfoService; + @Autowired + private CachePlusOps cachePlusOps; + @Autowired + private IVehicleAccidentIrsDataService accidentIrsDataService; + + @Autowired + private RedisOps redisOps; + + + @Test + public void test(){ + + TreeMap fieldMap = new TreeMap<>(); + fieldMap.put("appKey","test"); + fieldMap.put("timestamps","1667444946960"); + fieldMap.put("originPicId","0000001"); + fieldMap.put("vehicleIndexCode","10000001"); + fieldMap.put("vehicleSelfNo","20000001"); + fieldMap.put("cameraIndexCode","sssss00001"); + fieldMap.put("cameraName","监控点1"); + fieldMap.put("uploadType","2"); + fieldMap.put("alarmId","300000001"); + fieldMap.put("alarmType","1001"); + fieldMap.put("alarmTypeName","开车接听电话"); + fieldMap.put("captureTime","2022-10-28"); + fieldMap.put("url","https://www.baidu.com"); + fieldMap.put("thumbUrl","1"); + fieldMap.put("parentPicId","1"); + fieldMap.put("faceRect","2"); + fieldMap.put("picType","3"); + fieldMap.put("plateNo","浙Axxxx"); + fieldMap.put("regionIndexCode","330107"); + fieldMap.put("regionName","滨江区"); + fieldMap.put("serialVersionUID","1"); + String appSecret = "test"; + String str = "{\"appKey\":\"test\",\"timestamps\":1667444946960,\"originPicId\":\"0000001\",\"vehicleIndexCode\":\"10000001\",\"vehicleSelfNo\":\"20000001\",\"cameraIndexCode\":\"sssss00001\",\"cameraName\":\"监控点1\",\"uploadType\":2,\n" + + " \"alarmId\":\"300000001\",\"alarmType\":\"1001\",\"alarmTypeName\":\"开车接听电话\",\"captureTime\":\"2022-10-28\",\"url\":\"https://www.baidu.com\",\"thumbUrl\":\"1\",\n" + + " \"parentPicId\":\"1\",\"faceRect\":\"2\",\"picType\":\"3\",\"plateNo\":\"浙Axxxx\",\"regionIndexCode\":\"330107\",\"regionName\":\"滨江区\"}"; +// TreeMap fieldMap = jsonStrToMap(str); + String paramStr = fieldMap.entrySet().stream() + .map(w -> w.getKey() + "=" + w.getValue()) + .collect(Collectors.joining("&")); + String hex = SecureUtil.hmacMd5(appSecret).digestHex(paramStr); + System.out.println(hex); + } + + @Test + public void sysout(){ + System.out.println(System.currentTimeMillis()); + } + + @Test + public void video(){ + TreeMap fieldMap = new TreeMap<>(); + fieldMap.put("appKey","test"); + fieldMap.put("timestamps","1667444946960"); + fieldMap.put("orginVideoId","0000001"); + fieldMap.put("serviceIndexCode","4000001"); + fieldMap.put("recordIndexCode","0001"); + fieldMap.put("vehicleIndexCode","10000001"); + fieldMap.put("vehicleSelfNo","20000001"); + fieldMap.put("cameraIndexCode","sssss00001"); + fieldMap.put("cameraName","监控点1"); + fieldMap.put("alarmId","300000001"); + fieldMap.put("alarmTime","2022-11-06 00:00:00"); + fieldMap.put("alarmType","1001"); + fieldMap.put("alarmTypeName","开车接听电话"); + fieldMap.put("url","https://www.baidu.com"); + fieldMap.put("coverUrl","1"); + fieldMap.put("beginTime","2022-11-02 00:00:00"); + fieldMap.put("endTime","2022-11-02 00:00:00"); + fieldMap.put("streamBeginTime","2022-11-02 00:00:00"); + fieldMap.put("streamEndTime","2022-11-02 00:00:00"); + fieldMap.put("regionIndexCode","330107"); + fieldMap.put("regionName","滨江区"); + fieldMap.put("videoLength","60"); + fieldMap.put("plateNo","浙Axxxx"); + fieldMap.put("serialVersionUID","1"); + String appSecret = "test"; + String str = "{\"appKey\":\"test\",\"timestamps\":1667444946960,\"originPicId\":\"0000001\",\"vehicleIndexCode\":\"10000001\",\"vehicleSelfNo\":\"20000001\",\"cameraIndexCode\":\"sssss00001\",\"cameraName\":\"监控点1\",\"uploadType\":2,\n" + + " \"alarmId\":\"300000001\",\"alarmType\":\"1001\",\"alarmTypeName\":\"开车接听电话\",\"captureTime\":\"2022-10-28\",\"url\":\"https://www.baidu.com\",\"thumbUrl\":\"1\",\n" + + " \"parentPicId\":\"1\",\"faceRect\":\"2\",\"picType\":\"3\",\"plateNo\":\"浙Axxxx\",\"regionIndexCode\":\"330107\",\"regionName\":\"滨江区\"}"; +// TreeMap fieldMap = jsonStrToMap(str); + String paramStr = fieldMap.entrySet().stream() + .map(w -> w.getKey() + "=" + w.getValue()) + .collect(Collectors.joining("&")); + String hex = SecureUtil.hmacMd5(appSecret).digestHex(paramStr); + System.out.println(hex); + } + + private final Integer cnt1 = 0; + @Test + public void onlineNum(){ + // 获取所有车辆信息 + List vehicleBaseInfos = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getOperatorId, + NdVehicleBaseInfo::getId)); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + Map onlineMap = redisOps.hGetAll("online_index"); + // 分批 + List> batchList = new ArrayList<>(ListUtil.partition(new ArrayList<>(vehicleBaseInfos), 5000)); + // 创建线程池 线程数是 分批的数 + ExecutorService executorService = Executors.newFixedThreadPool(batchList.size()); + //线程计数器,就是 分批的数 + CountDownLatch countDownLatch = new CountDownLatch(batchList.size()); + List cntList = Lists.newArrayList(); + batchList.forEach(e -> { + //每个分批用一个线程执行 + executorService.execute(()->{ + List result = e.stream().filter(v -> { + // 取到每个数据进行业务执行 + String carPlate = v.getCarPlate(); + LocalDateTime startTime = LocalDateTime.now(); + Integer timeStamp = onlineMap.get(carPlate); + if (Objects.nonNull(timeStamp)) { + // 将时间戳转换为Instant对象 + Instant instant = Instant.ofEpochSecond(timeStamp); + // 将Instant对象转换为LocalDateTime对象 + LocalDateTime endTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + Duration minuteDuration = Duration.between(startTime, endTime); + long minute = minuteDuration.toMinutes(); + // 判断最后一次上传时间距离当前时间是否大于5分钟 + if (minute <= 5) { + return true; + } + } + return false; + }).collect(Collectors.toList()); + OnlineNumCnt onlineNumCnt = new OnlineNumCnt(); + onlineNumCnt.setCnt(result.size()); + cntList.add(onlineNumCnt); + }); + countDownLatch.countDown(); + }); + + stopWatch.stop(); + log.info("共耗时 {}s", stopWatch.getTotalTimeSeconds()); + int cnt = 0; + for (OnlineNumCnt onlineNumCnt : cntList) { + Integer onlineNum = onlineNumCnt.getCnt(); + cnt = cnt + onlineNum; + } + log.info("缓存中车辆在线数为:" + cnt); + } + + @Test + public void jsonTest(){ + // 获取车牌号的所有事故信息 + //Map> accidentIrsDataMap = accidentIrsDataService.list().stream() + // .collect(Collectors.groupingBy(VehicleAccidentIrsData::getCarPlate)); + + // 获取车牌号的所有事故信息 + Map> accidentIrsDataMap = null; + //String dataJsonStr = "{\"code\":\"00\",\"msg\":\"成功\",\"data\":\"\",\"datas\":\"[[{\\\"TJSGBH\\\":null,\\\"LM\\\":\\\"海\n" + + // "宁市农丰路\\\",\\\"CLJSG\\\":\\\"6\\\",\\\"SSRS\\\":0,\\\"LWSGLX\\\":null,\\\"BADW\\\":\\\"海宁市公安局交通警察大队\\\",\\\"DCSG\\\":null,\\\"SCSJD\\\":0,\\\"RDYYFL\\\":null,\\\"GLS\\\":1003,\\\"SB\\\":null,\\\"GLBM\\\":\\\"330481006200\\\",\\\"SGFSSJ\\\":1678750636000\n" + + // ",\\\"CCLRSJ\\\":1678751217000,\\\"SGRDYY\\\":null,\\\"JBR\\\":\\\"朱洁林\\\",\\\"ZBLX\\\":null,\\\"JYAQ\\\":\\\"2023年03月14日07时37分许,朱晨霓 (驾驶证号:330481198408070022) 驾驶车辆号牌浙F9230F小型汽车,在浙江省嘉兴市海宁市硖石街道农丰\n" + + // "路南苑路口 与田夫勇 (驾驶证号:371322197609083813) 驾驶车辆号牌浙FM8761大型汽车发生交通事故。当事人朱晨霓转弯未让直行车辆先行负全责;当事人田夫勇负无责。\\\",\\\"DZZB\\\":\\\"120.700542,30.514331\\\",\\\"SWSG\\\":null,\\\"SJHM1\\\n" + + // "\":\\\"13656604531\\\",\\\"SJHM2\\\":null,\\\"MS\\\":0,\\\"GXSJ\\\":1678751230000,\\\"JYW\\\":\\\"59076598972026599116453825079992\\\",\\\"DAH\\\":null,\\\"XC\\\":null,\\\"DJBH\\\":\\\"33048120230011595\\\",\\\"JLLX\\\":null,\\\"SSZD\\\":\\\"330481006200\\\",\\\"GLX\n" + + // "ZDJ\\\":null,\\\"XZQH\\\":\\\"330481\\\",\\\"PZFS\\\":null,\\\"SGDD\\\":\\\"海宁市农丰路(南苑路口)\\\",\\\"TJR1\\\":null,\\\"LBQK\\\":null,\\\"DLLX\\\":\\\"22\\\",\\\"SFZMHM1\\\":\\\"330482198203205719\\\",\\\"SGXT\\\":\\\"11\\\",\\\"ZJCCSS\\\":1,\\\"SFZMHM2\\\":null,\\\"XQ\\\n" + + // "\":2,\\\"LH\\\":\\\"67014\\\",\\\"SGBH\\\":\\\"330481420230011578\\\",\\\"TQ\\\":\\\"1\\\",\\\"JDWZ\\\":550},{\\\"TJSGBH\\\":null,\\\"LM\\\":\\\"海宁市马桥街道经编四路\\\",\\\"CLJSG\\\":\\\"9\\\",\\\"SSRS\\\":0,\\\"LWSGLX\\\":null,\\\"BADW\\\":\\\"海宁市公安局交通警察大队\\\"\n" + + // ",\\\"DCSG\\\":null,\\\"SCSJD\\\":0,\\\"RDYYFL\\\":null,\\\"GLS\\\":1002,\\\"SB\\\":null,\\\"GLBM\\\":\\\"330481005200\\\",\\\"SGFSSJ\\\":1678848921000,\\\"CCLRSJ\\\":1678852288000,\\\"SGRDYY\\\":null,\\\"JBR\\\":\\\"刘晓林\\\",\\\"ZBLX\\\":null,\\\"JYAQ\\\":\\\"2023年0\n" + + // "3月15日10时55分许,史帅彪 (驾驶证号:412326199705092718) 驾驶车辆号牌浙F2BL86轻型货车,在浙江省嘉兴市海宁市马桥街道经编四路16号海宁市彩达包装材料有限公司厂内 因操作失误与田夫勇 (驾驶证号:371322197609083813) 驾驶\n" + + // "车辆号牌浙FM8761重型货车发生交通事故,造成财产损失,当事人史帅彪负全责,当事人田夫勇负无责;。\\\",\\\"DZZB\\\":\\\"120.678630,30.479932\\\",\\\"SWSG\\\":null,\\\"SJHM1\\\":\\\"15167388545\\\",\\\"SJHM2\\\":null,\\\"MS\\\":0,\\\"GXSJ\\\":1678852\n" + + // "301000,\\\"JYW\\\":\\\"99790670379267313188861065794064\\\",\\\"DAH\\\":null,\\\"XC\\\":null,\\\"DJBH\\\":\\\"33048120230011858\\\",\\\"JLLX\\\":null,\\\"SSZD\\\":\\\"330481005200\\\",\\\"GLXZDJ\\\":null,\\\"XZQH\\\":\\\"330481\\\",\\\"PZFS\\\":null,\\\"SGDD\\\":\\\"海\n" + + // "宁市马桥街道经编四路(经编三路至新民路)\\\",\\\"TJR1\\\":null,\\\"LBQK\\\":null,\\\"DLLX\\\":\\\"29\\\",\\\"SFZMHM1\\\":\\\"33048119881119501X\\\",\\\"SGXT\\\":\\\"12\\\",\\\"ZJCCSS\\\":1000,\\\"SFZMHM2\\\":null,\\\"XQ\\\":3,\\\"LH\\\":\\\"97010\\\",\\\"SGBH\\\":\\\"33048\n" + + // "1420230011840\\\",\\\"TQ\\\":\\\"1\\\",\\\"JDWZ\\\":200},{\\\"TJSGBH\\\":null,\\\"LM\\\":\\\"常海线(G524)\\\",\\\"CLJSG\\\":\\\"7\\\",\\\"SSRS\\\":1,\\\"LWSGLX\\\":null,\\\"BADW\\\":\\\"海宁市公安局交通警察大队\\\",\\\"DCSG\\\":null,\\\"SCSJD\\\":0,\\\"RDYYFL\\\":null,\\\"\n" + + // "GLS\\\":180,\\\"SB\\\":\\\"1\\\",\\\"GLBM\\\":\\\"330481000000\\\",\\\"SGFSSJ\\\":1679614140000,\\\"CCLRSJ\\\":1679630991000,\\\"SGRDYY\\\":null,\\\"JBR\\\":\\\"韩家振\\\",\\\"ZBLX\\\":\\\"2\\\",\\\"JYAQ\\\":\\\" 2023年03月24日07时29分,徐银甫(男,65岁)驾驶车\n" + + // "牌号为浙FCZ483的普通摩托车,沿常海线(G524)行驶至常海线(G524)185KM+382M海宁市汇浪桥路段时,与田夫勇(男,47岁)驾驶车牌号为浙FM8761的重型货车碰撞运动车辆,致受伤1人,直接财产损失1000元的交通事故。\\\\r\\\\n 当事\n" + + // "人徐银甫负全部责任;当事人田夫勇无责任。\\\",\\\"DZZB\\\":null,\\\"SWSG\\\":null,\\\"SJHM1\\\":\\\"13806703150\\\",\\\"SJHM2\\\":null,\\\"MS\\\":10,\\\"GXSJ\\\":1679631053000,\\\"JYW\\\":\\\"07721463458575243981940373724857\\\",\\\"DAH\\\":null,\\\"XC\\\":n\n" + + // "ull,\\\"DJBH\\\":\\\"33048120230013692\\\",\\\"JLLX\\\":\\\"1\\\",\\\"SSZD\\\":null,\\\"GLXZDJ\\\":\\\"1\\\",\\\"XZQH\\\":\\\"330481\\\",\\\"PZFS\\\":null,\\\"SGDD\\\":\\\"常海线(G524)185KM+382M海宁市汇浪桥路段\\\",\\\"TJR1\\\":\\\"韩家振\\\",\\\"LBQK\\\":null,\\\"DLLX\\\"\n" + + // ":\\\"11\\\",\\\"SFZMHM1\\\":\\\"330419197212202035\\\",\\\"SGXT\\\":\\\"11\\\",\\\"ZJCCSS\\\":1000,\\\"SFZMHM2\\\":null,\\\"XQ\\\":5,\\\"LH\\\":\\\"10524\\\",\\\"SGBH\\\":\\\"330481420230013673\\\",\\\"TQ\\\":\\\"2\\\",\\\"JDWZ\\\":180010},{\\\"TJSGBH\\\":null,\\\"LM\\\":\\\"常海\n" + + // "线(G524)\\\",\\\"CLJSG\\\":\\\"9\\\",\\\"SSRS\\\":0,\\\"LWSGLX\\\":null,\\\"BADW\\\":\\\"海宁市公安局交通警察大队\\\",\\\"DCSG\\\":null,\\\"SCSJD\\\":112,\\\"RDYYFL\\\":null,\\\"GLS\\\":200,\\\"SB\\\":\\\"1\\\",\\\"GLBM\\\":\\\"330481000300\\\",\\\"SGFSSJ\\\":16796141400\n" + + // "00,\\\"CCLRSJ\\\":1689321834000,\\\"SGRDYY\\\":null,\\\"JBR\\\":\\\"陆远\\\",\\\"ZBLX\\\":\\\"2\\\",\\\"JYAQ\\\":\\\" 2023年03月24日07时29分,徐银甫(男,65岁),骑其它,沿常海线(G524)行驶至常海线(G524)1公里111米时,与田夫勇(男,47岁)驾\n" + + // "驶车牌号为浙FM8761的重型货车碰撞运动车辆,致直接财产损失0元的交通事故。\\\\r\\\\n 当事人徐银甫负全部责任;当事人田夫勇无责任。\\\",\\\"DZZB\\\":null,\\\"SWSG\\\":null,\\\"SJHM1\\\":\\\"18457370603\\\",\\\"SJHM2\\\":\\\"13819319909\\\",\\\"M\n" + + // "S\\\":111,\\\"GXSJ\\\":1689321834000,\\\"JYW\\\":\\\"05491240436273013758918071494634\\\",\\\"DAH\\\":null,\\\"XC\\\":null,\\\"DJBH\\\":\\\"33048120230037409\\\",\\\"JLLX\\\":\\\"1\\\",\\\"SSZD\\\":\\\"330481005000\\\",\\\"GLXZDJ\\\":\\\"1\\\",\\\"XZQH\\\":\\\"330481\\\",\\\n" + + // "\"PZFS\\\":null,\\\"SGDD\\\":\\\"常海线(G524)1公里111米\\\",\\\"TJR1\\\":\\\"陆远\\\",\\\"LBQK\\\":null,\\\"DLLX\\\":\\\"11\\\",\\\"SFZMHM1\\\":\\\"330481199506031216\\\",\\\"SGXT\\\":\\\"11\\\",\\\"ZJCCSS\\\":0,\\\"SFZMHM2\\\":\\\"362426198008191311\\\",\\\"XQ\\\":5,\\\"LH\n" + + // "\\\":\\\"10524\\\",\\\"SGBH\\\":\\\"330481420230037382\\\",\\\"TQ\\\":\\\"1\\\",\\\"JDWZ\\\":200111}]]\",\"requestId\":\"60fb9ddf73b5ce135647e724e62428ae\",\"dataCount\":1,\"totalDataCount\":0,\"totalPage\":1}"; + + String dataJsonStr = "{\"code\":\"00\",\"msg\":\"成功\",\"data\":\"\",\"datas\":\"[[{\\\"TJSGBH\\\":null,\\\"LM\\\":\\\"海\n" + + "宁市俞家桥路\\\",\\\"CLJSG\\\":\\\"1\\\",\\\"SSRS\\\":0,\\\"LWSGLX\\\":null,\\\"BADW\\\":\\\"海宁市公安局交通警察大队\\\",\\\"DCSG\\\":null,\\\"SCSJD\\\":0,\\\"RDYYFL\\\":null,\\\"GLS\\\":1007,\\\"SB\\\":null,\\\"GLBM\\\":\\\"330481006200\\\",\\\"SGFSSJ\\\":16874026470\n" + + "00,\\\"CCLRSJ\\\":1687403022000,\\\"SGRDYY\\\":null,\\\"JBR\\\":\\\"朱洁林\\\",\\\"ZBLX\\\":null,\\\"JYAQ\\\":\\\"2023年06月22日10时57分许,刘刚 (驾驶证号:341223198107042130) 驾驶车辆号牌浙F3KH62小型汽车,在浙江省嘉兴市海宁市硖石街道俞家\n" + + "桥路东山公园 与代伟 (驾驶证号:510525199401023015) 驾驶车辆号牌浙FM9199小型汽车发生交通事故,造成两车损坏。当事人刘刚负无责;当事人代伟的行为违反在同车道行驶中,不按规定与前车保持必要的安全距离的 ,负全责。\\\",\\\"D\n" + + "ZZB\\\":\\\"120.699347,30.531393\\\",\\\"SWSG\\\":null,\\\"SJHM1\\\":\\\"13656604531\\\",\\\"SJHM2\\\":null,\\\"MS\\\":0,\\\"GXSJ\\\":1687403047000,\\\"JYW\\\":\\\"85919282240453431800722251912676\\\",\\\"DAH\\\":null,\\\"XC\\\":null,\\\"DJBH\\\":\\\"330481202300\n" + + "32093\\\",\\\"JLLX\\\":null,\\\"SSZD\\\":\\\"330481006200\\\",\\\"GLXZDJ\\\":null,\\\"XZQH\\\":\\\"330481\\\",\\\"PZFS\\\":null,\\\"SGDD\\\":\\\"海宁市俞家桥路(北关桥路口)\\\",\\\"TJR1\\\":null,\\\"LBQK\\\":null,\\\"DLLX\\\":\\\"22\\\",\\\"SFZMHM1\\\":\\\"330482198203205\n" + + "719\\\",\\\"SGXT\\\":\\\"11\\\",\\\"ZJCCSS\\\":1,\\\"SFZMHM2\\\":null,\\\"XQ\\\":4,\\\"LH\\\":\\\"67012\\\",\\\"SGBH\\\":\\\"330481420230032068\\\",\\\"TQ\\\":\\\"2\\\",\\\"JDWZ\\\":860}]]\",\"requestId\":\"4b54394e5e7ec319ee991add8f9f69b9\",\"dataCount\":1,\"totalData\n" + + "Count\":0,\"totalPage\":1}"; + + JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class); + String data = object.getString("datas"); + List array = JSON.parseArray(data, String.class); + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + return; + } + String carPlate = "浙FM8761"; + if (CollUtil.isEmpty(array)) { + log.info("该车牌号没有事故信息!"); + return; + } + for (String datas : array) { + if (StrUtil.isNotBlank(datas)) { + List accidentArray = JSON.parseArray(datas, JSONObject.class); + if (CollUtil.isEmpty(accidentArray)) { + log.info("该车牌号没有事故信息!"); + continue; + } + + for (JSONObject jsonObject : accidentArray) { + VehicleAccidentIrsData accidentIrsData = new VehicleAccidentIrsData(); + accidentIrsData.setCarPlate(carPlate); + String jsonString = jsonObject.toJSONString(); + accidentIrsData.setJsonStrData(jsonString); + // 获取事故日期 + Timestamp sgfssj = jsonObject.getTimestamp("SGFSSJ"); + LocalDateTime accidentTime = LocalDateTimeUtil.of(sgfssj); + if (accidentIrsDataMap.containsKey(carPlate)) { + List dataList = accidentIrsDataMap.get(carPlate); + Map dataMap = dataList.stream() + .collect(Collectors.toMap(VehicleAccidentIrsData::getAccidentTime, v -> v)); + if (dataMap.containsKey(accidentTime)) { + VehicleAccidentIrsData irsData = dataMap.get(accidentTime); + // 数据已经存在 + accidentIrsData.setId(irsData.getId()); + } + } + accidentIrsData.setAccidentTime(accidentTime); + accidentIrsData.setCreateOn(LocalDateTime.now()); + accidentIrsData.setUpdateOn(LocalDateTime.now()); + accidentIrsDataService.saveOrUpdate(accidentIrsData); + } + } + } + } + + public TreeMap jsonStrToMap(String jsonstr){ + TreeMap map = new TreeMap(); + String[] split = jsonstr.split("&"); + for (String s : split) { + String[] string = s.split("="); + map.put(string[0],string[1]); + } + return map; + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/OSSTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/OSSTest.java new file mode 100644 index 0000000..d7ae104 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/OSSTest.java @@ -0,0 +1,115 @@ +package com.ningdatech.carapi.oss; + + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.crypto.password.PasswordEncoder; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.driver.service.ICertificateService; +import com.ningdatech.carapi.driver.service.IDriverInfoService; +import com.ningdatech.carapi.driver.service.IDriverScoreInfoService; +import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.IRegionService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author liuxinxin + * @date 2022/11/10 下午5:30 + */ +@Slf4j +public class OSSTest extends AppTests { + @Autowired + private IDriverInfoService iDriverInfoService; + @Autowired + private CompanyService companyService; + @Autowired + private IRegionService regionService; + @Autowired + private RegionsCacheHelper regionCacheHelper; + @Autowired + private INdUserInfoService iNdUserInfoService; + @Autowired + private INdUserAuthService iNdUserAuthService; + @Autowired + private UserRoleService userRoleService; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private ICertificateService certificateService; + @Autowired + private IDriverScoreInfoService iDriverScoreInfoService; + @Autowired + private IVehicleBaseInfoService vehicleBaseInfoService; + @Autowired + private OperatorsCacheHelper operatorsCacheHelper; + + @Value("${login.public-key}") + private String publicKey; + + @Value("${login.private-key}") + private String privateKey; + + @Test + public void test() throws FileNotFoundException { + String endpoint = "oss-cn-hangzhou-zwynet-d01-a.internet.cloud-inner.zj.gov.cn"; + String accessKeyId = "oZFNfkh9YexqzTED"; + String accessKeySecret = "xewpDvACMzLQAGvY14fcXjkijBKSNH"; + String bucketName = "sanzhuangche2"; + String fileNamePrefix = "your_file_name_prefix"; + + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + + + //// 获取所有以指定前缀开头的文件名列表 + //List objectNames = ossClient.listObjects(bucketName, fileNamePrefix).getObjectSummaries().stream() + // .map(ObjectSummary::getKey).collect(Collectors.toList()); + // + //// 删除指定文件名的文件 + //DeleteObjectsRequest request = new DeleteObjectsRequest(bucketName); + //objectNames.forEach(request::addKey); + //DeleteObjectsResult result = ossClient.deleteObjects(request); + //System.out.println("删除成功"); + + // 关闭OSS客户端连接 + ossClient.shutdown(); + } + + + //这个下面是单独函数 + public static Workbook readExcel(InputStream is, String extString){ + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if(".xls".equals(extString)){ + return wb = new HSSFWorkbook(is); + }else if(".xlsx".equals(extString)){ + return wb = new XSSFWorkbook(is); + }else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/util/OssUtils.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/util/OssUtils.java new file mode 100644 index 0000000..47dce54 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/oss/util/OssUtils.java @@ -0,0 +1,126 @@ +package com.ningdatech.carapi.oss.util; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClient; +import com.aliyun.oss.model.ListObjectsRequest; +import com.aliyun.oss.model.OSSObjectSummary; +import com.aliyun.oss.model.ObjectListing; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/09/01 15:12 + */ +@Slf4j +public class OssUtils { + private static String ENDPOINT = "oss-cn-hangzhou-zwynet-d01-a.internet.cloud-inner.zj.gov.cn"; + //private fileout String ENDPOINT = "oss-cn-hangzhou.aliyuncs.com"; + private static String ACCESSKEYID = "oZFNfkh9YexqzTED"; + //private fileout String ACCESSKEYID = "LTAI4GL7uypycnBjiRn55rMG"; + private static String ACCESSKEYSECRET = "xewpDvACMzLQAGvY14fcXjkijBKSNH"; + //private fileout String ACCESSKEYSECRET = "qwYC7bW9bkStsko7qkLVnToAzj0Y98"; + private static String NEW_BUCKET = "sanzhuangche2"; + //private fileout String NEW_BUCKET = "devplat"; + + private static OSSClient client = null; + + + /** 创建OSSClient实例 + * + * @return + */ + private static OSSClient getOssClient(){ + client = new OSSClient(ENDPOINT, ACCESSKEYID, ACCESSKEYSECRET); + return client; + } + + /** 关闭OSSClient + * + */ + private static void close(){ + OssUtils.getOssClient().shutdown(); + } + + + /** + * 获取根目录下所有文件大小 + * @param bucketName + * @return + */ + public static Long getOss(String bucketName){ + try { + if (StringUtils.isBlank(bucketName)) { + bucketName = NEW_BUCKET; + } + long sizeTotal = 0L; + ObjectListing objectListing = null; + do { + // 列举bucket所有文件或目录,每次1000个 + ListObjectsRequest request = new ListObjectsRequest(bucketName).withDelimiter("/").withMaxKeys(1000); + // 列举bucket的指定目录(yourPrefix)下文件,每次1000个 + // ListObjectsRequest request = new ListObjectsRequest(bucketName).withMaxKeys(1000).withPrefix("yourPrefix"); + + if (objectListing != null) { + request.setMarker(objectListing.getNextMarker()); + } + objectListing = OssUtils.getOssClient().listObjects(request); + //获取当前文件夹下所有子目录大小 + List folders = objectListing.getCommonPrefixes(); + for (String folder : folders) { + sizeTotal = calculateFolderLength(OssUtils.getOssClient(), bucketName, folder)+sizeTotal; + } + + //获取当前文件夹下所有文件大小 + List sums = objectListing.getObjectSummaries(); + if (sums.size()==0){ + continue; + } + for (OSSObjectSummary s : sums) { + sizeTotal = sizeTotal+s.getSize(); + } + + } while (objectListing.isTruncated()); + //转换为TB + //sizeTotal = sizeTotal/1024/1024/1024/1024; + //转换为GB + sizeTotal = sizeTotal/1024/1024/1024; + //log.info(" 文件夹下所有子目录大小 : [{}] TB",sizeTotal); + log.info(" 文件夹下所有子目录大小 : [{}] GB",sizeTotal); + return sizeTotal; + }catch (Exception e){ + e.printStackTrace(); + return 0L; + }finally { + OssUtils.close(); + } + + } + + public static void main(String[] args) { + Long oss = getOss(NEW_BUCKET); + System.out.println(oss); + } + + private static long calculateFolderLength(OSS ossClient, String bucketName, String folder) { + long size = 0L; + ObjectListing objectListing = null; + do { + // MaxKey默认值为100,最大值为1000。 + ListObjectsRequest request = new ListObjectsRequest(bucketName).withPrefix(folder).withMaxKeys(1000); + if (objectListing != null) { + request.setMarker(objectListing.getNextMarker()); + } + objectListing = ossClient.listObjects(request); + List sums = objectListing.getObjectSummaries(); + for (OSSObjectSummary s : sums) { + size += s.getSize(); + } + } while (objectListing.isTruncated()); + return size; + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/redis/RedisTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/redis/RedisTest.java new file mode 100644 index 0000000..04ab624 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/redis/RedisTest.java @@ -0,0 +1,70 @@ +package com.ningdatech.carapi.redis; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Set; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.ningdatech.cache.model.cache.CacheKey; +import com.ningdatech.cache.repository.CachePlusOps; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.scheduler.contants.TaskContant; + +/** + * @Classname RedisTest + * @Description + * @Date 2023/3/1 16:33 + * @Author PoffyZhang + */ +public class RedisTest extends AppTests { + + @Autowired + private CachePlusOps cachePlusOps; + + @Test + public void remove (){ + // 模糊匹配所有以keyword:开头的所有key值 + + Set keys = cachePlusOps.keys("cm:"+"*"); + + System.out.println(keys.size()); + } + + @Test + public void get (){ + CacheKey key = new CacheKey(TaskContant.RedisKey.IRS_ACCIDENT_QUERY_REQUEST_SECRET); + String requestSecret = cachePlusOps.get(key); + System.out.println(requestSecret); + requestSecret = "abcdefg123456"; + cachePlusOps.set(key,requestSecret,Boolean.TRUE); + String requestSecret2 = cachePlusOps.get(key); + System.out.println(requestSecret2); + } + + @Test + public void getValue (){ + String timeStamp = "1689081083"; + // 将时间戳转换为Instant对象 + Instant instant = Instant.ofEpochSecond(Long.parseLong(timeStamp)); + // 将Instant对象转换为LocalDateTime对象 + LocalDateTime startTime = LocalDateTime.now(); + LocalDateTime endTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + Duration minuteDuration = Duration.between(endTime,startTime); + long minute = minuteDuration.toMinutes(); + System.out.println( minute); + } + + @Test + public void removeBatch (){ + // 模糊匹配所有以keyword:开头的所有key值 + Set keys = cachePlusOps.keys("*_online_index"); + for (String key : keys) { + cachePlusOps.del(key); + } + System.out.println(keys.size()); + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/report/ReportTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/report/ReportTest.java new file mode 100644 index 0000000..ef49ddb --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/report/ReportTest.java @@ -0,0 +1,2977 @@ +package com.ningdatech.carapi.report; + +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.util.NdDateUtils; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.car.vehicle.contants.VehicleContant; +import com.ningdatech.carapi.common.contants.DefValConstants; +import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum; +import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum; +import com.ningdatech.carapi.report.constant.UploadDataTypeEnum; +import com.ningdatech.carapi.report.model.dto.ReqBulkCementLogFacStaDataUploadDTO; +import com.ningdatech.carapi.report.model.dto.ReqMaterialLogEquipStaDataUploadDTO; +import com.ningdatech.carapi.report.model.entity.*; +import com.ningdatech.carapi.report.service.*; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.entity.dto.RegionDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.service.IRegionService; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author CMM + * @since 2023/10/10 10:08 + */ + +@Slf4j +public class ReportTest extends AppTests { + + @Autowired + private IRegionService regionService; + @Autowired + private IBulkCementDirectReportSystemAuditInfoService auditInfoService; + @Autowired + private CompaniesCacheHelper companiesCacheHelper; + @Autowired + private IBulkCementSupplyBulletinService bulkCementSupplyBulletinService; + @Autowired + private IBulkCementThreeCityUsageBulletinService bulkCementThreeCityUsageBulletinService; + @Autowired + private IBulkCementDirectReportSystemAuditRecordService auditRecordService; + @Autowired + private RegionsCacheHelper regionsCacheHelper; + @Autowired + private IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService; + @Autowired + private IConcreteSupplyBulletinService concreteSupplyBulletinService; + @Autowired + private IMortarSupplyBulletinService mortarSupplyBulletinService; + @Autowired + private IBulkCementLogisticFacilityStatisticAnnualReportService bulkCementLogFacStaService; + @Autowired + private IMaterialLogisticEquipmentStatisticAnnualReportService materialLogEquipStaAnnualReportService; + @Autowired + private IBulkCementTransferBulletinService bulkCementTransferBulletinService; + @Autowired + private INonProhibitedAreasBulkCementSalesUseService nonProhibitedAreasBulkCementSalesUseService; + + @Test + public void bulkCementSupplyTest() throws FileNotFoundException { + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-08.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-09.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-10.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-11.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2022-12.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-08.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\散装水泥供应量快报\\散装水泥供应量-2023-09.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 区域名称 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报月份 + Date reportMonth = Objects.nonNull(row.getCell(1)) ? row.getCell(1).getDateCellValue() : null; + LocalDateTime month = reportMonth.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + // 本月实际散装水泥总量 + String bulkCementAmount = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 本月实际水泥产量 + String cementOutput = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 年初至本月累计完成量 + String completedTotalAmount = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 年初至本月累计散装率 + String bulkRate = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 年初至本月累计 比去年同期增加量 + String increment = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 年初至本月累计比去年同期 增长率 + String increaseRate = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 年初至本月累计水泥产量 + String cumulativeCementProduction = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + + // 区县名称 获取区域ID、上级区域ID + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + Long companyId; + Long cityCompanyId; + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + // 创建市级审核通过申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + cityAuditInfo.setCreateOn(month); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(month); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(month); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + // 创建上报记录 + BulkCementSupplyBulletin concreteSupplyBulletin = new BulkCementSupplyBulletin(); + concreteSupplyBulletin.setUnitName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + concreteSupplyBulletin.setBulkCementAmount(BigDecimal.valueOf(Double.parseDouble(bulkCementAmount))); + concreteSupplyBulletin.setCementOutput(BigDecimal.valueOf(Double.parseDouble(cementOutput))); + concreteSupplyBulletin.setCompletedTotalAmount(BigDecimal.valueOf(Double.parseDouble(completedTotalAmount))); + concreteSupplyBulletin.setBulkRate(BigDecimal.valueOf(Double.parseDouble(bulkRate))); + concreteSupplyBulletin.setIncrement(BigDecimal.valueOf(Double.parseDouble(increment))); + concreteSupplyBulletin.setIncreaseRate(BigDecimal.valueOf(Double.parseDouble(increaseRate))); + concreteSupplyBulletin.setCumulativeCementProduction(BigDecimal.valueOf(Double.parseDouble(cumulativeCementProduction))); + concreteSupplyBulletin.setReportMonth(month); + concreteSupplyBulletin.setCompanyId(companyId); + concreteSupplyBulletin.setUnitResponsiblePerson(null); + concreteSupplyBulletin.setPreparer(null); + concreteSupplyBulletin.setReviewer(null); + concreteSupplyBulletin.setSubmissionDate(null); + concreteSupplyBulletin.setRegionId(regionId); + concreteSupplyBulletin.setCreateOn(month); + concreteSupplyBulletin.setCreateBy(null); + concreteSupplyBulletin.setUpdateOn(month); + concreteSupplyBulletin.setUpdateBy(null); + concreteSupplyBulletin.setAuditInfoId(cityAuditInfo.getId()); + concreteSupplyBulletin.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + bulkCementSupplyBulletinService.saveOrUpdate(concreteSupplyBulletin); + + // 补充市级数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(concreteSupplyBulletin.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(month.plusDays(20)); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(month.plusDays(20)); + auditRecord.setUpdateBy(null); + auditRecord.setReportMonth(month); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + Long relevanceDataId; + // 判断上报月份所在市的关联数据不存在 + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, cityRegionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(concreteSupplyBulletin.getId())){ + auditDataIdList.add(concreteSupplyBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(LocalDateTime.now()); + cityData.setUpdateOn(LocalDateTime.now()); + cityData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为未上报 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(concreteSupplyBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListStr); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + cityRelevanceData.setCreateOn(LocalDateTime.now()); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(LocalDateTime.now()); + cityRelevanceData.setRegionId(cityRegionId); + // 获取所在市散装中心所属的管理企业ID + cityRelevanceData.setCompanyId(cityCompanyId); + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + provinceAuditInfo.setCreateOn(month); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(month); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(month); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(month.plusDays(20L)); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(relevanceDataId)){ + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(month); + provinceData.setUpdateOn(month); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListStr); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(month); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(month); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(month); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_SUPPLY_BULLETIN.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportMonth(month); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + + System.out.println("已成功插入第" + i + "条数据!"); + } + } + } + + @Test + public void bulkCementTransferTest() throws FileNotFoundException { + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-01-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-02-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-03-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-04-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-05-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-06-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-07-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-08-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-09-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-10-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-11-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2022-12-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-01-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-02-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-03-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-04-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-05-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-06-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-07-中转库进出量.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-08-中转库进出量.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\中转库进出量\\2023-09-中转库进出量.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 区域名称 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报月份 + Date reportMonth = Objects.nonNull(row.getCell(1)) ? row.getCell(1).getDateCellValue() : null; + LocalDateTime month = reportMonth.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + // 上月末库存 + String lastMonthEndInventory = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 本月进库量 + String thisMonthIncomingStorage = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 累计进库量 + String cumulativeIncomingStorage = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 本月出库量 + String thisMonthOutgoingStorage = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 累计出库量 + String cumulativeOutgoingStorage = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 月末库存量 + String monthEndInventory = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 月末库存同比增长率 + String monthEndInventoryGrowthRate = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + + // 区县名称 获取区域ID、上级区域ID + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + Long companyId; + Long cityCompanyId; + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + // 创建市级审核通过申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + cityAuditInfo.setCreateOn(month); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(month); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(month); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + // 创建上报记录 + BulkCementTransferBulletin bulkCementTransferBulletin = new BulkCementTransferBulletin(); + bulkCementTransferBulletin.setUnitName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + bulkCementTransferBulletin.setLastMonthEndInventory(BigDecimal.valueOf(Double.parseDouble(lastMonthEndInventory))); + bulkCementTransferBulletin.setThisMonthIncomingStorage(BigDecimal.valueOf(Double.parseDouble(thisMonthIncomingStorage))); + bulkCementTransferBulletin.setCumulativeIncomingStorage(BigDecimal.valueOf(Double.parseDouble(cumulativeIncomingStorage))); + bulkCementTransferBulletin.setThisMonthIncomingStorage(BigDecimal.valueOf(Double.parseDouble(thisMonthIncomingStorage))); + bulkCementTransferBulletin.setThisMonthOutgoingStorage(BigDecimal.valueOf(Double.parseDouble(thisMonthOutgoingStorage))); + bulkCementTransferBulletin.setCumulativeOutgoingStorage(BigDecimal.valueOf(Double.parseDouble(cumulativeOutgoingStorage))); + bulkCementTransferBulletin.setMonthEndInventory(BigDecimal.valueOf(Double.parseDouble(monthEndInventory))); + bulkCementTransferBulletin.setMonthEndInventoryGrowthRate(BigDecimal.valueOf(Double.parseDouble(monthEndInventoryGrowthRate))); + bulkCementTransferBulletin.setReportMonth(month); + bulkCementTransferBulletin.setCompanyId(companyId); + bulkCementTransferBulletin.setUnitResponsiblePerson(null); + bulkCementTransferBulletin.setPreparer(null); + bulkCementTransferBulletin.setReviewer(null); + bulkCementTransferBulletin.setSubmissionDate(null); + bulkCementTransferBulletin.setRegionId(regionId); + bulkCementTransferBulletin.setCreateOn(month); + bulkCementTransferBulletin.setCreateBy(null); + bulkCementTransferBulletin.setUpdateOn(month); + bulkCementTransferBulletin.setUpdateBy(null); + bulkCementTransferBulletin.setAuditInfoId(cityAuditInfo.getId()); + bulkCementTransferBulletin.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + bulkCementTransferBulletinService.saveOrUpdate(bulkCementTransferBulletin); + + // 补充市级数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(bulkCementTransferBulletin.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(month.plusDays(20)); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(month.plusDays(20)); + auditRecord.setUpdateBy(null); + auditRecord.setReportMonth(month); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + Long relevanceDataId; + // 判断上报月份所在市的关联数据不存在 + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, cityRegionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(bulkCementTransferBulletin.getId())){ + auditDataIdList.add(bulkCementTransferBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(LocalDateTime.now()); + cityData.setUpdateOn(LocalDateTime.now()); + cityData.setUpdateBy(null); + // 有新上报的数据 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(bulkCementTransferBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListStr); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + cityRelevanceData.setCreateOn(LocalDateTime.now()); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(LocalDateTime.now()); + cityRelevanceData.setRegionId(cityRegionId); + // 获取所在市散装中心所属的管理企业ID + cityRelevanceData.setCompanyId(cityCompanyId); + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + provinceAuditInfo.setCreateOn(month); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(month); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(month); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(month.plusDays(20L)); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(relevanceDataId)){ + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(month); + provinceData.setUpdateOn(month); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListStr); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(month); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(month); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(month); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_TRANSFER_BULLETIN.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportMonth(month); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + + System.out.println("已成功插入第" + i + "条数据!"); + } + } + } + + @Test + public void bulkCementThreeCityUsageTest() throws FileNotFoundException { + + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-08.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-09.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-10.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-11.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2022-12.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-08.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\温台舟使用量快报\\温台舟使用量快报-2023-09.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + + // 单位名称 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报月份 + Date reportMonth = Objects.nonNull(row.getCell(1)) ? row.getCell(1).getDateCellValue() : null; + LocalDateTime month = reportMonth.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + // 年目标 + String yearTarget = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 占全年目标 + String percentageOfAnnualTarget = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 本月合计 + String thisMonthUsage = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 累计合计 + String accumulativeUsage = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 本省本月 + String thisProvinceThisMonthUsage = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 本省累计 + String thisProvinceAccumulativeUsage = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 外省本月 + String otherProvinceThisMonthUsage = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + // 外省累计 + String otherProvinceAccumulativeUsage = Objects.nonNull(row.getCell(9)) ? row.getCell(9).toString() : StringUtils.EMPTY; + + // 区县名称 获取区域ID、上级区域ID + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + Long companyId; + Long cityCompanyId; + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + // 创建市级审核通过申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + cityAuditInfo.setCreateOn(month); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(month); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(month); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + // 创建上报记录 + BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletIn = new BulkCementThreeCityUsageBulletin(); + bulkCementThreeCityUsageBulletIn.setUnitName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + bulkCementThreeCityUsageBulletIn.setYearTarget(BigDecimal.valueOf(Double.parseDouble(yearTarget))); + bulkCementThreeCityUsageBulletIn.setPercentageOfAnnualTarget(BigDecimal.valueOf(Double.parseDouble(percentageOfAnnualTarget))); + bulkCementThreeCityUsageBulletIn.setThisMonthUsage(BigDecimal.valueOf(Double.parseDouble(thisMonthUsage))); + bulkCementThreeCityUsageBulletIn.setAccumulativeUsage(BigDecimal.valueOf(Double.parseDouble(accumulativeUsage))); + bulkCementThreeCityUsageBulletIn.setThisProvinceThisMonthUsage(BigDecimal.valueOf(Double.parseDouble(thisProvinceThisMonthUsage))); + bulkCementThreeCityUsageBulletIn.setThisProvinceAccumulativeUsage(BigDecimal.valueOf(Double.parseDouble(thisProvinceAccumulativeUsage))); + bulkCementThreeCityUsageBulletIn.setOtherProvinceThisMonthUsage(BigDecimal.valueOf(Double.parseDouble(otherProvinceThisMonthUsage))); + bulkCementThreeCityUsageBulletIn.setOtherProvinceAccumulativeUsage(BigDecimal.valueOf(Double.parseDouble(otherProvinceAccumulativeUsage))); + bulkCementThreeCityUsageBulletIn.setReportMonth(month); + bulkCementThreeCityUsageBulletIn.setCompanyId(companyId); + bulkCementThreeCityUsageBulletIn.setUnitResponsiblePerson(null); + bulkCementThreeCityUsageBulletIn.setPreparer(null); + bulkCementThreeCityUsageBulletIn.setReviewer(null); + bulkCementThreeCityUsageBulletIn.setSubmissionDate(null); + bulkCementThreeCityUsageBulletIn.setRegionId(regionId); + bulkCementThreeCityUsageBulletIn.setCreateOn(month); + bulkCementThreeCityUsageBulletIn.setCreateBy(null); + bulkCementThreeCityUsageBulletIn.setUpdateOn(month); + bulkCementThreeCityUsageBulletIn.setUpdateBy(null); + bulkCementThreeCityUsageBulletIn.setAuditInfoId(cityAuditInfo.getId()); + bulkCementThreeCityUsageBulletIn.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + bulkCementThreeCityUsageBulletinService.saveOrUpdate(bulkCementThreeCityUsageBulletIn); + + // 补充市级数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(bulkCementThreeCityUsageBulletIn.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(month.plusDays(20)); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(month.plusDays(20)); + auditRecord.setUpdateBy(null); + auditRecord.setReportMonth(month); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + Long relevanceDataId; + // 判断上报月份所在市的关联数据不存在 + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, cityRegionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(bulkCementThreeCityUsageBulletIn.getId())){ + auditDataIdList.add(bulkCementThreeCityUsageBulletIn.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(LocalDateTime.now()); + cityData.setUpdateOn(LocalDateTime.now()); + cityData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为未上报 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(bulkCementThreeCityUsageBulletIn.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListStr); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + cityRelevanceData.setCreateOn(LocalDateTime.now()); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(LocalDateTime.now()); + cityRelevanceData.setRegionId(cityRegionId); + // 获取所在市散装中心所属的管理企业ID + cityRelevanceData.setCompanyId(cityCompanyId); + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + provinceAuditInfo.setCreateOn(month); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(month); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(month); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(month.plusDays(20L)); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(relevanceDataId)){ + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(month); + provinceData.setUpdateOn(month); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListStr); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(month); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(month); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(month); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportMonth(month); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + + System.out.println("已成功插入第" + i + "条数据!"); + } + } + } + + + /** + * 计算温台舟使用量数据同比增长率 + */ + @Test + public void calculateBulkCementThreeCityUsageGrowthRateTest() { + + List dataList = bulkCementThreeCityUsageBulletinService.list(); + for (BulkCementThreeCityUsageBulletin data : dataList) { + LocalDateTime reportMonth = data.getReportMonth(); + Long regionId = data.getRegionId(); + LocalDateTime preReportMonth = reportMonth.minusMonths(1L); + // 获取去年当前上报月份该地区的散装水泥使用量数据 + LocalDateTime preYearReportMonth = preReportMonth.minusYears(1L); + BulkCementThreeCityUsageBulletin preYearBulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class) + .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId) + .eq(BulkCementThreeCityUsageBulletin::getReportMonth, preYearReportMonth)); + if (Objects.isNull(preYearBulkCementThreeCityUsageBulletin)) { + // 如果去年没有数据,那么今年的数据就不用计算了 + continue; + } + BigDecimal accumulativeUsage = data.getAccumulativeUsage(); + // 同比增长率: (今年这个月的累计使用量 - 去年这个月的累计使用量) / 去年这个月的累计使用量 * 100 + BigDecimal preYearAccumulativeUsage = preYearBulkCementThreeCityUsageBulletin.getAccumulativeUsage(); + BigDecimal preYearAccUsage = Objects.isNull(preYearAccumulativeUsage) ? BigDecimal.ZERO : preYearAccumulativeUsage; + BigDecimal growthRate = accumulativeUsage.subtract(preYearAccUsage).divide(preYearAccUsage, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)); + data.setGrowthRate(growthRate); + bulkCementThreeCityUsageBulletinService.updateById(data); + } + } + + @Test + public void concreteSupplyTest() throws FileNotFoundException { + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-08.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-09.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-10.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-11.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2022-12.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-08.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\混凝土供应量快报\\混凝土供应量快报-2023-09.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 单位 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报月份 + Date reportMonth = Objects.nonNull(row.getCell(1)) ? row.getCell(1).getDateCellValue() : null; + LocalDateTime month = reportMonth.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + // 三类指导目标 + String threeCategoryGuidGoal = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 生产企业数量 + String productionCompanyNums = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 年设计生产能力 + String annualDesignProductionCapacity = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 本月实际产量 + String thisMonthOutput = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 累计实际产量 + String accumulativeOutput = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 本月使用散装水泥量 + String thisMonthCementUsage = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 累计使用散装水泥量 + String cementAccumulativeUsage = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + // 本月废弃物综合利用量 + String thisMonthWasteUtilization = Objects.nonNull(row.getCell(9)) ? row.getCell(9).toString() : StringUtils.EMPTY; + // 累计废弃物综合利用量 + String accumulativeWasteUtilization = Objects.nonNull(row.getCell(10)) ? row.getCell(10).toString() : StringUtils.EMPTY; + + + // 区县名称 获取区域ID、上级区域ID + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } else if ((regionNameStr.contains(regionName) && regionNameStr.equals("丽水经济技术开发区")) || + (regionNameStr.contains(regionName) && regionNameStr.equals("景宁畲族自治县"))) { + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + Long companyId; + Long cityCompanyId; + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + // 创建市级审核通过申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + cityAuditInfo.setCreateOn(month); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(month); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(month); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + // 创建上报记录 + ConcreteSupplyBulletin concreteSupplyBulletin = new ConcreteSupplyBulletin(); + concreteSupplyBulletin.setUnitName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + concreteSupplyBulletin.setThreeCategoryGuidGoal(BigDecimal.valueOf(Double.parseDouble(threeCategoryGuidGoal))); + Double d = Double.parseDouble(productionCompanyNums); + int proNum = d.intValue(); + concreteSupplyBulletin.setProductionCompanyNums(proNum); + concreteSupplyBulletin.setAnnualDesignProductionCapacity(BigDecimal.valueOf(Double.parseDouble(annualDesignProductionCapacity))); + concreteSupplyBulletin.setThisMonthOutput(BigDecimal.valueOf(Double.parseDouble(thisMonthOutput))); + concreteSupplyBulletin.setAccumulativeOutput(BigDecimal.valueOf(Double.parseDouble(accumulativeOutput))); + concreteSupplyBulletin.setThisMonthCementUsage(BigDecimal.valueOf(Double.parseDouble(thisMonthCementUsage))); + concreteSupplyBulletin.setCementAccumulativeUsage(BigDecimal.valueOf(Double.parseDouble(cementAccumulativeUsage))); + concreteSupplyBulletin.setThisMonthWasteUtilization(BigDecimal.valueOf(Double.parseDouble(thisMonthWasteUtilization))); + concreteSupplyBulletin.setAccumulativeWasteUtilization(BigDecimal.valueOf(Double.parseDouble(accumulativeWasteUtilization))); + concreteSupplyBulletin.setReportMonth(month); + concreteSupplyBulletin.setCompanyId(companyId); + concreteSupplyBulletin.setUnitResponsiblePerson(null); + concreteSupplyBulletin.setPreparer(null); + concreteSupplyBulletin.setReviewer(null); + concreteSupplyBulletin.setSubmissionDate(null); + concreteSupplyBulletin.setRegionId(regionId); + concreteSupplyBulletin.setCreateOn(month); + concreteSupplyBulletin.setCreateBy(null); + concreteSupplyBulletin.setUpdateOn(month); + concreteSupplyBulletin.setUpdateBy(null); + concreteSupplyBulletin.setAuditInfoId(cityAuditInfo.getId()); + concreteSupplyBulletin.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + concreteSupplyBulletinService.saveOrUpdate(concreteSupplyBulletin); + + // 补充市级数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(concreteSupplyBulletin.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(month.plusDays(20)); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(month.plusDays(20)); + auditRecord.setUpdateBy(null); + auditRecord.setReportMonth(month); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + Long relevanceDataId; + // 判断上报月份所在市的关联数据不存在 + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, cityRegionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(concreteSupplyBulletin.getId())){ + auditDataIdList.add(concreteSupplyBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(LocalDateTime.now()); + cityData.setUpdateOn(LocalDateTime.now()); + cityData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为未上报 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(concreteSupplyBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListStr); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + cityRelevanceData.setCreateOn(LocalDateTime.now()); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(LocalDateTime.now()); + cityRelevanceData.setRegionId(cityRegionId); + // 获取所在市散装中心所属的管理企业ID + cityRelevanceData.setCompanyId(cityCompanyId); + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + provinceAuditInfo.setCreateOn(month); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(month); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(month); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(month.plusDays(20L)); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(relevanceDataId)){ + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(month); + provinceData.setUpdateOn(month); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListStr); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(month); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(month); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(month); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.CONCRETE_SUPPLY_BULLETIN.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportMonth(month); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + + System.out.println("已成功插入第" + i + "条数据!"); + } + } + } + + @Test + public void mortarSupplyTest() throws FileNotFoundException { + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-08.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-09.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-10.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-11.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2022-12.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-01.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-02.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-03.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-04.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-05.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-06.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-07.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-08.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\砂浆供应量快报\\砂浆供应量快报-2023-09.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 地区 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报月份 + Date reportMonth = Objects.nonNull(row.getCell(1)) ? row.getCell(1).getDateCellValue() : null; + LocalDateTime month = reportMonth.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + // 二类指导目标 + String twoCategoryGuidGoal = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 普通干混砂浆生产企业数量 + String dryMixedMortarProductionCompanyNum = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 普通干混砂浆生产总能力 + String dryMixedMortarProductiveCapacity = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 普通干混砂浆散装能力 + String dryMixedMortarBulkCapacity = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 本月总产量 + String thisMonthTotalOutput = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 本月累计产量 + String thisMonthAccumulativeOutput = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 普通干混砂浆本月产量 + String dryMixedMortarThisMonthOutput = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + // 普通干混砂浆累计产量 + String dryMixedMortarThisMonthAccumulativeOutput = Objects.nonNull(row.getCell(9)) ? row.getCell(9).toString() : StringUtils.EMPTY; + // 普通干混砂浆同比增长量 + String dryMixedMortarIncrement = Objects.nonNull(row.getCell(10)) ? row.getCell(10).toString() : StringUtils.EMPTY; + // 普通干混砂浆增长率 + String dryMixedMortarGrowthRate = Objects.nonNull(row.getCell(11)) ? row.getCell(11).toString() : StringUtils.EMPTY; + // 普通干混砂浆本月散装量 + String dryMixedMortarThisMonthBulkQuantity = Objects.nonNull(row.getCell(12)) ? row.getCell(12).toString() : StringUtils.EMPTY; + // 普通干混砂浆累计散装量 + String dryMixedMortarAccumulativeBulkQuantity = Objects.nonNull(row.getCell(13)) ? row.getCell(13).toString() : StringUtils.EMPTY; + // 湿拌砂浆本月产量 + String wetMortarThisMonthOutput = Objects.nonNull(row.getCell(14)) ? row.getCell(14).toString() : StringUtils.EMPTY; + // 湿拌砂浆累计产量 + String wetMortarAccumulativeOutput = Objects.nonNull(row.getCell(15)) ? row.getCell(15).toString() : StringUtils.EMPTY; + // 散装水泥本月使用量 + String bulkCementThisMonthUsage = Objects.nonNull(row.getCell(16)) ? row.getCell(16).toString() : StringUtils.EMPTY; + // 散装水泥累计使用量 + String bulkCementAccumulativeUsage = Objects.nonNull(row.getCell(17)) ? row.getCell(17).toString() : StringUtils.EMPTY; + // 废弃物本月综合利用量 + String wasteThisMonthComprehensiveUtilization = Objects.nonNull(row.getCell(18)) ? row.getCell(18).toString() : StringUtils.EMPTY; + // 废弃物累计综合利用量 + String wasteAccumulativeComprehensiveUtilization = Objects.nonNull(row.getCell(19)) ? row.getCell(19).toString() : StringUtils.EMPTY; + + + // 区县名称 获取区域ID、上级区域ID + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } else if ((regionNameStr.contains(regionName) && regionNameStr.equals("丽水经济技术开发区")) || + (regionNameStr.contains(regionName) && regionNameStr.equals("景宁畲族自治县"))) { + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + Long companyId; + Long cityCompanyId; + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + // 创建市级审核通过申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + cityAuditInfo.setCreateOn(month); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(month); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(month); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 保存上报数据信息 + // 创建上报记录 + MortarSupplyBulletin mortarSupplyBulletin = new MortarSupplyBulletin(); + mortarSupplyBulletin.setRegionName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + mortarSupplyBulletin.setTwoCategoryGuidGoal(BigDecimal.valueOf(Double.parseDouble(twoCategoryGuidGoal))); + Double d = Double.parseDouble(dryMixedMortarProductionCompanyNum); + int proNum = d.intValue(); + mortarSupplyBulletin.setDryMixedMortarProductionCompanyNum(proNum); + mortarSupplyBulletin.setDryMixedMortarProductiveCapacity(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarProductiveCapacity))); + mortarSupplyBulletin.setDryMixedMortarBulkCapacity(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarBulkCapacity))); + mortarSupplyBulletin.setThisMonthTotalOutput(BigDecimal.valueOf(Double.parseDouble(thisMonthTotalOutput))); + mortarSupplyBulletin.setThisMonthAccumulativeOutput(BigDecimal.valueOf(Double.parseDouble(thisMonthAccumulativeOutput))); + mortarSupplyBulletin.setDryMixedMortarThisMonthOutput(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarThisMonthOutput))); + mortarSupplyBulletin.setDryMixedMortarThisMonthAccumulativeOutput(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarThisMonthAccumulativeOutput))); + mortarSupplyBulletin.setDryMixedMortarIncrement(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarIncrement))); + mortarSupplyBulletin.setDryMixedMortarGrowthRate(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarGrowthRate))); + mortarSupplyBulletin.setDryMixedMortarThisMonthBulkQuantity(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarThisMonthBulkQuantity))); + mortarSupplyBulletin.setDryMixedMortarAccumulativeBulkQuantity(BigDecimal.valueOf(Double.parseDouble(dryMixedMortarAccumulativeBulkQuantity))); + mortarSupplyBulletin.setWetMortarThisMonthOutput(BigDecimal.valueOf(Double.parseDouble(wetMortarThisMonthOutput))); + mortarSupplyBulletin.setWetMortarAccumulativeOutput(BigDecimal.valueOf(Double.parseDouble(wetMortarAccumulativeOutput))); + mortarSupplyBulletin.setBulkCementThisMonthUsage(BigDecimal.valueOf(Double.parseDouble(bulkCementThisMonthUsage))); + mortarSupplyBulletin.setBulkCementAccumulativeUsage(BigDecimal.valueOf(Double.parseDouble(bulkCementAccumulativeUsage))); + mortarSupplyBulletin.setWasteThisMonthComprehensiveUtilization(BigDecimal.valueOf(Double.parseDouble(wasteThisMonthComprehensiveUtilization))); + mortarSupplyBulletin.setWasteAccumulativeComprehensiveUtilization(BigDecimal.valueOf(Double.parseDouble(wasteAccumulativeComprehensiveUtilization))); + mortarSupplyBulletin.setReportMonth(month); + mortarSupplyBulletin.setCompanyId(companyId); + mortarSupplyBulletin.setUnitResponsiblePerson(null); + mortarSupplyBulletin.setPreparer(null); + mortarSupplyBulletin.setReviewer(null); + mortarSupplyBulletin.setSubmissionDate(null); + mortarSupplyBulletin.setRegionId(regionId); + mortarSupplyBulletin.setCreateOn(month); + mortarSupplyBulletin.setCreateBy(null); + mortarSupplyBulletin.setUpdateOn(month); + mortarSupplyBulletin.setUpdateBy(null); + mortarSupplyBulletin.setAuditInfoId(cityAuditInfo.getId()); + mortarSupplyBulletin.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + mortarSupplyBulletinService.saveOrUpdate(mortarSupplyBulletin); + + // 补充市级数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(mortarSupplyBulletin.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(month.plusDays(20)); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(month.plusDays(20)); + auditRecord.setUpdateBy(null); + auditRecord.setReportMonth(month); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + Long relevanceDataId; + // 判断上报月份所在市的关联数据不存在 + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, cityRegionId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(mortarSupplyBulletin.getId())){ + auditDataIdList.add(mortarSupplyBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(LocalDateTime.now()); + cityData.setUpdateOn(LocalDateTime.now()); + cityData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为未上报 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(mortarSupplyBulletin.getId()); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListStr); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + cityRelevanceData.setCreateOn(LocalDateTime.now()); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(LocalDateTime.now()); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(LocalDateTime.now()); + cityRelevanceData.setRegionId(cityRegionId); + // 获取所在市散装中心所属的管理企业ID + cityRelevanceData.setCompanyId(cityCompanyId); + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + // 有新上报的数据,就更新关联数据 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + provinceAuditInfo.setCreateOn(month); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(month); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(month); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(month.plusDays(20L)); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(null); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, month) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditDataIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditDataIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditDataIdList.contains(relevanceDataId)){ + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListStr); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(month); + provinceData.setUpdateOn(month); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportMonth(month); + List auditDataIdList = Lists.newArrayList(); + auditDataIdList.add(relevanceDataId); + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListStr); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(month); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(month); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(month); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.MORTAR_SUPPLY_BULLETIN.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getReportMonth()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportMonth(month); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + + System.out.println("已成功插入第" + i + "条数据!"); + } + } + } + + @Test + public void bulkCementLogFacStaTest() throws FileNotFoundException { + // ------------------------------------------杭州市------------------------------------- + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\萧山.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\余杭.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\富阳.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\桐庐.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\建德.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\临安.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\淳安.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\钱塘.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\杭州市\\临平.xlsx"); + // ------------------------------------------宁波市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\余姚.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\慈溪.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\象山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\宁海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\鄞州.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\北仑.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\镇海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\奉化.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\江北.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\宁波市\\海曙.xlsx"); + // ------------------------------------------温州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\鹿城.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\瓯海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\龙湾.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\瑞安.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\乐清.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\永嘉.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\平阳.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\苍南.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\文成.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\洞头.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\泰顺.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\温州市\\龙港.xlsx"); + // ------------------------------------------嘉兴市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\南湖.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\秀洲.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\嘉善.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\平湖.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\海盐.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\海宁.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\嘉兴市\\桐乡.xlsx"); + // ------------------------------------------湖州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\湖州市\\德清.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\湖州市\\长兴.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\湖州市\\安吉.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\湖州市\\吴兴.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\湖州市\\吴兴.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\湖州市\\南浔.xlsx"); + // ------------------------------------------绍兴市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\绍兴市\\越城.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\绍兴市\\柯桥.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\绍兴市\\诸暨.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\绍兴市\\上虞.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\绍兴市\\嵊州.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\绍兴市\\新昌.xlsx"); + // ------------------------------------------金华市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\金东.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\婺城.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\兰溪.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\浦江.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\东阳.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\义乌.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\永康.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\武义.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\金华市\\磐安.xlsx"); + // ------------------------------------------衢州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\衢州市\\衢江.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\衢州市\\江山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\衢州市\\常山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\衢州市\\开化.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\衢州市\\龙游.xlsx"); + // ------------------------------------------舟山市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\舟山市\\定海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\舟山市\\普陀.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\舟山市\\岱山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\舟山市\\嵊泗.xlsx"); + // ------------------------------------------台州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\椒江.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\路桥.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\黄岩.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\临海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\温岭.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\仙居.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\天台.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\三门.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\台州市\\玉环.xlsx"); + // ------------------------------------------丽水市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\莲都.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\青田.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\缙云.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\松阳.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\遂昌.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\龙泉.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\云和.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\景宁畲族自治县.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\物流设施统计年报\\丽水市\\丽水经济技术开发区.xlsx"); + + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + List dataList = Lists.newArrayList(); + + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + + Long companyId = null; + Long cityCompanyId = null; + + String unitResponsiblePerson = null; + String preparer = null; + String reviewer = null; + LocalDateTime subDate = null; + + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 地区 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报年份 + String reportYear = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : null; + Double parseDouble = Double.parseDouble(reportYear); + int year = parseDouble.intValue(); + // 设备名称 + String facilityName = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 年初数量 + String yearBeginNum = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 年初容量 + String yearBeginCapacity = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 本年新增数量 + String thisYearNewAddNum = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 本年新增容量 + String thisYearNewAddCapacity = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 本年报废数量 + String thisYearScrapNum = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 本年报废容量 + String thisYearScrapCapacity = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + // 年末数量 + String yearEndNum = Objects.nonNull(row.getCell(9)) ? row.getCell(9).toString() : StringUtils.EMPTY; + // 年末容量 + String yearEndCapacity = Objects.nonNull(row.getCell(10)) ? row.getCell(10).toString() : StringUtils.EMPTY; + // 本年实际作业量 + String thisYearWorkAmount = Objects.nonNull(row.getCell(11)) ? row.getCell(11).toString() : StringUtils.EMPTY; + // 单位负责人 + unitResponsiblePerson = Objects.nonNull(row.getCell(12)) ? row.getCell(12).toString() : StringUtils.EMPTY; + // 填表人 + preparer = Objects.nonNull(row.getCell(13)) ? row.getCell(13).toString() : StringUtils.EMPTY; + // 复核人 + reviewer = Objects.nonNull(row.getCell(14)) ? row.getCell(14).toString() : StringUtils.EMPTY; + // 报出日期 + Date submissionDate = Objects.nonNull(row.getCell(15)) ? row.getCell(15).getDateCellValue() : null; + if (Objects.nonNull(submissionDate)) { + subDate = submissionDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + }else { + subDate = LocalDateTime.now().minusMonths(9).minusDays(15L); + } + + // 区县名称 获取区域ID、上级区域ID + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } else if ((regionNameStr.contains(regionName) && regionNameStr.equals("丽水经济技术开发区")) || + (regionNameStr.contains(regionName) && regionNameStr.equals("景宁畲族自治县"))) { + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + ReqBulkCementLogFacStaDataUploadDTO uploadDto = new ReqBulkCementLogFacStaDataUploadDTO(); + uploadDto.setRegionName(regionName); + uploadDto.setCompanyId(companyId); + uploadDto.setRegionId(regionId); + uploadDto.setFacilityName(facilityName); + Double d = Double.parseDouble(yearBeginNum); + int beginNum = d.intValue(); + uploadDto.setYearBeginNum(beginNum); + uploadDto.setYearBeginCapacity(BigDecimal.valueOf(Double.parseDouble(yearBeginCapacity))); + Double d2 = Double.parseDouble(thisYearNewAddNum); + int newAddNum = d2.intValue(); + uploadDto.setThisYearNewAddNum(newAddNum); + uploadDto.setThisYearNewAddCapacity(BigDecimal.valueOf(Double.parseDouble(thisYearNewAddCapacity))); + Double d3 = Double.parseDouble(thisYearScrapNum); + int scrapNum = d3.intValue(); + uploadDto.setThisYearScrapNum(scrapNum); + uploadDto.setThisYearScrapCapacity(BigDecimal.valueOf(Double.parseDouble(thisYearScrapCapacity))); + Double d4 = Double.parseDouble(yearEndNum); + int endNum = d4.intValue(); + uploadDto.setYearEndNum(endNum); + uploadDto.setYearEndCapacity(BigDecimal.valueOf(Double.parseDouble(yearEndCapacity))); + uploadDto.setThisYearWorkAmount(BigDecimal.valueOf(Double.parseDouble(thisYearWorkAmount))); + uploadDto.setReportYear(year); + uploadDto.setUnitResponsiblePerson(unitResponsiblePerson); + uploadDto.setPreparer(preparer); + uploadDto.setReviewer(reviewer); + uploadDto.setSubmissionDate(subDate); + dataList.add(uploadDto); + } + + // 先提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + cityAuditInfo.setCreateOn(subDate); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(subDate); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(subDate); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 创建区县关联数据信息(对应每个设备名称的数据关系为一对多) + BulkCementDirectReportSystemDataRelevance countryData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, 2022) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + BulkCementDirectReportSystemDataRelevance countryRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + // 说明为重新提交 + if (Objects.nonNull(countryData)){ + // 先删除关联的已经保存的各设备名称的数据 + String auditDataIdList = countryData.getAuditDataIdList(); + if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idList)){ + bulkCementLogFacStaService.remove(Wrappers.lambdaQuery(BulkCementLogisticFacilityStatisticAnnualReport.class) + .in(BulkCementLogisticFacilityStatisticAnnualReport::getId,idList)); + } + } + countryRelevanceData.setId(countryData.getId()); + } + countryRelevanceData.setReportYear(2022); + countryRelevanceData.setUnitResponsiblePerson(unitResponsiblePerson); + countryRelevanceData.setPreparer(preparer); + countryRelevanceData.setReviewer(reviewer); + countryRelevanceData.setSubmissionDate(subDate); + countryRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + countryRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + countryRelevanceData.setCreateOn(LocalDateTime.now()); + countryRelevanceData.setCreateBy(null); + countryRelevanceData.setUpdateOn(subDate); + countryRelevanceData.setUpdateBy(null); + countryRelevanceData.setLastUpdateTime(subDate); + countryRelevanceData.setRegionId(regionId); + countryRelevanceData.setCompanyId(companyId); + List auditDataIdList = Lists.newArrayList(); + + // 保存本次上报数据信息 + for (ReqBulkCementLogFacStaDataUploadDTO uploadDto : dataList) { + BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogFacStaAnnualReport = + new BulkCementLogisticFacilityStatisticAnnualReport(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + String regionName = regionDto.getRegionName(); + bulkCementLogFacStaAnnualReport.setRegionName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + bulkCementLogFacStaAnnualReport.setFacilityName(uploadDto.getFacilityName()); + bulkCementLogFacStaAnnualReport.setYearBeginNum(uploadDto.getYearBeginNum()); + bulkCementLogFacStaAnnualReport.setYearBeginCapacity(uploadDto.getYearBeginCapacity()); + bulkCementLogFacStaAnnualReport.setThisYearNewAddNum(uploadDto.getThisYearNewAddNum()); + bulkCementLogFacStaAnnualReport.setThisYearNewAddCapacity(uploadDto.getThisYearNewAddCapacity()); + bulkCementLogFacStaAnnualReport.setThisYearScrapNum(uploadDto.getThisYearScrapNum()); + bulkCementLogFacStaAnnualReport.setThisYearScrapCapacity(uploadDto.getThisYearScrapCapacity()); + bulkCementLogFacStaAnnualReport.setYearEndNum(uploadDto.getYearEndNum()); + bulkCementLogFacStaAnnualReport.setYearEndCapacity(uploadDto.getYearEndCapacity()); + bulkCementLogFacStaAnnualReport.setThisYearWorkAmount(uploadDto.getThisYearWorkAmount()); + bulkCementLogFacStaAnnualReport.setReportYear(uploadDto.getReportYear()); + bulkCementLogFacStaAnnualReport.setRemark(uploadDto.getRemark()); + bulkCementLogFacStaAnnualReport.setCompanyId(companyId); + bulkCementLogFacStaAnnualReport.setUnitResponsiblePerson(uploadDto.getUnitResponsiblePerson()); + bulkCementLogFacStaAnnualReport.setPreparer(uploadDto.getPreparer()); + bulkCementLogFacStaAnnualReport.setReviewer(uploadDto.getReviewer()); + bulkCementLogFacStaAnnualReport.setSubmissionDate(uploadDto.getSubmissionDate()); + bulkCementLogFacStaAnnualReport.setRegionId(regionId); + bulkCementLogFacStaAnnualReport.setCreateOn(subDate); + bulkCementLogFacStaAnnualReport.setCreateBy(null); + bulkCementLogFacStaAnnualReport.setUpdateOn(subDate); + bulkCementLogFacStaAnnualReport.setUpdateBy(null); + bulkCementLogFacStaAnnualReport.setAuditInfoId(cityAuditInfo.getId()); + bulkCementLogFacStaAnnualReport.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + bulkCementLogFacStaService.save(bulkCementLogFacStaAnnualReport); + auditDataIdList.add(bulkCementLogFacStaAnnualReport.getId()); + } + // 保存关联数据ID集合(一条关联数据对应多条不同设备名称的数据) + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + countryRelevanceData.setAuditDataIdList(idListStr); + dataRelevanceService.saveOrUpdate(countryRelevanceData); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(countryRelevanceData.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(subDate); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(subDate); + auditRecord.setUpdateBy(null); + auditRecord.setReportYear(2022); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + // 杭州市 + //String cityUnitResponsiblePerson = "赵斌"; + //String cityPreparer = "蔡义超"; + //String cityReviewer = "王瑞理"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-15 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 宁波市 + //String cityUnitResponsiblePerson = "卢汉"; + //String cityPreparer = "杨浩杰"; + //String cityReviewer = "徐立国"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-09 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 温州市 + //String cityUnitResponsiblePerson = null; + //String cityPreparer = null; + //String cityReviewer = null; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-01-01 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 嘉兴市 + //String cityUnitResponsiblePerson = "潘卫国"; + //String cityPreparer = "倪竹红"; + //String cityReviewer = "倪竹红"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-15 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 湖州市 + //String cityUnitResponsiblePerson = "傅饶"; + //String cityPreparer = "付平安"; + //String cityReviewer = "沈宁儿"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-06 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 绍兴市 + //String cityUnitResponsiblePerson = "丁正龙"; + //String cityPreparer = "寿晨杰"; + //String cityReviewer = "寿晨杰"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-13 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 金华市 + //String cityUnitResponsiblePerson = "汪欣"; + //String cityPreparer = "吴昌蒲"; + //String cityReviewer = "杨裕发"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-10 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 衢州市 + //String cityUnitResponsiblePerson = "徐欣"; + //String cityPreparer = "徐欣"; + //String cityReviewer = "徐欣"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-10 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 舟山市 + //String cityUnitResponsiblePerson = "刘海港"; + //String cityPreparer = "吴煜之"; + //String cityReviewer = "檀坤"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-01-10 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 台州市 + //String cityUnitResponsiblePerson = "陈虹"; + //String cityPreparer = "林"; + //String cityReviewer = "林"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-15 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 丽水市 + String cityUnitResponsiblePerson = null; + String cityPreparer = null; + String cityReviewer = null; + LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-01-01 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + Long relevanceDataId; + // 判断上报年份所在市的市级关联数据不存在 + // 区县的区域ID + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + Long parentId = regionDto.getParentId(); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, 2022) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditIdList; + if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(auditDataIdListStr)){ + auditIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditIdList.contains(countryRelevanceData.getId())){ + auditIdList.add(countryRelevanceData.getId()); + String dataIdListStr = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(dataIdListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(subDate); + cityData.setUpdateOn(subDate); + cityData.setUpdateBy(null); + // 有新上报的数据 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportYear(2022); + List auditIdList = Lists.newArrayList(); + if (Objects.nonNull(countryRelevanceData.getId())) { + auditIdList.add(countryRelevanceData.getId()); + String idListString = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListString); + } + cityRelevanceData.setUnitResponsiblePerson(cityUnitResponsiblePerson); + cityRelevanceData.setPreparer(cityPreparer); + cityRelevanceData.setReviewer(cityReviewer); + cityRelevanceData.setSubmissionDate(citySubDate); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setCreateOn(citySubDate); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(citySubDate); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(citySubDate); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + provinceAuditInfo.setCreateOn(citySubDate); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(citySubDate); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(citySubDate); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(citySubDate); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(citySubDate); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, 2022) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditIdList.contains(relevanceDataId)){ + auditIdList.add(relevanceDataId); + String idListString = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListString); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(citySubDate); + provinceData.setUpdateOn(citySubDate); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportYear(2022); + List auditIdList = Lists.newArrayList(); + auditIdList.add(relevanceDataId); + String idListString = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListString); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(citySubDate); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(citySubDate); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(citySubDate); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_LOGISTIC_FACILITY_STATISTIC_ANNUAL_REPORT.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getSubmissionDate()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getSubmissionDate()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportYear(2022); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + } + + @Test + public void materialLogEquipStaTest() throws FileNotFoundException { + // ------------------------------------------杭州市------------------------------------- + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\萧山.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\余杭.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\富阳.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\桐庐.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\建德.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\临安.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\淳安.xlsx"); + // File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\钱塘.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\杭州市\\临平.xlsx"); + // ------------------------------------------宁波市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\余姚.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\慈溪.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\象山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\宁海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\鄞州.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\北仑.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\镇海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\奉化.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\江北.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\宁波市\\海曙.xlsx"); + // ------------------------------------------温州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\鹿城.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\瓯海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\龙湾.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\瑞安.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\乐清.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\永嘉.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\平阳.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\苍南.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\文成.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\洞头.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\泰顺.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\温州市\\龙港.xlsx"); + // ------------------------------------------嘉兴市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\南湖.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\秀洲.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\嘉善.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\平湖.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\海盐.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\海宁.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\嘉兴市\\桐乡.xlsx"); + // ------------------------------------------湖州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\湖州市\\德清.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\湖州市\\长兴.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\湖州市\\安吉.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\湖州市\\吴兴.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\湖州市\\南浔.xlsx"); + // ------------------------------------------绍兴市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\绍兴市\\越城.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\绍兴市\\柯桥.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\绍兴市\\诸暨.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\绍兴市\\上虞.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\绍兴市\\嵊州.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\绍兴市\\新昌.xlsx"); + // ------------------------------------------金华市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\金东.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\婺城.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\兰溪.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\浦江.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\东阳.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\义乌.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\永康.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\武义.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\金华市\\磐安.xlsx"); + // ------------------------------------------衢州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\衢州市\\衢江.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\衢州市\\江山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\衢州市\\常山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\衢州市\\开化.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\衢州市\\龙游.xlsx"); + // ------------------------------------------舟山市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\舟山市\\定海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\舟山市\\普陀.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\舟山市\\岱山.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\舟山市\\嵊泗.xlsx"); + // ------------------------------------------台州市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\椒江.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\路桥.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\黄岩.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\临海.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\温岭.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\仙居.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\天台.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\三门.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\台州市\\玉环.xlsx"); + // ------------------------------------------丽水市------------------------------------- + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\莲都.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\青田.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\缙云.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\松阳.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\遂昌.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\龙泉.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\云和.xlsx"); + //File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\景宁畲族自治县.xlsx"); + File f = new File("D:\\work\\水泥车直报系统\\data\\物流装备统计年报\\丽水市\\丽水经济技术开发区.xlsx"); + + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + List userList = Lists.newArrayList(); + if(wb != null) { + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 根据区县名称获取区域ID + HashSet countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + List dataList = Lists.newArrayList(); + + Long regionId = null; + Long cityRegionId = null; + String cityRegionName = null; + + Long companyId = null; + Long cityCompanyId = null; + + String unitResponsiblePerson = null; + String preparer = null; + String reviewer = null; + LocalDateTime subDate = null; + + for (int i = 1; i < rownum; i++) { + row = sheet.getRow(i); + // 地区 + String regionName = Objects.nonNull(row.getCell(0)) ? row.getCell(0).toString() : StringUtils.EMPTY; + // 上报年份 + String reportYear = Objects.nonNull(row.getCell(1)) ? row.getCell(1).toString() : null; + Double parseDouble = Double.parseDouble(reportYear); + int year = parseDouble.intValue(); + // 装备名称 + String equipmentName = Objects.nonNull(row.getCell(2)) ? row.getCell(2).toString() : StringUtils.EMPTY; + // 年初数量 + String yearBeginNum = Objects.nonNull(row.getCell(3)) ? row.getCell(3).toString() : StringUtils.EMPTY; + // 年初额定量 + String yearBeginNominalRate = Objects.nonNull(row.getCell(4)) ? row.getCell(4).toString() : StringUtils.EMPTY; + // 本年新增数量 + String thisYearNewAddNum = Objects.nonNull(row.getCell(5)) ? row.getCell(5).toString() : StringUtils.EMPTY; + // 本年新增额定量 + String thisYearNewAddNominalRate = Objects.nonNull(row.getCell(6)) ? row.getCell(6).toString() : StringUtils.EMPTY; + // 本年减少数量 + String thisYearDecreaseNum = Objects.nonNull(row.getCell(7)) ? row.getCell(7).toString() : StringUtils.EMPTY; + // 本年减少额定量 + String thisYearDecreaseNominalRate = Objects.nonNull(row.getCell(8)) ? row.getCell(8).toString() : StringUtils.EMPTY; + // 年末数量 + String yearEndNum = Objects.nonNull(row.getCell(9)) ? row.getCell(9).toString() : StringUtils.EMPTY; + // 年末额定量 + String yearEndNominal = Objects.nonNull(row.getCell(10)) ? row.getCell(10).toString() : StringUtils.EMPTY; + // 单位负责人 + unitResponsiblePerson = Objects.nonNull(row.getCell(11)) ? row.getCell(11).toString() : StringUtils.EMPTY; + // 填表人 + preparer = Objects.nonNull(row.getCell(12)) ? row.getCell(12).toString() : StringUtils.EMPTY; + // 复核人 + reviewer = Objects.nonNull(row.getCell(13)) ? row.getCell(13).toString() : StringUtils.EMPTY; + // 报出日期 + Date submissionDate = Objects.nonNull(row.getCell(14)) ? row.getCell(14).getDateCellValue() : null; + if (Objects.nonNull(submissionDate)) { + subDate = submissionDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + }else { + subDate = LocalDateTime.now().minusMonths(9).minusDays(15L); + } + + // 区县名称 获取区域ID、上级区域ID + for (Map.Entry regionEntry : regionMap.entrySet()) { + String regionNameStr = regionEntry.getKey(); + if (regionNameStr.contains(regionName) && regionNameStr.length() < 4){ + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } else if ((regionNameStr.contains(regionName) && regionNameStr.equals("丽水经济技术开发区")) || + (regionNameStr.contains(regionName) && regionNameStr.equals("景宁畲族自治县"))) { + regionName = regionNameStr; + Region region = regionMap.get(regionNameStr); + if (Objects.nonNull(region)) { + regionId = region.getId(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + cityRegionId = regionDto.getParentId(); + cityRegionName = regionDto.getRegionName(); + } + } + } + if (Objects.isNull(regionId)){ + throw new BizException("区域不存在!"); + } + + // 根据地区名称获取对应散装中心的企业信息 + CompanyDTO companyDto = companiesCacheHelper.getByName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + CompanyDTO cityCompanyDto = companiesCacheHelper.getByName(cityRegionName + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.isNull(companyDto) || Objects.isNull(cityCompanyDto)){ + throw new BizException("管理企业不存在!"); + }else { + companyId = companyDto.getId(); + cityCompanyId = cityCompanyDto.getId(); + } + + ReqMaterialLogEquipStaDataUploadDTO uploadDto = new ReqMaterialLogEquipStaDataUploadDTO(); + uploadDto.setRegionName(regionName); + uploadDto.setCompanyId(companyId); + uploadDto.setRegionId(regionId); + uploadDto.setEquipmentName(equipmentName); + Double d = Double.parseDouble(yearBeginNum); + int beginNum = d.intValue(); + uploadDto.setYearBeginNum(beginNum); + uploadDto.setYearBeginNominalRate(BigDecimal.valueOf(Double.parseDouble(yearBeginNominalRate))); + Double d2 = Double.parseDouble(thisYearNewAddNum); + int newAddNum = d2.intValue(); + uploadDto.setThisYearNewAddNum(newAddNum); + uploadDto.setThisYearNewAddNominalRate(BigDecimal.valueOf(Double.parseDouble(thisYearNewAddNominalRate))); + Double d3 = Double.parseDouble(thisYearDecreaseNum); + int decreaseNum = d3.intValue(); + uploadDto.setThisYearDecreaseNum(decreaseNum); + uploadDto.setThisYearDecreaseNominalRate(BigDecimal.valueOf(Double.parseDouble(thisYearDecreaseNominalRate))); + Double d4 = Double.parseDouble(yearEndNum); + int endNum = d4.intValue(); + uploadDto.setYearEndNum(endNum); + uploadDto.setYearEndNominal(BigDecimal.valueOf(Double.parseDouble(yearEndNominal))); + + uploadDto.setReportYear(year); + uploadDto.setUnitResponsiblePerson(unitResponsiblePerson); + uploadDto.setPreparer(preparer); + uploadDto.setReviewer(reviewer); + uploadDto.setSubmissionDate(subDate); + dataList.add(uploadDto); + } + + // 先提交市级审核申请 + BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + cityAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityAuditInfo.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + cityAuditInfo.setCreateOn(subDate); + cityAuditInfo.setCreateBy(null); + cityAuditInfo.setUpdateOn(subDate); + cityAuditInfo.setUpdateBy(null); + cityAuditInfo.setAuditTime(subDate); + cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditInfoService.save(cityAuditInfo); + + // 创建区县关联数据信息(对应每个设备名称的数据关系为一对多) + BulkCementDirectReportSystemDataRelevance countryData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, regionId) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, 2022) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + BulkCementDirectReportSystemDataRelevance countryRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + // 说明为重新提交 + if (Objects.nonNull(countryData)){ + // 先删除关联的已经保存的各设备名称的数据 + String auditDataIdList = countryData.getAuditDataIdList(); + if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(auditDataIdList)){ + List idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idList)){ + bulkCementLogFacStaService.remove(Wrappers.lambdaQuery(BulkCementLogisticFacilityStatisticAnnualReport.class) + .in(BulkCementLogisticFacilityStatisticAnnualReport::getId,idList)); + } + } + countryRelevanceData.setId(countryData.getId()); + } + countryRelevanceData.setReportYear(2022); + countryRelevanceData.setUnitResponsiblePerson(unitResponsiblePerson); + countryRelevanceData.setPreparer(preparer); + countryRelevanceData.setReviewer(reviewer); + countryRelevanceData.setSubmissionDate(subDate); + countryRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + countryRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + countryRelevanceData.setCreateOn(LocalDateTime.now()); + countryRelevanceData.setCreateBy(null); + countryRelevanceData.setUpdateOn(subDate); + countryRelevanceData.setUpdateBy(null); + countryRelevanceData.setLastUpdateTime(subDate); + countryRelevanceData.setRegionId(regionId); + countryRelevanceData.setCompanyId(companyId); + List auditDataIdList = Lists.newArrayList(); + + // 保存本次上报数据信息 + for (ReqMaterialLogEquipStaDataUploadDTO uploadDto : dataList) { + MaterialLogisticEquipmentStatisticAnnualReport materialLogEquipStaAnnualReport = + new MaterialLogisticEquipmentStatisticAnnualReport(); + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + String regionName = regionDto.getRegionName(); + materialLogEquipStaAnnualReport.setRegionName(regionName + VehicleContant.ADMIN_COMPANY_NAME); + materialLogEquipStaAnnualReport.setEquipmentName(uploadDto.getEquipmentName()); + materialLogEquipStaAnnualReport.setYearBeginNum(uploadDto.getYearBeginNum()); + materialLogEquipStaAnnualReport.setYearBeginNominalRate(uploadDto.getYearBeginNominalRate()); + materialLogEquipStaAnnualReport.setThisYearNewAddNum(uploadDto.getThisYearNewAddNum()); + materialLogEquipStaAnnualReport.setThisYearNewAddNominalRate(uploadDto.getThisYearNewAddNominalRate()); + materialLogEquipStaAnnualReport.setThisYearDecreaseNum(uploadDto.getThisYearDecreaseNum()); + materialLogEquipStaAnnualReport.setThisYearDecreaseNominalRate(uploadDto.getThisYearDecreaseNominalRate()); + materialLogEquipStaAnnualReport.setYearEndNum(uploadDto.getYearEndNum()); + materialLogEquipStaAnnualReport.setYearEndNominal(uploadDto.getYearEndNominal()); + materialLogEquipStaAnnualReport.setReportYear(uploadDto.getReportYear()); + materialLogEquipStaAnnualReport.setRemark(uploadDto.getRemark()); + materialLogEquipStaAnnualReport.setCompanyId(companyId); + materialLogEquipStaAnnualReport.setUnitResponsiblePerson(uploadDto.getUnitResponsiblePerson()); + materialLogEquipStaAnnualReport.setPreparer(uploadDto.getPreparer()); + materialLogEquipStaAnnualReport.setReviewer(uploadDto.getReviewer()); + materialLogEquipStaAnnualReport.setSubmissionDate(uploadDto.getSubmissionDate()); + materialLogEquipStaAnnualReport.setRegionId(regionId); + materialLogEquipStaAnnualReport.setCreateOn(subDate); + materialLogEquipStaAnnualReport.setCreateBy(null); + materialLogEquipStaAnnualReport.setUpdateOn(subDate); + materialLogEquipStaAnnualReport.setUpdateBy(null); + materialLogEquipStaAnnualReport.setAuditInfoId(cityAuditInfo.getId()); + materialLogEquipStaAnnualReport.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + materialLogEquipStaAnnualReportService.save(materialLogEquipStaAnnualReport); + auditDataIdList.add(materialLogEquipStaAnnualReport.getId()); + } + // 保存关联数据ID集合(一条关联数据对应多条不同设备名称的数据) + String idListStr = auditDataIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + countryRelevanceData.setAuditDataIdList(idListStr); + dataRelevanceService.saveOrUpdate(countryRelevanceData); + + // 补充数据审核表信息 + BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord(); + auditRecord.setAuditDataId(countryRelevanceData.getId()); + auditRecord.setAuditInfoId(cityAuditInfo.getId()); + auditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + auditRecord.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + auditRecord.setCompanyId(companyId); + auditRecord.setRegionId(regionId); + auditRecord.setCreateOn(subDate); + auditRecord.setCreateBy(null); + auditRecord.setUpdateOn(subDate); + auditRecord.setUpdateBy(null); + auditRecord.setReportYear(2022); + auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + auditRecordService.save(auditRecord); + + //// 杭州市 + //String cityUnitResponsiblePerson = "赵斌"; + //String cityPreparer = "蔡义超"; + //String cityReviewer = "王瑞理"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-16 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 宁波市 + //String cityUnitResponsiblePerson = "卢汉"; + //String cityPreparer = "杨浩杰"; + //String cityReviewer = "徐立国"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-09 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 温州市 + //String cityUnitResponsiblePerson = null; + //String cityPreparer = null; + //String cityReviewer = null; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-01-01 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 嘉兴市 + //String cityUnitResponsiblePerson = "潘卫国"; + //String cityPreparer = "倪竹红"; + //String cityReviewer = "倪竹红"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-15 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 湖州市 + //String cityUnitResponsiblePerson = "傅饶"; + //String cityPreparer = "付平安"; + //String cityReviewer = "沈宁儿"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-06 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 绍兴市 + //String cityUnitResponsiblePerson = "丁正龙"; + //String cityPreparer = "寿晨杰"; + //String cityReviewer = "寿晨杰"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-13 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 金华市 + //String cityUnitResponsiblePerson = "汪欣"; + //String cityPreparer = "吴昌蒲"; + //String cityReviewer = "杨裕发"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-10 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 衢州市 + //String cityUnitResponsiblePerson = "徐欣"; + //String cityPreparer = "徐欣"; + //String cityReviewer = "徐欣"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-10 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 舟山市 + //String cityUnitResponsiblePerson = "刘海港"; + //String cityPreparer = "吴煜之"; + //String cityReviewer = "檀坤"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-01-10 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + //// 台州市 + //String cityUnitResponsiblePerson = "陈虹"; + //String cityPreparer = "林"; + //String cityReviewer = "林"; + //LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-02-16 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + // 丽水市 + String cityUnitResponsiblePerson = null; + String cityPreparer = null; + String cityReviewer = null; + LocalDateTime citySubDate = LocalDateTimeUtil.parse("2023-01-01 00:00:00", NdDateUtils.DEFAULT_DATE_TIME_FORMAT); + Long relevanceDataId; + // 判断上报年份所在市的市级关联数据不存在 + // 区县的区域ID + // 获取所在市的区域ID + RegionDTO regionDto = regionsCacheHelper.getByRegionId(regionId); + Long parentId = regionDto.getParentId(); + BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, 2022) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + // 已经存在,更新上报数据ID列表 + if (Objects.nonNull(cityData)){ + String auditDataIdListStr = cityData.getAuditDataIdList(); + List auditIdList; + if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(auditDataIdListStr)){ + auditIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditIdList.contains(countryRelevanceData.getId())){ + auditIdList.add(countryRelevanceData.getId()); + String dataIdListStr = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityData.setAuditDataIdList(dataIdListStr); + } + // 更新最后一次更新时间 + cityData.setLastUpdateTime(subDate); + cityData.setUpdateOn(subDate); + cityData.setUpdateBy(null); + // 有新上报的数据 + cityData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(cityData); + } + relevanceDataId = cityData.getId(); + }else { + // 补充所在市的关联数据信息 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + cityRelevanceData.setReportYear(2022); + List auditIdList = Lists.newArrayList(); + if (Objects.nonNull(countryRelevanceData.getId())) { + auditIdList.add(countryRelevanceData.getId()); + String idListString = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + cityRelevanceData.setAuditDataIdList(idListString); + } + cityRelevanceData.setUnitResponsiblePerson(cityUnitResponsiblePerson); + cityRelevanceData.setPreparer(cityPreparer); + cityRelevanceData.setReviewer(cityReviewer); + cityRelevanceData.setSubmissionDate(citySubDate); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setCreateOn(citySubDate); + cityRelevanceData.setCreateBy(null); + cityRelevanceData.setUpdateOn(citySubDate); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setLastUpdateTime(citySubDate); + cityRelevanceData.setRegionId(parentId); + // 获取所在市散装中心所属的管理企业ID + CompanyDTO companyDto = companiesCacheHelper.getByName(regionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(companyDto)) { + cityRelevanceData.setCompanyId(companyDto.getId()); + } + cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode()); + cityRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + // 有新上报的数据,就更新关联数据状态为未上报 + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.saveOrUpdate(cityRelevanceData); + relevanceDataId = cityRelevanceData.getId(); + } + + + // 补充省级审核申请 + BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo(); + provinceAuditInfo.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditInfo.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + provinceAuditInfo.setCreateOn(citySubDate); + provinceAuditInfo.setCreateBy(null); + provinceAuditInfo.setUpdateOn(citySubDate); + provinceAuditInfo.setUpdateBy(null); + provinceAuditInfo.setAuditTime(citySubDate); + provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditInfoService.save(provinceAuditInfo); + // 更新市级关联数据 + BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId); + VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!"); + // 关联审核信息ID + cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId()); + cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + cityRelevanceData.setUpdateOn(citySubDate); + cityRelevanceData.setUpdateBy(null); + cityRelevanceData.setUnitResponsiblePerson(null); + cityRelevanceData.setPreparer(null); + cityRelevanceData.setReviewer(null); + cityRelevanceData.setSubmissionDate(citySubDate); + dataRelevanceService.updateById(cityRelevanceData); + + // 判断上报月份省关联数据是否存在 + BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class) + .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()) + .eq(BulkCementDirectReportSystemDataRelevance::getReportYear, 2022) + .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode())); + // 存在,更新市关联数据ID列表 + if (Objects.nonNull(provinceData)){ + String auditDataIdListStr = provinceData.getAuditDataIdList(); + List auditIdList; + if (StringUtils.isNotBlank(auditDataIdListStr)){ + auditIdList = Arrays.stream(auditDataIdListStr.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList()); + if (!auditIdList.contains(relevanceDataId)){ + auditIdList.add(relevanceDataId); + String idListString = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceData.setAuditDataIdList(idListString); + } + // 更新最后一次更新时间 + provinceData.setLastUpdateTime(citySubDate); + provinceData.setUpdateOn(citySubDate); + provinceData.setUpdateBy(null); + // 有新上报的数据,就更新关联数据状态为审核中 + provinceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.updateById(provinceData); + } + }else { + // 如果上报月份省级关联数据不存在 + // 补充省散办关联数据信息 + BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance(); + provinceRelevanceData.setReportYear(2022); + List auditIdList = Lists.newArrayList(); + auditIdList.add(relevanceDataId); + String idListString = auditIdList.stream().map(String::valueOf).collect(Collectors.joining(StrPool.COMMA)); + provinceRelevanceData.setAuditDataIdList(idListString); + + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setCreateOn(citySubDate); + provinceRelevanceData.setCreateBy(null); + provinceRelevanceData.setUpdateOn(citySubDate); + provinceRelevanceData.setUpdateBy(null); + provinceRelevanceData.setLastUpdateTime(citySubDate); + provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID); + provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + // 获取省散装中心所属的管理企业ID + CompanyDTO provinceCompanyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME); + if (Objects.nonNull(provinceCompanyDto)) { + provinceRelevanceData.setCompanyId(provinceCompanyDto.getId()); + } + provinceRelevanceData.setUnitResponsiblePerson(null); + provinceRelevanceData.setPreparer(null); + provinceRelevanceData.setReviewer(null); + provinceRelevanceData.setSubmissionDate(null); + provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + dataRelevanceService.save(provinceRelevanceData); + } + + // 创建省级审核记录 + BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord(); + provinceAuditRecord.setAuditDataId(cityRelevanceData.getId()); + provinceAuditRecord.setAuditInfoId(provinceAuditInfo.getId()); + provinceAuditRecord.setAuditStatus(DataUploadAuditStatusEnum.AUDIT_PASS.getCode()); + provinceAuditRecord.setAuditDataType(UploadDataTypeEnum.MATERIAL_LOGISTIC_EQUIPMENT_STATISTIC_ANNUAL_REPORT.getCode()); + provinceAuditRecord.setCompanyId(cityRelevanceData.getCompanyId()); + provinceAuditRecord.setRegionId(cityRelevanceData.getRegionId()); + provinceAuditRecord.setCreateOn(cityRelevanceData.getSubmissionDate()); + provinceAuditRecord.setCreateBy(null); + provinceAuditRecord.setUpdateOn(cityRelevanceData.getSubmissionDate()); + provinceAuditRecord.setUpdateBy(null); + provinceAuditRecord.setReportYear(2022); + provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode()); + auditRecordService.save(provinceAuditRecord); + } + } + + @Test + public void updateTest() { + // 散装水泥供应量数据 + List bulkCementSupplyBulletinList = bulkCementSupplyBulletinService.list(); + for (BulkCementSupplyBulletin bulkCementSupplyBulletin : bulkCementSupplyBulletinList) { + Long regionId = bulkCementSupplyBulletin.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + bulkCementSupplyBulletin.setUnitName(regionDTO.getRegionName()); + bulkCementSupplyBulletinService.updateById(bulkCementSupplyBulletin); + } + + // 中转库进出量数据 + List bulkCementTransferBulletins = bulkCementTransferBulletinService.list(); + for (BulkCementTransferBulletin bulkCementTransferBulletin : bulkCementTransferBulletins) { + Long regionId = bulkCementTransferBulletin.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + bulkCementTransferBulletin.setUnitName(regionDTO.getRegionName()); + bulkCementTransferBulletinService.updateById(bulkCementTransferBulletin); + } + + + // 温台州使用量数据 + List bulkCementThreeCityUsageBulletins = bulkCementThreeCityUsageBulletinService.list(); + for (BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin : bulkCementThreeCityUsageBulletins) { + Long regionId = bulkCementThreeCityUsageBulletin.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + bulkCementThreeCityUsageBulletin.setUnitName(regionDTO.getRegionName()); + bulkCementThreeCityUsageBulletinService.updateById(bulkCementThreeCityUsageBulletin); + } + + // 混凝土供应量数据 + List concreteSupplyBulletins = concreteSupplyBulletinService.list(); + for (ConcreteSupplyBulletin concreteSupplyBulletin : concreteSupplyBulletins) { + Long regionId = concreteSupplyBulletin.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + concreteSupplyBulletin.setUnitName(regionDTO.getRegionName()); + concreteSupplyBulletinService.updateById(concreteSupplyBulletin); + } + + // 砂浆供应量数据 + List mortarSupplyBulletins = mortarSupplyBulletinService.list(); + for (MortarSupplyBulletin mortarSupplyBulletin : mortarSupplyBulletins) { + Long regionId = mortarSupplyBulletin.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + mortarSupplyBulletin.setRegionName(regionDTO.getRegionName()); + mortarSupplyBulletinService.updateById(mortarSupplyBulletin); + } + + // 非禁现区数据 + List nonProhibitedAreasBulkCementSalesUses = nonProhibitedAreasBulkCementSalesUseService.list(); + for (NonProhibitedAreasBulkCementSalesUse nonProhibitedAreasBulkCementSalesUse : nonProhibitedAreasBulkCementSalesUses) { + Long regionId = nonProhibitedAreasBulkCementSalesUse.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + nonProhibitedAreasBulkCementSalesUse.setRegionName(regionDTO.getRegionName()); + nonProhibitedAreasBulkCementSalesUseService.updateById(nonProhibitedAreasBulkCementSalesUse); + } + + // 物流设施数据 + List bulkCementLogisticFacilityStatisticAnnualReports = bulkCementLogFacStaService.list(); + for (BulkCementLogisticFacilityStatisticAnnualReport bulkCementLogisticFacilityStatisticAnnualReport : bulkCementLogisticFacilityStatisticAnnualReports) { + Long regionId = bulkCementLogisticFacilityStatisticAnnualReport.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + bulkCementLogisticFacilityStatisticAnnualReport.setRegionName(regionDTO.getRegionName()); + bulkCementLogFacStaService.updateById(bulkCementLogisticFacilityStatisticAnnualReport); + } + + // 物流装备数据 + List materialLogisticEquipmentStatisticAnnualReports = materialLogEquipStaAnnualReportService.list(); + for (MaterialLogisticEquipmentStatisticAnnualReport materialLogisticEquipmentStatisticAnnualReport : materialLogisticEquipmentStatisticAnnualReports) { + Long regionId = materialLogisticEquipmentStatisticAnnualReport.getRegionId(); + RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId); + materialLogisticEquipmentStatisticAnnualReport.setRegionName(regionDTO.getRegionName()); + materialLogEquipStaAnnualReportService.updateById(materialLogisticEquipmentStatisticAnnualReport); + } + } + + + + //这个下面是单独函数 + public static org.apache.poi.ss.usermodel.Workbook readExcel(InputStream is, String extString){ + Workbook wb = null; + extString = extString.substring(extString.lastIndexOf(".")); + try { + if(".xls".equals(extString)){ + return wb = new HSSFWorkbook(is); + }else if(".xlsx".equals(extString)){ + return wb = new XSSFWorkbook(is); + }else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } +} + diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/safe/InsureOutdangerTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/safe/InsureOutdangerTest.java new file mode 100644 index 0000000..a6da96e --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/safe/InsureOutdangerTest.java @@ -0,0 +1,442 @@ +package com.ningdatech.carapi.safe; + +import java.io.*; +import java.math.BigDecimal; +import java.time.ZoneId; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alibaba.fastjson.JSON; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.safe.entity.NdInsureInfo; +import com.ningdatech.carapi.safe.entity.NdInsureOutDanger; +import com.ningdatech.carapi.safe.service.INdInsureInfoService; +import com.ningdatech.carapi.safe.service.INdInsureOutDangerService; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.Region; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; +import com.ningdatech.carapi.sys.helper.RegionsCacheHelper; +import com.ningdatech.carapi.sys.helper.VehiclesCacheHelper; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.IRegionService; + +/** + * @Classname InsureOutdangerTest + * @Description + * @Date 2022/12/22 10:47 + * @Created by PoffyZhang + */ +public class InsureOutdangerTest extends AppTests { + + @Autowired + private CompaniesCacheHelper companiesCacheHelper; + + @Autowired + private VehiclesCacheHelper vehiclesCacheHelper; + + @Autowired + private INdInsureOutDangerService outDangerService; + + @Autowired + private IVehicleBaseInfoService vehicleBaseInfoService; + + @Autowired + private INdInsureInfoService insureInfoService; + + @Autowired + private IRegionService regionService; + @Autowired + private RegionsCacheHelper regionCacheHelper; + @Autowired + private CompanyService companyService; + + @Test + public void test() throws FileNotFoundException { + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\出险信息导入\\出险详情\\出险详情\\2023年1-5月出险数据.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + Map vehicleBaseInfoMap = vehicleBaseInfoService.list() + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + //Map outDangerMap = outDangerService.list(Wrappers.lambdaQuery(NdInsureOutDanger.class) + // .select(NdInsureOutDanger::getCarPlate,NdInsureOutDanger::getAccidentTime, + // NdInsureOutDanger::getAccidentAddress,NdInsureOutDanger::getId) + // .gt(NdInsureOutDanger::getAccidentTime,"2023-01-01") + // .lt(NdInsureOutDanger::getAccidentTime,"2023-12-31")) + // .stream() + // .collect(Collectors.toMap(v -> v.getCarPlate() + StrPool.DASH + v.getAccidentAddress() + StrPool.DASH + v.getAccidentTime(), NdInsureOutDanger::getId)); + + //获取最大列数 + for (int i = 1; i vehicleBaseInfoMap = vehicleBaseInfoService.list() + .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + HashSet countySet = new HashSet<>(); + // 根据区县名称获取区域ID + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + //获取最大列数 + for (int i = 1; i countySet = new HashSet<>(); + Map regionMap = regionService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + !"市本级".equals(v.getName()) && + countySet.add(v.getName())) + .collect(Collectors.toMap(Region::getName, v -> v)); + + // 根据企业名查询企业信息 + HashSet companySet = new HashSet<>(); + Map companyNameMap = companyService.list().stream() + .filter(v -> !StrPool.EMPTY.equals(v.getName()) && + companySet.add(v.getName())) + .collect(Collectors.toMap(Company::getName, v -> v)); + + for (int i = 1; i vehicleStatusInGps = vehicleStatusService.getVehicleStatusInGps(); + System.out.println(JSON.toJSONString(vehicleStatusInGps)); + } +} diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/sms/SendSms.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/sms/SendSms.java new file mode 100644 index 0000000..3274f38 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/sms/SendSms.java @@ -0,0 +1,42 @@ +package com.ningdatech.carapi.sms; + +import com.ningdatech.carapi.sys.utils.HttpUtils; +import org.apache.http.HttpResponse; +import java.util.*; + +public class SendSms { + public static void main(String[] args) { + String host = "https://gyytz.market.alicloudapi.com"; + String path = "/sms/smsSend"; + String method = "POST"; + String appcode = "daab49d0cf344614b174a9bf8303b4e2"; + Map headers = new HashMap(); + //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 + headers.put("Authorization", "APPCODE " + appcode); + Map querys = new HashMap(); + querys.put("mobile", "15058187290"); + querys.put("param", "**code**:1234,**minute**:5"); + querys.put("smsSignId", "2e65b1bb3d054466b82f0c9d125465e2"); + querys.put("templateId", "908e94ccf08b4476ba6c876d13f084ad"); + Map bodys = new HashMap(); + + try { + /** + * 重要提示如下: + * HttpUtils请从 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java + * 下载 + * + * 相应的依赖请参照 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml + */ + HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys); + System.out.println("短信验证码返回:" + response.toString()); + //获取response的body + //System.out.println(EntityUtils.toString(response.getEntity())); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTempTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTempTest.java new file mode 100644 index 0000000..da657e8 --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTempTest.java @@ -0,0 +1,44 @@ +package com.ningdatech.carapi.sys.helper; + +import com.ningdatech.carapi.AppTests; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + *

+ * RegionsCacheHelperTempTest + *

+ * + * @author WendyYang + * @since 22:24 2022/10/24 + */ +class RegionsCacheHelperTempTest extends AppTests { + + @Autowired + private RegionsCacheHelper regionsCacheHelper; + + @Test + void refresh() { + regionsCacheHelper.refresh(7L); + } + + @Test + void getAll() { + regionsCacheHelper.getAll().forEach(System.out::println); + } + + @Test + void listChildRegionId() { + regionsCacheHelper.listChildRegionId(2L).forEach(System.out::println); + } + + @Test + void listParents() { + regionsCacheHelper.listParents(128L).forEach(System.out::println); + } + + @Test + void getDisplayName() { + System.out.println(regionsCacheHelper.getDisplayName(128L)); + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTest.java new file mode 100644 index 0000000..1121bac --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/sys/helper/RegionsCacheHelperTest.java @@ -0,0 +1,68 @@ +package com.ningdatech.carapi.sys.helper; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.industry.model.dto.UseCertPageParamDTO; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * RegionsCacheHelperTest + *

+ * + * @author WendyYang + * @since 17:50 2022/10/22 + */ +class RegionsCacheHelperTest extends AppTests { + + @Autowired + private RegionsCacheHelper regionsCacheHelper; + + @Test + public void listChildren() { + System.out.println("regionsCacheHelper.listParents(1L) = " + regionsCacheHelper.listChildRegionId(2L)); + } + + @Test + public void listParents() { + System.out.println("regionsCacheHelper.listParents(1L) = " + regionsCacheHelper.listParents(2L)); + } + + @Test + public void getByRegionId() { + System.out.println("regionsCacheHelper.getByRegionId(7) = " + regionsCacheHelper.getByRegionId(7L)); + } + + @Test + public void downRegionJsonFile() { + List longs = regionsCacheHelper.listChildRegionId(116L); + List regionCodes = longs.stream() + .map(w -> regionsCacheHelper.getByRegionId(w).getRegionCode()) + .distinct() + .collect(Collectors.toList()); + regionCodes.forEach(w -> { + String name = w + (!w.substring(4).equals("00") ? ".json" : "_full.json"); + String url = String.format("https://geo.datav.aliyun.com/areas_v3/bound/%s", name); + try { + URL url1 = new URL(url); + InputStream stream = url1.openConnection().getInputStream(); + FileUtils.copyInputStreamToFile(stream, new File("/Users/wendy/desktop/" + w + ".json")); + } catch (Exception ignore) { + System.out.println(w); + } + }); + } + +} \ No newline at end of file diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/user/UserInfoTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/user/UserInfoTest.java new file mode 100644 index 0000000..257a37b --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/user/UserInfoTest.java @@ -0,0 +1,129 @@ +package com.ningdatech.carapi.user; + +import java.io.*; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.common.constant.UserRoleTypeEnum; +import com.ningdatech.carapi.sys.entity.Company; +import com.ningdatech.carapi.sys.entity.UserRole; +import com.ningdatech.carapi.sys.service.CompanyService; +import com.ningdatech.carapi.sys.service.UserRoleService; +import com.ningdatech.carapi.user.entity.NdUserAuth; +import com.ningdatech.carapi.user.entity.NdUserInfo; +import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum; +import com.ningdatech.carapi.user.service.INdUserAuthService; +import com.ningdatech.carapi.user.service.INdUserInfoService; + +/** + * @Classname InsureOutdangerTest + * @Description + * @Date 2022/12/22 10:47 + * @Created by PoffyZhang + */ +public class UserInfoTest extends AppTests { + + @Autowired + private CompanyService companyService; + @Autowired + private INdUserInfoService userInfoService; + @Autowired + private INdUserAuthService userAuthService; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private UserRoleService userRoleService; + + @Test + public void test() throws FileNotFoundException { + File f = new File("C:\\Users\\CMM\\Desktop\\年全省预拌混凝土、砂浆企业基本情况调查表2\\账号.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Row row = null; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } +} \ No newline at end of file diff --git a/ningda-yw-api/src/test/java/com/ningdatech/carapi/vehicle/CompanyVehicleTest.java b/ningda-yw-api/src/test/java/com/ningdatech/carapi/vehicle/CompanyVehicleTest.java new file mode 100644 index 0000000..691e9bf --- /dev/null +++ b/ningda-yw-api/src/test/java/com/ningdatech/carapi/vehicle/CompanyVehicleTest.java @@ -0,0 +1,800 @@ +package com.ningdatech.carapi.vehicle; + +import java.io.*; +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.ningdatech.carapi.AppTests; +import com.ningdatech.carapi.archives.enums.AuditStateEnum; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels; +import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentChannelsService; +import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService; +import com.ningdatech.carapi.car.vehicle.manage.VehicleManage; +import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo; +import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService; +import com.ningdatech.carapi.common.constant.VehicleTypeEnum; +import com.ningdatech.carapi.sys.entity.dto.CompanyDTO; +import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper; + +import cn.hutool.core.collection.CollUtil; + +/** + * @Classname OpenApiTest + * @Description + * @Date 2022/11/3 10:47 + * @Created by PoffyZhang + */ +public class CompanyVehicleTest extends AppTests { + + @Autowired + private CompaniesCacheHelper companiesCacheHelper; + + @Autowired + private VehicleManage vehicleManage; + + @Autowired + private INdVehicleEquipmentInfoService equipmentInfoService; + @Autowired + private INdVehicleEquipmentChannelsService equipmentChannelsService; + + @Autowired + private IVehicleBaseInfoService vehicleBaseInfoService; + + @Test + public void test() throws FileNotFoundException { + File f = new File("C:\\Users\\PoffyZhang\\Desktop\\海盐秦山混凝土有限公司.xls"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Assert.assertNotNull(wb); + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i equipmentNos = Lists.newArrayList(); + equipmentNos.add(row.getCell(2)); + equipmentNos.add(row.getCell(3)); + equipmentNos.add(row.getCell(4)); + equipmentNos.add(row.getCell(5)); + equipmentNos.add(row.getCell(6)); + equipmentNos.add(row.getCell(7)); + equipmentNos.add(row.getCell(8)); + equipmentNos.add(row.getCell(9)); + + List vehicles = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate,carPlate) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode())); + + if(CollUtil.isEmpty(vehicles)){ + NdVehicleBaseInfo vehicle = new NdVehicleBaseInfo(); + CompanyDTO company = companiesCacheHelper.getByName(companyName); + if(Objects.isNull(company)){ + System.out.println("没有这个公司 " + companyName); + continue; + } + vehicle.setCompanyId(company.getId()); + vehicle.setAuditState(AuditStateEnum.AUDIT_SUCCESS.getCode()); + vehicle.setRegionId(company.getRegionId()); + vehicle.setRegionName(company.getRegionName()); + vehicle.setCarPlate(carPlate); + vehicle.setAuditMind("审核通过"); + vehicle.setAuditBy(1L); + vehicle.setAuditTime(LocalDateTime.now()); + vehicle.setStatus(1); + if(vehicleBaseInfoService.save(vehicle)){ + vehicles.add(vehicle); + } + } + //1.先删除该车辆下的设备 + equipmentInfoService.remove(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) + .eq(NdVehicleEquipmentInfo::getVehicleId,vehicles.get(0).getId())); + + int j = 1; + for(Cell equipmentNoCell : equipmentNos){ + if(Objects.isNull(equipmentNoCell)){ + System.out.println("空行跳过"); + continue; + } + String equipmentNo = equipmentNoCell.toString(); + System.out.println(carPlate + "," + companyName + "," + equipmentNo); + + try{ + NdVehicleBaseInfo vehicle = vehicles.get(0); + + CompanyDTO company = companiesCacheHelper.getById(vehicle.getCompanyId()); + if(Objects.isNull(company)){ + System.out.println("没有此公司 !" + vehicle.getCompanyId()); + continue; + } + + //2.添加车辆设备 + NdVehicleEquipmentInfo saveEntity = new NdVehicleEquipmentInfo(); + saveEntity.setCarPlate(carPlate); + saveEntity.setRegionId(company.getRegionId()); + saveEntity.setEquipmentNo(equipmentNo); + saveEntity.setName("摄像头" + j); + saveEntity.setVehicleId(vehicle.getId()); + if(equipmentInfoService.save(saveEntity)){ + System.out.println("设备添加成功 :" + JSON.toJSONString(saveEntity)); + } + j++; + }catch (Exception e){ + e.printStackTrace(); + } + } + } + } + } + + @Test + public void importLvDao() throws FileNotFoundException { + File f = new File("C:\\Users\\PoffyZhang\\Desktop\\绿岛上报的设备通道.xlsx"); + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + Assert.assertNotNull(wb); + List hasNoCarPlate = Lists.newArrayList(); + Map equipmentCountMap = Maps.newConcurrentMap(); + + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i vehicles = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate,carPlate) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode())); + + if(CollUtil.isEmpty(vehicles)){ + hasNoCarPlate.add(carPlate); + continue; +// NdVehicleBaseInfo vehicle = new NdVehicleBaseInfo(); +// CompanyDTO company = companiesCacheHelper.getByName(companyName); +// if(Objects.isNull(company)){ +// System.out.println("没有这个公司 " + companyName); +// continue; +// } +// vehicle.setCompanyId(company.getId()); +// vehicle.setAuditState(AuditStateEnum.AUDIT_SUCESS.getCode()); +// vehicle.setRegionId(company.getRegionId()); +// vehicle.setRegionName(company.getRegionName()); +// vehicle.setCarPlate(carPlate); +// vehicle.setAudiMind("审核通过"); +// vehicle.setAuditBy(1L); +// vehicle.setAuditTime(LocalDateTime.now()); +// vehicle.setStatus(1); +// if(vehicleBaseInfoService.save(vehicle)){ +// vehicles.add(vehicle); +// } + } +// //1.先删除该车辆下的设备 +// equipmentInfoService.remove(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) +// .eq(NdVehicleEquipmentInfo::getVehicleId,vehicles.get(0).getId())); + + if(Objects.isNull(equipmentNo)){ + System.out.println("空行跳过"); + continue; + } + System.out.println(carPlate + "," + companyName + "," + equipmentNo); + + try{ + NdVehicleBaseInfo vehicle = vehicles.get(0); + + CompanyDTO company = companiesCacheHelper.getById(vehicle.getCompanyId()); + if(Objects.isNull(company)){ + System.out.println("没有此公司 !" + vehicle.getCompanyId()); + continue; + } + + if(equipmentCountMap.containsKey(carPlate)){ + equipmentCountMap.put(carPlate,equipmentCountMap.get(carPlate) + 1); + }else{ + equipmentCountMap.put(carPlate,1); + } + + //2.添加车辆设备 + NdVehicleEquipmentInfo old = equipmentInfoService.getOne(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class) + .eq(NdVehicleEquipmentInfo::getEquipmentNo,equipmentNo).last("limit 1")); + NdVehicleEquipmentInfo saveEntity = new NdVehicleEquipmentInfo(); + if(Objects.nonNull(old)){ + saveEntity = old; + } + saveEntity.setCarPlate(carPlate); + saveEntity.setRegionId(company.getRegionId()); + saveEntity.setEquipmentNo(equipmentNo); + saveEntity.setName("摄像头" + equipmentCountMap.get(carPlate)); + saveEntity.setVehicleId(vehicle.getId()); + if(equipmentInfoService.saveOrUpdate(saveEntity)){ + System.out.println("设备添加成功 :" + JSON.toJSONString(saveEntity)); + } + }catch (Exception e){ + e.printStackTrace(); + } + + } + + + if(!hasNoCarPlate.isEmpty()){ + System.out.println("系统不存在的车辆号 " + hasNoCarPlate.size() + "个"); + for(String carPlate : hasNoCarPlate){ + System.out.print(carPlate + ","); + } + } + } + } + + @Test + public void test4() throws IOException { + File file = new File("C:\\Users\\PoffyZhang\\Desktop\\宁达文档\\联调车辆信息新(网泽)(1)(1).xlsx"); + InputStream is = Files.newInputStream(file.toPath()); + Workbook wb = readExcel(is,file.getName()); + + Assert.assertNotNull(wb); + + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i hasNoCarPlate = Sets.newHashSet(); + + Assert.assertNotNull(wb); + + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + //获取最大列数 + for (int i = 1; i vehicles = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class) + .eq(NdVehicleBaseInfo::getCarPlate,carPlate) + .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode())); + + if(CollUtil.isEmpty(vehicles)){ + hasNoCarPlate.add(carPlate); + continue; + } + } + + + if(!hasNoCarPlate.isEmpty()){ + System.out.println("系统不存在的车辆号 " + hasNoCarPlate.size() + "个"); + for(String carPlate : hasNoCarPlate){ + System.out.print(carPlate + ","); + } + } + } + } + + //这个下面是单独函数 + public static Workbook readExcel(InputStream is, String extString){ + Workbook wb = null; + + extString = extString.substring(extString.lastIndexOf(".")); + try { + if(".xls".equals(extString)){ + return wb = new HSSFWorkbook(is); + }else if(".xlsx".equals(extString)){ + return wb = new XSSFWorkbook(is); + }else { + return wb = null; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return wb; + } + + @Test + public void testTTTT(){ + List carsOnline = Arrays.asList("1","2"); + Boolean update = vehicleBaseInfoService.update(Wrappers.lambdaUpdate(NdVehicleBaseInfo.class) + .set(NdVehicleBaseInfo::getStatus, 0) + .notIn(NdVehicleBaseInfo::getCarPlate, carsOnline)); + System.out.println(update); + } + + + // 导入设备编号 + @Test + public void importEquipmentNo() throws FileNotFoundException { + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\中导设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\吴霞设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\绿岛设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\马良设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\星软设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\中交设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\网泽设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\道为尔设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\金华丽驰设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\嘉兴信达设备信息.xlsx"); + //File f = new File("D:\\work\\水泥车视频设备数据\\视频设备添加-星软-11.29.xlsx"); + File f = new File("D:\\work\\水泥车视频设备数据\\视频设备添加-星软-12.12.xlsx"); + + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + + Set hasNoCarPlate = Sets.newHashSet(); + + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 获取车辆基本信息 + Map baseInfoMap = vehicleBaseInfoService.list().stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取车辆设备信息 + Map> equipmentMap = equipmentInfoService.list().stream() + .collect(Collectors.groupingBy(NdVehicleEquipmentInfo::getCarPlate)); + + // 获取车辆通道信息 + Map channelsMap = equipmentChannelsService.list().stream() + .collect(Collectors.toMap(NdVehicleEquipmentChannels::getEquipmentId, v -> v)); + + + //获取最大列数 + for (int i = 1; i equipmentInfos = equipmentMap.get(carPlate); + if (CollUtil.isNotEmpty(equipmentInfos)) { + // 当前车牌号已存在设备信息 + Map equipmentInfoMap = equipmentInfos.stream() + .collect(Collectors.toMap(NdVehicleEquipmentInfo::getEquipmentNo, v -> v)); + if (equipmentInfoMap.containsKey(equipmentNo)) { + // 已导入该设备信息 + NdVehicleEquipmentInfo vehicleEquipmentInfo = equipmentInfoMap.get(equipmentNo); + equipmentInfo.setId(vehicleEquipmentInfo.getId()); + } + } + + // 保存设备信息 + //equipmentInfo.setSimCardNo(simCardNo); + //equipmentInfo.setEndPoint(endPoint); + equipmentInfo.setEquipmentNo(equipmentNo); + equipmentInfo.setEquipmentFunction(equipmentFunction); + equipmentInfo.setVehicleId(baseInfo.getId()); + equipmentInfo.setCarPlate(carPlate); + equipmentInfo.setName(name); + equipmentInfo.setPlatformId(platformId); + equipmentInfo.setUpdateOn(LocalDateTime.now()); + equipmentInfoService.saveOrUpdate(equipmentInfo); + + // 保存通道名称 + NdVehicleEquipmentChannels equipmentChannel = new NdVehicleEquipmentChannels(); + Long equipmentId = equipmentInfo.getId(); + // 通道信息存在 + if (channelsMap.containsKey(equipmentId)){ + NdVehicleEquipmentChannels channels = channelsMap.get(equipmentId); + equipmentChannel.setId(channels.getId()); + } + equipmentChannel.setEquipmentId(equipmentId); + equipmentChannel.setName(channelName); + equipmentChannel.setUpdateOn(LocalDateTime.now()); + equipmentChannelsService.saveOrUpdate(equipmentChannel); + } + + if(!hasNoCarPlate.isEmpty()){ + System.out.println("系统不存在的车辆号 " + hasNoCarPlate.size() + "个"); + for(String carPlate : hasNoCarPlate){ + System.out.print(carPlate + ","); + } + } + } + } + + // 更新车辆类型 + @Test + public void importEquipmentNo2() throws FileNotFoundException { + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\中导设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\吴霞设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\绿岛设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\马良设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\星软设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\中交设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\网泽设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\道为尔设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\金华丽驰设备信息.xlsx"); + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\嘉兴信达设备信息.xlsx"); + + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + + Set hasNoCarPlate = Sets.newHashSet(); + + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 获取车辆基本信息 + Map baseInfoMap = vehicleBaseInfoService.list().stream() + .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v)); + + // 获取车辆设备信息 + Map> equipmentMap = equipmentInfoService.list().stream() + .collect(Collectors.groupingBy(NdVehicleEquipmentInfo::getCarPlate)); + + //获取最大列数 + for (int i = 1; i equipmentInfos = equipmentMap.get(carPlate); + if (CollUtil.isNotEmpty(equipmentInfos)) { + // 当前车牌号已存在设备信息 + Map equipmentInfoMap = equipmentInfos.stream() + .collect(Collectors.toMap(NdVehicleEquipmentInfo::getEquipmentNo, v -> v)); + if (equipmentInfoMap.containsKey(equipmentNo)) { + // 已导入该设备信息 + NdVehicleEquipmentInfo vehicleEquipmentInfo = equipmentInfoMap.get(equipmentNo); + equipmentInfo.setId(vehicleEquipmentInfo.getId()); + } + } + + // 保存设备信息 + equipmentInfo.setSimCardNo(simCardNo); + equipmentInfo.setEndPoint(endPoint); + equipmentInfo.setEquipmentNo(equipmentNo); + equipmentInfo.setEquipmentFunction(equipmentFunction); + equipmentInfo.setVehicleId(baseInfo.getId()); + equipmentInfo.setCarPlate(carPlate); + equipmentInfo.setName(name); + equipmentInfo.setPlatformId(platformId); + equipmentInfo.setUpdateOn(LocalDateTime.now()); + equipmentInfoService.saveOrUpdate(equipmentInfo); + } + + if(!hasNoCarPlate.isEmpty()){ + System.out.println("系统不存在的车辆号 " + hasNoCarPlate.size() + "个"); + for(String carPlate : hasNoCarPlate){ + System.out.print(carPlate + ","); + } + } + } + } + + + // 导入平台ID + @Test + public void importPlatId() throws FileNotFoundException { + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\中导设备信息.xlsx"); + File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\吴霞设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\绿岛设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\马良设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\星软设备信息.xlsx"); + //File f = new File("C:\\Users\\CMM\\Desktop\\水泥车数据初始化\\设备信息\\中交设备信息.xlsx"); + + Workbook wb = readExcel(new FileInputStream(f),f.getName()); + + Set hasNoCarPlate = Sets.newHashSet(); + + Row row; + if(wb != null){ + //获取第一个sheet + Sheet sheet = wb.getSheetAt(0); + //获取最大行数 + int rownum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + row = sheet.getRow(0); + + // 获取车辆设备信息 + Map equipmentMap = equipmentInfoService.list().stream() + .filter(e -> "video".equals(e.getEquipmentFunction())) + .collect(Collectors.toMap(e -> e.getCarPlate() + e.getEquipmentNo(), e -> e)); + + //获取最大列数 + for (int i = 1; i{!Za#b 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

&fHNC*jshoKN=jzxUt#2YY{ZZL2<9SXk{SdT$FB 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

{tptU^MFb=O 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

>l@sZAGHipF3JUR8)m(9M^1l*j_55BjKaH; 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ྠ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 z zS%y&_?;Qmda)o_zMn(D>*#Wr4Sa?16YSNA&d<{xt7id8gTTobhc6RFG+b)un4dpH~ z?v#|B|AU{ha(&tFYv{?bhO5j0MXEe#Qy-)s|I}akr_w0v4{16O!x9f|4FV6)6b{b` zg0At~7OxW$^p`+rDikQT4xKY=>cn+@TxaOhx{^~Cc4A`7pKEPfN-rvs91>!+*X9X; zAqKO@)0_X;UKsI8jqoSk41hOT-<~Y7q5R^3XoHv8)`Bv?*ZQe}Qi7muUYy_r@oM~h zX<`Vp$NY#ler{H7-nD2=zV}vrqTPYS*mj-Q?L60_Y+?23Z!Y_YZZv-+&&@05m|ZyL#%KBg%||;+&2JTQqi& zTk8-TdfQawGBBt1UC>@VnKB1G1A{PzR28&enEQnu(V-*9qdY;E3tGT1&x#S+aLn$$ z&Om&+zHFw|V@X+9Re?`+P1>E1%0I)y6-N}@Yp2qagAaIa2)G)CRn12p7}5fzO?@UI zO19zi@Y12FQKv)ittdavozZ~e&Aw~2fFECm5`ja99&w!9s9btJK+!A`32PKX86~50 zhsgx^+#T7aP^R|u%jDJ-bnO632=w+qtlD`lpocfVv z^l41J0B!{hEWtI97C2m5X1dQuikN5Hj=&2+2_b1QJ5`j<{WM|{t)_XBmeXVCZIC1b z9>7?Kv~<0FzIsH=PGS}C+(HcC7_k#Xw^WHT@IMGS1$&0Lk{rCgFzABzFh5l{yMl2g z^&L;WSD-W#URIWD2ZTeMDXx@G4Uf!nn(Uvo0w~QGkFeZM6E%1yq@llUNN5YGE57iO zJ_AC&?wv^TpXQnO=3>#f{l1~PLF#Sg05GR}f0na4bOo{y|J9eU5SOmZ+F1`y3k9GF z>75b;98Yti(c-wiDMR{&DZkpi(m&aLdj1WUrT|63%x5(X8kLF~t?jN=nYrW>Ta$i!iJVu{GN%j zV)$AkWxYME-keLYTwxVj!o;DZbI?#BaW#1lSY$&8d%+mMHQDr`120cB7*56_t0LdN zlaT#!$RuHd@NLg3|6q$q|M`yf_2Q+lkWF7E7pwNl^ug-UCQJikow5!Dz z``5`8M?$I(B!=dcqOicePd98HwoZ6u=~P6!24%wvlN4y!?mBE=DpmB%>vuj5>GeXm!Z?UlmXd0E2WE2m_dntXxjG{r-~R&?cFDQGui4`xsA4W|7G-` zl(9ukS8xW57DWZZ1m=qpmov)(=?P39$$9mN{XAVlZ!qav8Y)-}-W?_@MvSNZIXvb} zq7{m#A&k~>U1@Ak%k!%I1ow&p9sf6+-lw0=_OiRAG=l3}iSXiWNO`poS`pM}t*5 zCY72jV3ZiDaA4fk=07b7FF-~I+RxO~A-xa3(w~8LGe0yT|EHnj4oiL~*_Hp_7I*>3 zgxnfW&UW{??Sc*uB3P|4E*3O+Ye8E~eUL%QW&fQCzLpkyTt7sAP=5`~XDH@3Nt*SJek zkqlq}6ZCS%rO#roVB{Q6fnj{*u1WYlNbGdj=JfT85A7-&TXbo@UwPej!6(9vvJ&te zvMyGC_=WVEVlH+pRAJ8?*ZYKL4%(lZ=up|T2X~A6%RSrg2NBMk=5V?2)3sawtW9^? zg5v%98jN$ki7wD}bS&PQG#cz_KRCQ-X90Lyg*6{)gG}ejGu!c}TZm5u&p}e!u{F_xlQy!_wiY zQX>m+Asr~VJ#Y>b_W&qzBd);z0%DZzSe?6KDoGpkEWyhzBR3r1i~%!ylRkRf#rmcC zIJ4KGhX-UwO=V;vDc2{bobK|O=di#9lWPWRhb!#uo{9?pv!*?KTzh)%NBZVjgTPZs zHS_7?QPJzNGXrLYJXa;I-?OrQWueP+?dfHcW$$GLW0oa&sZOES9DB+Hd!kVJL^w`5 zh4AhWk{#bTWF!hl!vt4koJurH_#2Kz0ynPagBUgtm;q8;fPKg32(E)hD`&uQ23)sF zVgSU9N5nK-2V*8n9d*nk5|V8idhRq_XB0ugjr(L&KIC&}!gahgnps8y4c8&T0#T!( z8BeU&(FaD3I&iqqR}KTNbN@SV-K9zi=yYZX!3azDR^A3gzcy?Y#&qu>Ty1X%K7T`i z?)>pUcb=RAWK677{|b|t;MBC5^Gk1mNfg-R-S%Rt4Uaa5{-&%I#s;))3~=3Hceub1 zL=;p*Q@>21cI0u1A)>lBM3tKT%H;&dnUAXpK)hzrCVBXUib)WC+8=HbY~;y9uI(yH4hl$wB#JpFo4GU}f8@Bn58QynmgveZ;(q2y)y z=A@1v)~-Bg-c-jd=M&#FOj8|R@lFr+!vBDHXHMwf7nF{$N%=eK9WbzR_m@-XxEVz$ zHRYhxJ22oN)H_=w*BBB*IC~9FZ(KzwKC3wDowG^mlR#wqJ3fH_^|I9vA{lfDz;>(i z_-LU?%!)1&338M*a%A@Psq4Md!L7^Lr5R?Y*$?yuDM*EUWR2B+xQqVM6bW52Ak86U zMf}nu<~_tbUC01Vi|TB%b#9Dy`--5?~ay=O7Ao(Lp;hgaS_cm#Rr6B9hm=7s@)x*4Mgl; zb0++pvB)dll`$>ArzaYnLF(ThIQ4Iz0NScLKPecH9|jo}sMEk?dzJFS(z*=wgag9) zb#?ajnde**Z_K)*39sRo#l1NS=2H@JNBSax*!kNUU7ughRY)K?CvfOT_R$AVue$?z z0d)%sb9Vzeh z7C3mm7F(iz+GA3J^vz9ZdO6d3-Z4qskIS}J?TUX5_lTu}|2p@c1Pdz`-K9JGp#S$g zq9nkDnN4350Cps*%iJEOPKEUbPV~oQM|!P;wk5n?*wDV&`-oR!!AWt8Sm7H8w=d?C zAn&*UP6HCGs9|spukY-)ow3OIU;@ftPc~yI~9g)$6XB$%% zC0@N%_VBIni*AKA9?pl_93(dRx}^_&Kc-|wJBB_Z1Cv7d{`hWZnLVxp#mk0M%TDYB zbL4Np+qgJesBd-7iI{t-Ze>cDtFrUl=6OHsH_K&Xnf9b`CAOcjziULho*U}>aU&1R z7$;1UPo-?+6{pWvxubg)DV;6W6E1`&T=@y|*kX z+E-2Hu+$VU_+VdG5i)U3n6CquuDlzb!vkh->yYKC%MOGW)bP9UjX03P7%%$!4$429 zTX^$Hs3^Rk*hkjy1S(Aq;2etU(xv&i*e@m`9x@%k+vhiD#mMnBJGJGV_J7^YVn$4W zQ@=@&iTZx?=8w+lA3lo+dJz!Zs(}eRkZk6%tStzZ6g1CvCCK0cxj@eBEtt_8cWwzX zU)OgM<)c#_T-)ni!Fj;2iHJRayHfHl3UZpaPznFbUiU;FClBa1{T?XcO9VVle^l** zF6m3(p&STvKoCKx1BN}*>5qYSn_@W|dQH;k&)I4kfGvPNw*I#FU3w})GWg9CNr=%3 zIc`Q11*Q}6ZyOrspBl=wLLscCwFiYN*(Kjhr&FFYJjH9%b?&k0#|FZZ*dw#T1d16> z(`_ApFNm-Cd9pnASsPwQr|TQ1EPRCgMqY*SV>q^)ZlRY>^7L2Tp6e>N68s%A$lJj~ z<(^cN*o6K8clp4pTP)!qEYSO$CMD;np)fBw=dBz`gawWRa|jFjjN+#!z-P%I5Qi^$ z&I_U?ppFvML8e`jJ9|So z3!yf*k|6ISl%hct2t7j?33&0PpVU70 zVFga=PktZ>UfVBJAjIgB{l-ls&jc4FI6nlPrRCxe zREy|e08e#3^QlrMK`6l_z?*%C4gHUamX4ubz_c|5x-S2UJwNOTsM-xDD%t%&rEM_@ zgL_X>LxKsBm(({*wS(9OXm6zQL=pa~6b3##DJKLMP;DBZTjO6Z#j_9+``%sDF zIK1mlC>QxJ_0tQtU!5w*Mp2w?`TyQNNb`a;OYHH+s}JPe40vjQy?{Q3d8pc9 zky5vHlI^N*_uXK@dSE-5w;ahU|QJuZK#8wl*KGX(EKRmS*5t`X5d+HKo z9R0>}dM?q3y|hE-Xw-S4*oYl~c5XU1+0zOc@T&)XA5>6$cW82_eniankfSG*AP5VL1m;im-FE{J$6!ORVn^CVqR)k3d60l%VH=q>5 z;Oi3_%0S9K^8+x#v!zlD1H@c;6hVDLG%uh&Srm=)|0?xKn6+6EQT=+Z{@UQ8YeiAw z*IWEjURHAC<*6&=9&Vp?CLf0pouGEgxyo69JTc=?jY>6wbrh~F$thbf?BwYmT@nO@ zEw^P3hIna0bti?tH9;zb*(*}Yj^kOeG|`4!#uR7ebe~Dxw2;ON5w`C{2-9X|I>T0H zI4Sdf0t4TPJDZ%hxUr4e*d}UPityx_riMStnj#yMDh=akJmMlbR(v>b{9H8m@8(x} zrxkO4BS{PE*Uh)2lbMY{WL|e<;+*57~Bghx>JsSGcQkXfT;=-R6FIRW-pBC4})UskMSA*;WDzZl8 z6y;HR4?NWk$zdU}7rP7snj3OeK!DxeYh|~-aen@@4w#Nh6b(&&?FH#Q)XyLgNTy02 z6rn=?6Z}hN?$ibhq*MDtDhgzFGmu^96y+tAOb>4Y5oXwX@xrfP&#c2Z%oLCL#apg+ zCGWca9Ay2%Kw>e^FM&^>JDb0)Rnj2LgmetZ(p)20%*+{RIe4S}(X)3}2`P_$Q?pPb zi0ZJ%8wBYcb#*{oVY3R14iEM$AF2&p-Vx)-M8VPgAMIs-1jlSHw^6VP9fwI%j?IfU*4< zF()Pq8_1Z=dQxok2%zYv=EHEt!gSC`6oZ7AT453V!QJD#L4^oj5K!DfbIE2PP<>6`%mM*4-x1|Xm4+(^&S3GyCpy23QmJ?ZBj z{Yd2tQNG(&DJH=9Y$1 zr+#|iS(Ow;-x?7!mzmrSi!56>w}y!fqBYN``_L1!vhhsxYy{`G*fc>mT2^DQ2ezD{ zgEz45!KB#)3dpEFO(1&2`wr`s|9hi+C*_LV&Fe5mOg87+iIJt*3 zoD|=`9*?@L7uP|Tbor1eg>DaNAhrGl06$jaF-%sv+~KqWr?GordH3m_t2- zSoP-fR*`?*({(b;4?*jaI^dW@V^<+uAbOjfX~)-Nk^GPnK_Z#B0s=Issz3mXd#uC# z1n^HLuGnsRtg*`e=BY(IBV7)t0Yx;UwBb2{miieqHf*buo0D2^NC z(=4LD7`>;{sF)sPphx22Gz0eQ?J=LAEwLUj!~EFR>Tj4I^{y3-?M&Qm4L zkDnh$4$?po%-jyJfCme@Qv`$gG0*}C^J6OsFrF>p$r3M=IaV_CGBFSD%JwQ5@8!khmLW}w) zByCa+pMV)kmSer_2K_sIFZK|L~l2sO8i zh`8z7`0E^RTZkrYcRX3?tRD)9)okd zxoqEmA+8Ellp0Y#ahFP5N+_PAN5CJ&HD(Yf;{Y1}Kh%ABTvTQI{wRvMk{KGN(WWM* zsD%=W=-X>nDws0ECZHmjEbfSafJtS!Q6ga~V!0qQz=#N_tiFmUD5y9hBH)I|AfVu| z!~E{&Ip@q-=FBiyeLmmcUvD4YnzKF6bKm!MU-xxk)%uk>BkeTY0eg+Aj5LfpLQwja zFG=OBHd6SwcDW(!MeLDT9kZKcUv{N@%sxNpoF5SQwYrloRfh;mpohO)tFCjjM8l?d z+z~r5P2DF}m>lthK%t7g%)JFA1mQF3hKR_2L;M(Vo7k8;tORg2@2>dq0do-^nggme zktx940+5GTdC!wQ!0co6mVLu|fWu*Ksz@(p$|NEDQw-=@WL*)%h?$%0?GZ2=j$aw< z?p*P3+w4#nA4ZlwJ_B#6^Pz4$YWr5P$$o=Ps6hrtM^pM!Zc0gh$zM*L22;TpO&Qgq z9eNBEhA_k_&<(HE2gQ=+-(_b@$#j;Vnh4l`000Q@_N4(JaTiC z>mh?0Uz-CRFI**$#E$+8YBse07JTp7M&rinIzPY5N~IS$Yk8q#b7suOkB6Dswzd15 zUF27M>y*`rOnb$-p#I;u&NZyc6%Qr|ML;p}i}eq2lj-M6pcv&2S3m*fr@zE3ILKnv z_War^zZ;Q_;^6%1v(xn^wpM&%Fn@%ELHdCJ|*Gd7w~800|ZQfSY=>A!)-*sbz!H|!~`}@z(5|8bEoy_EC@9|Vf^04mOI8J z-W?mZ)*F3GImK=C|87>xUw4mL?~DkIoFNIa{f|qXFBs*tw}s^At~hQ<8bl7?#jR_* z)*d4X>vMk-Pg~e>>zT>q4!0yAO;hrFgqYF_I9Jz8w(O8dqbDDRYvn_4*->a~BjQ|~@_PIMQq`Tw0wW3qJO=V; zz)UOJPzl7)m_!zpEPWknOwx@c< zZ;X*n&e;6yrGu|5dSrutrUu&P{sGux`&Lb?a`A@rGs8En^$ARTQ5_2mloWe|ug!qX zG@{4R;bHQR;GZ<`n)2JkgI}GUG9t?~Qg7dY#NrdaXa93wxvAgbL#B4=al^?>;lN>9 zF$m3ndlk@tdZ7Eb#b43%z9L={2y)`Vl-EEBI5{jsl{0c0aa#8kXCp?PI zi!GzF!@iIC6PZaw50)Sa*aK+-%~*#6GqEJ*Qz8-R4w-6$a2n!E9;-K%raArtj{~?IPv;H<(SMWiwREgfMubavze8e;89pwVG)VhXyyv z!As;6@_^y>xTP+`#4_*-36n$YWmT_093n7IlJm|sAYf2W$>G?~`IZf_LP*>7tVD+G zy5ta{FTuOeA&F5nQB;)_OqZZaN^M4rcJS5mbS&y85hHVcadhvw=KR-T{Y7%@H@$?` z?Bis$M2n3WEkF#ls@fOq+LVR(f<_X=ZlW71xJSpB{6K}()a-QmU{ACUL|IwY z$iJ?e>?RN#W4=~$hS>ZYm^PrXh?%s)rkUA)S*2_R8rY^ z5xX)PWv;ZU6K`t72uD=miX#eYLb6qzblD4UoY)-zZ9rII*kjEu9n-V+Kz7hFbICt6*L<&9?{7dIfGR402TY=h6-TRA1EUc0 zZ3!6O=&X1~-QprTi-x|Zk>Ik?7Cw#>gdtd!Xs(%8D+OnisKh(D+zieWE!Klw4>nTW zq@RRe*pH;Lmk?`UQIWVmPtSxt>bRK)-&C`mWq<5WP6>X0Kraq9i~ym47+?MZ>Jjib zlYpl@aV$Wq6;Mygla)Yg;L#v+V-+Qwm_fu_J~2L4cc1YLybnhG5mI*QesPT%FIxm3 z3GR?!CdL4YVb7M-jb`Ya4~!K|cmn!kYnhI77oZ7C)@ zHtS&35#Yc1d8tj*n%3gZ_F~zbL6y=5PzsbtBM6VBSeuag^7`1~s2#PNZbn@_UVOr? zqgB%Kq~?x8MBBWdievBH#^&q)xh)Q2b`DvkH|ro_OI70;sw<8@Cf|W(z^csHx*?*< zlttmw(hk!0O5sU0FMoR!+WzRX$Kcgy-(#dk5#|=591vQGUD37hHm6@Iy&-3V zZ!~oV@YeDSpa=Q7$2*2AR5YP*4MHu9LkE8hWFYhkgXp zvxIfysw-ykakdD^Q=JB<$_YsGdOpa4kzuiZfPSxV`jd+l@q0dgyYUOf!3jDUq2Dln z`^768p+mF;J0h>^sk>Dm9fP6Is0QAH0)+A#VJaHcdk9C)h!qMCPH&3x$(VL5SG?f& z;&n(#ZmyB|gNn1?cG{f(uK%A{;|-=Nk3zIy3w%Lzvzj0+O{?`so$*&^Gf{f1tX>;Q zpV2r}#rXUT8Vqx3alnUr2cP;LIyqVMsW!{!IvtA`_D-G*Qlv>NNzZs;Ytr ziR!^<5y5(dBzd~vXFmaMOzklTY>K!u()IgGJRGr3tRD#g z0D`9mX^NT5&q2IVjNZ<0OL8x;2dgkVS)j?K1+f>pVYq%N1kicEB9Hqpg|Pt5Z$#OJ z14Kb&gY3@IXxSv~Ob&X)^N^j7;mk0JfFA$=-8!CAA7y>xIzhB%G-Q2=0xKd;vyEnQ*_j0qS%l#}IkI?GV>#f0ok6WE8yc+ZoqhT% z%L9f3Ayn!=G)tH43Z0D%G3Uj-356;&YdBB*=v4?K^nPT_8iK~UPN^3{JV9gq2MwZ4 z&@p4~HljRZzz=L*5($bU_i$RY=@kHNnrBfX!)^0r;@vvsWJIvXTn!A0pFp5EAv%PC ztHGW}P(x^^@cu)&N?uTP4x)2>rntjl%ClYZXI*@5_4!w(4LS5Jl67=hi|2?2(h=cm z3hSx5PHHh6CYgAHSQi?7)ZIXjn;0Xe4?CcWC&bkKUphI+~fW?6Q)l-xc7!bZ* z5%EM0n$KUPyN;9;SsARk2XWvZqaE$a34C?sgc6g>B_^6xn}8jr$@~Lvx^4)q>rqe^ zY&sBH9|T>DR}oqdlM_} zqNCKKvs=a)V-N)R5X`BVMK&B_Kv(Gr+|<`f-DL9OwDi_px#xlw)^#`)C%~j3o_$G~ zsJO5>51GR@6vzXUA)mRJ0Bd4l&$dmelV%Zo)j^6$8U zg*y`D19wCFf-2D6g#*P8b3mLpC1TrO=k%-8h8}aDz6eb8pZ@W==$t;~9WVPvN7WQW zIR`#o(`iv>_c=N7sNDAUUghs|-dDNz9&u4rOP?G_aa-YB`w1kZ>zv>p9wvAYB7zXr z+c>KbmUBz8$&(T>>8%0zz3o5?A%nIG_=UBiD!O@joQ2`(`ZB%LK)?Q5GwVxQDrl!S zp-;p29?>jVut`NiA_U(nYWj- z@u$xY9U4};QrcR%dG6F9Sx+MhKM#EHMd_rVb15a0qz5j6Xv~YcaR+m=7aGj2tXg|x z+4OG<~ zS}_?_k^`fESrwluZBnkZ=Dd-m*8GZlCm}^mS@gv^!%(5q##j&mp|fz#E``rDUGF}> zSbUD=2cASq05tjzFs4cj>M>Rs8_i_3xEP-W z-z^^0qoF^>-I6t5G`HrXP*J;{`x;fBOTDIqXv_lz($@^+dqXsm%z^@`OFHztto@3_ zZLpv~`ic;{xpPC$P1xxrn^Cd@uve$X zK9z6UXXw=WDevU8en14M^FU{7c6soXrt+-J%4?_g&YEu17Vptu)qa8CZ7-$ z-0|_2{Wb0F@TqmpO3RP#q)HCfo>VGRquZ>KlRcOg0`zg+1?0in+4OO}Q{!>X+Nz9- zjXuaAr_|*jqp~B?qI;q))FAR8Q<3?}gA9^Nbv%&wwCQU*CLR2e@HNG~v^uh|qZEE@ zh!{XzBQL7ZyQ5`8UNLzT;&?zV2tbw74xN}lTF`|O3L^;85)x#%itgfZ$!0H0LV}9U zf3Ru@);7ei2DJvc5)#B0WbpwQJs5m6Qy-E?LV~<$ZobaUBYE19j8&sA<6ThHCDq%J z^fIH`-;8fUKP6u~l05Fvc6LY~)USR?IU9y~T}0~DH9cl3a!RKe zZ>UHuG!F9FC;X57w;`P`|M%DEHH~XKe~3Em1?{>S9;sl7J`{H3BJOf$Ed&_iBWXVh zm&+U58a_LZ^S-u~=M}Xp6RkQueHIIUiESM?on_>%EI6M3@-f067F zm6`u;Ttn$8t1}0~#a4?~?c8|EgGnw1V4=dK;>E0s+U*Re_B$Y2(0(tH{Po66J=-xP zn%w(PtOvt0oYezRryNrr2PCY84TO-4$kiC&h-s{&c{Uq_EYQ@8k8`{h6}9`oUx@+! zE*qlLS2Wp;Tn=AcN6``TOZ}^ad_r^tQXX~dTe91{ z8(>I=ow{>ns=Vb7Ff|=@dUmH9wj;baOOena0Pjo)Q!Z{oneb)nG&GFWm9L7HEm00bpr7Zc@06B84;a>n`Os zEzVSA^m}D5Q@=s?Bl3FyEf8cz7QgpAczW*z1rgP%VPDn=59mY};r{OjcCws$AKWn^ zeNA^l*4XR*p76ZBF%7a06xm~ycdm%pq?_>7lC2qBA9DtM6Cl@tv3dug+0~^qF;C-5 zMV2NSIo)8_TO#fg6capGsigdU_aW{w?rwYXG#etQeH ziy1NU;O@6;%W_vg-d8lIp9X)Y$wE@txqzzjow4Fb*N%P!`3z=5J0gI>JzJ22t(xehrMLBAwEtwFE& zx_g=VzJxgOmG5YAVpNjD4?}eDN(a?;c z;rL3t;}kp3`bG~lMc3%T#dBx*faruy(hRT#X?+TcFz^mV7|=gK#xY)b;-bY;3%TCk z(q#im_4Lh5u}ul24{ABjFCaroeHYM4_gqVHC>zAESe3uODHNL_)c*e z5sVy>PFNU!)R%!I8DY%+%t)fSKtsf_v9-cbd!U7er}Wf!ks_^ISpHWyQvqRe7|Bta zAK(cGA3;jHG<>iq2Wq@4CZ=(#z?z*jCZtD=L*y4VfGKp(6bPQsGhGtrfj8!+^V|8@ zNxVc(CP|6pFQ9&_sr_1tK*+!mS(603tU?H|NkS0mzEUEQK^|!+QQr$)u?L9#gu@a1 ztK4uj0nBK^e<72Yxt8fLhkQ08c6R{7JAs%hy+_WKTBD?)O_t!_(IChP{3k_QeUaNv+IfpLhEQCA zI3UsrXY)zf6fuHkM284!TavS!48&Jc-$%Vz2W2EyM#YB4FvHDLu@|bG5o@jr1qf78 z=r2lgao-@TksW8i3tdDB7)`A|B%I{QI&I<7vlm3Zg$Jm*;9d!DkRhycfM9@8Q|Mjpuk>d`&=RN3Yf z*V|2fB@HDpxg%Zj*RF0lU2LpOvWU;UyRr51i#eTZ6H5Z`NHZ(lUrK^(g74lco<3uw z)!y@_<*UUbQx&QX4$-8aRNj$LIw1gb%?qrJ$M%1S2oj1p;;8i1U}&}X02)^^ZLf~7 zcoHE!)IO?uO|vAkR*_;i?vrnMJTiZidvvyMxc6pcX<@@((`tlD+XOpt^ra3P5Eu0m ztTDP@a|jsNfaPexnlRKhUF!dtuYXlf;gsf_H+To|v_ek^1?>%IzeC(`grIYo=6}zu zToy7n-S9c|WZaL`2i=ggU~ARLcb?1Rw%DYMS1L2 z**NIzM*}$SeRUh=W`b=r7`&hFHL%!%x9EsUw=Q&X>VOYHZ&KoJv7nYNgR1YJunxeR zokW9cz7`bfVnaZjHz9;^C4EgXVwx~^7UKaq97%Av!T2f$p#RX`h2#Fp0C5QZCip3l zCb~{n#Eu;k>@og40QHeB*}^;l6Driuo1xziW=5c744ON0s56p#^fK?3YL_JUBBk5! zKrHC4gz^02pyTr|N*L2++4=4Gl_FRXSeZnM2baFEElIpRtgk3s2gS(3 zLQMo>QVc0}NifW@j;tJ7d>Bmnu!tHb3)?@3D^&SX5*~+L)Pn8lfZ@t;nng=NgcVAUMXa5I~{ZEix+~ zRFO|f7?TFeT&fytr?A6oPuWT-7(#(Up!JrB)DE*X*v>3rS<+EFMR;6$;?8)w5Dyr6 zTTIxQ$x)@sv@;7Wu=hM1+sIITa!wq+_L}^3Q3|Q_^Lc3e$7o*1z(LPiCW$)bh+$)m z_GIQ(e(5uIfJ6M;6a&iNEW2f0Ee%hD(!)Q--j?kN-$~%d+9iJ8oeN9aRsSi6VG2ix z%5WDBM;?DF0wP5I&sua8sH%kIG_&a1%pm~Mr5p{sAQdR4jsgqe_)T+<6tD-v9sXB2 zc8B->OHR1MBOL`M=Y|TxkOQf?-w-+qmtdijItoBQAl%;}Ez=H#P>gLJP{$gEoqFBh z8a{eh>@9kdf`7#`cy-7i-Pi69sPRBJTz!s$nmXjK1OdVX%NrGhNjBWDZa+Oop(P1= zP26#a^RnSxz@DQtev0n7#DT1W)~21hGA;fMEMu%t@p51#NrNvsX2Kln3^&6wXGpR5 zag6CVSSt(}<7>Em_Ud+^lWB#YQd^C{Dw?=^cZGm&o(RYo5c#mekG{sT0DV5_xoHoP z@R>jzQ}vlxi-!l(;+rReb*yQ)m34^Xbb}mo~JqT^7G3?I)O%A?!B3}7&mBt%O#Q2>4l4TkbafV|7!YgIXFz9-m*p|8sx-ubj z7`+3aQ-vgwgRYw8ytyg;Ru47$DH|T#Zz$=C?V(QdL}`9-Hi!If&U zXx%lB+hizWf`j1s!7uK!>nr4e8q+fd8E^Z}Si9iR$L5jdXC(O}Ml`hAp69o7-T$r8 zt1A|I8$R+DUaF=Nnh9f^gFVH>fNKTZ2?U4BLWN)DIfhRm!-LmUZv%zh!tggvt6{HV z58eS9yZT)W6z#L!#@tov@EHzNRKCJHP^2r-PQ{x{hN)xC14UiQfzaT17XwB6Y{%&G zXuJbOz@}jE%BTRTtx82X7FQ901PGC$83qUuW=;cyeCQELw0U~Y4Js8>u7d9vu&PUj z79i8HW9B2QR@YZrE0*0DKc(6&t z$86vaY;poy)6rXg1s!8>gu^!QZ|@TmYH=}B)|>($quySjp9A{g6p`?hSYPHd)vr`Opb+Z~V^eXX-uDqAZo-F*0NRr3eRGsQJCo)wihOm6M4I$&`iC;HL0$;}mQ z^OM~C+O`7gXz29t{?Wg8%<9M%7y0}*)^5>kN2hQ)A6Bhz70CICh}# zl9zc^e`c&XQu~%wX-Un#qWO=YYHMyXw60hdLs7B{&v!wG#Aq9Ya2m-W>5!TSid4A@ zE26T?5`CH6;q^9I!?!m&e1pt4&Un)1_FJ9B$O4JKi(*~v%jf`u4!24np&=BLybCs> zp5QV}>@z3fc()vts6q-lKyq9ByNt#4pr3-T?g^1Yjkx&aG9*95Ec^KWUCwub%hKrQ zagAvX;~SDcK=V>b7PS_pF6XQvKLlt2nLR@b=I0m-_+K3WH}aY#Zy*H(paQ^LkQOQc zqo#O`gG5psiLPD{O@*bANCF#S{y4XPq3X1guo;a+4(O5&fj`DRf#dIjpEw_bH8##( zlw_wEZz#NUeq-aN)Y{^q*lAtr|3ZI>_j(YSbP}Lq?}FFFN4Uj{4)G0oIzy8FRkrFk z(pDB(6^p|GSyewev^?%fooh8WILci>p3xpS2hO zr_-HZB2pfV>aJ_38e*-i3GP^!(_SwN%UnKkP_UvXZpfpG%qppCdq>1(<-qoUvXAFh zeSX8wfANMsN2)$THKnQ2E-kgCytA&k5{W|b9*e9$qWvGv@!9-re6GW_`GO;^)&>JV z+_LVsg)7v&Io-gc;MkYWZ-@;4=uGG}@gy|7vdjf}AlX>K-gy|qfP3StTFq<3n z91(1|W!;+v8G`uClZ9~Z0NJUFk3}^%U?7si_hqRG^KMpp7KA%T)JwLufbN8G4nV3G z=iGM*=3#J^p4}HP6c@RtK7CCEUkX5p9BR0vdtc2AJ9y8$Ryp()=_zLJ$;irGsKp4% zgm~hm3)T?7=m9BBr)8EI1qglSvZ4c^n`!}Q4t?xpg*O3Su6$F<>W@n-EBtD@m{R86 z0ky2~-F7jh%w5#d-#^-&-Yp;LreY)2NAvdoUTTK~#^<|rbbV~ML z8Hd`2@3NJfR~-$!=KLscbqRewc&a{&j#not`T3e!`uy^2%-5WB9P1UJX{+u`z}-dz zvN+-6&Awj~hiOT2%m_6`XfA%mH;Dv8xonw5=KX41Z2B?=H~Ssd%l@G zzaUD8oIs*Y*IpHO3~H0-l;)*$eD0F&5*X-rd74dV!>VBOKU78_odt%aEY`-f#C4eR1jyiT#cXf-g?P|MrjF={4$h;kPZZlqK`bVR(aMI;zWv<0>n*$W_AKWhg!pF8S?q+>tW7WlrMGY%|sCaf#xhJkO z@aeNtq2&>&!EsiPvnRDSDe7M=NVBv`|3nE%*_ctCL2o=w@sJ8 zgo6!$Y~J_F41qIIf7@{Od*yECykQ3J>g_H%jd2n z28}r7ABx&tot7Brf5>-CdVN$w;;FPD_uHcM?MGdbm;G#I`CD^v(D3`%w?s=rhkGE0 zcr09mo1d)(2Jgncb9ECKEFGAyI2`xatnoL4CZByXChy6*2z?JB4bo3NyuWeJO6BH9 z4_(vr-+dqx%Ts5#TGXGr5;d$TuXu*l2rFq~rFF})vTH>Ww->!GS9rD5SFHIs>b;ht z2^CMA8>?2Pj!%vV{qtG-KHumI8#cB6kQsO}PiSp3Vf>*3e*Sx(w0u#VxlsT@e(1eJ z|EFJ?!OS7xsY)rBe{UPM(&Fhr(-nQJD+h}E1gwxf$X@E&aVDT8IoRClL4ZP0@m}3@ z%ly=i2g~;h5Qn_cKB@iDrRhtL{h}uzyFSDZPKtqc0wP(`zaFwM37mZ2T51*-BOIS` zipvLu-VDboiF>jkNu`s^kRB^xT-jG_hJAXwGUWh21n3f}IuvY62WkObkI~%S4gsz> z)3cIHC{Wx<&Rr4fa_Gq2tPgIBFK&_z5plr-IxxeuCZOzr!(^WtS+^c(c(kykI{liyC$_B@#cZNIbKuN^jiXZxU&54suhaLwCZeG)((l}z%JJj%3Qtg=fL31 z_}d{1jFFR#YbrGU{Un z2OYXf-}`Jqj)z9?PK=#03*Hs>qvo+Rq}l;=!ep;PkxvY$Og(didKC^fKXamRcchw&$%HB%6;PjDF)pwE{vV1bxm za=R^@@0X5L9j|;k@@4**LG{masxF={^?b2wM56q?+HHY~N3|6to$py$-RY>#`@GE0 z|DbQ%g_Wkg$&sgf<>OaK548KO%{*AsaN$LRML_Ld(+Ynj}jMm%cVSc1wxtrB6RZ#-k$V5hUk17@NP3NThJclPzW{HUlkfAqNS#NX zJXs>C%;v`|GmbDEHw6CR0ZF}gI5G1iT$c8v(Sw^TyDymE1)-1lOsJ6?uA)`pmekKl zAHstYrbPnTX*gfh%>eh$E1b1@lT0BVOVGwjA9k+#ETHsp!H%{HuPEc)QANe;qc=~g zdr~b+a9ZV>u^E(woXa!fwhN5h(*EQ6@h<>26;`&)yoyW z{ATy?MP^TIyXyt$eZLd6yz0+~gGJ=P1tV|4YLaTW9CJUg`l`hJkpoZY`ytK`OkZ`O ztiw3SanKqdKC&N?exefYo>~zLu}edJ4y#U1P#R!XpQ1FN%OZ_b=2XQ#+Z^_mXa1ku zOuD;cRp1fg zVdfarT1G+SlBXW`m|SJkTJ`*4bLh2i*D4)j=Uq)S-f=o=-UP+VQ)llT`~KAaiKKLQ z$7gk5%nZ`qpC$miuH4KnCuD=gvvl8B7v=P?YMcU!-U54 zwh@b*XG)X>sk0*_*<*stoTS-3EC-rhadO&^N~z_*lV9)DM6=`mCeWgM82Z34g}X&g z*y6zwWX#}FQV|*{QAEu}igxRSS+l|E0bN*3;$Y=y38$EGpAqW~vu;5~m44nfPGscl z6Oa@`0qpOeXe7oV*uTz1xJ$(uN5l)g;UOeDp~f@A7#y3@VP-yI%TBP=50 zjBEa&Hq&Bx`L_HCZOwsa+lpF0KeWOsLmCmf&9CWY^Zit0-IG|_l9(4dBHy*rC(J6s z)wIORLfWwEo2b_8%xvW+!TG62)=oZTeRHX_T@jH;6!=C4H&-UaC7NtZK)y;GHZY`` znjeqC$LK1)_V>h^Ro|43iOpRdZQ^?;>QPza%JgZSZhni05?)2m9{HzsoOB8-*#6Y6 z6MGc}A+MsXuE|aj(>6*1rwp@_c%^>XDjPP=)o$=44B7ZcT&qCiPW>LfUo$35{y{}S z*%W2XknPu^ZOl7{bt>kLOw6;Bc8rp&X)beZYAul{79j#keemqm7}d>_<0rge6~tLu|OrU?`T zG}+ayktY0*c-RMhNM>e7n=&zAOO~?={+3|X1ct7MIiq{rGy?C`$tOnR^Nz+`-_Yfn z_(n)nl)7Y|hfs5+PA?p?gu5$6YXo;SUh=h=7!SyKYCz0yA%qxDr(wXKG2+a*4&&3l z4xj`W^{Au_yC=kewg~Njr7IVXSO7i0bLxqlx}Z(K&;?_M8MXVS*UoUX{eUi~18%)~ zrkT;G!VUJ3G1n4}gT1EgkdMjnTB~f`SD*pZ9SKIN;@0?7-|VJy2h&&8S7vvtOD-_T zDX4ySc2UMY-v)*J&iE8l*NhRnW$~+1_a5*qj*hNLzLRm#`&hp}sY)vQbw~G-b(0kn zW>X z3e2~`HnoLUUo)z(Gx*%uYUSo4`BHdJnQx7=4l!_%QKG?sDT|rN zbeJ+>CCU+YUBFKL)yf)5hMuHWULZhY3V@(8Jx%Qr*v52fPGsSPE)q-&YD0fOK19}W zK(fA{U*nO@Prp@!xh0soEMq>@p4SZhD~eRbG}W4&m$WBq&O5G3jY4Zi)(MrbeK;K7(q7)28`BU z^YDnUsXw^%!vlyIiGFZU^ct_C7Qa}a<9!><( z$@$m;A>^c&ICb1=l$WD6q}s7TtQ0V8C5kAOxfnNa4$vkg1ZjzqW_}JNQ`+Re!g&I6Z3{p zMK*Y;&pl{fjdwZukTY1u19kHBqVYQhzm~8RJINc5%u?*$9;5v<SUav8cYQG-!ldQ3U9mkq z*jarNDm!fuHEXz$2umNzknITF?*qWaaIk1hI*PYCxrwWTYy`esA~Ev|NFu`0o-V>t zhzB>~{wrb0Z%Y^oOYcrp4@zsL??@YBa831aymR&r>bi%aS6A z)YQNaj6lk245Gtk{EfH-Ah;N=iD#!fucJ|;mE2Jyp13qKUw{y7#{4TNJm97pj!PG( zBQB_hmSPuiN!RVh%wxH6$xVzpvWzT+SNMzkW0!FWDm`vh&pwS2P|l4@L=1)6R`xK7 zhBZldBAx)tZl`0AoQ=&vdq`6%tmQ$03_%N)AoK>ENT+-@qlp}I3FEvAD$c(n~{M4?+UXow{=8# zDe6975fRv)aj(O(<2}>Aau5S(V%?#4j5jwGjyV{VJS})*%WoH2s?(eYhI>zmEb>cf zHjZ~~cRF~#V}04kU12Xa>=_hLA;d{qH6MPCB#2a_q~f|97)Uw){>9d#wvS^r!3~MVbeQzYPUPR-X30_Z(6W+b=&E( zk;;VW6Y>ri?433;c)4*=NzJxWd4TA@naaeNLY1q4~dH{>@~`ISY!%ni;@+3-n^0p*eJi2F|! z?|xC3Ub@>s_9?;+GNo%whR(Ho92uSCmtu9$x{vm>gv|du{Cp!z>-{Y2IzO27;_>$lVd502hUo>ow=nu&VlmdWW~7cckw~Jf^HzYc%kn9gHWTg9nn`gJNr0-sAR_ zyROz9=zY4jW$@<3vN^RUNVYJEpG^{(s?-9ex9OzIJubd|( zP=gMkB;eYfaK0B~NpX1QU8jbOCB>0r(Bvr2xi}lNXEVw*?R9Ro-c{3w`BhZco4sJZ zzpfXcmnjcDM~5E?@qitF6GbM)q^LOJI0rI-I-}FC@ll(9%cgz4Ve6DydOmmOqMi>Z z=2w>9FgLOpQ+3iVD80g~!~a?A_P|Ra8yvl=W4AkR?}+Xw%&Gf5F-4lhg*`K~>MQad z*mp*cU!g)i8(+@#0^pOosMrk%`c+WJ;BSEzsTB?WWgROv!hqzrscwh7r$v%;r)B+$ zH~J1*FASO{JbR&YL{qX2Od}cRJ*tlbiz8+nsK*vZibsVnJ|EnEs`T8wgrB`CW*pcN zB}{hyuw#9{k6m=?7^NuL9ix=5cSb0WX9m4UajmbJ`n=9B@uOp8Y8txz&`MA$aOsq8 zTHk<%k^%v7>N+jMn}yp?LPJUU^8^=sqqph5flE37(Z8pfiQMJNeTA5@0_U>))JGMk zwjW!(qP|4bV{b~)dT&|Uw2{Xz6vpW(H-^rN%odVK5))mSA9`BGV{gg9-d!WH+ zh2?EWFAc`0q$g9kYfznRO2;8Q3U^s!kcBgwJ0L=T$}jjHlD;^6Us|q*e#oruxXIx2 zit&)T;MG*ULOyP)(#a?|3ia%gSuVbBPezd(IS z7<&X|3{~-^%4xI`8|jk=5xLYX_y&ko>=))GwE%(;GP+jGWrGno6Vo-DrH?Rl6J5{J z^Hc#^6WD(vCkwtD)lmE0!JW}zr_W4DX!g%5ZdKfIFl^h|r|NW?%Ua>Hh0mmIORXd zrI8mFhnHImYfoC`q}LSs`?lxQpZR!*L(AKn=+PU8!5y98Hq?sThF%LQUgcbC|KH?w zQP;8yOiCu~>HMtsP^skSecsADUPIIKp46|14t=xtT6)$B0Fdk_06=v1SGFG8U0fk4 z>f9qV-&`kkf@XAZp=)MyiD^sY+s#dB4tsBsw7og$=g~o*-tPM1$&<{E@)vEKxp3Z1 z2#t;TUjSp>#Rn^iLL+)>cxL1c)BKP_*5Zho!;yWV4NX!$9k)z>bn%v$a_d&>J8F@g zC-tqmXezxXzMy?xFG-kJ+)%hS(l^O@w3!$B|PTVuvV+b+^=WpN={V7!2u$aey z5TzhX32mKv95OVI*6=zMX}S&KQMlxMn9V{ic)&~fPUCsXJ={<}=v48E$fJOl=?o?BvzHqrt$hNi=9io+ASoSW^NFzpV^&N^^Au@!@>^J9ANZj zftZ-NsTWOjCyj=rJvS8z1+rUbVh1-HoAx~MBu|Lx&hrEl9L}zp?rOQv`CvWTgt~Kb zv<=*JP4{PhQvQLPi?$=Xp}tGB7>6tg^X&;E6=qZ8M!uXcOb=1AE`{}{1Z@_X!2WMM?y$D|lgK^0rnEtb&+A+lGZHHXk5PiX#XlmuFq z>#|Lr4}d8@z7`*|&CDFk;;1Hen|Q+`f`BJM40>fu|5DMO7UtzNU~mVMohTzTdMGJYUoA|YVgMr44Wpzuo)I>u1TSlw?9R)oKfC=*JQQy_Tw5Ej3QpE zkzL}jjMa++RjxwzG*MOyR(xXjBomc>2n6}`&cU9K(34&=!S;J-ElFe9Hax`W+D~@Q z()~S2ccEGUyo%;`rU9qAvE@OtU!d$CK}%RN`0EZv7m!Ig{t zXw2<0@M|*SEhQNCY=!}=#MZ1NO7x*u#3pMp7b22OvcErFOdiJTZ)CqK`^g|`O^Ua8P1Btb0KHSjTv3j0D;;b1K3$|YxN2S!# zKUIIfz|q})_7AeJq-bFD{C2K?jn+z#D!QP)QYqb8@TQW|Ai1ZxN_`}%an-JPZx+5F;a)3*h`BO_umD-ySn|7N3$$OHkM5jNrT_H z|KUG4YcnVPtA5Xf(RJruMI#|2j$wI64%_?zvu8M6A%YWsRJv@m1$C?Q1d$vYG+@8b zlD+)mDBXxkT6P;js_8N+X{|U_P?dK$ib^l)a8xS$pHgE~;)gK!q7t#VQ7)dA%w|3j zloklD;JcvdSi4~IL9Df=9I0ywC~hK+9(1c5)C=~Ysmb6X`AX!YI%3UbAz>@x9}?pj zH~AdQW)^BGpD0Y4YP!Jr3L`h)#(mAfTX+K${-cpC(XWHp@lQ|O#QeSz|()BSxEW_ALDhIgh$g{m>X8i6xnl`8~Y=qk#F3QL6fs%9lLHy2c| zlDu!?KUK}yz^nuh&c(b%;=VCb%$c(p1uahky4KvEV4=QZN8v#`RZa#{VO>wQ!MDd( z4IauH*i8Oa7QO@ z6#GDZr$y=c5v}2SJZ?T>)wS+%|M_ssQ9B$Q zRl_!1Gcv|Oq2B$2PoRC)W`7si9?uS7XL}TxnKf$jVFeQ8X^fYhaOyD?S9?frpl6-l zb%qZR(8nIOn1mn~@~>L69DQ2jEk(OF#$uip=m$&zN*PeL&~$-%0zga;x1ld!2XGmO z7!3S;I=kW$>hZEuH$>p80JMvPF?Ha;zNzd!i^;311=#kDza6oIgQFZ zYZ3kH3ai|0t3+0xeY>Nr=wZ)${4m|9D=^WV=4tl)rkohqj!Ek_8B9NA{{u5TRK`VFrkTBVt7_6HG8evmi^ZpozG} z3H_$)T^Gnm(18C;&?Gg&TDvC*Z6$m!^f&--3di{)1gUsjD}SFAF{U#z%6E@Q~( zZlOQ|VpfTQE@B+s6A+<9DZ?{smm8{y-~j3jj71P_>M~5Q5i%N(V2j|y5RCw$kkFJk zVO@dv$?%4FMR4AWX#`TU&NoDC#Wv1_0VJDU>ntw9I02ZO#R29(L6@87(o3I9IZy-UM&eY>O$^)%wKq!V(hPVGkJl#= z`UGfdA^V#|+>kG1$U?;l5A|4b zu*X}RVH=VurlI>w>^8jgQ8UB-6xwp6*__Tx6dk4eZ09gfRI+<0#wR~_W}LespvdK~ zvWi5s>vwVmxPI5H+yWY6at8qn*>q7n0Vf^KMwSHB;@+w>oh)&fXQZ}sgcWMF?>I)R zpXGChJy65=|2RSuaNbqdIa)r0iIh;iL1+6df&cO|;p&M(iSP?>f%67m5#}rmmFwd} z-3L(ugn>n+soh^_;i&2V0!*@)Y*M(H(Yu8ZCpP?0o8ZynRpz4j!d++?)6|*t)Sg7V zE5^@LOe|m4P(I^9d!k3wHTapevG_l}XuNEuc>X--3qa0= zTz#O=w4B* zF=)RX8};Mlpf^vAdy-eYR5{A2qwRXJyK$zeuhKF2@(!h%d{3s*W}SIQU44;kLGibR zev!UAGT%l#?%!0Lp$(hEunqL)K`^cPj*~5J(eHIrys}cm03WDcgltqNDOH zlb$ROUuyOd;9RnYDKuORphvx633sAqbwzUO!=b$@&VSRzq|e4xC05?@SmUVO#@p{l z)ZDJvon6yE*QO07eb&0rlRjBtLa_Pq6PEeO^vgs8A%y5{+1E!90!_vq@Dh|Q`;MGj z_Y}rzp4BQ(o=E)# zg6~%d_G5Mpf9VClJ4n>=1MkEMMs$Qn%CHC+x2cHIHSUltH*ZM}MI zY&;N6{UGHIcDhT-{7TQc`1FI3I_>?V>6Y8p(M-6G)uGY%up}ZeEqC8GuJd~Q0gXry z77cwkAnODIe6S|sW6UB^NeOC*O>}kzXNXI1us0@0xe_u8lsYPz`#tMx< z5Lev{PjKQ+1%aJK5yGEZcFHzdy7}B<4Bl}OM))F%6@KJTuO;A#t{ zC|eHpI1wWpEr^I+Z2e`V^qrUq)-B#+BtIc!0vd)mZ-m3OT$H_;N0f_7D{->Y#~hNC zh#ox)1fQz3g@KF(F_fe8%sP1_#Lwq1F=(8d&`^oM^WA$rY18wa0j9#_pI zi%8;A3J{;*Gt5{%&|HXmx;M^Ooq153)cgeqHXdE0VP$>VmFQ#p%^rfkF*?qcG-*Qm zCP#RLM@r3vxt)SLA$zk;0T@Cm*XO>7?R-Hw`pN=)@Rxf*4A}@DM zU}(4#;Y>u8kCKZ}`vb5n3haANh^HmCNE8=i5#%BJTwE=T#+ZMq?~bJpQSC1NCRL5cr-A{=9>eqa$R6v2?1 zBu!{7ZX{C94^_c>l4fSgk%Ds9Aj>@QSnV(Y(Ja8a{`>;%>PFR!_l`?{+|(h1>P=2i zHL`^QvZv00YObOocP>dMs@%=bTn<70^$U7pOX;L$>SowQ@L{`2LNel zl{^=Fs`&t_gQq~}qIV`zKVAZ0FqwfanXLki={?9?HY|D+Xd|;SP^7qKYQL6p=;dwr z&`A=cr3^fh$UrG|AK^IB7>!2^>n9k+E&d7Ij|H$*C!wv#$tA7cHHEqa)_&>W)~g3pcH6&?{7n6 zz=JYo8gXe9FGJknwONzwdZ3|LQqDvO@>iO@v52CNvAclg7=R>vUnRhp)WBkO&HK1s zfy^9Sp);?hBT|rPTwauyb0ICjfAjNFo2WId#kK9l6>|nvN*e%2%#%hCQX(g8keN_y zv1-U^)0azMRGY4-E^=ETeD(=!y881!N|p`t6kc^S(*^VHYg_2Tu=(@!kj2dCcrywL z#H|}s4to3Ukk44EHa&jogm-l4h%V;GooW)#HaobN%)Tkjux~lH{paFFATr!Y^_md8 zvGvPuULS_$G>pdvHzv2Nj#}U~Bk+G!na`!J@_o)3{xzl!KVE3+JZD$#5@(K8?7+M7 z^a1T3pQSeY@rnYQ9G|k{8I}d9VSmjWHt^i^xYa#BDjL-B6QMt$g?vDt_>)O!3-dqh zB@<@L(R}#h`jVlsM|C+}$<(O>a1g>sP|Nf%O$1@o8u~IYyPz~fxl%|$1K$5ytLLE?1bpzb*Jx=Ap416%yWm-o+86+tz zo~*(`fFc#6d2WloBjWvFQWttZ#A4X$akC5bmSCR^nVI^=O!!x6C<|^^U1N-kE70$i z9uy<_1zLK7G~4N2zWuD#Xp??Qd3RK{Aq^l&WHc=csw?0l`Css`t}G6ug{tKSXFBf!rr+s62BHHoM*MtfoXMld zXO*$1YQ_qG|MAr2-?2x6`-$y)EBCiVZM~rnfIQGskgYsa1ndcVC;%p##FwVk`pdxN zMOdD+La=}dGG>pBX{Z`|^@`@fMxtFgS~f{NhbGZRlOT8!fzNH~=SPxBEKLo>EV(-zA4}XnVvq-fF>CxUd0@pZn26*N zWL2>$npS7X&xfPbDqfZag$Xe?>LOIt74UL(DIzL3#8}5OKs{%^7)` z{Ac)=y?S>srZy>NxAw%C2_q!oW(3~W^Hc$ig&6S0FCr!O?der-jhc-f*-%zd#5D?Z zpc7~64#{VX>L$xk!17b z;p$?LP*MV*);*2lV;%4OV}KrL6yLP1P~g0t7tz~?jBPL_WRI4?5siv>Pz(@&UL*7m zy9em;&@4yGz@Y48?rRdr#E|47yK>Upq@|(*-mh9KCvZ7ur31Xb$>C<$_4stA58_%L z6u@}|Kd*gqi=sL*_XA1Tv|S{D5n}t5>&|}-dlC-sojOct;Nqy(8D7=i zFk{{V^Poh|fyDgQ6I;OPbe&=*UlwsvHhRo2bBP1%n^G5Voft37S55WD;vLPNB2paa z`NRK`oGI_?5Po#vOqmr)2KoOTNbhoq34NrN+S1khuCL6Plpt!}7X+q}jTswUAOXGW zdIC1{0fe2YI77y|5HzHTyJX!R_+<@Rk|(L|TZDnokz5^Oix5itfZl1yY9PDvS#(eG zPQsM?APC%hK$=TZ4>1<_5979JaT{D05*XdlITTwD1Yy&-c!JQ2WCZxRTR6kQP#8%Y zndXqK2Ih4ce`v~`icZ2v@DP}H=^(0Skd*@u;g|_Dj0N2 zp*ZyBQiD4ndhv>K;Jy8vvUvoG!C7+?4ExWDnY>QO@($aJ)0mx~2);tcE$wJY8A?FX z%eD?v8yg@DEn&+MR9;D2TOL&_J>|KQ zXfugd^cbKq48WKqmC~S$45+;F<+5J^T|aNJ#!zJstaFQrNw6T#kq`Jv4pml0MON;l z4Ruqj86)bCh*`9zNDehsi~0S162WLVV&nsldnDyP6_-fn^NdgaQ{u!2HUSTpsR{*W z7zndKkg)hqlYP?WDXXRaM^1?k-3m}TZippQz51cY{r9a-0C;Onr$bV~6QJ9fiy{%; zKp#C++7FB=#H|>;W#2Hs%ad|bMS3w)CJEu6V)`Aud+~~iXLycys=3H}E0KSiC7F!( zTwr7+a&<+lf%@S`FLcgLZf*KAF>gkYYi(yz=dZ(VkXn{Dp#~Xk;7)E;5^0s%e)&PW zPg(p=xl<10SEo6(8x)y#jvusNdC+&xqvg{hk6v(TVd06(oB&vSnBZ|)Zwq$+m^}}< zfQ-VS2N)hX66o;1<}X0lRM`@-OR)ZuTM%W-MZKxA7Md=cac(%&|4psp>vzT9kW_0t z<%ih$`tLq5>Y`>`I`ha65J%s7omG)^t6C(=C2sGS^aJgF(a7~EuXk`P>-+rWYYBO~ z`a)SD4j3}DV4@RDXe|sp+Fo4s`;XZ>)K9Pn6^8zkU zvk7fj6})%1K8nlygWAkYic!X5v;j?f3Vn_~{KLV0`EVuVSG2efIzVjJoCCkw_h4t< zGr9ke9MI83L7FD&eOp}U8<=smg}+<+aAieaF&dW!?JH;F{$^ER=+)>P)#Q6(^kfIN%%!UL}a@rL(sYLrNFgId7lIL@n%B z%eYuG;N(e3GMjWLN*JyRJQ)|{1{yLhoaMAm5U-qk@a3G!oMS_6lG@!89qvWgoT1D^ z4Hl+*>8O`#!FB};mIJebP9?`CkFvL zmCH$D>x5{;x==!($_t1L7CG1H=66molvr&#YDRK&T`#1u^N!ObU8+(e+ii4GiPH&p z1dIny^FnM345sHLSA={Mq$1d(0)w!FoV_6OB~LDeqXU34;AT;DFn0e-V!#AI3{1r{ z?*Ym$yyefGe@`_p1pqaR6<#OdMxXWn1J5U%Nk!0x;}0ZcCDwkRI$W(tJVH zj$_h6sOaEs@BV`f+X`i+ z@Q8XfCw3qtgeziuGC_G(fFnw;scCX(T>L%ra}P-AN#B>Qn7)q(%tXahIKXQAkP9WA zQX=H40b3Hh`?SXvzE^--6R4W%5CRLPB4iwk$IWZVMSLZV=P6NmM-ukw>rmnSid8eX zEIAk0M}pmnweX@X`d>9+a)jlLtu+IhSR-r%oiv$%X$bS&+L)>Yy#w-riYq3jajO8x zAPmR2LdB#xD!ZCeagva4y^cOh$WurY)JM=V8qs967I89G0HO*ts(QoZIwp!iHxyY- z?msp6Z1GRv-Y_zXtz1W&@FT7_Y z`;Vg*)HM0y&phMx=K7174Gq?(y#4wsT?2+Mfg$!yLubz7v~(D2hh|NXkts43MnGZp zt46=(i80i3S1SdH8EA>HK(ZTQ%8>!M@(Tge_rSO@E#yaZ<~d8iYZXkE+~Nrb?5X?2 zGLs{cRnps7x>fat)G<~@{|WB2DR#Sq1ebJNvY=MI=6^wtiJ`o_DaEdxCCIe7&l%DJ z{c}~8!FpFbjY9eip_G&t%}RC3Pfnff6Lr!gGg5qSY4GlVl4wP3b7;j{hg->ob9P&u z3azebys%1PIqomlmVnkmmY(vRxW?ke?LY{4zsk-vcC+*Bi(YNuAo|pKN`%$4z@s1i zj2Hsq(7jdxCG9CTA5B4?@2<^7rao6ExTZHo#QyI=Kya!4D(Mt7#l%BMVi3<*3k8!D z9P$rE?XFHs4D>(bJ0`t8YTe*neea*%_;l)rTQrXs^Xe~C9z>q9V_!Op687#`98|Kk zTit(@qmZ`ae4G--m+2)tddB_B6)Brt3R0C<2j%4Fc==vU^p1X{5Fd*5D7qp(%Jcz; zO{^y{5Zv8};UM0lhxn=k$ZkH)s4%%|p8ynu-r!ptoZZFRjVMzhoU?Uu2dC81@dx2p z{Aft$)HWhX1p|L(-d)E*_Nd2&?gq&K%c4^{4R8ycOQMVG%f6u*U>u7d29KBKtdV~t zxIdTyMp}H+Mi1<~LH)_``@sw_z*Ld$0E2VSIDUAdJ+eSoF~GXls~{O*h=sp>pLivM zl*oP|%=JKh$ZzI2zWB##Cb?>|RXB7qt1dm_FEDy(UY0oF21wwi3Vm*krJ z)mlls0=^D+|MTNh6*!+U62D(@_S??rC8xg!k`i>6`TTK^DZ63ODi_~$1RsMIyOH3Q z(H4RoFNIn0wO`9O`}bRa3hE*{#%Za5Sh+Qkj$&;hPbho|Dh|<1W7)l_Hi_CT5~WOC zuRD(;k+{g&&u&PkFLkGhj9P;f{oSdyF1TPI*bxr^0RkO&=>7(onE-XL@#G`HtyVXl z9a>;#^fEr+f4Q$=d3786S-@EWn?SNjJH%GKGlMD(sLZ|MCdW?xA8u>w+@NLbCseex zNx)e+w~rlbXssIn5i!!^wh$Tz10*|7l8)YN0Dy5xwNHRHJJT`+Y?d#1q#jDRTc=$$ z2BEr5tK;*>J}wTe|MP&%W_R(!&ZIK}4MW-;K`_L^RcD%q2=X8`!HWxM)`=x^FMvAO zR_K@k3DOf(|C<$MsXwB1QM*03^a}Lg>m39<&dXsQQQ83sCNMxUz;KI>7N*t0;iB>u z3N7gOC&tt&YGnJtdl?d1#{_^6UPTyR6D*hA;h8XbQbEwiH-jdhy;Yd^WL<=QuKefU zB>9=MO7rCfenn=INg$N|Oqeh8y(W9{ZseeVx{;EB(+$=D8upJha$7t84mQW07v#{3 z5F_QXkjH9vV!mJ}Do}M97{r0Y$aW0%VW8^|7U+>slIv=LPLMi@bvsWC#3Xw7j)WeF zhN*T^Cl1it4`X5qD_Cf*f&7MMfh)~AahEBTYBU24riA$1Hz7m87!1eb5>1CG6ZBxJ z@h{cL3436WmyOKG9P!&m=U=MiC4g41J}*cyX#qw<3@*?j(9!joJ_!LI#p(eBJtf7? zv%b*-sfsju@RlRY41+pVAP*yI6dI49nI*)$;M+io)oosI&Ob&j0=^~)PVkoP6wv_> zSdQa_@Bf^DGp>(-q~Gx;c<8B`?9l!&i0=g`0iigqt&ZmG31(E~q6ADRoz7j~KY`p> zG;w4I_?j5O$7(6WATa&82qka?1ROt8G<}&j_^*Vg^wf8e-X&NX-KQ7rvn6*q0frri zuOB9KaV&j&OeS;v(au@#SGprWKL$51SMAC`2uUz7y^@+#h-%J?HCu#JC$2uUcBV0ViCuY{xvexGQw2BN&ayF!2r9W;a_a6i`~6aZ^i|MyswFlreVB$7wK{pnQ! z-7EE!h7=O}f7HEsTvTQIKR%F4n#*H`mK&8%`h*K=u85$I*{Wd53?Q3|Xrh3M$iA2r zB?gruCYxD`&aemy$nFwiAX3qY$fgpI!zSXe&&>C_?{m(aWzGQF^ZC7AzrRevnX}yY zbzj%}dSCB1A&tqF79|4pDvv)0G4OKFK>tNQ?}s(r-ZRV7vcFIztr&d)^!1Hj+6@1i zMSA6(fkFA0>!JYZuVQEe4VGR6{4M_FuXbHvjIGjj0#PvMYDbf`1s9^6K~KMB(+XfE z>JOjdu7{08bFNw>h+eb9eVmVYh&wY%_y0E8-ZLIoUsX9al{IsABt`al@6C&9Zol5v zZsgl?%&@-7FUROWQFBp*VX$LrW5wLMdb^HCJG17b8Sbz-kGMo`5~{~Q999UT-4ky# z1b7nTG7H3Y7rlL@lf#AbpR0SzPCM3>hpoA1J|iN1p7gq3NO55A=j|n8|Hara9SPk&>U2?pNO9?jxSpu0`KEk4M5iQDV?$ii%G`icE(brNhpJ;wypDdZ+cF z!mi|=o+mDMCS2~ka=^0kv-?SX2Likq0AaP?sme!P(|a#hyP7tMYA(LnqljG> z&2+rI?7u3b#Nnlw!(VI+`Psog`H6?#IEmEayE~$9290P#ehFv9&{h`4f*Lu`SI9Zi&zC1#J$c{}&sRtz>Vs8n3vWrT8RpAwA1RA8g#bij~@s$U;xa zu5IGwRdyyKlP!N=`uyyt>s57cygT|&F|BLBJ(o1VDwH5yJv`$6zLToBifxL-A@k-= z80Dck*#l2K?HfoiUJ(4EbLFyjzeENI0*CkbAhl)dVD$rmdW1&NTs{^MtfjNsHn8Tc z;n#p0M`*YShEWC;7Kn$5V6(sJkvWFL68+>EyNmoG4V#Tt(@3b)lkp_9z-FL^k2+io zt}@`s+MQ!C=0fA2c;bd4u|hzEQ(F6UGkue<(l<$`Fa63;(Km^)K~ii`jR0vfl!!aW zZ(~Lf+@$v9_@ekIuNeigDpSRFsc1lxb>h&k1F*EgD^fDDdadV(_T4wgNqhDy@0T>7 zeth)(5X(!81U~ztX)4%9r~_G6;Fm@OZKOk@K?{ZX&DO@c+AY=V3KgvZJ)f7B9B3$+ zYr1b~U^Lh^*#_k7zW6BncGgbAM-x>O-hUI+Gk@B@*d>qPaKPPP5|Np!B5hF4nL#H~fCS&ZwH`X_G!+ zXkQLI%*NPmcf>`fj};jl-xvL>o6XR9^uaRlkTl(sfr!f@6@sgb)%?oxIk9E!Ev6T* zC%4b9nA*O(;*nRz;R129k%%BoaKi!}A!BraUt4jTs|3vI2x*UyoWVSNF0wj8+|~xs z>Oz8f;e3@E)e%w$1ajAt=gypu1^(*30{0Ns)|#ac9$w}Tj_m@9t7FYzFJb!+4c++TO1vGPM{8K>Wg1OfseO50;n_ zyQI_DlxUuc;3|?4fT`$3e-Go%>GjIVKMtQd`IIWX7_XiVSaYqQQ#?!O-*khK5eT>< zbd3M?BAuKG(KrHkwer&$|9g%Oy&Kqf$+$Xg83=usFz?DtB^kR?(~*bqDhJ>TYo;TN z(8CvB8EN?-{X^K1m?g>1c%8iOnED|^o99Xe2c;aszKA!^orQJ5l2(AHd8P`4nHwEV zZ2bMZ(*kc!?BvlW2G&}q{7Kuq)){q5Pg4-T*^$-0BSL>!RNif{@0putPn6G>BA$i> zhK$cvr(s)?`dFss*z4?-Ui03#FhCyM9CpR(hsKtbyT|#>Z>?{XCffuY#HO2l<~Fyh z54^pkHO1V#qWMw8-H#aSi5!!<(BqrlmDLqiT;CV*c)mp0VFKTyWk zAt)5jvlbvBB~&&fz4L)&ch(0z(uuPiEXO4qt?)4EwAigwseTnR zQwL~BAlc?a?GD{Pj$sNI5CD?8CeY}v%f)pc2Hs*c*bN@T;E9(0F$->{+6Hwqnh_tYR^k>=z{u>du~8*Koa^YzxJ!L zaa$w86k(pP?>;5M$BdSI4K`!=s#L#y8M`FJ)J;sGGQA+lcc=VO##^eAqYDBmeibvT zRtR2YB5Nd+6!*T9B9}3{j8ORzW|j$7NMNEQLAN^PG(pw2WP1@%UP>P3Rup9-?Kq2htbdJ5Cb-{>oeQ;z)&Bf?y8|zi2Y%Rj*;Rk3CB^UTvXD zGb%K7H`PET$v$M0$wwh(GAnHGmVhWSrvc#`*~2pV`OTd?N7nz&5PftHa}IbAhUmof zukLvShAz*WJgeGW@kg)0^P3?|xsr8T=g9C!`|oDizVX;J20Nv@NnR$E`(VQ{Pei)0#oi9SEWXS#R!;40oZEW$c;lWfgRAiY&Uf|rlveb6K5 z?IcmgsDEi)4umel2@4=}vK6=4BoA^d5YHCe)0p*#U^pkkBZ(L}-)* zR{S*UeV|aUz7vG)DyB@03Z2|yAL91c3E}%A`6ZzyJ$)akR7dE1gfuWI$5~RwreXZ> z{9iwFFcJtlU^4KzaP%6{s%lXip-T-i$c^|f^k6!NKd@E|MGw{|xq+mHB6N&c-fR6^ z)~JKU^YaIoY927_@T~j+#(Dap_z(e`;Q)^~)UQk1Unog&>E3*dlpvAV8G?!N3o|yKAyihi=eBgkiDxadK7!5)*sC!W zRtL*p(`?n+{#_yN=73>6YAItC>gx1`ekk>mjh z^wIYSL>qNmP~QpEFyMR}ggOa0I)w(MKEL^yc1I^lnVFQdU~Ugfb<>3^yPzw>=jg;> zEaPrklF^{VhMBuTO?ZOTS}qde^{PI51n-P9cHL8lTP?1AiZfYYY*>qA*jZe5)(G1HsUAq~rlaO(}u z_Q?V4{9DhMX$@7%Pv=efCt|~|yGguqp!A6nOZD&7{oH7{4j+4P@(`!r5nExjXCiBn zKN%&c9d!k%D0OkghI#aWG|*r|n*_LD8C&%R$X8A=iWVT3GWQy>e#m@fXa9DT#De`y zc8<3Rh|mFkaT26~52zjsT4r{jW>6uNT>M7X;Xvjg&ZN(X00pTG((>wWsiTcJ|NL2I zVnz;|4kBWY5<`tOaE`7{+%efr)QQM$It8{vu_74Z=Y*uJv`PMH(naC%W0!S2fDL{U z17vgz#2W(K&Q908s!iL!OERqK7~B0YVA=Afyls*|eWR?V+RnNbhsLqqF^aBSdy{GP zRi(9u`e^{I@s~jZXn3(2c{siHl|1FXw15={MENGQtBmIC$`{|w-=uf(*>qy@i)D7~ zn_ZVxv`motUlaEo5bq0CENgLzy^~dIdc45tlL|BaWy+f-iRl$%v!tEzUj@{)J~EFq zYAlGW4SuuBDa#|nG5y{S_qL0LY3i2!#b*7;;?thxw#ufb-<^JaF0f+Hn`}@vxqx-m zk9Yl`;}!V8A@9%mS$^_+4k;spTNNIYFX!AtcH+>w`P~)dIJGg*=v9Mzl7;&^`u5v4 zL^qeVXD@#gt~wU-=~_Wt>gv4dI?p41hHziI!+$#IeVlQ#E`5&G59Ei?**oK1bAL#K z`OHFb>cpaX%QdW~rY7k;7M!vhE~t%R)I;>mF>q$cSIj{nUkrvVjGp#DtyTj19KW*Y z<&_-hlTuXX{WAPR8d1cB83UQ_^FS&fS zICjcK46-igbqM}_^Y@RPg>rBRKHTcD%(v>Vl91lI-CS(c)gjk!*%XOg4F!z4B>OL` z_y`J*Qu_tXorynbtq8FGhr#C*HNhzrEbVA!f_;McT5ziP$k7HRM5Z_k>j{N#+Mqy` zaqLHf4Kcgw14q6$8QuLx?n}oH0>1y~CwrUgJ;1!xJ5>yJ;x7alF)UH%n0**+Zob7# zv`D*-u4WF3j&&f?Gufla4D0Vfd81M*QoTiO>L{CO!zD9&!e_>hdIpZv`{W^j!9uDQ z!UL@6xE~*tm^o}S=nt5rkGy<2^O<16y@-g1bPHU9NS_(9n$fHUr=nW0e+?jTTV;3v zPa$j@)`zPN|M-~zqkAO{7+#I5&oyHVmc$` zI5c5*x!O@HAv75$$qa&IiXMZCm=M3TIi(7(Z_R>piVDmY#_{gvp4CORVH8x_rqGrO&Hk&ZkVjF&k$8d)gYEDMl(YL%N1+lz_8=Myh)v;lCK+2 zF$_wFmZi>v!x4%(F5#ZK*_F*n2bUv5DUgRm^%qr|b5jFYw-jlc5zjD~f!n^^`b$4H z`OZq~sq?wkF5eN>Ep@kA1cPIjE;aSeF$w|O z+>g`8_R0#XiqaLU19GE!X_vdJ`$shmWJuU_yduKTVN8K@S-M?eaaL1l=>ePF4!6^C z6Sih2Olnu7ev;$yN0{L7U@6*;Vlxb>V_0MBG{IV}$1;L7`k`n8md77@c`I^Wigx%s zVQ>yF6ONIX(Fqi>9+0EU2lBq`qq}WPK9QHj3xG9kJ zu>=7upq_(mbbqQoN71CIdO`DqSK|K3LJM+$@j)+%PTF4Bz(qW?k#AtVV(cjK5AZnW zwR2}~Ggxmx*dBzx3_@^tg-o<1c-+mRf&8&@(|#lj`aA7L!<-5_>KygpsM8UX(>g5m zA}YQj;nQ&AHU3#;WLMT5bpKcCXwFxgU(G{ZljdNi!UuzkfM^nY)Ih4;&itgqiz^XEJlA zTNG$s^-R7U;XM8Iwu3&hL;^~OE*yh`@b^(9wQ5v~fu6BxC*Wgh-M;Y7*kff@l zZ&_>TjbFWtJ`5@P)I4HEfL-`P;gs>mQJ` zT8~pGOITV%R+YJ@fQ~fOJpbBxwF8>eS^U8+$qf$d-5>E0qc$4U@R~o0hs^Wy^f@=T z@|@8P^Uedyw+l;`BCb~Mwewc9=>6g+FA(k~Tqfh;Q}+xLcQ-a2FKP7dj4gj~xBEnMsCQcPem|SK z3UQH5T&(Mg$63`PJ_Kh4a7AlM4sB({U+_`NjS%O&vW9%wcID zW}V1=N^nFLo&qx;wg@DKV6lDXvyih02nkI_ZKicm=;j|IjUkb}G4wqUNEx<+AAmGY z24XevLK32J6Pl|W#{1=?5MKf+2>K@B@BNjW3@Yp}DayZKungTK2N0%@FwIT~dhCZ} z(DMbgDtwbnjIG~#1~+?2=I$sTwBfdj$H1Qh1N%g@$3Uxk@$kFpGS(misKKhBn(K4DvyEGq2GG}NQ5(*|Kb=fUpce6#^m|pkF3X=rSg235fMGL+Q z&pTM4UtS=4<1x zJg$25lyv=%I{V!2pn?$;FN=>Zf{9A>ue0BZi zhtakQ&0LI36Jj0~3Kao^k*sA-tmF`Wx zGnjh=^h0)9UpyXN>m6~ZR9wl%B^lp9{{!-ei_~BEDw+X;zAH1O1q>6Hb@W;7T)abuO{sq*!vx-a#12@9O1x6}{yHH!v%0rOtL$#X(inE%*6 zTjv(1y)i`k>lF^ai2H2G_vk7W!>@7x=6g+LFOfR6~vqarhs+yH7V(Ad8%y*I*L@@oG98`w!Iy7Pj$`h!Nl_0Z9C>-=RzF~n^+>D^m zw}Q}3LKLVRU{}zgg}O&8Vr+4+A&dOR#J5OfyMTUCynC4OLwd0yw#PGtEOi)y);fI) zS~D!pGlpfno#h{-8K8LXVwBij`&QR>5o^{*kLKiQ2$7(p0M1*b`lnBhF1YBoAUDsq zcf;Jp`7NCV1yX;-UTZ%)r|vy>`aV$PxCJ*xjGB4f`+zcDR$vzE(erlbn)b}=AGbFv zJZD@|HDc^>W;)l~FlG%ayBpmOyHOt;ToalAy*D}Q*#c#7%n zkOq6j)f5NUB?STgeu|#9J-h9Dn%|N?@NZM@OqYZvO#v3JwdLQAOZdg$&d6EQZN5%jZWZ^_ZWHB$(y-n0qK_o{ z1}<8=UlJeCyU!=R^HE>*?wqCBezO;=Ry^&<&oaH!tJ)nnOENyzG_BDvShk|%QS)uj z*gZaRot>Tsf=hj~^QvFg3k%ChcQTzks$Ev&tcdq%UHHS8xOVHs)BZHA@k#by-mzG^ z>ts!AeY3D#*xMmCd0(+*L0N3F(n$P^t57x8K)T0bd{yE3OnYO~sp(E`olmoyEXz&{ zRZ*(WyUh}LN{`{U^+{j12RGz>e!#p!(dN)tn`!^H#9@EmrtFHA19{C$0$*wP;(F^C zd748^Xr3@|zFx13;+k_pg7Q*cb(E##gk+1SnP5h#-$_-MZlmAgTgsh3t6E=*U;SRX zb3owjMoC=Kz4JXGXJtu075**SkTd%yr3|#HJQE9VigE$InKv%M*ivpQk5#pHd29^- zE)5jOOLK0E5*`H zce;&?Z&|qfD02E589CMD&)gN>D3-sj$~b>-7_7Cj1m$mMg7QL%Epud(yfa;BpQvkW z=~C;W_mfBwEq0T9wgCMa#kSm|64b*F*;l7ac3 z;xVy;t~7&s3&@Ma*Jlc#^8|q-N}QYE-0mWLsX?5PTIepF93@G+p!@AiXJN3pz*a{P zBe=8*e$B{F_jPDjCkSH%mG_67`oJxr7w z*lp)=>>T`~4^nrb2zTB+G zLvVBGvXLVOx~maE_$#a>ucnH9j(y0Jr;Z3}6uTr!(g0bDBEEN>cuu?oyl)Hh4en<+ zPll_YZywzh%uOu5jr_s##ium?=f9;7jPqKqhC6Oe5a&6^Uii%C+DCG)CzA6soP}}b zf}cnFT`QDY%!EsS1egBs+?a;)Pxk~=%gs%;x`1AJs<>OcLT6<(^GR={pE-1l@(n7t3MbDLK-e7-6d_9Y-sypEq!7L`?ZebB^2KPf z#%d@mj6-ldTN~G5j&^(9*NM1c`SKg~%vmx5-y|Sv2UVzWZEt{hS zTcDdCgC0Q-TzKB&7~#>KCdDP~dp9=8R9jkV#LFD27W;?SUAMkC$tJM1;z7?_*SmM0 zucX5Z{z7YWK@ z1;C;Wvw8``33r6<8f!`&OY}ZS{l*=yIr6dLs6qxBy$?N>mZ%<#z6D4~>gf3Bnf1`~FdWrRC zq;u9!or(Uo!R4s)OCh)u&E7qOyHl7Q+ZDb&vcH2SCyUc5%roD-@#!Qh2@tl;>hSf>j72H=>Z78*Ev=mbTfO^Uk|C-Hd{BiP?GWb+Mmt0Kdo))s}c7=f4W zZ>b2&P**{4sG19mb^g9Lf@8S@I3aK82Q@3u*@BNcoA+I|K0hZUDbLg-@nq|i5UIk( zLs9(TO!om*Pj}sqyG^S7eEk38YwmDd;kO{B1Zauf;$BZ_S?06mcz|%CtMByu9lt_Y4Um? zGXCO~A1eKI^QUZ`h6U%g^JL{rcpP4OOF{~&44u?n9iT9lZ(dq59I1o0IYXZ4TPEw7 zQP*JFw=Q{kRZ4d5MsJVaC&J@ncTAj6TwGYDPo0g zT$DpuUrJYI;gbhVFPlex>o7IZ;g4GpMPZ6tYXleHO<16F*{SYYo1grHWXTtb1*j}U zoUVb;E2w;-U7L1c?4H{aq3a7nzLXN79QNKK$PfqEWK0qcEEPDT(MZsm&!rDur{5to zqmV&FKX4YK{KlIJzr*bDn5tt`*g&nK>&0^~9 zC)P3F7>23}3Ut!ei`+3=WRbbGM~U;T6_N}@TwLugw_K6A?*woKOA?2fNgMTFG`@x2 zrshEM1LMh~Z@)C$sZD-q&z??^{~HCTy}#;J$3kP%yNc4r)#biDDNPMWf1NiRMwTtB z@@%SV5+=HZ)wRn4a=hLiTQIibVTNVkg{Fv#;$#PXhr9seDUlHYz90H~Ib;XkYZliw z=HE^iqH#>Zx3Ye0vv|&|WyphSh7=5;KsR6bUZV4z=t#y~`6h|2&gOW*k(Z$y;GJ1E z7kn1O5Z5{+BaGOneGN2&32E`Du9zyhqDN*(Xg#oJ1nJ}b)7GEwO2@v}oe`(A7&xsvbk=Hx1{t6);v;~2wR5sF z9FWzUr(S-EtXhVk!Ve{kzMS)geUzY84tYCMMVp*8HU31hR^V#2)BXBK?UoOOWdbe) z%)xl{RxO$gni~-Q%WCY-Y-*8pb~H9Lr>I&V?rF-I)lragSMD>_-cp{d2LjMU;`F87 zvoPWuHz4f{TuQzsdTooxiE}{HSrUIKW6POt$>WowXO#~I^MeKh4G-bx?=)!4Zx|EZ zgF-F`8tkk#h1*Jb&-?LC%fJWti17ZLSwx+z>BxcV&3U=97K3HTrBJ4NyoSs8Yd6llAik_|>dF_L{*-tAzmR;|Cs3>){oa$hBfS~?Dwv8Zz zNYhJ_v*@H^=MvPrP7o#vR*D2@*YJ)qn+vwa2rv{4v5bcg1T?&t%wL!St0e4&VTokL zo1M-_wFAO8RM7qLW64?n{&E*atmDl) zC|cZxj>@)AB`W%S?g@@+6fZY=+?t5@c$*)UK^aRwRl*LS0WM%`I8o9Mc5~Ji`=U7(1ElipY71vA0Jfxh)^;L zIR!X#L;|Jp4=%5crzV*O3Vjz#G}XAJx_(d_+lKjW_7lYJEJ zg7zqI(0zU09&y^LMZW_8^4cjh4ll>=t`Sx3Q*U4V{eJeI^>ZdfO&HT63qR!e`)s`_ zTJjpdAwaTE$_z};%(F49o>tT#Rrs`Rm=>y^mhYaV++1#$9_g58k{h7#TDsU!(eZuH z<6JM*r3zs|SxB^-mg@G zvjg_|3dz-?=^Vyn`s zRdrF3FgqkEaCe!*m?Gt)wyT~sAf)Eo+rFa=^lVkekc_!2+6hQMPi*cjcT08dXh<=o zApJZg1?ivtX}A5jYXTAkAz5m)Obd_1e8qUQ@m z{i3jmrjc9IC)F35ivla({bg%sZ*8sfo@KUytxu;5SJ~428CAy!>4ValQOcK8J!eAm z>votczhAes?{|mvFDfM8KzStvW=Pf9{!f!pV)+?)ue|+0xyp0z(vE7qUPtRDpA}`o zvXF+j+O($Tn3xDf`6*>w^$+(mWjj~jFtoBnP|jr0&pr>l9_e~4?gCoZZU9{c`*a5} z=1$F~0#%F$n}`ECBXtkw@evuAjrZ z1+D^a9HZzC&QGp`?&JYH;0iXqBoFJlz6Rx~URG+BDoO~#Ar)Nce{)ByAobZ8>>h~tROXa<16DP1t2 zYBCDOpdSjIYLdpQe*G+x6Zh~Y8^_S9W=^xHLz$Km1-E#KtHq0zPk9z@mv=goUaYvr zlkN-N^8JDP27fHpJbxldY=q{NJ7! z98q7PXl#fGPU-e)e;rAPc3+?n4SSCwd#Yu^NC075;hZQhbPzvyzRwNwxjgdPl3I`A$1d)~3? z8uoL{5mt|QoZ{A)9eAny_M)jy?QLUQA348V>y%ek(qyHb)4@89xF4xe`7D||s-fGo zs!|@9x61T zr1QGV1N@)-PmCBG3}qKI00|Y~l>lYpOu>9}!436>wCWWfU}ENu@1r!5S}CL`E+9BBg7S>Hdqv z0vAraKTS*G`|Al)Q#{ayDrAgi>9Da@B7Tr(XC$8i# zeuhXNX(NZhjG4={`+JI^Sq7~)5H@>NM0BChE}{mjY3NN|>1cfg#7e-eF<%JyOp{Lh zm_cV)+mj?;3p#Dm3zzGpfvn(+`Sz)fi#RR|uUQPlLxDio30oByg!`a+k_Vra?KxiZ zWVhemK8Qh(!rlA9YJ!8MwMmqn>`~nw#rG2mop0Y1Hq@L7aBFW!X^oMd@D;iHhP%sy z>v0qDkp5IjnQ7)eBbYOewHqBJc3HpfDS+6+{)3*88eBbS5!}9e;ZnmX79m69zBrWS zQ+MBL;m1R@g*qeM{~1y@UZNY5Y2ftc#p0!7ia~+i3$jLK|K>x z$20XbLkcouSY==^P#vdkrp~s0E1+9i?}Fx?p_LCtP*q#?2yeouTtbEvL6{G#OIs?(w$1eF*5sQ)s&KIz)7M4c1BfMS6nT&NDQ^x=APlr07qbpWio zJ92Y^Gmg_<*AD|8NCItxihe|CM!K`Eg;tB3)m|~^3!)qo)YKVJgF4mVJYv>9tdOL7 z`=-J^1k0)CqSS#=63UEd7BFh#c>Qt@wQ+73>~Y5&41|NRKwn^WAlUncrCpMdF1Swp zBS0I-bwkah0BC2PXT&WHeZg6RBYHu5iMAIPK8CV!#LC}T%}vPXm~>DOJG-V30sv5V zXx7150*Das>|6V-nOPSD+!8LVg}b>q8Y5vm`5B8JiqlUbitdO%09w7;AtV?K%y_#+ z7-kg-z$M{Ls4GRCKd)pim`J5onuh}KE@+2ckYNSlf-cZ+2U)&(wT^5o9o$VU$GVN(XZu9g^MRtA3yJJc8B{h40gd9Hf0z z>xfA7_z*d&mq0^t(>Fwq8OAJH&>`^og-y}Wfa?z*!{MJX`%9mZ44+Nz523Xp%MzIn zhb{SJ@0IzUI@@4Z$VQ)azF744;R?yR;XDTo+#%6v!EAw(&x!t`Y36Uzg{<8NpPaTg zab&zO?w$Q5!p0r#V@@tHh^+rGr_)VXU=WfdnXP|&uG^NA!QG-@K&cv97bSUTL+|mn z5cRIPxF1?t)uOs=!k=(6dL5~gfbWD(4>QDcoB)K67)kYgTWDb5>i`OgsO*$cz;2VA zfB^6RH17I#jG;a_A&$-QZ)*vYD@`kE3JrYvlI;SQ&F)1r#r~Zm;#!+aV(nBnAM~~R zWla)$`8DOt>6NPX050h9M_>QApjYCg_8}Ol05s+%XFbCD=65Kh2q|zffkEM16Ke?= z6lQi_adoJ|28GJUQ##c&;N0$&iqo}a533HO_qybD|8(wjjcVDS6#?ExO3~1~t$7I! zR#myD0*W0b$B4h#DA`iow@qHK?%mx7Hm|iZiP5erIdXp1Lbn!zCa%lemXdaOhNqAW^29#HMEFA!Y zr!Xa(RA=~A7MVp;^ohY^qQ8@OAZ-{7II(q)=|h(KO6XM4cS+~Q{ooy=L0gfW@z6Ho z!z+M8Aeng5i?#`(zYzyHNa}WTAXWMv2beO3aL$djaQ2gvURs4-h%n0m=9?XAd&k#^6aPBn@osQP4nq}Sf$^n2u#Zh2ii?ob5GHha{W6= zdA%*;&1x!QO|z8WUGHx228KXmY!VT<%Qv5}REa zzXpa2QICkBJ3?=JBIg+*_2ah4$givt3%faEqKtThLndoC(*bJ~hXKL~uf!L#js?26 z@GMx>xS10>~8W+Vr~vEQGoGf^asG}1?o8& zl*bSHYSlB%(3L`c9?120X={vL0G$xgT`2%u@dWmuN?x)nr5mydv6jS-=!c4c zqBU!!zYpq&Am3wVxZu4P)Q@Ih;V(vxg|{S4HtTmJnJVd*fCVE=7%xzNBYtr#A`RaH zB43G`UBlR0+D4M`1Eezu6z?<^tL8{DBb3n36^)5<^Bq{1+>vDbV(1O2T|5%jCHE!L zSBt~WM!u^hcRx3iWrQ8RbdIqzG&5OzwZu&G0O4bmhcTVW5^;URDVq_S;ivtEI`X1} z>Ge#1CpJzQXgiZ3i~35(5w8z$m(2Z75J~V-$I1rJ9TY7*l;esm zik_@ilLt?86x|ma!JaTMCcWTEhO+x`K|yszO6=$_5v%5vHmZ6SRegN1r~6Jwb47Cc zdHZ*u*V>~zNn~N&j|y7vgt(cOY4AH|S|M_Dqw13Up_=09+4I(cfi)=95d-cI!#Z$( zaXnA%{8B{zv$ka^mfc!}Wm^mzE~oq6YY9_r(l4u#RkiJEbIqzyq}B9&V)1*Da)qL0 zy<2bHqb?i0zQc;NfGv9EvNB`)zTJnboKJvmi+u0+aUoT$VPTT1(7ehi4YL@!7fs`} zPnUP*PE}USvr`wZGVU^V0D*3?S$YK57=>M#20d}L-_-#B%EkD!p8je(!Dkv z2h2-~l)Klf+^c>5jusS{`VGIv+hXMANxWMbwHW6v`6b)N@4pq2lH0^_(XMdY+}@32$P-#z+Cp&mCUgt7_9TjE&Oy(6->@; zPB8M9#z?+g4nuB$IRo_)MnnM^=cj2CSoizH=W<)G%>JHsQt@(8!QdMh@Om^^_~h^p zaV;~^wP&!z+pBpcuyfl&8z&EbobJjx})v28&sWfSxYQmTM{zTsVy}?w!J;t z5qvkNC?Egfmlde!d$NA9zMDyoy8JNP&Y-^9+m6n@oS9MH2l7$xSlb2xm; zh-0g{fS6AGvXH#MmSjNXa%cgT~@vvW|S%wGWmHb-Ag%Gg=A zQ0tkgE%kykQ%f)3)MU(sFH%mvgM}Wv3&p-7#}@12X5nqA{z*xm?Dz0e#8^JCXph)l zwetSX7_vnIt#B{Rmi@8(veIi;t8C<7ObMxfqeb1bf6}+P(>!UcQ|qImlvwk#(q;Sd z(j83QA{2oWgB@G#l1-22CzdrnDU>||(o#YT94T-hc>|J=eJr>(*rlyfVrtb<)Lefz zDJ;psbXsWf$9XwFn`9eSn>HViw#m0PR2aaFILy~zsrl~JSg0p`roG&}Rf( zPh)H1g2}*H3QG{&At#oX#KYxax)ss7;boXl9@-Ow+ed$qyYv)52(vt9`!`THS z!#_MyR%!2Y9F>GbOc@v`qu&xP326Qw;$=hY7zVY$6jpbMWjdkB;KXKX5rYAn{iJg7 zbbO#GvZRWtXC?Rf*$nlz$tTS;l)oiLikY1*7DFjbl%adYO6OH1evlNuPdqFdnlx%_ zFUUa#HD*fqX)rg)GfadKEpZ5|Xn2-xB2pp2xmV0N;am}DWkg1ZmVj%8 z$7rk{1?4^9L)wsiln5hkfwXH8s4f7d#rqIAz0i~vDt@4ZkpJ+}x+f`03-hfG79xg9 zy4nER`1Q@wlfQULLs{Z$u($i!(`0su+q}et8U#8xXvEj8O^PnI<+q`Hyf@u>$5ukJ z=)n27i0kr?H~mMlY`SH1;Gv$J;@F~Gd_+wxmqbZS7g{2%plN-7TjeOdgWBN)AjHBU zbb+$Xf|V##HDdZ7oCYI*Hj3Ku(^c;Wr#8)AI%i6ybk^{K)7Az{vlrI1IG|yK;(|!V zDb+sig5~qiv3-`E06aJBZ5{Y&#G10$ldLh~1^a{-TPi`%141ec&cJm7HZ?RTS$Ccp z8tfkSx5a29A)|ueo-C&6SKt{%!82pk&fBUe{7UOzH6x5ZPQ4#-#aL zByxb3I_Y6Sw9L6#FuQ)CQCf;shR+pL;k$(+2aC2=aIn~FS#wR*5Hsv9kUwIE&eNK} zu#Z?+`oa(-pz&l_;}tt7g^0)wp%@dC2V&7M?(ALh#j96f)cLK?rHA=C9sKMq^qYg~ z=>r`rDR-BA_dFP3(;q&?ec}~_q~%<-a5?ar-Co~RXNXuJFFX)ylejWSJ~-1g1Cuo| zVhj7~e?DEas9I&)F|+i+ev_gbhkD8!4Aa~Ss?YiqgDi~1F=w6ppApj&+4gXF*^>Sfe;CI^eIaRIl`^=70(}<$uI~TdHCL zJkO;op6u^S7#WZsV3T*DCcD1v;f{?>qU+h+zskZQzp`oy2=ucBrLo4==zyOMzCy%> zlltfLI-4JZU7(TLE-?9WU(>G+DI-(K_pfJ}Y%T%OI zft%!BLpgC4ReWjKrIs+Bqj!O^NM5i-a?syp` zm#Vdi&IpE-);;}P`&(-49Df+8;z~o{e4RJOm$9BQ1ls{SZ;a=|yxnM!x_O2sI(Y>& zHoO@rK|sHzvfmVmzFItAh^L4|35CN@y1G@oop*_;F-CmlSS<&bvP)*ALZcc)6NL!y z$P5G#MJ+r(>&5?HP1xK#MUF*31MG(;Y+fJ1Q1sYNkS*blXChm+4)H2a_oz0#x4Qv= znC`CN&i#wNZcC|Y-0{!(n;_JQ$R*%hx8ik|7*%PpovJfS6o%!ha&|3}iLMa1i-YxB z!u$S^&d~Qi^5;z}9Gn(jZW%F)sD)VI-rhv|Hvv#OVX46gE*KcxV+Gc)slZAM*q|vI z-T@nCKF(9-sFN$AfFS2i2;C$ewIl9+q|kmwq{W#yF<=8#PJiThSmBYqOP1`yc;4R_ z&jZHn+$$^ibKmXdpbwC}YtiFBWCP6C@Z2YpQ~AdEdf0zk^u~!Wl{ry1H)ye^&O)ew z+()l88BDVY?{0)m=!~&Ukc{z$>1C1NIw_twunY*#J2?uI%nRZdTysY1fdfsTaU&a* ziD5jvdc=j|3WjILQrSTWQIf}$awq^4NEcvZvr8Csmc>BA7Ava5l!5E zydq}`Xb1h5vhTxktXVr2)yGJ&ecx(#4$29@VVS6NiA%YqqSzS^HibC7#X)P;mAl zF}RGD()2s;K{fV{=wPITnCPQrZ(yJZ2@IiewRoSWPbnimVJFbxKrW!du{%4{!O*_& zdfW9huNJBP?B2Qq?oDL{Wl8#D3+m6**l*CUp4b|DAWPQelicp2SL-5$vnomq>Ti8N z+ARS+LhkSgajt<#>PW%1q3Cq?b5eW#!U#JiFu;5E*8LaInzhc~BbN7`K(s}=?|*cE zTxlpx{>Du)P3ReN8ge_XZ3FU<^KkI&kS- zMMHB44d8|5s1-#j5t19=rNUImf&RE*tbZ&}liT_4_wGo&!UN>3^=L6_|)J3(VMYzr&a zHv@N(Hzy|MCz_@AK>G$-MfZ|VsynHS`@l~Xq7CmfKiw&M56vQsT_=4oJGQR8>tPoX z6Ia-zzLPvVHxc#R{wys5(b_r3q~iv{=3E|l2Tiw6dUEgzq0pR!f;)mNZ#^eAx4m}$ zKf&f0_OhTcRdl-1e4Wrf2}dTZ^!HkZ*xJ*TF)NL*IYA0mnav&b+xbcE$XOP5XfRP3 zHs-)+I4?GL!Xl2y2DR;WLX}M;dQXoxqp&$>U6I@72hDB6ee0~L#NoOQF2{ShuRS_a(094#1 zc9%jX{7;5#zDO6c!x_xxxkO2HcS#?Os&be1lxH8R|EBP)_l8!5jWoHC$oPtEPSkJ7 zl|IPxzt-(rylWa7)^W!NBaNO=iSgoU)Ug}!di@&MV+l_Zr7OjA)`Hd`oa6^BY^>s8 zXcUB$^D|_ZGi~d#NA^{nZb|<1j{jKx0k-mOpj2?Z)Y3(_tKx7#=lGQ``AXgclDG5~ zS=T4Ox}Hb^&55x5`n=%kT(8aoA60C#o0D8spkE=6xSkT|}M3W-WP|D2NihC05vG`KKmGlsP+(FTAZE zGjXkYU}w|SrHY#jDp6F~OL@!5ft@+0U%|TlA6qHhRUYGZ$~_g%CzhC6EB0QT_rh|W zPv6iv0y)}+k?0OkX4d6G_wY~>X<`|Ul!QSi8Blz?@N^J1M>4NCJw^@Wx)E1=+WPia z9?z*NZBH?s{HH3aY@c2HB-Ng`cA-ati$ru(tQC)^PK+h-m7A}B1e9$M!g}HY3d73o zltbHB->55)g=|*_`#Pn9Un9+TgzHNeuBriifa+Y*z&Bxn0r}>Hmc#{c$h%qV*phdm zMMjRA59MZcAf!rI){-6IkMR&Mw}+^8Qy*diK4hWwcwc&6>$H_!?nq(OvHcww^(IU1)e3XUdbjUkOvNt*SsTI-f;v_BbLk)oT}|8jo_8y>)wkeMb&&G zY`qd7^VfU+OeGQMPLr-60sccpdb+CGmsh^ykmzfZ-w3$}I3gdEea_^#5E;x7TWM6$ z5?niwy0U9QA`6kBiaz_ZTlQW3!($Fvj92JC37K73^^b@Dq%;($a zYx*_KA@kf!p#&ks9C;JR_7~Gg>E;dQhG3av>mb_k0z-iK<_gKhgA4`Y#rNd~`YFSr z#4xvA*K~h>H7PN?Y@?R$^7e~c2Ix?CogXhiZq?G~WP0R#*(~}?-GMI4LG5U|9sZr< zq({S9MqP9Vj2vE_C9p>4)`FFB&bN@rnEH?)V#d=UT8CLsKDea_>Gif)4F&C?m5a=u zMY(|r71XhI-C%k=7DDocYk&-Q&;up}YC22`3KXD!0~zkLpM3)ETPI8Ok33OlxZJ)Q z-NI&Ml~DdyI`?Jf8^HD;yU!@Kohd*q`wySz=G1gfChC$oY;aR4XbWaZ*1`b}_~$Mm zQMH3yA9>QukiMp^%H>bCp=w9(8l+JeRr^5GesrcxRP7WS%CgGd1@&s)JS)=}g;L|5 zbf!U;_4qSDXkQ{K9!|s_R9~aBM?ZP7K3sN*)lk<&T55}`6;Mq?ayhzAHVPY7|6dZK z95=uzh>#dEnr?fh<^cn@LNdy|lG_NrxElTpGTqF(hJFSihfHcM{G|0vrI8ax3CJ2~ zV4kVGQ+)V+p<4FC(Az|9H+ z`=oth-8kp=-~-nC73a^>{H#ewop10q1VB*;r3)aIOvNfj>N4c@zei{oqX6zjh;<;e z^McbNV68q6D++1$v(8A?xuhY>#$6_?{Wb_zR2mQZPD3sL`k_uFaW0AT#em=fA@DwQ z)Huk?KpT*h04KDP$VdWvZ(!aYx`lyz9#p``Ky#T4&ZX|9_fKRAP!pQeHW61y7^1+u zDL>`SFCx$b2C`X@qx&LCsd!;|YvHqYytIG`EllLYUW!3bwY_tafwA?sd#j zm2{-1%+6J66BR*bhw>6jW0Q{R;|j4!oitDS!_C+tX@h~8@HDRQ+sw!b(mO`9iZgsTAOxW^xU#M?Z zT(hz(Nxs)knpPS%C2vA&T2_@?Z?XOwJ%y~Mw3YG}yqa{^t#M*UqGDxB;rkv^85{M z`?{Sbi|DaG7NbU8J21~ag1&^6emOLo*DM;}Z)z?psc=%&g?9k_&j^a=j%0$=4tl3U;#NjK-SC{yB!&W;kl z!?%ACWI^ijYUMlwVXu!x}p^qa)K+`MB&tgQ_h4RsdK z_jsfKdt`jTD1`1&Z<228ks$TuA4&(wTJm1};Q4idA@RZ%SY@B^5<1mC9EQ4q6t#_M z=wzSZd@VRt9D1}tdGYN7aTeAS3k_^=C+XOaGd9HRsy7|_)B7l4){v6IXCNkN$?g?5 z0*v+qS#V|P25r*$^dN~Od?c2B|EIV2$ct7|LXLM(ryx~#5~W!KN(0f9)(IpCu1U0J zyb^jX5Lh;qT;Uu9*&qbko*I4%Mr)x7F@Yvb)8F8K7gw0nEU%7M@CKe z4B?exshS|qXKdB(T=&@^X(JtaSv|nU*4H+U1qzsF!Z2tV6P`brVzsO?0{Ve< zPf2fG475w-9rZj2~zEO`WDpFWaNAgm^1YU33B7|i{hUcLg|=klRf@^ zoonEn$`Kb}LaWJY>R=>eA*20~Zk*ze!3V->STjt~V^b5y1dx>6#*&l-9PpLazO3H4QN6U7WcPnw_$S)N;I;Z1O}=t2 z`sjwb+YX@7bjwAJx7RV~I1D=_u9771r6C8$)T<1>ML{72z`TNPX=Uk0M?pc-CYd0a0U-@+jk3s@8Z*+a8rCYCp#$rg$&Kl+bq|32m*I<-#3Lpo z%!1L8#W4X<=NJN4D^897j$=r2>>GV47ii=npFfQdK~tZPQQb;K|;{MG6`5$ zp-64T?LAV=4-V1U8^fn`*jL*e!91sJ{1c!U8z#6a4YFmEf0br^^PB=wN`QR>FK4#b-c z<4f-Q9VNq!?mNhO??-qFJ*zi*EG^pMy*PKNQqi{8LnUfn3${pDf>r($wJ=|D^0>*8 z+yB;AG;=ja-?+?l?4AYaOnPxtlz7hiV&reC)f;m#_}_xqZCC6)dcY=F(wilJ*qrQV zUzIe`u%-0!!PGve_NE$2#wxi?F*HJeKO+|v;tve%`gLum^$K(`#P_@k2ZHtylP{}%&%vP8_n7T?@Jhr?Wpu3Ph9;R!m#VT9nH5Vf3TE&v z8fLhJA{G%L!5h;R(O-abxMv~|IMLDuFn(|X$81JC3C5p?PtXD)FqXNx#-n2i990z5 z%4js;^AtV$%2XeaZZR3Nw0>?7ik3cy&fjZVkO>@Jc#BNHag_(qC$Vicm_NMg;GSqS z^)V{)o{K7R6dsbjD$N;vBs%~Diwe$)=pTI(H)KHB%gWG_LFQf3Vv`@ zvn%Sk?qfqy zmS59))1j(TMHw~uX$c_sJn2r8#k!f?HU4kY6Gt$eT-+KgUh*+M0NkQsv^C;VTUsH5 z+C?4g5M+3z>@WZZMX~p|Q>n5IKc8%|Sn-ae#f;Kp#uHEQU?XQPwM!hk)Na{t#%?>|JDR1V@B~j2IsGNBx6M6|-V;3@0Y=Z(8M8l#PMWrJu35K72+41%$2bwZ zFE`27+=N1{Fh3$fcIY5DYw=3nF$t{!g}D}3Ip!ybaN)+B+2CqqQ@t~45zv?xQEiz8 zxxmobhes?|q-`Y=ezu_l@A4pjh!cJ+yKxdh^QH@h!596G@2Cx_t~+$DZ{{Yd(?PC=AdVcrzX|PvZO>uBtQV`(pr|4nGPUH z6PMSBRsj#%M_tC@zmRigP?tOYCEi|@fftB6m(vs670L9jp_G znQ4A&(eMH@hM-x{cdeqwBI`HAcw$4ZJd1)miXtSZppf3i2lBov7q?oPzFJ4Pj7?~PILC^*SCNe1X>D%ZqEo`2tP)3h=EfTce5|n`S z0tV@A4+9?y-CK|`0~d-K#ng_3Xj`dj&NMM%3S3EpiIVI~nZ+MV0FqD29QHaNp_Lok z0Z{S|x-JY6qPdS}n#5$Hgv0`a7@0;WRe?VD)anZlIr>8kItEV?LZPSx2+#0chvtfA zx0*NMp%idw7zBYqgMvW{SuhB=4#ssDG|0vlOTjN7Y`CeB$i{2h{bQhF_&@Spk2`er zm49+l&94>}d*uMqh3Udz^R(lv>e5%YMHaEolj(Fp$EE~fEy+Zfc3p4Vf#gz~0 z7~V=^mpJ`p0duNdJhN&#B25n)^hopKYNpCu@{FejNy3fZm_0l{E(%@EQNji2Ij3|DO1742Ch5I0InRAZhSNohVDi{e*c3uwHo9B?Y zi)Qd*aKQAna=_q=FR{>Bjl29({Z6>MW5K!YbYV>4T0l8MG(VaH2IUMk%5$yXZ|$c5 zOhoF}U=`m|lY1;g-Ec4W%kF+k>9_Cy7MSBwKNz@??Xokho>tT#Rrs`Rm=>y^mhYaV z++1#$9_g58lFM}$5*Cz&M1xW%HVeORq!#obbAJsFCA_mVNN2!l8gCLW^oTO=B^`oXSTE zoEgf*3CDlFU9|B;J_zY*p6MFBYABhw1?qcNQ;`^Krv^OCv$vovz-=63JPQW4>Z4J& zBV*a`CB|EvXfhjb*wfq;3=BhE(xST6d`~9y4?)nSyVBr(J*irhq?Tf zLya*P7QBG$aGS@A)|*@H1W$HoD>K+p%u=07l^LU~4%Tcj7&x8*BcyXMUOpgB0vymU znp}Qat1?Z0sx8c{3|$QI_mus zq*$~yHC~{(GRX!NfT^~Y9urqaW(km1jg|^YgAa_z@_H&D%L7=~JzJnnJ(mZl;cNgV zoMD6{T9F|%lb50yqxjDPVxHMPp}0ZW<)-nE!r&K&?RpSzWKc%91d_)v z!rjPe6eA;Cn8Yyo*Q-mB=JDTz5iT0!)>L^Pj4}J8%?tl2c?oc3ZG$2M)0Z60V1x&A z8i+j2w7%$9QVgcE(8v$Ln+Ub7%qjt*&!ZN{M#NG8j#|_;jo6A{+Fu?|#L2Y6=07MXa z$jsu5B)w=kk+`~1Jckb_T_EBb-bb{Mb+dGaI^%$ImFHBWpDbn1$VMxOgdVLV!V7#5 z^NYY<+Hqym^AjpYK1l;203`{aO*IO-SdbTEd1*|f;2dCj|Aq5ktGqOhY;eZf2L@t? z8cv6dCw6Lsy$DhVT+F9ffKN8>*$AI_pHjIWhMN3tIH$)X8~v(P{1AYT`m>kIjJLXc z4<{1g%}!8uw^G_1YD|FI5dB|0>M&u#5IT|A>?H(hL&F-$TJmNyRGcALh3`SA0ajtE zm=KK^J&O&k&yda^%(f({vrEyF+>*~$dg#xFkx|8BEJjUU0&8|SxJU#QG8;z1z`Kd? z5An;u8SO?6Yqqzx7W5bH{a`i0!P43!%1-tO+?KwdP$)b0o#b}jDn)gDiBruA$^6dv z+f9V$2x!6Rj}6!#pZ3`J3h-C|XL|0#kG}T&N({LP&!Fc{SY%Lo?i6!r@Otit2}c^p z7|YzOqsIW)jJZoh?C#XUPSlLmIHx}<1H}*^JCWQaY=BX1z&60pzF4WvhHG%51Ib5S zD!wQ<`vV)ZyD87+aS zXmR)RG2{>f$_9iRK+m7i4uh-thr}hud4`gL2QE@zaI6)~H`I-Sg`+`S0_gq!lDKrE zmztoo_6R&(>SSJ#?&!8LXFI5v%2$Md43x3uXr|QxihBby3`5a?j0zJZzi5yAf_Ke?84qVfD^~ss!Ex$f_y}Y!f)@J(h z3dq;$Xfd>qZH(L>*Ye!CxFBNR6I4|gag~c!MCD&@PuC2F50>nTZZELDKE30fvAL++ zsdb0maxeXM)y4h|ifVEE-fs3MG(v*{CkleS+sbQyZ1bAP?UFT>dUSI{fjy9}`UU2X zsqc(<%ky6+NdON{6b~DmSLv+oych=uOQ}c0fM^g)Vm&Y7Zb<4VKjC{vvcmxFCyQsp z_>PElLD+-xo|>8t{tOIFD;7q4=Y7mvTD)j*JUfRI&G>!jPXODSCQ1{Z78?umA%5H! zpqzGSFtkeRPeVR8^|AVrxQUS9zzRb6YmzI9Lhkk#VtwdkY5VaVOBhDQP$!*07pTn{FZmapLU9@7USu8NR~MY|oV^na^UJ&d$O>2cYEB^>RXrn&?1HTQEOF|N)eD9^DE;SQGGS+ zVlEcXTRY0$UEk+*)fQhc9Q=!q>_Go`$L4$4#9VsbtU+6KjFGRCRfgQoT_jaFpUr$c z?h>Tp&_h?~=O+ll1UqWA8$J;?U>2_eALk$H?Uh|mEL>J&TXavyD z(;I33br!8a&U3ml@~M9l>NM}@TKl(z1%v4~wM&!l=ww86wO!#|4o$}HjwY8P^KG+K zb3s$FUD-tFf6U()+$1lT|JFveVeWI!1!OSkH>QOpR>qNz<^`7K{z;C09myIw1m>69 z6%`L`R1r}l=_rC*#<53?Fc+9$Yfug&ZM&1&Q;`9Dlhc*#U)oAK@I^KA8%gF($}Dwg z6No1uynM%%2Lms){U*5++V!mFmUPe+M6h}J;5V0wv+r+fHJ%&6xKg`JTF!}3bxU}oy zci-kU-u9`DH0@L=v&7;R&6@quN(T;gr^znbD%-p>^V64WknDH3;M&0XFv~@b)MHPn za#RnV=tqOmH{C+9S10-*t%^Jxz0+Oczk=DkLag}3d?RB#-+ziIVLqP|1{e2Y>k~=* z_k9Zg-7YTl{_?9@AU&@D9)hLdb(~43$(iqe(ab@-W{)x}x<7T1=B& z6@JHV-cOkzUA8wt{#@AcmBH=dqPw%yA?^zZ1I)KiA#x@JGGV0s&V7ro{~Zh|kMu4&SH`{NmErqa@~q0>$)ZXI!~qL2BWh5)HZk1> zthr4*KWq!IYCQV(19MwK|ITrLpcKoDWyxF?C#${1X#sWh_n z6Y>7!9cwdj4-USB_9v*#HEGtdKK<;u`Mawa=Er}{lTh>lfb zyXAA0%zt0@K-;o9`<i?0pvt!Nz|mGj|2I6HMuWm}_5q z6A+#EV1E48L;;exUtS+mi1WetIN7Q-{m zCg>%^3iAIxys89T(p6gHnOwaOK!vEv0Zr5BRd{@x~eCUz6hety(ihdsxoi(>wi zgEQ;33h(rA`J9KI| z-|FZom9@-B&Ep|3ezcMnOP9lvxPRI*-pPnn6^ zOoAVIXU!bc@E~_>!IF?agQz(*p+M_* zA;f54zOyYhXQ`wFgg?F82*eO|G(5SPHUkQQ(22I=OzEd&~Aw%EalIX)LHp)dRY`&B>Cj`Kz(V8Hc-R6j3?WphgWJv05wrgW&L49zY} zT^BIvphHacqCg@tK6nN+m6yk=B;z+8%_uaoE(Ron& zlKzgg^trGhX}>Y8)1K;1K#%d<~&?xNDS^i+ZFjLk$Uo^uhaP ztf>y(&+=`3 zvL&pE@RSnAc%|>!Jt^F}r6y~s&n*8tBMQ>n_c>?Y^Ej+*Z$-f9owVmAOXXKP9x88n zSQ|PS??kyI?knt5K|aSGvTz5vcmZ(KJz)L}oUnmo3&o}uVI2i$?}V;&c6eXno}AP8 z;OWY5LO%70{#o_fp)qI`TJV;i7gG1U0GFDp?&%emS`A5PsC&9CQ*@ohoh0EBkhxF2ue;p=brt1G2%uFbrAEtm?*Cdg zm3j?Q_jx!;%8VcxKGH?HabFLI30ygo1GdMXT`|I`X1~Xb^4TLGFhSnu9=}NLf}I|G z%X+&ZaBCruTQ4DfF94(qmD&DPqXSW- z9JpV;gO5IVKX5}U7iq6Ea1uZoeNmJIIy10hWded9MjmEDIa+UkOrV4V2!e9uJL2;U z*X1b2RhmE}y!)ixtBv`ZN~A~i2X5#QbP-iA6D{pJUNsnyKud-xED9>HaXTZ;e?3{= z`Nr+~&EPv%8b5k_f&4GW%GJs<$?dt2I}djoY<)a=uCv#1Qa}X53U%B&0a|QvoHfhb zC*5`tgv|V2qCTh_{bsjB6j7|l;x+nDg%L3+0ZA#D_PteNdP?5%l+gYPLVMB1G>G** zVO5R(aoUPE-8V3{&s1HR+AoQ(GK{C8XD682hP`HL!};?Fj~e7Rdn<$Bl$2p3D09D>cs8-J$lG-V_xOJDjA zw#n8Yw%lWQ0942x01INJVWi?92hPXy zkZwuI_>mFlpuOmVPws*7A3A#F9^e#FutcZY7A$KUz6M|xo!~*9A6Q$=R8E!=SR*(6 zEw75XBAF63M!inB;5gA1>_g_ynBH$D0QELXEwqynYNu}u_#Z5@4$*}Rux1E20IZp? zCqkyRy|Dyhf!#Vc=)I=V5xE8)YnXY0Mq?dSCWFk^?)uRnffI3e^xc(R*cTkP+Q z{)k1zhKo)SgdW?8Fp45iJ?k3qlVzj(uAQCP8{;nqM2W^9&nj4Syk$bQuW#Av`fXtJ zzxI*%mgkD3`1b8(UU{y6nMj5s$*jY6uesOHUM<_5EjI`oFzW%-JY=n0ge0?*GX}4K z*$A`ZHAfVm_BP$RB6QNMFn|{e-hA^wmDT00wGUgr)&8~0qFw2ko z;JmeAW=&n`!!D26yGxH+9_*-mntX4pS%^a4-m0VFsAIV-dDNefKs0bL#- zczc+jF-&W{n0eZ_?I&4UHdxBq^bga!h}N2G!(GlHa>O-UTiZr2IclvXgr5^mcC_aT z>~#*GN)|5gn(;yl?HCe*RzNlgqQs-ZjDZvAh$p@& zISfRNU0>D3x+>kv9GgCImd%Z9=}M5>I5%wnu~PYG+vH_UQ_EeO%E4kMeq(qZywC$1 zY+KJ5Qj<{MbTj!uZbDcS@3o5A66d-us?kQFpA8$2I6Ths{eu z%~HFrcRlwii~h!F#>xDeG<)T+U;sH?^14oWFRtj?W%{SMBx8*6ZoAAerV`iihPO@@ zCVlB3Ox-0N{anBwh6{HTW_$`%G$j9qE}RZmhDK`rp7!_5Y$b>LN2Rn}+G$<-<^7n> zoxVN?c9&!;>Yl|^uC)b$QrVMd@vRrjJj|bpkiC)8{G@43ebD}4z+2y0X!(ELMXMIs*_$wPm#BxtT}!W64VZ`jHy9T8pO{;Gt75Ig&cqRoxegZZq2I7jtn&GO+4hLkrfm6y!G^&%tcJ(~d|tX~;3_QF75xHuaVc2mNlys! zBiaIzmlv8J7kt!P*bU9$E+0q`J0}?F;<`s7g-}t@``R5B=o622DBaqrky9E~WNmEx zgBOaA6ITCl^IWLy88Ke~8phQCx_x0!fo?ogaz_1QwxQ6jP644+f|R(`UbE6omjd^} zFAavz&wW+5z!c`=Mh(=OEIV189V2R-)fn*3I-py4S+qglcN-iDFJK_h&XcAe^pXwZW z{|NZ=8lBNp^?vKwa*sQ2A%+6I(#}$aOZSWs>cQlscpvO2s;_icC@M>u7A9YG%5N@k zIv@*Z33X^_$llfxuGk+p$-m3SIJ3UG)IVKSY8<|$v$*bgv0`y^L`+l42jTJ zS5VpY%*SD_mwaTCN3x?~iejWqhF|emx#~jY)6K!YP0_8-FP4r8_$~@`R1>tX6fH|u z7Hg(_HC!qLl4|Oluan1T8cObUwY}Do7*tdGz$y1?V^o=;|A?_gCAIrY<%>UGl-b_$ zJa~Diq9yz4exp`{RIl{)2F3C{GhECi>rx+AN4#c}?lEp%ta5$4?eqMTHQ|OxfrOgV zyv6eH^vzu*6Rb`K!O!EVg22w#s$;@B-#fXbwah7L$)Rf1*-Zb2B&WvOna}Ed;*EYE z=3L#-k#;gD{sHoenWu7UsHzI+$gBwG6Ci1x9(ZpYkB`W{n)1|rYW7;ic z;?E0oI@jT3Es*#+CTy-25~R^uokVo%!)iWVJ~Ss+yhk%}vPQYuGR9e~$yGP!&A`*n z1G(d@QC0(bSVZ)J%+)Ng(#W_APW>G(@r~@@mIixkd<|(OuV&+#l|WL^m{(n zIzeT$Pppza7jq6o!1xd7sUKAm==Oobe&ekP#2@u#YO(E?Ahw0ymA?b!`K@4SoIpJQ z{#|ua=P^IB;d`hoONEmqLUhYumSsM>Qt~SxQ2O!#v_ICoNH!JpI%r2?t9p=-Xr~`B zzAks7;8y^F4r^iIo>@c7!S=f`O`SB=*5wR9wejV?fJ-} zmky`Z)%D2YYjwLlvgkvgulhSOR(H=w7GA8qIkM;tsa@}+OKeD<#wt*tV z(?l_T2zt*j{@72pNvD;>ereY6r0(*VJw4AKHE_-PUqTf7kN8bb%iOJW%ok-f2jy+t z>XbRNX2a5}9ESpqM zUVmg*AM;d{k?vdcN{#tqlbca-?V-&LfBaE&YtvVi?wZ&B_0PxFRJQCdOx1oozC$7pbnIWcMGpD`o`Xp3?n}B(rQ=qW`=dBAHoUz2)}t zr`yKfo~EZLiS)KiQf)e)UY{p3|HLH89=ot5*(1HL$9r&1_#_d43BPNq@S%FDd$C6E z*ewx?6>rp+Hg1|%-<5i2tm)W;rDrB3hUPaIDvdoK&+EHo?!?a>0?wBTgWtZLIWzBr z?{DSax=>;k?Y%!>^03_YK41ApTrGH5;hU;FZ?AmcqG)|*Tx5J#*RIwTq5u5=!vL>- z(|)VV*WS_L&A7+A9lb)PeR*t^EHY%;wqsVm1GQ~#U%~9YKb#YekxX&14BGEiTx@2R zmwLoeSrGYykF-5#b>FEZi$jNd2LSa3bq*iG2-wr%bBDZbDVGOsyqsf#7^oN>8!vNB zH>}lW*v}6)Q`jFWQ5gFJyaZq_gqMKD56g*zw-F=$2xotSux#M7fQ;X3>gT(0vW{!q0<=z*aJQXlcRINT-+p8;@)xJmFK0#jI2O3<|chGJ+9-unJvK-1{JfiWVJ za>bLke~LNTxM^$Vsd>R2SF61mZbv%(m0IcRbuLVlacZ(t#?xVnrhL`i-^0uP<1)hIai**!&;@a+ic7If$+Y0nzF<5ZMd?zg< z8V(ptOlmrSQ~EGLW3a??P1dZAsCT!A=nQ+sAz4~5jq&oazU8UsHYy*yJ2rGou&?j4 z_J+5gQqbfAabA3}Bv0|qjFXZ>1!E;MP0VM%mgnD5U6oym0L8}Vt6O3qvW>V*H96*A z7eDr`2T1E*+GdJo&xTMj#faW%)u>ilgk|OK-ubd3d@wOF~c#-S3`?Gy|&yB)LEORF&o+~_*}yXPwZSLRQ1nlebT59^sWRQ}bl zL-A>Bl<~B-YU~Qk5VP^tiNRv8K6fXF7dF*p9#o!bioIi)v##XHE=O6DxM*&S@7G>| z3qim#>aD3#$9-^HNZ7TxS7chCJ`hBHJ4u@Uef=T<#5VnsAp8}L1WW|np&`$+)x3wG zJ4<4Yfn>6Mtd^iOZqa01-l2tvj*3H=*K)X{%Dk7$y50?cRQ&AeMgOOFm2L?i#ZK~{ z5|?H^+j!|b&uH)DD?iBw;_?;}Ax+t6QWYZm4h1_$C$|U9OWAe>yirp}&l1Kwn}2`F zFV+dIAK^@r8Y}_;KKY>EFt+~Wj|EM4Q2?O7nUlY?8ozZFTa9~lem&}!K!Zx6Lv1O=`(4i-EbJRhDa zd~mk=+e>2Q7|0b6{HIZHx||Qi!o3U(IgOp-?xLyCMA2RsK{V39*`+0N6Oiv}ogp*N zeuDB+3wF{_G}vi_a6!`L%tx1t&BuoIGc*5G@jUIwI{We~s+KVQJMUgw8rJ_tftn-Q zO;3!Z9roWl?T9mi&kS7h)%~|%Les;3cTibuhV2zfvmv1||mUCk7@!QY7e;vR)SPGoH|!tGAryVN04+ zLgHA$uFD5jnLM`Q8wqG@p>avX8>q3_wFsuSM_xBhNx#d-p{3}uytGJS1G7G$!#JcFWIsxFq@66{M=BH1E&PUg!P(!OamBRtjI4n`6w~PT{UUePmJ? zf{uY)O~HBCN`l$&4-E$x7?S1I$Al=r&vAftp8~;Z^(ni4Wo;8B^-$9MB|c8eUE!i12#@;D3&*x@CTHD3aa{T_%efmN{2 z#5MO7Xy6Uanwc$^1Vl9hz1S*qZ7YA56%it+UzSP$I%7o!@tV)U-i_HZHW1=hef9xd zopYgRV9}c|avdTfuURM}hNQmr&n`i1BV5avMG9yxg0~*)1?tRE=p*y*eQ!f~ zE|76uOL51GBjB}@>9q7#Wky|pwlI0 zPo@X`_Ovy3u9#969ItE&UZ*JE<6`aC8GBFZqC5jT%e*kRzQd=b6;hX-%pSDHmp+NF z33_VjRPD9OOy(4G$K5oh$wL_42%{(SNA&2aez&5=*rldup^LC~+L#Tu+8v)sTt~VI z|6SgCOSdJKP7dk#%A~EV_1KS@w!UvaXeq_S@7-|QJ?Q4fi89x&K1XMlK1uoV6xY_XXe=ItI%_qlzX*Aw>t*M z7cFnQ0Hge{T;+qNlwI=M##N=;(oJ{N)aC{ocPxyrDVd_Ea%gz6H8m>H*u@@vwn&&T zVf4q6b@rBL%aY$WthSmL22Jbr#;!+mFNX~D8toim+3I|L^IIhE4%ICvZE*1<%@5e+ zi)9Z`Xyj(_j@}{g1%SI7+t&dkSiFyz^GD)d>D^~;Oo?gK*v-ece?OpjM{Avl!}4`= zV_Mon4J7nXp%>byyWsP{nu9`GRE;8{O|@ftk*dQ%0wA5tuc$0xwAaM@1fu3-`=0Rr z9=K=Iniqpl6MQprPJ0&*7oCO7h|cJFq9NW=xGiAR?^-PDr=YR8w<8bx65{Q{zNn3w z$oXYHM%}{z!Gd7|^{ttE&Jb4@Q#ssHhDG<&%JgIl#_3N$wNL1h4DJZFSZo#Y9?$Kc zdq`;>JonI^C!SJ)&E_I7L`v4$`{5Q0DH&8%Ri{3-?Uas9Deioo(Irmbd3aFi%~#AURr8B)|h$fTQWn%X>dVe+16v+)EGQn#2SuuvS5!0tlJl$SX9j zh?*TA6BXDDIpkFc62}gGY&|;nXJ;O=P*00QJ`*mv;UMynQ8sX=!7riHgqAAFBpVy| z7rL;qA;5^u#>NgrOg1(skbv(T?l9zEVq-5}1!fQaMWv}(%F=DkKtLMNl3Tnz+1$@@ zq-AJ(R+@dZ^?r}^J#CH70blIgQ$pkWmF_hqM%PP>==dVDC++sDub1i4pKeS1MrH4CUr5q6U0-67Q zi3#L=bMyh^t-zMJD`~@z$coNi+wekZn}5G)xXJ=DUK3HqYdy|*ePk=Bpz9lVu~9S! zqC7!Z%0Ua!5CBaeFakCa22Ez^f!7Hf0-9uVYU|Ov;e^$G=1HU$R~iiud|4Eoyat&N z{o*G0h66ir<_E+r2VZEskD&|Aok2Rm4t#1;Ljvp}VF$=t?hba){B^#g(HTwHL6>HX zt7M{Jay9h@eNB)dp)@^^Aw86oe2`xa09V;N3BZm)MQZtXFj;x$?I=hA+q$>Xel~G33?=p~PjdbWc^@6&4WFGtKTai8vI6|Muwey!F zIC~rkjevcRnv4FN7^Cimd1`?=9b;sdwuTd9#My}q5JFSp12IN!WsXrx4pDWf=b_jt zx~In{7FG%Ui**T9LQt3fJ(W69kGX=!TBA77o-?)$ zZHBhWKyqoCfIyD9T@)lh>SO~(v{doL(a#=aG1RLJa7bhIV4M}ivDFj0Lc_dQy4TpZ zs>*JmOwyb23@bVqjnE#`?Dh=45jb!eo7$Qn8U#5wB5Dkp*l13TV6NJo!0RLuRj#U{ajhG&e=uW_znw|A@Tyrglh z$><8$IpVC(3D1N!&+sknw($j32ed}dzEAZ(B6U#W56f~?SNa(gs`z{1@t(119);~QEWPUtVB{e@P zeBK)C=wDutnw>qMT-i7=4c~MToLWKzh0KV4@7#S^gm@68hL8c&ACS2N>o}(~#7k_d}yw4FK8}BWX zK^O!2(Y}M<#WM4c32w63)54Z9ck0CU|LHtdZeeV>)wAPbnPFGL+(|VjhuxmTrkAT+ zR=Ggl@v}37{Ifh9>TOChPM1~3^tY5MokCaYg za)`w9t%szTMS1o)S2Q&A;D7fNB(6W&TJBj>2%;gsLgSX5b6(4fs1H9mR+Vuj(r%K1 z9Dnb+QKR*^V60<&eWN1CNSLa6oFaGh&s7%Q)j_4vBHq}bZh&_{thSitl^^c+gU;`d z9~g9hpCY}F4N{Qmci$x6nR z&@L=XLdOKm0fG9YlNS({CE4~l!MK|+y=GbamIc^hY!?5hsNfo5Q>z1~@7DLAN+F=G zemA1~-GG1fl$cTEwV=ohkdS`QcJ+G_&rFM(0v?1=ZyCo37^j*zxTt(|u8MbVf&WM@ zU0_f1LKXYuI%Q<28!!^R{dY$-T*Qa22yldJ^|<5RYUH-yO7L#VEKpmVmvO!P;eMpI=5@T521D?|cSjS=Z?pc^bg- zF|4^|jDm_p*Ar7$op5U`iOs1EXB_0^^3n$`4O`Po{qIEizb1Sx39t+(zHJ*2FxT(g zmrk+vMRPf!V6&O#jG*Tf5|cI>im#Uyoyox=>6}K*xLK{(V(pGbJnAiF4UUA!$Zb zsV0?yr$<+kYEIW|@R0909RcqR=h?e`=Sp+)n;SNjg+7-D96q@1__X1do|Qg%FnS=; zDZt^ELA3(i^=FLjX6NO2bem(=%9v?w*&@B?1c_5;dJv&Kc#EDE>&xV}&Y>Di+`~nJ zU4k2NeHoBD_tH&XgkS`5L>MM@E&0<(jm&h@C(_TJ8kNw%ypEfg9+hCXG{&fexQ1!j zfOOfpt{x-M-wBp4O0d-EjG4bY5^kc>3CXnm;WlT@_isBxBV4_$`V z2R9JC(fZ(lB2lt1`KpI2J$=uI)r_@1Sc3bG)+b4?CB|2Pfg=4R`KV%yf0y|Jg!-<} z7i0sWtJa5ZN$CaxA}X{u8}wo%hI0c?Z^j4HqGhrLy`LmnM~!}t<|WsxdZG0}5Ay%y ziF{Rnu~`3i%M*1d{Nv6I-OYQ@b^FJh)4I*1*$bR?JhA^LdRH@=IkN6-=j-fYTm0)f zZSkVc+4YC7f!gM$A-fet_W6Y|`}4(jUBE;~mI(jH?{@?24A&Kb*rvHTL1T_=e4cA| zQ(+u?OiSfLcjm$3zFNMSX<>xZ!y^gus2?_aN1&X@^~Xxg!ylG4Z%v=m>E>foh;t%4 zCz(Yjl?+Rj1^sfsUsZ56AACh0EHvmmP?}N}d%#_xX4R}3Bz2tmO6;Ak*y2f`VNw(v z9veC6;kew6BUSGx3d&}vYKM#SvMpzIjqFk^H9XK{ZQ1qH@>zcMF(vO_YYMpKl-XKh z+}8X?YfGB#vA_4nHMQ<3%gf#eX?Z=0v~y0|IrU4?&{{VPzQm#3oQnQYF&G*!mod>> z^cms20NodPN8(%CiQ(pL~)Rev{C^lP2n9spVy*%&xz?UiL+{cohP0`a~dnizT;V{zfFqHyvp6Kz61kYOk#Fx{XE5Fy@~t zc*#dFRnEE5(qD?4UfhOZ3IFthBd*Z}b#yhyH2$2((L2OMSR0Jzsc1c|2qXEKpaXN0 z_+4{N4U09!M$q8qtL+ThGg2lsKlSL>TNNvdEvn_2GkSRX zgofGeL}}kQVZG!E_A-b3%z0)v6lNv`fidK7{o9p`k@H}_EJ#M(tlC$89~kZP&S|i} z+i@$0CSHDYPN$nav277|4!oMSi8I{9%@f+*E%?SITa}%y=XgeH0cN7l-?%;3S!N>n zut;iAE6kU9=g9(|-aNL-F{ZItb}7>L>j8Z%k%lT*?=zHb5kuxY3Ez@+O@HIL#e|_b z533vgxLoR{_#TYa-mX)tZ5p4iVd%96{Q8er%a1l2#8}T3LW)G&!qhMR%mJGKfv}w)q#Ho zt2sU={MBG^cmZOPMy*Af(eZ+j($(89f5sr!@NP1?s&J(?gRF3c>fP{?;-QiIZ7U_U zAxSm7b%_NIQ|%xWt0kCJqaI$CI&MarrW;pOx+;*^r5p;&YI|pFnV@!9#Hx)~+@L%) zj*?u;k`c4Fj5xMx>)(>vpnU?60kKcq#i;l}yw7vZxgM6IJsf=Lw_xBtWW=e95BZb9 z;0fetOn)`58XkQw{{Yz%Fc$RN^4_z-P@^dUa!&(ily}4-5|R&a61x)eK0i>{^P15x zE8(B&a=_S6_`(bOy6Wu3U(i#6fx5xi=0{W(ag3f19BxboAGPioXASkE z)45upTRSC&T&7;&0EjoMFGIxQ#GDd|LsPRWh?2g@g5X(gpb&k&&|4c`ViSG|416Hb zTe*p_};pf1$H*4n)nax)uOC(>zZ<{nmH;Lbya;PX9CT^|XP>)G}9ZqxJ-tZ(~cRNy9K)PRmUO*Nntz{e2Mz~qPU>0|YB=*;x{ zQ+@#^{@uBKvKtny3>t!l)e{F)Uv`g0abrAYk^_nqpbhnG1?a)B{=D&WgKftsD@qyTsAmgou1`x1-c2}U(#lk1#nCN=8f;Z{+xuin4ytBQi1 z5e3oaaprqMfh=wnkiIVdNm_oYa8C|Q&|AFe33|l^$P!|XXM*m)c*X{aeo#W?pr3Ub zMW7o?Kk-#ZSmcKlPl8)FM467bkXq@UYCpYYpytd)a(8Fv^&X}!J5Q>e+44q8oL=bC zzq_GUW&~e=S4+dhLb+Z>ELTp~_k@!pEo)8+dZ^c;gmzjYL;F#tsx{qA;X zg4;22r~q>e4*K2g(1fCEfL$h@V{odTwxJ2eKk$f$@H<1#g4?;W$eLX65r10jQUWYC z&8bU2nLjVEO(E{qeIB>)y(eCg+DxqI_vE$9Bmu^092kyzOWQuzwZ0=hvv>sicqG-*F+|@5<>r2$mM~q|J+!n`XG@-v%#nG?r~T zvM?6Uv$eDU=i3LB=6keV2=i7sJRKGqlvTH4M2SU2*1*$k(W&0DmXuy{X+Jag7=C7K z${_oXok5B3M~eJKPi95P8z5u}o0|_TTz2l(`*ZeOG2XYi?-`wR=BSGY`3*%`ww1g- za1BtFzY!LRLYLl&ygqZUI|5C-t>eJzVEclOP&dIfHMGXs%=Du{%a|qFgeRN;X~bZN zi=t0@I_sf?QiYL{f?%A1<}%GZ9inKz)fteIT%%G(%i#V4FlW8p_bCR?h?_!;^e3Zd zbw)*}>EB?`Z+7#XoNuH)9XN3nWY+i>jgjcj5#{*;ogNu&(qFvl~AWv-JrM1vYux*qZ>>yPBDdTZZ0AY#OG%0bPi9l)fVcv^I&=urVCl+Kgv7 z{AJ=7AZ{E(;nOyW0aO5rBk8!Iz5{co1sV+)M2q+YUR_izTnvvIoHw+=Z<_ZZ^}gVN z-!L42G&YZUoj1s{&TAcKs7;lG=%_}Ez@oI_YruKKE|xb?m3j$oQJ`OfaKC|q%W%KZ z?k14KbrXota1%(`mP7gAEHJr=?-6jt&)ZEq8qF8O5%@UN;!UdwFCU&Tv`#*4!2Vxm z3(tdb_`P($-Tv>NERxVhO8b3=-T6n#0i*f`UnqRDgeT1}G%YDA4`G=reY8!uy(~GB z9!kJAohJBU8VdTxZUP@hfQE)aO@RfVH~&UoP*6QqeSUh?QLVk5pzB@C}}_Yex`ST3@z@u=${DD7C#ih9;z^r zdfX_$d<@x{F$yKm`XL$4DHnXfQw+r*B$944RQNaP^#)qd?gSD%+hXl6qMrq;&u`1? zkCI?0xj~QQMo60Y+C}dWs2}$0>AA^>LwqDB@%V&Qwl0VTDQ&7i9P%#>xcE5GS9Ie% z+E>=fqCszf@bTRVbln1coON&3MAy{UV{HhI_gOSiG(p|`vD!55 zg^+#GC7VBV(Ql8Ayc_=L$lN!=3{@~&2dVC{??{)v7+rA1wU}}Vm zE7hTC0wp@7oCCS`c_60g8+dwvK>cGgI&C5YlE~&+3!(M8qIH^U7eqM(_)DU7e12`b zKoixPFxo`8%HIVQl%M~@@+UqMvJx}CR@KiNavqdg^Iq1z2N}&9YBC8eD13QR3rehP z7&Yo51Z5iGz{Vw1=)DX5)&T^7TMqU}wVPK3WBLJaZa2W;8R?g;Hj73%K&3!rYL;*f zwiM`PNMBE>=>wU#Dzy%fHXtSU(q93+aT&5ZWccbJ=n$*{&Wj9#Zp;%!h3A#Hm7SA@ zOi+|%iVP*B1!Csco5obxqhx_o{)JEDll5e7Z%R-HjoSxCMZ?O_L|157#s{7lsb>L? z0<`jxj_c91XO+RHia`@3XA6yjgq~ZarqU_avqSrLRsL3Y=8OD}I*@^Q8<&TT&8bpA zN)MGE^I!|Sn6koqbD!3dQOf2CffJ=sAu!AltvXk+_`TG%8K-K)GhdUa>gJ?AtO%;C zGp`xutWaeW9PoK&X03H#>D%?RUUlSYkSev)%fu?Sc!y(ksl5K1wDzRY^)$j5U(VL( zR9}t}JFK?vKUZ*(;g~8MCp%~yHAVp{?7RU2$LN)Y!6qZmtpQWk&JD72;PMtG9cLli z8aB+>?)*n`=tUY*n+MN7KTYr}a#55HIwcOC5coMLSO-gp%&2lki$n@~A_@VR?-S`* zvB3cB;vA28J0|>WT>blZisFM+6I9i?!cU+BAP6Prn&E2GH?Z>QlZNwC=9FYd_;~*< zQOyp`Ev>T{ekQrAYL{((iHWX-IQ zH8BPS!V`9+Kak|xHOO!f9w#D#Fnd#IPA=yR86jO=VFTcTpM7PCSk)G~I{vK+AZl!i zXy3CYVcesDWa~l`rU@x*%(g_M$0dj-4c#Ue4T94jt;^0jqhDc2y;}dJ9;CR`wRgL= zYcCN?Bzo$ zc+Kj_HiW^5_(DD0MU8EQ-cb1At3`Svt(|Z^Z_PnI8Kw`_s{H;d2~plnh4>weO}wBh z!L<@GXxG^zT6Tk?hBMUnBxDyt4)OrHAfzC=+>-{iSR>Sk;}-&7>w)@fvG@wq3{kU% zCx!BmLP)toN1(c=BiWbHrx0+4A;vr*vjqOhI4Bu?I*Y4>J=0Zo4jR!R{=M4Suj@`je4X49L~gWGFw5t4*Q~k^dqq{c_S@ZR1v(pWaG>u@QF`Bw&=%pI z7nl6b4)hM~`}(lBC+EF0KEAKoHR$xu#v{|C#ktY50unssj6Mmq&6^7^OWJ?J&lJ% zCX7abC%-0`NMf(NfGqqGj=u}YC7Spt)nMXIi7BlizpB2N7hnEN*xRpt5+v2uyo zpYach8^)f@d)Sp=_p=Szywp7L*`A(jkR$*0M~Ow|g3^3>flm=8;2wTT5O7ff!R~rP ziS@2A_rEQY_`NlCix>q0{8P{SU9$}JcEfGyg|4>cq7TbN-}|J)aPX8kZ|vQ+-)icY z!FGF5)BFD*KQ+DifAtMSz%9Sjy*D+96SKj*KoQ`6k2Pta)nYnjgKn-nPDaEx6A_ytAk_0OnE*zTx18g4gp46-C?!!5ND zCbew}ip>hwGW`2HNCv=@st8;Uq$gxAF!O{sk03qqIIMG9G>R$$j{}pQzTtz*cz5Yw zF;o<2CI1IVPpe*0LlVOJD1T+8yVCcuRJ`ZfK6ksB_k{@u6O1-S;cd*zKxF`ZWUp}; zpUQwht22dbJ!Y5GjmX<`C8TqwbX!ODs(b1@A#tLi`L|=d%J`(b zfR3+Rn;M26R(&0yT)F>Yr|d}PhT%iYJ8B#sV0)QWiq3#Vsc?(vQBpEkd<5miY4Z*S zz7xYiNLe8V^m89~ZX*NT42HBGL~Sq4|E>DsX^5e3F?Oz)ar@9+ux>1zhPP+t*(xS22l zkaw=^PY@qI643?L7ui;}BXf-GadJ=anei*bT&q;C9h!m8!U)E+fMLi27a!&4UbR)u zMUpCPvkU5+P(4C_(s0)(QWWuyW$EN`1Es{ z2qC^|str}EPYze+4;S@Ns;I_~@srYM#E;Ae-PA7v1<-)%p&+WylxWh_7NW(N;2XnP z_!@Q=-g9M;eBeauSt11CA$|qmM6|Ss4b_nX1T-9qk#6Ho5drNRCRjH{uuLln58c@A zIeCGDm)XTvwch=gA(3TwE^0mZSv(#Ryv2iPv#_i&gyu&Q7aGPAqi)rC%9AIz4{~mZ z_kX;Rp!`Kmxm0RC)4a|Rx!B~@$clm~h3~IvK=1;ivR!a(!IG5%30Ah@Z$?T!D6khC z*kEdtSySiWwK}7hR6wxRWDWPH3$-%Fz$8sSaI5}XOHu4{%AnIenHffj5#yZPYj&7J zpuyVu&e-*NG4J>bn=$%XUO6+|Yfu-EH>!h_`E2L``Ycb$ml=?{rOojib)R}eM}}I% zU@<3KBw(iC@Bz_yz&Bn7{Cs|%2|2<3lnmrxPOusEoHuTX!h7+)f!sj9q|Ax;2BLvv zlnppDvs|U9PD^_s!kZXdM}7hak(^;^9N>5DZg=-BBzSxW1dngKA;DvW^l-O=M+-|w z&-`&9cKo|mxxJ~P4yCF4q@3!Y2Wp?2>HmX4^}4jE(Ihksl&XWrrHASno-5l>%ddiI;X}zDjHcHms$X^2b)8J{76?S1`9<dc1Wv?71^2o~o(P2`jT8w1fdS=Q=2K?0`@ zFY?!8Xc=>hkTgOL@(1uOkB=+kL(s>BHslXp;(E8=L*pfShy0z;K>kSSJrnsm@oyr3 z)8Fj-50JkFWg_h)U)X1_CyRNcj@L#7f|OJi*!S|r>Z>Nd7rQ%IT!@-UMDmGU4yh3^DxeI>c-py?1v$9c9DRCAK5{C z6Kp7HB(AA1kV|d_)b7!q5Rc55{-Tfa;@l|;L!`Mza6K;-!vw;!4doDRqWT0$Kf8nU;wge&&P9T=lEyR6pr9HFdRnOo67j$dcQy}y#TB!n=6U$@tkmCF~4!+sVnKHFd}l(ZvEWxaSK<}|tz zNWyhkwj8Pw^VcGCke|h^7hLYa+<3KOLTBwej&=^_wMvz0bxZjiTd(ieL#KtAaYW`J^Uer4 zCPer!wwHKET7~W;y$d@cqP8%9GX{0V{5DIPry{#cL33B=svqGZKmtTlbw2&^!Oc25 zh|~X&?D)L(-~rw3Xt4g55XJr@emi_uyDF@5k=?-_jl>Jxk;=B?rQj}*E~42(ksF#sCE?62|8fhF1l5jiXhkk{g&K7I|{H|78^$JU3P z_339%7;|lljsS1FDc0{xMzN#O|8lHcy{BlkG6GVU{@j(GvtOzg;o7u+r)7eP0{O8{UFMgS%#Gwi@?2nEC0GItwW3io!;V}9 zJzbOuqA8h;ekp#Pz4_~vL^e7&V@&1PYf>?gY$Q}2@3J1Y2gJJwNl!ov0pP~4cCg4; z6R7~<3Bb54Xj#1hi0@_bYC=xG`(GY&n_{zxAZ^gfDaOj*$MKKH7_oyh{Aj%+FTE?< zL|l9|e&TUb3mhukf1*|b%*UwB)aQ4tCJLt7rsh$z>n-hVIHAbU*xh8&1*_#_YR^Bo zHam8Go3IIV8~iB7GVyExL&03`4qxxCquw(^|pZ4v?*bxii18$ zt7C?i`gSx{=62n9+Mc*H-N)L`_nwEOHn+GiNq8tp2rt)rLhynJxc(yE1i`q(FyDy* z0{H*53nvjF7)B=?LNL)h@cXIICnvkWl7wKe{$k3Tds0uaS|1AI&jss3GG2kl6C3Fu zmv1%p{p0Ql5L_8deFl;5a2XSi2$yn45kxCUq14O7!+ZGfz-A7UHvTPlbF?cZNPM6? z)co=EWsz`uqL&V-%!KS2=rSOCMk*vvoAcvX;aoiR=tud*BId=EK>84j@!3lfSuDN= zUOv#RppJhAf~U-YnKru?rKQ_}VA&?tv`(Sb1xs`ANA$<^01KIG?&hB_A#q13r^NJM6VD{`y|>_sqZyMVqWb~B)zseKBSoK+GOlM=KjTCM6T_p zZ-E}&bD-bpzYi4F?P@+NZ6+u_(m#9n0B^<5`xf3jWpszXF{*GJ`V@RWQy{7!(>~vk zx3|3!m1OLc@pM>Tv}fw=lipbo*|mvxGfr*ZW1qFl{um9fzmQ@X6brbyC;Y+TI@66t1$LT?68 zKtbS3n#1sVtWgyTA&a1be7XVL=6v>f@whgfu$n+4v6@wi)1MJv3UrG^(t)<&J%vwD zb0g|nPhfleRx5DjH_mkP$^_XEzin$KkEjarf3+naF@rTE?MJOuqR9`b2z2*5k^mNm zX>$z#2~y#QZo-XP?!=-xh!_4@=gtbNx}yy|u?$i?gpOEg@#gN3dng{n{`B zy`fetkIV?}bR(s^92I_b&+qk@yFUwhFOXMI#Dwt*lO{EcyX50-D)lJ)yu82}7xJK_ zo$$ws{<*5mr5jYSM}!L*Wdz>ES`XXff1~w!quEpvJdA;-od>Sz;kt?I5-VAm!NsAO zL-dzmw0Pt_m(bhOEEV2%koN`19+75^Fog7U!DNhq=|3I-e;8;)$vknXi`Iq8|HjBP znPePk-;J7YO!CRVTk2<`dHR`E+BN?J_4@e=wTeU-)Un=pKal=eC9eiDyEXR7#knAo zqYB2aN^s6}8*AWYjTuh#g5%+;@O}ck2CxYbO<-ZIEjH@QB7dRu2yBXn4@RgENIx~x zy=sSUspdiPfN{QPsyQI*g*BE4Dl0 zg@s?oo`4rzPpM?SIA7r}&C!U*tbgl3JkO>B0?#%Da zaYPUzrg!PqkxU_cYLZ{l9Sp64Um;%*HlIXw#VGC}gK zsQC2t77)lv{Tkf!l|J$qOLDLnyic}mJ_h;e#nVLD-B$*5;phdysX|`PYmKv1lI~{m z46ZxG^~w4eX)g<{8XQu3feG@E1o@x=0=PC|3YoSiK{TZ#9|8t^K8~^`@#Z-($U_DC z(A(V(PSF5(V%MUVMQ7nj#0%g}33brRA~qf4Q}I3!b5nOYZF&^_-_f!dcSU|0*%&*X ze`qztRH(l7XlvutLq_t^;5D6=e%Hh^rtsZsOGVP57QZ+&=p;d!L5eA2N77& zfIi{jt=_&foMNNK9%|fe+1LHmibVyC%E!Vu*vmu>>A@E31*E6-AOgt?3F$%MWKW+a>SgY6f4QX>&{Y4Dtck#>2cDb9q49?5WN#9{=3^r3H?cklX0Ib zxaBcHjO6sYQ+rDuGqFU2dQ1bPJ@cSE=Z=k?@fUz(F48_sjX&Su?3Wth_J1Przm76- z(S!`a@x@l;EJ~B%1-K8rL5^uGN{r|+4Q8N=V~^g^1_4A5$|NtM*Uh?Fta-STh~7~) zqQ~_@#buSXEx64AgpnXbk1x57;=-Lg`OxwCw+SGn{AY4RHE>Bb2jIUy*S7L^Sy9@B zls3t;U)%&|yRWQx-EqK-HBl+2Pp?4J2tqDk~hFi5{I1F?#b*ehF+N*tte5VNHQCJ{v zl4L#Gy4=J%d!M`M({yjCW7phEpXb*I&HnQ`;-gdkgMf4r!#@ajA*j>!J06}kwcRpz z>lW+q*|T2Di~Leel`T$l+_T5${W(G9)un!O$5dW&^y&n!)fd9fe@GIhIbv_ns$sQ$ ze=EGt$^+GI@Nnp>lR+p1iey@^`2lsOgKtogJ0zCF>>^=ye@63eh-L$8|CIj#jw!K& zbaYJN*=vL>m|V5*cR!cz_Wni8r6Cq%xXJ>@f=uoVAYwrt+X~h*UO>?A86ZP)&GGlt3VU`M^&^{kE(x)qNNEid8RI8fxkWI>qbl=GB27BB<}sKuSNmpWB^?_XT&W<2qjZ0H=$V?+i)spm<7-6;% zX*}V%He`RB=%lK7U_`h{hr0(H*x6!yb2`KBLScSs0wg=vV*}r+S`;`6PR1hFw`6Y1 z2(AV4DFSKfdf6LqN*wnQWG-;ubA~*yifnLl0z@$`Lw}R1^LHDicX_eF*nmmiD%*hf zC661{r*~$Adj|y#%jl>ae%QPu)GW2@de?KWvgmJ&W}M8gNwZfD3kEo`z8;+17FTrb zGX3+L^!6erZc1F%dKpZY&`F}%R=~b#qpXI&v=a&!dt>dBzr{3zmzVV|aqxQi%gn}- zCzT)6Z5~^cdNuR-e&;<+dwnCW7Cfx*O;w(^SH3TP+@f-qOEb;Km|0zpxf4}mC@C3v zyQ4GVex%*3gvZr+gcrQ+a)V8qWwbjv=jNvg7Gr=c?$o?_V+x&JI$EdKTlgx>BkWUt z7JO50F)Z)vHAa(%+4W5xW@CbC`Y%nbyyaV_^o}*( zVKyRlp{@HILugl3)$GL`|^mV0WlK@`gd&oN#bd7MU>^V4CeS2Zpro++qo#xS}S#~g% z!m&+fayaQ~#JKsAf5bo>$2NV@iqPjQ@}HJRx313@)_qREzsj;|*D@t$wWtrVl$9iN$sCQtF0{hwac1Y9I=xFJ3$k~5n-*?5{Keq` zrXAI{8vdrTJTnacW9UC(Y*9(={!;nk&kYyLG9%O`c-bqmJRIt643lnmxaa$evUc7q zuv}~{tEsvuWuH%4Rb7=Wy#konUN}o)9V~q8B)#l=aV9A>!iGZ#~Cgz+$m;H-6jez0bThuzIzqdQj=Usj9HfUL^Uqkh`bHav#bz4Js>_TK09st zM8VnZ)O!jCo;DSs1S-lXnddCgEFAQarkz58KOn1cQ19tHkP&##d%wefWEBoPw86hD z4O%cRgq&BQ3J2rZ=ET}_k8Sz|;O>rh0R0_%W%@*pvvOa(#20JNI6JtXKwk!S{NwnJX|LTS;`-e{#}%v*u?KB}+!9m(wg zzDYl6Hj22yGZrhI2EpB4w$F`3G& zsl)uDiPdoKG51r}i(zdX_)-P?LFzKda)w4-!{b z`mjr}d$#?aJ#EdME2aRKQ`r=}PEo$c#oDhk_MXy3d1lhVa6<5t*zOzH9+c{B`WVbS%sbnsO1?Y~ zhC+}2`sM8{ja%Ela=HLWMZ#>?IjWh;5%6GFG2RS62v(XFtXspHTgDB4+9^cW6H{-^ zzC1qDP;#$i(`6ae4eFTe9uT?!GLsgWn};8BHCw&;(9SpcS!q$DQeN7;L~-tr31ckdE>hG}pF=5Oo%6{;n(yh-1K}CMASv7#Fs$WX&15 zzYc3fX3#4V&l!)$M`T}3dFnnkysC6bOjq@V=Qrl)4J}t*JVfXS(sUV`5PCxTx)=?9 z56Xg|oY7!1YraxK7XpC4ss>s>#>Wr3xsTi&E@~W%@+=Z8Z5GU1TM1|tNlr#;5BMr< zu#Ytgo(njpwrC1auCX|itfLQsst>xvDB|Jru^!|dYEh5Iq>oa0{9ELGVl=;))9CI) zqC5sJ!SX5oXPN5nj(w3#brNrX?jiLpP}tW?0$+H(TMbF;L)V}rv9h*7dsP)51a8b& z-JE!!h@fWl2R^mhfELK$c=n6peI}LTj8iQ60{_`}KbL?*g6-_^A50zQ{k{5BV^F9x zgiX~@gN1-n!30wSr9$FgufSC>L>u*%PU7E%D-C%vj_K72;$OMh$Gk~zynGs>3D~D0 z0;U^G4xi>vFfZnSN>s`Gi?v=DX9F3ZiY%x9SylZsx{DJf3k4i<5`QPPmDt z?LM|$;jmp1?z^M%tqO(F*f@Q{nDO!bUH7)M*zI`-VxLxO;ZPr05cZhgz1Y^PBr$DZhYF~3o@AY@VpToHC4)L{9NYbEg zo?xsnOz`Cx0b>a)JC=c!$=U!qg}<>Bw8$= zn2!tH09mCIz^eq1S0y+X*Z{>w)9DHKHfT1fRr|xy_w+QZq#75J=AfzlK^HbH^@#o^ z=o3XJ*Zh3Cq0bql4u#+3+TqxGPn&{@^h$#{0BRM zX`Pk5G5%selxRHQ(m1}<*B62pwtXEJ!st~}Hkwq0$nFt(R6~?=&{7ub+twslJp12_ zf7)>L#g)wEq8=Zx_3gV={qPQ&a5*AIHzZN!@dnvfIQwji!6nK9pjVDzN6^g-=$_=4(g~D9m)(9c za8+P7-^^x;U62XYkK&?Q^@IHwXw}cwavfjD;A3bQ(p-dp*~t(xH)<83-B#bdyTc{m zN0EX?Eg&lXdQq@v!LUlOU??#U_&}s8_1>A4JvO&Apm1zXTx*-Q89j62BT{@2(-n32 zzdcOp?F{0X)l5g&g$zZS;3kXxf7tuZuqdys?EzaX$Vq&$D<(!su%ITOB7!+N#*y9@V8e!BFdlQf{e$Ff%>`+bq0@AXV;`wwxq2but8P4N4~W*``d4d z(DatOt2~lJd40-B$FBp&t-)Rm*1O@JTK(iw7I@l>Yhe%=+cpV!;S4FF%Kr0d= zykg6S(5Ip5E6k9w~3 zf<;x4KtCJ)AyC|-=noER02@+*rGcU27!Zz8E{-ae9Q$|K_e|OgU{{O5_B&L*5q3Bm zEdqi+bZszdfC2~yF$FdZ>%s3&A$mcI@LBMIcR(Lp3k~h8zWqJVTKj%*b4QhxumV7lZZiehI(R+R`0kut z*pBE!nm|YIYy4M1=a-RtREs}VXzD<-Lli^}3fK!}ypzr@&K^AnoPFZ#M%mj3X~E(} zwmuBShW-gxNnqp$?LX=zZot{orp}`zUq-?dL&$__{>7v`Kq(KNn>Z2Ke^|jWdw3Is z8AZ@gMgZ6j&H!^F|Ki_3Uc5hYPCILQ*vnDI9UHnb%d8Se{0CW?U@1b}lI0!$O%VbmYFPEI7jI~0xT7UeKEUbKMzPf z{s0Rgxfw5P{2ies8kRU*2V)W*rof)13EilwCCk}|<^<+5+;Wya0sx}1l@Ca}SfVPl_yiHP<=1xFJR$%}U#X$|%5;d>{`W71v=`!VZafLxw>NS?Ftr>BKC&F9@7 z`@T=`x{YuDI<8y$SBuB5{di)r=;Ho{e_inEPMMW?rcT54B*^?O>mUR*fvxUg`a)hs6ipZp|bgG`xDhG!%mWyy_p zRkP;G>+pUXx8_Gn?_PGb2E`Ec7Dmo#9EL3e=8{H#snmKk3 zlm%n2X)SQyM;ZvRXu+WE*5bITlr@rPIl`T&&y%Wi%~muT(k^kw*E)*$rG(86J@f`7 zm|@FRk3Un_u|`RsM8*!|1cFKgDpG!HkE~EGY9eK_AC(Tgf;K z+`nQSsg3W7xN4hJT9wYn9qI6eb#S-1PS@QiM1=&FfK7b+i@J)Z;)#UGQ zYG3g4S67U8{w*l4Js<4R)pVsjR&+YRGOSy_No-y!diqY>@iAtrEDb_tZ!`THT3fG8 zI4fARc@~(~g(;iXRhZ~%IZl}8p zLc2|o-9x}L(Rj^Y6Zt!^;|})7A(muZc0qft&3aTa@0T^+09?b4!M;*OJ6^fZp~PbiKDmy4Z| z4;(lLEe>@?_vh#=Fv>Z)7?-BfDcA1ph#!pI;f;Nu`)r$FBat%CaIqD=y;^AB%S3aS_&B?K~~ zJN(bn#RtD`%W{>v)qK$Pk;^@kgr4pTVr!Sqph)esioQh~x|Y<6J8DhqBmt#++fvq~ zAM?U$DT*$H)%fsXlWQ!sAb}qFkFK|_y-5g;j8K{nUUU|A)`@VUnONoB$bxW5z+Hme zUsNOYeyT`@be>t5eNU2U;bNZy0|nE^3k!+W2a zrbI}LMC(ngw77Q$oXBwC)mjz>+8N@6Y*;}Y=En)9(tm*YaXe;zoSA}|9|uS~4BJ{~ zXAIPv-7oeA#Zmv-;`X9})_pzu3i>Q9?zYQkirouLXV&sTapciF#WK_2l2cdt*YU3P zf9cOKGP9BHpY(c6wZ(VcmMW--%?p~ln~Pho$jcskw&WRf7hicG@y}1PHJGg%QF$dZ zz}LQe_u>Ay^2(jP8Lor(Jes15IvVrpw0lZcOfDVx6~(REl<7%}*W@h-&~}QF)*UpR z$vRdr^yq6C9xwOu{;YfAIglLfu6*|si{0nt4H^5~&k7Z}2z$-Lqf1p5$zj5y6d<>s z3;#mVB4o)#df zMj;to_Mz`Zu&r~EttizNvkqc&?o~XiiEt$J%kQVqSPBk z&Oz#pNdrJ7$C3Q8u~7O4pdQX>Q5Kw{?AOK#k5NB->r%v+;oKa1;|$M9g!#z~e1Q2+ z)CI8@5M$U9bfI$L5DMzEU2GH=S71^dDXf${?s%T?U~u4%$|>yyNj>t1`3p)O4`jCX zH#=99iOXvTJI2Phw>p{S$i6FVF6)BQ{l1yg{*c-Lo9?a;j1px@mZdWLZoPYM#&Hex zA4t2Brc_4l@YtHS%lLMaD7EII|HqPkKS|UF(&nTo9%kiR{Z<55O+KF2f7qp*RDRyirnv^DCM`bkPTTcpv^v%AjoDy<#+AU_>{n=9*}YlW>QrcdvUU@{ zt>gLh9v|&WX{T;;efFlE5|2ln0iD4)m3fsO`8xdP17>0Vl_}cAhxi=}x-0v?;_nnX zd4+VRz3U@%>y6eF9*_CPxGD~CnkX+RC$~svy%hQ6;tQIj+|zhMDAnm zzK!xOLdd%_bO};NE}OljQq+SIMol@$Q)XA1Rfr!DyW;;wnGPNv8#xMc{AwZ?5m{? zoef;Ce;V?*QDTS^5gWT&?9kcDyjrp&bcXA8$wLPgt4ennxLxe%=Db>bvC`@|CLLhy z=5wI)qYW{^CruO{8GGJt>^9>eq*|Pf&E+7wGq$7=yOq}pEOJI;6F(m{pI9p?d{i_x zX?7RXbN!I(xw1Zh49T?TO6eq7ze@uouuVqxys=e)J=Y;r#Iz59o;McpCao!cL-o`V z?o(y72oG5(DKmV5kVR#l7`(qjpb~ynenZ%9zAuOn30@>*k?+x#kfV7U4J%fW3xkxF;>h15lSN95u;H@1NNv%E`~o7B)W3E9-7}P-&5} zCpaWJ)2h^}wNltWQxbp6KKN$;z@;~G_)@b=7KNW~Jh&iU?BChzS#>I}y0HF=*^IyB zxw7`uN~>lUiPM}?r%5Tg`LcPx1UzUvF1OY#mwaL){jt91vD7CsAhR}b0icB;EB>ks z4qA~flx^2XNubEqPP!)~57aJ8t!xf$;?2KTcd)l>d}5c)DS7;NvI2w4ccxYg`lNmi zPOF1Nn?$wm^Fws`A7%bW>^DtvC?#2z@5TQp7X7@mgY9i-m>*s1wP3SZ(2YpFfoOWD*bBKA;&H$vdEV z0)+RxtH}>jy^-;iiN*=nay0pUD_`Kg#ogJ#5G?b{`Ja0TAD)L}VwNfV`)1+;6EqVt zE+X4L{=m?ul$d1i`-0epIndZI%_Qyr##e4JRf^`%j(#{?dZ~;!tH6s zT|Tf95)P=bE4EG3|+6%jCNwb53}c|At=e zSDAcZkGkf&n)5d6@f81J_yl{A@H^me1&aFAahcYln`5E#>8JVVg2)}F8KBn8Gk68? z_;#co0kf(^%~)Z^8gDRnQ+j-!$p}rGBK%?t@y&+spo>Ne@$eS#%bI&$SoPYI$LodQ zo!Brov{~Q|&k?4(kk7Ev+6r1nQ-q;S0_qayBegg73f2e~ofSr?c!&U;C-LX=KGK{D zEk*JL-K-QSuHM-JVc&}_HOlyvoG%})9(qrlSO1+w{K>m6nVPZx*vpsl1N7EBIL9-H zhZS@VR*={uceiM#@!5$^P4yQah~$M;`4(RJ+3x-Ny1UYL8D_|8D(m{^RRo@Dh+6IJ zf~S3SMfvcSxAE{ra^uwUpXu9PJ%orTN;1eCnRz&Z?TyM8eEk+ z`8kYAB4rxDkLkMF*=3h}FD5mnzxqMyXEnjIVxv8J%A8``Za3DKHZ|p3>FMyU(B0J3 zg+`5@kl+(H)(BwGGqm;KO*=@ICkr>N>kAybw?Nw+e2BB0ze=@+^aW~{$WMjQ1>VuN z&~NClN89_Or2bX>TFX%v(4NV+UyJXL;>A|`1^!ysfXr8^4^P?#drh$Lu1yMs5^^`b zPho4qUv1*ICqIibKOO>jpbdcqk8egj0JJ*7(VrNh3EKFc12*rZ&;@6Czoer549m=O z6oeZ3Te}Yp#;JO|F7$SFgs6iCJH_W1gsPSN3lHau;2N4h&5*6%;Z8KgSUZyZ z1u6t!*Geqw`}%uz&Rdp_7MV$Ff~8j-y5%-ABl3ERWY&{&9Lpy0%K4S{R(a3e`5Pg} z!DE1dgH=)jwA0{zydbzL?guW3Sik_NV*kz&VE!$r2<(lEZSOWSb-v)JG3UOZU)X&; zvfwHF&;L+l2?|N^5R%3Px)l{!peM%&2HE}siMiSKBx4Pj=_cqCtkzg_j)!;YQT%yS zDNtO{xSyl77n{LW6TqP{lIKnKU(q(*L~Yo4_hB=5hV$Le^4>;U3W7l+!~`_H5-tNh z;K`uPLP5hf`61rH#Wp%E>R_D<`^0f*$PfyHut`z76nhU~ntCiW`M})s;RaT>u$PBD zQTKXxJ_~g7@vzWiQTg-3o7vEy$g&<~V&#r8G*FZWT?&4Pf%%}jb1E9| zxR_Y?jI#oB3q~Idj(a8=o(}1y-XfzKOYCge(mEaR5DY5;dIC0$4Es(!9&G%n;5fI{ z5FDrNU>CSRIK%GToR{sx=-d&1;IK-AtHk3jf}tH|l+gX_@tDYmS9)c|QmLTtPO5cv zzD0TMOwQbC*SMNR8_ug*`F8_|jgP-?m; zFp0xr^|D8gNMI^D|pu@-tJWSA^ntnPAK(m`TfT%o4#g;Qu)bK0Z4@@?uZ2A%9=5c zo+U(UQR?Kg^>Bc07N<+3C5Rmzchw!oym5?o1~@WJ6jqLeSB)+< z-L^{{b0PW(e^vyRpxuR5aSoeuZ?EOmV{%EChTl6S;_tRwjUPZMH=03r zZWyg*)WkKt2D>#&>mO4s@sp5h-E+EUs$EcX6E~5sP%->#SoORD^`vdPCl@2(Z&9PB zNmW_QZYyAI#~OVM;X}o}G$A3n^y@TdQ`1#4UEMLhem13Jj@nE5XZ&U2B3dncvnSC~ zyP%~d*={wGI_PKMu2VG1bN%Z3!w9X2m%>J=L_ic6jj@yq1_S8LUywLy8h_znx z0~JfisVu_GtTr+)ETu%|Y4qEemnV4GC-)~b2r%+VQ>MMV-jxrP3t=#8bP4x4M{Dfn z&(TXk`2NLT%1nUAO;G0`U<2Ds5sC<5RUwK#HA-Sp@*8PgM8>RBES*FUkX^$)UfJ=BpVjSw zIPDgE(<$)A?IB#BaIFE(@d%$Rya}ls47$$Y;guUXx^Vb34~57RXI$Z<3%`yuTAuiR zh>qhytzp4_dBAmOOI`+#OV>^#ktne|tY56fhIz{uEwZ?BKN#kVq zD|m-T6QU`VJBET$gwZHnp9`h!i4a^-X2xT&O~$4hGKcjnDL?hHhk8gU>lC z_0xupx`k01 z#>#3MbKdq?-rqRiR&fB)jsujqoI?CHHB@*a-8_kEIff93byN{v0UO|0WK-esZ#+EY z$4#>fgA_EJpeZ_7vj~1bBC3^M_!rc(->O*(5X`V*JW~b z$@i7J=gG^v9c(7o7O3RIpq1nE-wxi5LQ3ycch2a#$#tA61*-?1EU?oE&3iY8J#)k_U$Re=j=Km*9czz{`tb zj(k&T`Jp2f@kbOquwNO}SLI$RwVzO?O7Or?CImb%MKh3f05bL-1QmimLXn`A`H4)9 z4DkW5=16iKMOtL=6FIMdY8|t;{EUd>{YR)^L^3+0-w*lcMFWlNtRat-9B21OGhq?=e zUkYbguVPEF;}>4mzh}9s`zUQ>A;SVyv6n$RkQL&Uc5(CMS|m)aT{&4;83n>*Rg2uX zQKa8)s|B-{@D8sxLzt{o^FxiMQZ+`*gNC4&EdcPKYSbTU${bGn3aEvRv^}qW=75lF z(+o{z{Ef5B0p_E!J?9JX8)JcF&4I2Iius7$P_&^=Mhqfm`V7W;Y7cHo8 zTQQ@tKCRxYt=%fqKy(Ktv||`IOlSvkiM^xc?h!OhwarE=Yd3rYjCBfeO-8LmlimvO zYWiux?h%eD&niSv%xeO{0~$Zm&LdsC!ntqMmeR()&pNU_H!qrecJjo1;>g20?k?2f zZcJmeYC{B*cL5QB?APwu%09A?u$M zdR~vG@_YcqYP_8#Y|{h9`ktfCj}j1@jKJ5_VCz&^C4C*Ju}*kA1<98pelb!I@<3t# z5IAwr4i69p>m;HY5e+I{8Rou2U<5;c|y-Ac$)WGpuo=va93I z2lq->6^V%3!t6ak`0G{pNtadK+H&3o0ublSKgb^<9h>K&NYvMUFm79tE3U3CJVID6 zKrDbx$8aAuQBoqL)x&x}sjdbpo~j3`oIYYDC8c+)6oOy+CjPG$=d@YGO?CiPL`RH) zoX5W}*e60FPplyV6$x~q@&;eu+jVrf7~HwtuOj{(Od=wJ+nbD z7sm*3G#BgIs)?qoNS#gFBcm)c{q}gj*gi1IoL=CDNIALJfeM_CN%C`@5j_Lmf(0u#qaXi_^9bLi z1P;Lz!M{XH2L|6Zwu+*E^}QPbf|%P0pPUv{Y#XX1q3RS8gA-Wt$D*x3Zwx_x>^-oh zb;H8&b|j*>BY7TpHTYJMi{Xr&c(1749i$}HY18+Yxw?qJLr|KKWjw2)tMk$BVsTN~ zh(y$P(H=Q^6XIs5YYz=a{%hl%Jg$Ww|8lC#JDGgOyusWj{p+_<<{F0cMQ6d=*1PE< zEtkBnZ^fIsfCsbMlwB$Q0lT$f?3zE2I)e^+K%YS2A&4V!pw7$!CjpZ30TOl2mC456 z6@Hy)VIeNpG|Oqu7zYeV?&*_~*(VSdFyT7b<~C4HzVxw#^Bo};P@RiScS86+G-Q`dE9?dh6Xw*J2P%G;17T=UqSi%f#D1$P-%7Ezpql@ z2F|kcLr+Z6*o6!^l10E4R7@Mpw~mDTGFIqVXAc1r+vq@Kax6b@9PDO__3fMYo|tGJ zccipHJ1?kHR_QNKY0bHEWHv_ob&)^seH5c>TK7Cp+Pu5m?0~P-4~-jaYY#9e36_{u zU523ulYqn=w;}Cm;Hl$dBq;@sZcY(-8zs?DI9e6^$B5^}3P-QTcr+ZAi*N{K@|V`) zMu$5Eu)MbdDU!zGhqXkZf`S0;mTu9a*JQUnfE9cb2*W-hgT?(qG-Uj;_qTSy-r7n&^zL)oW#(W5#6 zFtPr!fSu8+szDzdeB+Nj<2Q=V%St}{#`Y5bLq)_PjpdkYpH}P>;?0|q4ZJ{9ua`&V?=Oc~f=)8fC{z^c4mB4)WjXBu##xFlmlUxmwVkw{W0u&J0VrrTk6c zXPw+*bgt}K=XqJ*{qWY3ROsQn2YH*=8g#%v`%43T`#ZtSsI|#oU%U8t<>OSVkjpJm zm8Gdp@{yR6ku)yDF?SgHUu8WU758XyKIuejcZzeeQs+l%*&b0F-cwoKRvp}xgj?1Y z{!r81T-fOVmbKE1U}v2Qad}mo6cjr8Gx9H96W7mwYjO_4Qx134^#{c3CX9QGSmBN9 z#O-;rWR-drVdin3{T}k>DC5aZajW~*8`X8}4ym5MG*%uX>o2MezLi;ft)Qt?@O=%z zN;;*5xK@(EkfIov1sqb`{u49a(s)3Ow~O|1q~vjD-PJ|V$|`mVF}fsQ>3-YBU<0o{ zZj<&Rb*-V%B5{qjvYI1yibl4kXZ|1UfiByET5CLVu3&yWj2Hodph*xb^l7yRzORbT zld_bQ)iqM*CY>I9GdVzbN(zJ%zhZgM`EBjV2eJ!g@8LJqso--i=+BCJt`k_#Re2Ay*{=R1(4MENwk&K3`^ zlD@G@RfUw&dLg&w&y=;KRK9()E99P2L2so&U-yjOo?M&AKMBd*oh!Fczy``r zXJcc5w6=3V&6sFK>SlF5dgB#8(|k7vXu3zIJk(kcVs|&?{s-paV((Q?c4>b0x%hno zRo3~<>g;K7Jms@7I^`}T3pc0njS*e-^j1hW82k_AQ;1m%97e`^Rd(r)CZ;npT|9a^ zuC|nomYAj3Y3EIP)EnP((D2*NA7=?)crVBEzj)eOe!S8}9#>TNAi$~RxJzoY1i7Ia zo5hF+mk9gsoG$2Ia=v7*=paQ|LDH_Z_2P+Y`T{FS5 z%xap}V*eYr5AwjrE#;w?$P)kmKN1r%b3*nTyY;f?+iy zE`EzO;^MzpuY;2eiT66d%u8+O7)u~jH1Same+a271Ete!<-VZPGk9hqSkPO8?WSU*C27oN4n#*)Kcp=C*bG6_^u(JpGJxJxmo+ zic=elX$XDZ)#<+by}i;pOA-N)&$QP5#1Oi~Gc|y0g2=JHhcKsPMY|YQF;HaDC@DqT z7IFEB?yVsdirJdwSOXW-?BgEACu@Fo@uuJLYjWS$*SzPncpNdPj8NV*KK{OTo$6Wy zJI-l&7WV!|oQ0KC$@|=yX!#7c-^uF05N*%@20O;69dicXXS7t!NBSjT#+gM1t zdMs@eP9Bo@i>^j9?tI%uTiNT_Ll{FH2r$b!RlFSki=_ZK=Wz*L(!bZdhBU zIhF7-=HM|?YXsSq?=uX(yIlm1<wSFXnQ1VhW@Qv4P&%+ z7X}9U3_>O@?!NHwjP>MNtG*>M=bE4PL5>k#;_3p!UL8XYW2PDT0hV*yY?2ZmvUE1R zexV}sYt1m~U@GPo0TSQ*3CJ*jl3Qvf?CJ`9-`8QqrOD$rjUTgIa{GGfXQ#$ZG%w8@ zXfiNAi3Ed~7R+x_%ooL4EPs7%IQfLXRXzaXEoJ{6}0ocjp zQ75NPCRPlk{+xzdBiWnl;FThMI0{BLUvuCs+I$Xr{XjqCDv9@6+75h@pK5bcV(i;fEgO+cCL%-;I&?gA`}68Y>B zN~!U#^t=Es!ixX(=hotFb>!rwWTyqb`5u*$^1>@2{(&8(V5ikzBa@^x>#od|nHcmm z?2vZhmRbb@bFkDB%g+o$X>)}-(XdCz(L`iDa=6xW;(OYiw`{%jKLfewz5>^_N%#NG z+#0#cB#+ircddN7Zm5n+fnTY#qU_>>q$|!{Cq=r;Ur&7?g((5k&uW*~u9Cu(Komy| z&9*?b0#@cf7zg%$c`u~Sso<~F74nu_PFKc;nGG~M1_z{LU3jonJs6`1eX4pX*zI7j z-u>|6u=;m1dt zq>cqwaB1~h7YY9W+Fz=TZG^O13pNjG+3kWo1iU!Y-x>?$2ffPWeaWIiU^)Z#nPd6W zzEM@Up%iYW1B7$xPS*%TUHp#@hsR!C_B-Y|5Rg2*%^vD@%s${|7NdATe|Fje$oQ!A zz$=NySK}?uLiyE;VR`f+=>O}yW$Z{sR7q(}jNw;TdL7LUrV+kSQy$Ic_Jw*@hme51 zh8=&3Ctm`i3_)SDK*8{bBSC4H86$b*G7LHgd$U;p3{9^oYiJy2)s1~3h@gT9>N3C3 zLYHQQ*6vsk>J0Xl$o*{C1WzU|PJnRugcy*hc_FU9Vv3IHaHc5Dprfe;Lo)MVNap3z zRT@U$cK&CU@F!LdL_2boGBvbeCLp&w!gneXfiz}@{Im*Bqu+~n7l%~Ug1eO9+_%Ia zmaN!V?Q(-XKP2v=VW_}zK2RopCrw#>vu+w#4YardjbF9Z00z$4E?lu_X4PK{#uWc( zqrXCd&6O4dxrZbSHvBZ<0jS)(<-5EC(j0R^i!B7l{{)knX8Xd69i`W=IPF_r92^uV z9enEP=Gfo;pZ<>g-j2(a{NnQPbC@S6LwjR&(e=)db^}W+dC$=MbqU=hI=__;)xyqG zXm7Zi{;*cQS|kJn4j13xLKSsz?P-g3RA}K`Dd6y?PRz(Hcq2|j3~KFL^Qdc*+%fLZ zmKL#Hul(UX9@zWeO;b*`@P#pnal%p<04Ur%E>8sg8WtHnHA&}E^>-Jqe0KzS8`91B zyyc0%WI12JF^P-pfHySgllQ=QfCSh$D>`M7Gek7{R>V+W$O{~0-=yzH6Ps9*_h{i9oH&ij z)*bF#TP|#T73~cS-it)WfI2Jq+yhccw*4#aYsNtmedu1gvo(zBs8hh>@SII@xwF(q~g3MtfaEfo}&y(YHeC3UBZUReP z#@Yxwi;)q4+V1WI$T<~+U9tkjvb02u4nMU2jqN+aX-f7tw_5mjKus!y;aj@e!9IzO zGLvf`gUJjhDu+a6Fz#-R-~|Tn*_ht?{1y8}O^SZea0l;kG>mX*4eSm-&3|-_+@_MO zjAR%vcn@6F@WFeyOiMAHj&pD{q_f=8dpu;$LNcu$patR6twE+$%z{`Hv0FI?Lb+Q5 zV-N#_AJ;Z_Z93u*G+yo$Fn!y}sRsU&v7xp=jr*3hG89AwESo`EIAJH4vdxE-j4)-x zBR z%yAS&aBo;hcR}m`QQ*ss9NvOjAhnhoaiD-Ki_n=8oNPP`8Gufx_7e41>89!xzvT^caD?f)(GUrcwtlw|WS5evqg8Mn&r(dv<2kevf zV9l$69-{Yw`H*{YbMf&{d! z&UY1I1O1G*qGt8O8{7F{3y~~*cAp>9cc3QPI>qt*+P+$_C5D7EVcc2Fj2uo@7TDM1 zz35P8$hp@_CClSW4%8$&SGJJD0KKzH8OWt?-qlvpAxL~AZhJwJlXZ2$CDYFSy~SQS z7cDC;_uUd7j}d;eEnR?WT})C(Jq8F7wxGf}@RimAa6kwC2WXb^L6Xz{ceK{DCf!ww zR*Bk22xq-1Z*a6hUfvX45Y|0rK&&#g!=!0e(?FUA{D$H9;i=rl8w8THIm!l|Fh}++ z%=Y;cL0gh>dt86r;%NmLnSwJ0rDeV0Wl7WRgt_)#?a#VB40MP@8XNk6LS`z{0-@I`|iu$fPPVod+Nh_zkW+;$>1rX|y|#FFKgYAXk` zS_1YPc03k0?y8Tn0Y?gt)Y%y4XoV(BK!7>-;*K^5;Zo7RFVTNY_xg6>%X3t+ zMt5x8%fs@aJ65j^9$(KZ4a{l*Lw_q6kBWv^AifGRZefo9^;%qunZmjzVeR-O8~)Ot z6l!OAXZ)5FtK;uai66`;68u1`b>OJ=5Pp#l7ChwsXA3KEGSkc#-Rw{gz~lsWJ%D$U zi*f%4cBRfZgkdxyXFh?~U8^)Q!0rd!OP@bDqS`r0g%S_XdNGh09usR+bgju3NelB+ zz-et&`909z%v7mJq1P~pEac& zzUNn1x?b|t%<#qybt*`0Wfw{I(@8PnJ>euMVivP(q)6LR&7?6xQ0V?Mtvs0XLKVYH$+2_}q#w6sMb|gL! zX@At09*?1JyET4CZBj^n;Xi7c5~zB#tdCk`3G1Gai6abig$B0eaUfBh%d0Y-OJPI_ z8*+x_Ltr@Jo%%+(W;I>}A2Y{0nPFuW( zhfo5{#-~-Nt=K6j8G7tk?SgNQX~J{qIRIr+PRa9}WWJWu`ccSc0ZRLd;O1 zPCodu=RSN??#WF|Cm+nL6u>C9Ss(L!A`nIljG~-;W(i+)Ck$y`^6_{V@7ureQwlzi z)-;y6)UFmT?Mb}D0#GtKOs*kJf6cc42Bz<{Xw`&WuVNsKe1e)u7U7-nwPzAedx3}<t!TUe1tOn^&ji}M!0XC29Q{$lJKY9mA6XD4+!bJGl!qA07 z5VEng2Ej2))Vnqu4dud_P41g<3x3$pYW=%8u|#OfBPV(F=MK9irM7WFo(}|mvI8y? zV>TUS;3qR61`T&}K`D(fn_gy5{r4?|J7rB*%+Bn(*S9dG&D=uD@DL6v`*EY>jlKNe z>C-$JWD{l}qoOjFuEh60|1j{1<+*VWOZ`(TQ=$jHH0*1&Xqaf8vfrcUa<#5J)ihc7 z(5L@9+7Lm(6DxVF%=1#FwBIw(YE%IN2p)Jil9Qw#4DOT^Z~WInAJiHg4TVq7CbKO% zzw%9g-&K12uiAiBgPG=+CdPqFic@d7f%n2YW&zKl+-}sB$+8z!Il7~yD^{NJ#0VD( zHmOZduzOHzA)H04Ip9egIUjAMw~a#`9wqcm_BYjC?NqqM>G89i#a0Q6eZO;UAGl(s z+f*-(z9`x56zKb)b<^@UJKRN2|IC)RZ%@Xg8Dn{WLyD@{Zdj~_PMQ_ZUgOEbaj4*> z8A_;So55}(+=q8^As}qA4r7ZbSV4R)CwW-*lx2mYH>{wq7@y*O&Gn7gT2V{j!W?AP z5x9WB%t&@|DiJainM!p~SWqE;W9+sHakZFod%nu6C3_!aNT4PV?-;uc6* zkROOF*UcO1diUFzbc?l5Ne|?#>~5~dj5E6a%#8Xgtfwd}tUB2^-?0VB)%xbdXpf2d zlzQE?)lK~nl?^n5Wrbt~#CSKt(ghJGQ>44MwroncviN&`29i|zEdFrg&w)v2OsQP)^R-7QH0?nbh?vH{p=VOza*T$X!ERL6-e~< zH&M2s6cNo209gY%jG%thV=f%k%aIsc1mdg4bEu1-zw&O1iL(pZ1@Ht^30la!fl4~j zE&z2S(EqSq07m1$FGj6?y%i2Hi3WAo_vxsax+3n=|LMAmx%C-L57Iq$!6m)KU$7Zs zn7V_oLBkZHsymHr7vgb6t6^@Mh?I!xx@b)AAck0diJ85 zF3@f$>rMQj0!DEKAAd6y<_uzNs+ts!Bh`DqGw|`wj)Td{zMitwt)(e*gZbTvs!)0#G6ypq?y zcOQD%?=f7CkAchau9O4GvcK%5?#GkQ0vxApGh!2T46Ycje-5hP(eFTigDQb=xmNDt znYpHZc{XcTOfJ1pspz*olN@Lx*;P=99et%r3|J$ER403iyUm#{e+*y2rL({BOS8S8 z!-Zf;%tvx>prO(fA~SA`C8 z0C4j~09&XtdIwqz3mt?ijeb33mphfwYA4V^z}wZJgB(Hjq?lvE48d_h_$wP7WOvWi z;_C`}6`+G#x$c4p&bt|_g-o$1bdVa(IRrWgp{@y2?IX3;RHuV^Vi-;K@-)P$9zrzn z3rYPOwOg+wa4bd~P(mK7a~8meSh}+@Y=)D#rVT!0?3&*uh2ByJpyv(B1Sd5hWIpX?S{1cJ8MxraDsEbEJKIp{1&wuuV--8n?aHjr5o4Mra{M9!B;IYC2Wr#_P^iDa zgfW&eEDmDe&zBGZe+uk6=7h1~ZUkauLY@a3^FA@ZczGh4Rj!QxQA871Jj&AmC?%%2 z<7*xDSgQ(YGM;L*iXMU%7|1dYQ$e^%cG?I8k$keGEe@^sNd+vJFqUXp3P6~{Ozb+OdVDipjJbS(!T|pJ zAN?=YLWIbb2vDlLz!LF6u%Ts9tT-(_=!=x2dBsXfVcss@LxcaoaCF+8}reu!5cVVu#D{2_5L*(CzOhv5AZs~*pmkuC%(Bz9L;)y5!5zY0j6w7yh*4^*v3 z&%>DZzt}m7QAmoLJTlg%0j+Y-|PmFicDH5>q2l zy<`U&5c4`AkR9{lZ%Z;h_d`Ikty#>WKXN~+Z9b+NCQ-o%wmc*Lu&z zyfSJBm}2fSzTG6z%2+O1Z(^n8PjkG5oc-oF9#Eq+|ADu8^KMwU?-+%~c-rX@QU?$N zA+GWNuFdhEHEa)o1-uWecvL~6G^_;8y9v|4Q2)Zv(BV^)6i7e)lqbSJh%S(Jg>~|Rm1+GO#7Ncx5#M7(^OWW+j-ZbM8AjCeZ|TDhHi>7KB`Jr3az=Z*O1?G`$w8n6-^gNn(xGaJ=H|oRh@YiAVb|(X`U~a{m=-%z}a7kBuVQSV} z{jKvPbwQnV&Y8l9^5YxYgPghn@V#9vZ(j!n2*D2rM%zQ8=${HbAy?b0p)221_eO6GAZ=59uNMXa&}ENTfQ0)M!+v}wrpW|_6sl@Xeo67 zU|5Rb*^m}9P+8T-1m1AREtujFItbH7SX^$!f~1k4l44!^kUK&~@C_F-j-3!AcZ6X% zFd3aKo%*UIs0Hnya&YwS7Yr;HR)Qh#i(!lQBYG1IL-C2&3r5O{=Y{Udw|}021VJQd zrSNxx4mrk!0*i!|Q65+siN^BqY&8DOCPC#F=_}s++Rcci0_4ayYb}vTSH-YOv?4+SmY)tXijs=ZWi$&FJJl465FDi@& zg?Q+)zbs036;>?KjhiLkAHv0hdXve6noIDY+WikU1pW$S{heBv6s4=;`qSJxVo>@; z&WW@I#?7aXzmbQAC4GW2bIzpG;2e(^@Cw#7e=FE>eIMpv)H#j`PEd>BH54(S<|sMB z31`WZj;4_QDW*iT9iDK~4B~@kBtlqt1tSeobV8gw_i$2$`oe<(o|Sqg3X7*lHcX2r z)h_b1HKyQNti-q$j}{X{;U|RxK=Tq_8gGg2!c3QCiErF+T?=K=2A*Py)2MQug~c!g zl_+KJZPOPa9ydP6>2tg%kFkZ7OJVw9PT)uMR2QeBl#)CsV44kq1+%x}Vet~oNJ~-P zLF$USFq||wWk4T=`_Up)>So@?Tu>DxOss?c`rf%X3%69H7%j*+>`0HNY)9{rh{&ED zl9rukW8m0UQVbsJoffkrbTf-~q{y~a7-YumC@{?rmK|JSWDpeaagZ<8MHSRH7ZFos zSU?9ifd*lLM|DEM8Ogi%wmy4VVn7FdnheRjR)jKGQ8%P~J^008&QVvec{tuAPG5*0 zP8&c)A0DTY;to&mDb547p8<|?fWuP^B*1DMp0qxJMNQMOaNun?ruw$X4Q+$BZnzr3 z!8An(=}qZ+A>i!>S)=E`sFa}_ocPXESlrl(U}PTpZp9QQmEX+;g5VvlXi`wg8ePXa zGZa|{?J^5wS6@8a?JF9=I zmp4>8_1DWH0B#?%;;{sDOA|0XhC1NgB79W*SBGQ#8y;D|zkZYgduQ4>d}^fmDj)|U z@u!d^e#e8-$OPlYAwdop-&C&#eJ7?0?htI^$OmEVg0gwiizu5pw7)p?L1^G{M_H9) zS{Y{$JD*jJaDcKIielx|i)`hSs}Qw2?T$J9Vr>XeFDJsm(LcnglP4^?0AOXK@8}Hp zmo;I|!ofoznn2KTB|Wy;@SGyLu}%j}xK%DTfeY0gGZQQf(BVQr99em`u^cioHolI1 zA|!KAg5pLPRflf5&CH0ro+6p`Scd ztZ>Tws#16iQQ5lWI@K3dy>>=?gHn2iB})NDvwPZxP%q#BaKK&4@F4cW5u6Nzm5iq( zbS*yRf3n1*^71kSC8gl==c8Oton{@vedIft`rTRYwFF6&Z_#Vm+yzOEdwI zSd^g${A#g+5UosZj+Szx1Hw9TUjq8tMXnf5#YMPXwj~~ORdI6)h%iVK>2j?qh__hd zZ@E|Y!h9%T3taQP7FuQ+IF%G}wk+!0-ap&*@}^7xU?Ur%>n>2Zz>IY2m7@%aPJU4k z=3rpOMi5540AFSM)s$F)C{NUcdRDHZCOy1#DXO*S~I;NB6~jad$P8cfhsy zfw{YJ!5mT@CnQ(rKJgcQ3gEJ8-V@0a=E$Py^$;qcmL@>c6Jct!;)uem)Vv>(EkO|+ zad_d7rd!u07#wU;d-ll`uwR<4Kol8~l6mwpjL5O9!A59oDf~#WyilWK(%Hq?qqiYR zOy;<&S;Wxq1vKgc+#7gpNCG48KDwfpcog$}8u(J@uSu4+E36O`3|VJX(gw9FNDuf^ z!C^a0Cu0RMmIDv~+l&q9pyPHNLp_cjD`Y-7B0gLN9tXfYJKdz{5Xi@PSQ3$6*%FZm4vEO? zDkLJP{)fgZA!i-l(DgeX)h~S&=i8+1bG3-?u3ONVA*8rhO38y-y|X7z6BC)8e%sO z=B|%cL}N8{dU(cBwGJ--0b1AbB%XRchT`l|h2#ZRKAdegiGjoBF`P9dChYoRv=_ z()lTZpnkqY54$e|rWd#Z*=yLQ>`Pz_&O|4h28&}W5p7vfW@B4KnYv3Aljydt79f^b zpyxbjdW;efko54TBy(D$DJEG!XPI>hu?R7Yv=*`~z!PEi6AXa9=~@hC04g<82qcJk z?D+hfbaW~$*!D<*nQ;gv8nDX$6Bh9>5Ni0kMbITrgj1-zNfQrS}a z*Rd9oBp}8tDyS#%W>uQ;6{Z{E!y8?^Vwe^(;&aU9fE3FEbV@e*2>-P5uMWGWKKjMe zb8E`Xnc=$<9&roqjiMu7#rSF5vy3C;j#4f|S2wd2<&AK}N(E&jkp7lY2Fuc7- zKMzno_PVq8DRzc5M9@ZQ@L}lh05eR@>FM9+AlwZ>qi@Bd(>c5YXi<;bnqJ{@@K&p6 zR~ES&Xzf+l)+8%w)~mCUsM-l7j)+L~-(V%-h8}2LRU+B+8Qylskt={8)^4ly^TV4K zfbPb_mKq<N4Pa-G~P@DQe1G*7xF?cbl%B2QZ} zGoU?On!3;@ujXl0SJ+nbGQN3Jndr{p>imbH9p$%rn!{4!yK}-?WxdBG`yD)1UvfG~ z0|vcs%R@+5@SYU2Q*w8_mG6{`-)Qu|}w<4fKUekGM3u*;nM#x*X>bSMdF)gNnvpo<5AoA=@^ zW>xd*Gev^`Tl2{82*-qVD;q;4^R8;07%NU z2bo{0EoP|8#@J|pJR^8eIO1?R#4?InW9~MNaT-?{Jj5wHj_Phq^0ii zy{w+msG+3v_q9U0%iS%fmdQ7UNFRF?{9WnssMcz^@GHgC&zpx4MDH&vcwAZ?sJxOH;A`K#`*43;`9B-SUh9oFH+i^1V~Fku;~>FWP#btncS7=) zoZr+_uqY84#f)=@v+5$p`;tlE3`>^%9UJnd-VupJvi39WP^W&Ey-lFR!!|B!KhsW0 z&a1_K__{@!_*NZP&oJd_FK5gf}XU7_tf4W2yw5C zbm^2<`bZ_0TXsvDJ%W3`yw}s666YZQtxnS92O5j!xRk2}?Rg6a`sU2Alw0n8OTp9; zUpEkyWjeY!MdWRiL<6C|T>Ef^g+YR&nQm&*sbO9NmIB|Gdy^bRwILXc2Wm4 zim}=0M)8k*l>-3B4fGUzEiAa(e!Hfy+$Chi4DBY&9Xo!~M01{_dG?X&r`iRkrGhz$ z$Za$2v)6L_r=Hc8Uucj4fSZ;f?+BNVgh#xUog~mx4_La!qIliMC)34ACtABx_I|N3 zcojb@)8%?;n{$qtY)6oN`M0ce??|w`X|uu4TyRmaUBTreZj!w++YcW8PY&P6 zE%-`*{rtC#O17r#H5b+K!uhED*)E8Heg}+Vg05hc(4uKfN=U;PV~wd=tP_QL{m_SW z+v1P|eJsIGfOi=>rI!ouhs#du5HxC-kE?Ulni$ExK`>33n?{Gd=<-9N4Wa+xUctl@3n%}dVeJNXJ2oVA6j3InKNbS*W2UH_iC!SZ$UD* zMB{8!Ux=^8{dPMmg4YDq_)*6=GOso4_vOfXFipS1Mi#1h{L5Sil(m4u)e~#t-_b3Q! zJ%l$|_S$J}RhYdt*&7FwN~IwmWTA_-dZ1`W&@A_K42WxJ$Op`)VJXn*eH?Wf2zmqm zzeNy2Lq1N3n@5x#agc8No*ME&`EX!WC|Rj9j~k#o;X^)2`WiBMB~#~Ni(#~m`T~M_tOemg(~l7tRqaBYKIsi-fc$vg zK<&mE8+Cg^^uL+(T1H<|==)+pwV7bk&$BgtynO7`qulN5Wm$G(x9dF) z$4OORPoW}H&_IHBLa&!;lL;dx2_ z_mT2biyj|e8)EYD{IosB(=7^QuK9keyYDx6%`ZG?IlDQjB;H!M{XS#12^+%^Rf?tJ zJ!wzm@0raE(0wLN{p}Di31&&nJ)W!{;c2{Je`a)hcS(QEc*(oR?wyG!?CSgSR@?qG z01>?HBX=*^q`Ok~o0*$WPHlH{yPw}%7y4IApKkW(YVGW`^Lt}nt%pFbySd5DAozaY zzB4-|Q-rh2^>#h0Zm(=T;JMOX+VcFnXaA46FOO^L+S-m2wpFpMSFHou+EyzLC>94C zaJbsm0jQ8LDOeG$K|oPJ#-LPb9jg>^LbO$p1c;)5$`FSt3L;vJsUV6Lz+S5`Y zn$o^sarOFHeX&o$ zx(96h0~&5K$UdIhs71D-WoK7nnjk~!53RBm)?hp?!-4Cq^EOs@snaEsjXsi~qOnT# zoxVAxks*Sy^~=Rof!qR-e@&)*-97YUMo5#P_14mrQ{R>8Aob7@cZh%1#E&FRqqZim)wnZYMn4BMA@)x(nHk!S5as(B66I4*@Gh;mfpG`U zY52TaJxuLjpu0YpuP(J6BRWkAhw!6&L1WQm5q5##?=h>3bkzalo__>c4{X_6mR{_k zigM4+6sUN2`W7hmw#JAH`p#EvR#jA-cs?`C<<0r(A19Yfh02VVWzl6dd^q{X4m62c zHg1?2R`icemi+4PZtEWAg!zRi>RZ+)#wi(=*> zz6N83j+kv93W;U4mI~`v(cN2tv}Q6Zk;^?gqbbfWd-|zdq3wZ3zK2%dezSDD{M*1} zWWDS)$R1t-I}EEZvX9yjSX*f!6Yc2 zt0zj{wLYh_PAiIaMW$G+qbweLW~Y{3trmK6wnLtu&AoC%3Kr8A7=oys=x?#lQ*pOP z)c89NLhj2M{*nD37?1JFo$@eia9{j8Id@-~0g5L&4QYY+% z1Sk5h+l!S@w70;#w@SnLq3TNI(YgE7XC{{<3ViRxG>I#ET#T$z=BQ9s@q1Widwsp_ zn_-f1%14`K90YDP>Ak!iBtH$B0rdO%=05@q;p&2H4Y4EY=_(r84J_Y6WvYyNzm~T> zd_JNNeMI{K*T;;g+UI3>cT@vU;`};^14pnynB4VDnONLVa_Lr8hG~h-_Ud(CUkrI+ z-yr(g?SRVT@Rx;o8Ewk*cdts?MX&15xm`5+6hk=x+{c>D=yfOUXh}1rq8t-+G_tSh zGc?&!d>C{s#XL>{xNSpp^xN!3`s#woF7qI=XtQw9JgEa*f@is;2oBO^$eOj7bee05 zs@llzB6f1>x^KQz?A9xwYhu50?ie2YbCh&Pvfcr#e+bK$%Ec}QG`~)noN##Y`Lzf3 zjNhZqnTZUTKVOh+sWwss*H{e*l_lO>hBM2{EF9EnNn^eNM)^ojAaP$CFZyG`0<8I>$cTntA{y@2D4c$BcXhiQx;a_!SP~K%_SM~(je@|yuY&fL4N$GK zv|fPxtdd&;@>(;bZGJ8@#??7AR6SeYcHwqhkThbxka8+_KGW~m+|J5@`%}NHC7iy2NHKtv)N!`=OkZlXz8V7%ApZ3i%FbalQ`vQKO>_{ z?GOkr(u}h;o5Mf=2HB4y*ANPqabq!&(-__sdR*4U7+H1!179I9#>o(i#E_sG#p=&F zvE~Ge;1{k-MOz#+{qFEI!hH=}uXLH{ZLDZDL+S-W+txmFuUuq~hO3N)4rGoCsa-wVM4Z}@} zNZ^H!1#L_jjw%ye89wE>bKT@1sRajoihTESpF9IcK=h<;PRz?M%E@x*uH@jP55T6V z?y?{~Q{s~EmVTqKKFmTe-Z;nRNLzx#Ovg7n^Ob*#_lR9*4d0`%D?7H-q_k@I@PLf^ zW`1^qSAS&Zr3truAz|C48_K}!a1iI_pzsZ7$)a^81OTslAZLyn2Z6_s3$qOQf(b^tU6iC98VS%N4YR`eB zLrblO1>5LW80Y{kVWBFX6F^l8;`DxrNMD zC>1pDoPzLZz>_$T{#DjWHT3V0hsmJU)139ROfIDAvHPO<&DWFc-FGY~!%Kn>; z09(T|Og1#FQ&}!Sk64QzTBb`G9Fz_Z8&>b*5wp)0v+3=zP1A1&NI~`FHRTElo&&Ei z8e#KoP0+1GC#9gS0h9*W(q@ZMqV0g_qj7Cq4r#+cRz|vK016^q7jmuC8`h9L?HXin zr|*B#$;dQa4ZKMJ@vf%MdFCDHQ`d&OCwILCrM`5?VrfwHeQvq~%v@%9IEzE4u3vqA zSq2vxR{$w=g{tIjQ)skA;FL^WoscU4*%j(Zm(59*-Jv-(W|NzU7u;YhpJG}Q6kpmZ zOL6btvKPydT@D6KDyx6xHtT8IdF8ZXRN|z93ky^t3?mNwD@ZfuUkNkjA$Abz(6D>2 zqlqazz|V}tTo=NM1z!CrZXe;Z93_TZ{(jl0`c>OBH+Ad1;;P}<;zo5*8}GOK<*mRg zKl?l`t#5W~bw6vX;y9}e<*lb}ex=FVbJL4UYkqfY?;8W4W&DVC$2U1qtIUs_u29d3 z&pS3*oKt!^=KNguZYQJtiv01$)mq+u&rE2`t0 zS0!2YzffP=Eh99r*H){B;+Ch=z#(Z$Yq=FKhwIm{MgCpR@RrDY@227~)l9QL%GA>y z6o&-QXy+M8LL>>t980s02i=Y9bu4$AUEUWWiKF7;o}U$b;kTZmn+7C2xTdbR5YnWI ztem-X2W8~M&lgypX`fd1SAO>iK>Zm?anPORy2y@^M6+tw5@*;daEgCM42LJ zX*6F3Q>;R|gm3OLVX%JoFqT-NlOuXS2M+0>7j32!4y(;DGb|5+MnFHF_-q=$G)_4F9!;mhomgJvF<>V zxNJuY9=AK`H$}-?0<1!>Rj+AnSmQ8!+EK~fnzYTrY}f3PM%RI=O~0XEi|e z`inz%PFMeE8=55zX$X3elvlNQdv)TBhb}QTqvNc`3^cQsl=9mfQ;+Su{KwhW7_wrza6`c)wMj@8adfUzF7r2(~;BEIHcVICVyx z`s1RR-i@GK+9Trs<{;TZkK}4!B`BAU`0ULo%at6gSDg-8*%C8HakTbEfo0jas26Px zyq1gYdE?7e*(Kw9#$1;cSPvhqKJ5beX_D1a)r(rVLr=^IQT|jYcp4{pFi{esxapSC z-s@$S#2XU*3Q2W=TU%{RNNbeYAGz=VE4va-dfEQ&KSbptfDVQA6k?WHJKV8%S%825`|i6tH;Ef|&DNA{yC1_Wg3G$@aWxuHo# zNisA}h^dxK(TrAX` z)`>C-+PsL~m{mhwLRL^XC$LR>Xd8VNr7Jadoj7%yz=(mCG5+xeNe<=2n4H3=a z7U0yf5_ci2y>7YA%u&hSDD{x1JAO!7xF&m})I(0{_#tUu-d$RKoM@XRb)Nu)Aks&X z5%XzZN8Jw4c=;MNGO;r%PfuX=YYY)sZ%m-tF>5!Byy*Ufcl-$=bm*7Kp8>r$_>kLFdf-bn`Jx-3ii zFAihU&8@Y+PuKFZlRbrYIW41Aju);qKfJp9zN(}qeP#CD01PUVZ@_^vJP}#1_-)nE zJAXB-i5@;Z^kMa)p$*DFeSN+oKq_yUa;D5heeSue%wO#tC`dmn@!lCM-=DWOx&_UW(}>0&z^b8GPA&H)=U42*V2$tybpK_&VKCae`rNDf`!jA;m!3A{Cz-&QodQ16t=7*LP-aoDk617w+{&tBeNDv6*le#F>$B(^# zrqnts__8YgYGd{k2f=V|1|Vw_xT7Mrl%Px3e+&qf%u}MpT(dQ8>X#qBnv%sE=f;`v zd$j#2%N1XYNm%H2l7!;_qJVMo!;stX+IVxHfbk$P=ngA95nEfmtw78?D(eKXIXuP!`);QK3w10c%F9Q;U%g1ns2^8;K zQV(0r95!XXPgC=S=QepsKj!BDD9mVuSx#<``kb}irO5h7P_(aEP||0;IReoTUxqap zvHl@MC>gjJw>KF5q`0{&W-p}d4~KX~_u*q~jFaOdMe!GGMOXslF5H7R!Z!VSC#7Nc zPQmNJ;UJBYmML2P+9&gReIe5=KTf+MIWT>8a-}GyAksZF`gXCM@Oo=odAYa4F!A_V z)hfp~YyQ}@N%@l`yvr$a`vO<8?VjQy?3-Xh-_REd!8z~C$b#c1@LtKJhA+hoHkhzhx9e>YN$tvjZwmf z6Px==0jgZ!k#q(ID!DHO;+t!aSIHudJYj>==j#`q6j!Kcs8u7vgR+}}oj`ZI$aO7p;Zi|;f8*$L56B5%HgawxVls@VTn71YZDQ|&eK2CBW2@4&h z{j@~P2--m?enK{t$}N5WZ2oktF@1!`w8o=nY}!}hAbU}0o-Xn?-Vt|87!0d;s>lM` z=5CzKnjW*w^G`cjUY^=MJiXhx6NzY`McWYjx)k|g=|NB4H;txM@{CG(Sz4a_XPM}6 z#^9-3m%lyy9>BWHr%dX(`?*F2wp4$6*P9Db~3c$1l1-0&R@ zH(yd6BJ2JCVuwh&KYAj4|Lj`EjSEPI6oAwc@RRC$bN=Z)8+Bwn!kHu6v4-qKw~m~Y zp|uG+3Js3g!37Qz^Ddyfm%1;7@sQM4vryFur&f}~q)n)R$P6hn)1{mxWya{_>rMt? zbn+p8v=w=W1HFuI7S6!w2+{&=mtmVn(;oT@I7ERFeost^ry9ip6%<@H7cTf%vk~r))(iv$mHGvCV3KX}T8H%iE<(BG=0n(pM8#V8+rHmwchLRgL0< zo`mVFj4$zdM8D`UhWWm=7n3}5+8O6hsQ&hf#%D;wy2=~*41k!HN$az0#f~w?7@`1T zw3A#CcSCM5lecB3s2HOuhIo)01|$xZphLskt)DFS%aVTrGo;J>-X+DXDmJCbqzt5p z39nODr{cdF+Oigx<^Ep8>ZtRCUs)shSr<4i=+POX$sY?R`c} zdbxnJ#>lysZ{^2@WlI&qL?*?!`gp`?{^YZ|m^`BLoW3YqckVzRl`yfujLsXSs26pcFltqbuZfboe2X$Nrjrn}Z3_Lz8nCPMOECrZ4$z4HzdH&1 z8+fC0F&mPgPcW#>-pTe9jx1bv_|zXe%Yma@q4KfSh z{nguJO^ol3GR}?a5#O(8fb>v=yK9^&YW=-*%bsQRA4Rz$CMNRtre?4E1*fCd^#;-R zJF|l*m6Wsk#Bytv0n+k@yMCJT0TCOIbqPP(1<^vYd*4eKyb(=MqOANO#C1-r{oyw9 zMqYOA1NxEc+{>TN55j3^%p+H658fddKdFprG($6*lpnQCA?tJVs`Etj#G&U_K>FN zGe2{h5#~E+?~#8K038+^6%@w%oNJr}_zPtZt0*lqMW6Nvh0H zrDWSU#+F%gU%m?26P%Hg500tQ4cv!mh2QM4s_%QG?(w#v_BW-MV*BAt>RbEth7D7}wU_~Bhu*!v0ny@Zq)g%xllnxy#QqVV5N zgjf{D4V@vZbipA`j4NQsHxj+$)zmjK_)yGDm-VZzc(ScZ5;jf{znxkj}_h@FauH0+;ZxhDeT4Hc_WaPtJp zaFt41}TF^hI@Y*{+b~off|8@`$d1Bw7tUsjkFiZar zEzXqVhj#%XSXl62fMFu3RYyUkq*~roms{uemTX4Ua3`pQ&c-MFvPB~cpDg{&dZTc# zO~oB&#L`@RHfV0_H;-ESg$-Wk@*ayl(CUsU+ZaamMR=livP=si`Ys;rH|J6j%Q34- zyIb>3O~o?A3(X2%;t>0ZSxr`$hfc=FG9ZTfG;CAj<&zFy`>^qTr^Yz%mr6-lY7k6L zQUug47k!`J)q9KlB0K;)#^)=De){CH3GXJF=AImyH27sIlo6QjWjEsgX_LLl5|PMg zPU0UM&%cAH)>JbTIFUVO-y4XHp<~soq6;1$o;1XvD~MQTBeIvCqL@Xvpk3YIBTg+n zF$oYh24hXfu$$IdhP54W#@YyubSn4dxuT?*yiu%OD+(1tbxnJ|V%oM5>hHZSJE{LU zXjbQz*K55V72qmlegbyvFbNiCzE*KDbqXjDMoQ5NQsSLXu`nE_TmnE-6?b`$dzGf) zwCd-kJ$pxAD{=x9kThleMR_J42LpPG2rvNBKO77IF1EhcPD2LpX}4cNhWbPFM?4G+ zNY$|Mp_htdZH$e}nh@fB&9oyy7ln~JA`rhApd(^gHMj+kjtD-}a2?SkebqIgBYKEkf_imCozgC3 zyh}O!^hU?nKI~{%KR8kdn;!kr!X+{PW4NYySFY5+ltgsL@v|%2;5^E`v|N=K(#PU&?+eNMmp!*KS!v~K{Xwe z5D&ynJCL}#>quPFV0aQpTt{8sG?5pPgZoWAEJjU$m|;(QgUiyQmmmRB^IKycje- zXSF66et#wpOiqqM z;i#3G;$N}D0j3~MH0wGPcN$pgh0BTif1A2H3Y1K4qS7a+d>H~7zJ4L(g59}QQZvrHBq z>1%IeNi#tjq-rlXQCeAC{yN>fxuSK6;?MfV9@35N%U;=!Kk7^(gozGz^POD`;=&SJ zDHa3Q5-V-?<}A5iJag7KW#Jq}LCXQ}k>U3<3g?ABT~IPH>~ebXMDdZE5V>B9#~jVQ zv6RfC<0JI*k{NH6R4zfJf$QgXWz{e1&+#Kq6n=a-WsWLl$c#5*JB$ds@8o-al;5KY!7~nWG^Yv?iu$4l9D?#%8n;DEd)dFEARt)G1dt*RA(kiO8GHmK0 zp&V!HNdh_n3_j+2q8^gLF`%Ip?+L3}9jr*CF3C9>dYZc5NgTY+06*s5f_F&b$SnU8 z^N!F;f($p^)O>R1P#SXs!xF*{cq^cIE%f@;%A|vk1|jbcWXSZiWn*@G(~0x~s}Q$Z zb!tn}SM|forigqZ=UXKl6Eqc$IvSQ{CGc15yWUch2{crBO+~R+o!@<%p5O7>U9vxJ z(R6j*B?ICnXWn*{y>@ZU|qRFiZ8HxJ0hc zwsq-Nk(YqkDSZ62WoVQC-Xp5l!$sx7g{!1KPhNl1{=@lVRhpZiAn$n-%*>lyHf*mX z`l=bSxI3^fDd=wFvo*1G2fp*S-cnI+IifNHwUM9rUQ|A+{@i2EvW~??#*uX@KX6`b z@liGm6tsR>7S>IDcuL+;BsKJjuGX)u9~grmgLQ zm$TXemODj5`IgNI&jjNa?Lk>UF#prUY8QjZLVAMPDYo3B zLm?3Mjc+3a!a^cKA@H$GgY|Z-SWZ2rk--exI;qvPgh0%84yx5UFpOXk0x?|a^g}JA z5Qy=Ra9?+>%+V48FYd+X#U)@H+933}?y_ zXNbWm%xs1zkuWpN%h8+#0OsnZ*hU?Q-pTE%$A1$xW=CHMyH!8*q^AO=eIw&3X~~*y zqD#HX-kRHkH8o;Mbg5UlK=UeT=^p(Yc9!U}Wd>TK0$G=fpmn=yy zi?ki0|6j=1M&UBi4KJ+6g8$m}hN=)1OeT&KG-ns7JsVuU|HmpD$!&IqEuE=;8E-RH zwNB9fLjHMVgDemXaip?5OmP!uyg#umea6++oZqdEeG&EOYm+`gtqd(XC#a@=bVb9O zN7dy4qLyM=5YwnnUF)P9(*|1AgrqM{+4#ZO z;j)h=YU#gwJ!5epE>>$?i2bI9)QMe2-OLjd#z~rs%~~3VG|Mub4*W$@^$ItjTng-o zH*ahxYp-i=)hSiTS4lgB2sWH7PUbCsI5$auVuByu2!86uOP-nvy(}ups3= zDd83!q_ya03oF`9uV3{82h=U8@;A#{oh^zyrQ{@sZ8BsN%1-Vh+7FLW7r+Da&!gH` zM##9SrR%4ay}}vlQ(B}#EglsYQTY9@T$u!3NDvi~AE)LuA)aC9wVDajiT)Dbj<^tq2~W#RpnIV$%TYVp+lF<8q@F~{<4Sf9rbPZY_YOA)EKk&z+$u47mQn~p1Bpo zPIxwC0RDrVW#;+&ggss9^aP{TF(B znl-iq=!%#l`ui`m@Ioa*_#bX1Ml0a$<{@3(CNG^?7qGuhxcmDs+{w)VN&xnu@I;}a z*EQBWfc&R8_Dt^j;}$+*OdRE4YPwFGA+>o(IF}lar4|qXM{))xUbwX4)LXSeT`p!U zgk}{(rgP9zHg%s4qIE1YnUA@!2q)&g3EBDxKcd$W>g_6=SBogSRM24$^qL=SFc|ol7cD zNfme!W(eMa^K>ppaUr3AIb*3poH*BucXBYRB28ajgP#qYtjNd66)SEaEeNLge0%ve zIP6aL5%Wgf6!8-G;BpefCMJ;8Fj9bnM+Iu*$umy#NquN&#`03hfieAdw&g(XUVZAA ztFeR4T2PD*LWShB%9h3UE`0RktI~5t*TTY)ndiI}PwbJj z3dFx2;YhBhk^T1n7V~m!0X1>TlTFW_BwKD=f2YQ-hvqucHd(hEf`%Ev#DZ~kb-V_4 zt$CxU98;RB9;Ce(O@km`iFf|O>1GZx{1ctS5(wA%sU6(2z?9U8WfVgS)uJuTls2nzR&!9>gH^x z(CK59@wE|kVc>^W&{$QFJj-{gAQtwxeP~ulMs3!3rAKIPt{`tf=kPXVrGea7Z?)I?heO&|~x5!_4t1}G14Y&-i z&)*HuxOuj`Y^wF2c5!HOn7{H{rw>tWP_x(GDtLNZjLlbl!H(pOTXU6}-yJiztk*G# z*PjN1ZLqg^GU9BTsU0>QG4u&^doa=wgZo`sTYIl;9|w@$zz~h3`a7vOV2OPr8(;~TFj(%gLXo6V zCN^b~Z7v^438j_PYLn7Ve{^6U@+Fa&?61Qnpdm;b4<3`OcOaFfwz7VZh56J( zEsu9EFxS0Ko|1ZWNcoT-)AymL({2gcz&)}iZfHY=3jCYG*xBoA)&iYd5l|u-BayxB zSPURLAd)q5_nG$7!`8Lz;75(*QRsAvA* zr1ML$`OszQ*K;wyf>bg0dX{Fk&?{$T48Zhg&_dFXTZ%Z5Ine{YK%;?%vW!L1g&?8z z0x2-vFKzhJAPE4Zdiq$G21)?tSPWso=!oNn;-m{050n(SqraxxIAvr}sv|WUKbYVC zN71J9?YAeoL6SZ2$uNy)it;tM$Of=;bh0*1mJX13k@s(aLCkUey$e4iH0#F+mQr?I79TBkraFAfB;c)utTQ| z_HnEwQZLt4D}{wfPYwj9`aLMH6`9s`|GP34o2yl%mj&4$&O31Cj zPA6WHeePh;a0SRLv3m{DejIw&&w0d$E1)yVI$U9-bPz67p#mmeB(QBA0=LD+(G+P| zq$5ttfidtlKAtWW+pol!sPDGM{*xge&@M?Ef-u}iy;e*`ql^aGb>LbHxfGJ9`B;QW zZwtYGA@i!``u>FYs9!knxwShB6BD#b9UOwwISs!N!3QkjV9NN4Q~5o{D41x3ej95n z3xw2TLm0BmWF2z?vL|3ivj=0mB*PVaCg?DmIc{JXvP4WG(eAHmWpR)z zc#1N!oR6eCh+y1Sy2B8Ph)I-jkYRO*&%q+1#uh1=#;!F~OaHyn3(VPGp8H_gvXZV+ zLK~y?I0T^ZTv)>$g-J%=aZ(nh9zYS~s1VcxerRR`6|U%e6*+mVINIePS}`{#Ox_t! zi=*^gj8#tty9tfRvx6d)7?F4Pe;bk4|0CWv5qKePE&bKb?`y_*F4mlY`a@t;t|dnP zc*Dq_g?jm#6fC!}6Z@PfKDHxa93$JI)>>KoB0$6(hJB8v?ttH?&z0oulsbT}{sV4H z9cWrRQ|hoVCYT@w2Dfye)PaxatVG8?;@?;5{Pb@sb#{;ZUz9ppQ|a=)lerycxBzO8 zrHeviAF&}@n5Cv3Pd8%777Yof>Juasfw6Ru3ckx&I(mZhS;C&4Xq${k+|$$G?1fgG z5xhuEqsYH)I@Tz1X;$N&ZmZ40F}?#n^o)80W=6!;D8f^8Xp+2*gd4AJ2uzO5_c|Nr zK!2i6`Zt)Ul-Cy^HOxB)n+iPTpip7@hX@cK4I)6+J&^3dqoMJL_qm{_`QHZqY)eNF z9_{9Vh*7*58w}_0Je!x)SZVUW$Nr(hI;%$q#bZD?F$V% zAtE#o%OhMbS%sy4yV?D|jT!f@0Y z@GrpFE%aQEjE&U1If{)0B@s3_LQ@jyAMS@rBJc2ds4cOA#ZdI1J%l-JY7)!aCYvjG z#`KN$D=U4`}Z&rf<86QkIZBSVlj=3WQo!Gz*%I`k3?h8BTs^c4l1}e z;RMX8NmgEPceScxpAvX?Bv?XdM&_C&8@Vo9Ube2yQUop%;~qj81*P&H4y5*}Cmj4X z`(a911?i1BRWf8u*%no9t8nzYj~d*_sk7`k0l{cbe79XuZ~ox;F*Ap(q{Gk>M0=q4 zxK?3|lcB)H!YvPXv7n|7F6NAPx^(ncOShRz-Hz5b#lloK^0*tJ>b51#w6YkDQq@D< zN87>j3jD=Oy+71De(+miA$YZ-p|H9el3rD!X7Y$@@=a(OVrCjcs^5_cgVtif&N29k zPp<3kIO?WnTGGLhnu>Wi6NgC}RtQ=Ce^4)W97doIHHz zucuE!o*kdz^lFhACp-&CiA^xb37EDpkjWVw^$Ko0ZC)E?r4aVq8FtQTc&qfaG_UIV zxiC4+!`v-DAUkPmX3{eSHcb7Y;73^&`hTeJ+9x919~TSZ&?AcDL(>Azgu5IJ5jN|# ziBV>ER5Ri=2S$cl?H68-qI)eqW3U0+63(VVo z;k|f8%g!!Ub2r1hV5%3VAA3hw!^MnT5>iQyw;b{{hKRhw6lL_bQGsxGKj}z(5CKeN zh@hGt`hO18yx0oYH}bupm;_VJ$F5!n3}LEJ1p^#hSPJ5PHrI5xpo*_acRb<&dDSq{ zl^ar=8k^1V+Mq0n`9}Ym`w32Uf^A5TUwF+zQk}r8uQT@(JVRlkQt(*F{p6Y9?kD&G zK^C$)ckf#q5J=`&`>^-{!KWzeefJ2zIPwgQ$cB_Bv;TxwK?JNGm&oKr8wR!m+_xI{ z-2tjA!}`RK-XVhdX^yNbk}e;Rud{70tkV^g>j4~DsFm802o;*)XPqAkF{d%)3{+_k zI$%8-Vb&u8wiVitqgd=X?)uw|-^7{6K)_n&;(nyKUg#~YiRPZzvepSW0v_e0u+C>*f%-bGue83^}4S&*EweSTV1K&8ole^ z!&-P*ydI6hLg;k5l$Iq`ii@AE4U`p~zoh+vXxLcgjn$zq9C94Y;`-(&6EvET z<$)m;RZ=A}%9dki0fwRaWB0!yu##(#_B&Sy0{Rb_bWm%1eeE&JxrkS2&CLzfvlSWOQ-Ire9S zEGfPb#$}m+`^#^UHgW5fW^D~ImX$H$(&j}EpT2?_n7yENf|ff*J?8Qf=02wCH(DzO zHurc(r~J5Kdyo8{9vtHQCO$$Q$Ny;e`%f+_Db{#@FlWB*h$ zG!rUS=(VtzRWSY#r=T!~W|E?1?VYZZjuAS1={aZG(9G^qF!bxV;|NQGhJ=E%Ez|pt zMgm}>xWsuzJOW%}&TPLJNtsU4)IPwuJ(}r;OvIShzGv=zQq)Y|eJq0tA{k4Hmy5(h z!pvs?Fg0B1=Qt z!Upo7Hwh0(b-4*l`umyjfPK^z*QVh7jj%Cb!mi9w<;kidwV2E6ezguv6}Bh022?a% ze%onr&>~#Y^Y+*w%f6wV1ajNLZ>2dwU@rt~7SZtrP&}Haj8RKhAf7hRN-Vnf?vXRXqh|W~Hl;6ac8N3q+ScI36Z}DU($r;_8H(tT24B{+wOD zctn^JE{d$HuPLzXsRn0cq>3CIu61EfEOW_96R2X%||yel&92^$NX zS@r2zSwQ0`J_{EQN06gP%D{2(WYs54)N}pdI;`nkTwgZIu95sJhK&R52dLn?v%>ehI9=`^O z>#>xWQntP{Fl*LM(3vbs*LY&zXz_iiF+44|YB$EiKV)XJeC@)_2A9%Am&agffb?n$m@D@FyiK;Qb;WO!unPh`=pG%s&P|3L?9-!nrfVv$ zGaRLP8{~BaiHjk^t2qgjhU{2kJzSw?Ny%!{OgVlD?Kmhb@7M|wKbD@>yxr*TVMrgz zjwIUS$UdOMB!hk^F-3DGl0I&t&7IM21we}vm>NdLqbnazYu-kO6_0j;pUTCOW;9Jk zyH}OhD)aSNiO-78dQgb^o8x|y?qa(08#CPbWpzEL4g+9qNY`%h$g3cT8)??B@nedH7gtKt70L* zsF)QpV##Fix+SDd1 z=h6$^AX@Vela7A`TX4{auLkRxnhW8^AT<>&Cyn7v*OFlaJa52>z)&0*tNh+`tFn-@ zrE_1@p99-aW$8~9!&Z|}Y^=AF4 zilQWNS|Nr7oY7`CNl$$%HA#3pNwj0Jz$J-tR)nN0?d+g?sM~yL@WqS77#;`h`%^=6 zN_L3FXil^00+j5h(>J|dil5KM>FS2j(x;*AuQ#NR+3VnPx+!d|^8ELfmZ8_&W<47w zl6u#v>#|=;{8NP3G$lPV(TOhJeq?I`!<0uPT4Q8aYFI2e;Tmprh9aH{UD!#+@@Ro{ zEyQ*9S+Vpaf-LLVw+KvO#gPis8wWF|3j2-}@wD<2gSf~XnaspoAQS6^84x;9`t_hC z=U)eAJn(hML$0%-sn`5p`lYi!&1eYqXR&wiv%~D0S$w<(&yD$GUBn zO$*1Ssm6@y-kxK}QG{HQdr5!AdxJ$rTvsvHa@J%ka}vybxhm)EWPF|m&cFU1)2pni z@SQ6UQG6S^A-Bvwg^x;C@@j@8u~>M}N3=kblQA!8#F?!@R$>+Avw;gY;LIKZ#Oajj zgfj(L)B~d!rE6z5J8f$iNr6%hqn|ZMBENVC1^Vj0mT6DbTL_jmq-C0JKFPv;TC;1J zUwa>6fRkT7|Bi)dQgHM}#qx~`pW@5DH*2`wDMpwCr9yhO+V6UaXUlFFnGt=BoiIFP z@fu|271L!QT0Zg>5}~82U(br$Tit@XaQ>H3w`hQkMnG2SC0%z#L#P`3n<=Y)EF3B~ zj6dUM^qg@>;q`@d`S4ATaJamIw8#Q6U=`^qKO}!Nl&nvVebL$*^vWBgj|f4~uDoe) zSHISZ93g~zI{9oqK=X7;9XOjpjj6b&qjQIZAY0lD12wkeHI#_J(GBx-S}gn=e-t{< zL6mh+9&4LA=|6Wg`6EGg0=jyq`Y{$d2h8@O{~laFh84%``Y{Hh3|5DUAY&n!t{*$n zNzXY#&NLx_8-dV|fjKWxUZckZ{TS%Pas60_$VPveXkyp?9a`(5GzfSDJDEZI&$P{~E z0^ukTjCsmmB&v~oAiiw0f_^P&_c9|WPh`!}yxB3lp)WJhaqRLybEmMnb!&fe>Ir!{ zYX1s?RB6YcWZ-pcu_zTF4$FzIsVku~N!_ok9|38M7OR88`LGUlnFTj$?d1Hw?%#L~ zjm!G>)MbYp|FJrN>>3qsd@lwq?B(Hi^A@+N?0A@uD(CmQ!_tGEyfuxcRq~8V`Kp6= z7eqAekq&6=cJ#F#c;i?5s4jqalj(|K)=p!;Gx}d7WS^DtzU)Rp?j0Z;WEqa;4|05s zj)OW1ItAprF+YtP)oWP%dM6q~fs++>o4;S*z2v@h347kk5<_hPK|~xN#=Qg=;vua{ znwDlz_Y3id8q8fsLdG`>M|lWf?kppaXjmE!?uo2<=r|5Z?B>wr!W{exh0jL8fDn-Y zECa-2E!8b+vPN7=+Vd}Pr4;S1W!wj>j|h=Nn^lQw>I|L@6#tlr44c1AiO977E?wG6 zZ|h@c2YRbbi94J`6lkdL2WV?_kRuAW2sn5Wp3^^hsNKI3Xn4bQCM=CmzYaaG^mlw? zQ{1ym1>?x$Y763)hyJs^-4dvK3CbX1$ddB6X!U_no54seCu)`Xk<%4nhby$81#a-V zWMTsQAp~?Bf-S>Nd>L`(bT{1yKsY=5nf?guc5g{yT|Zt`x?S}28FA&MFE^aGYIpZr z7M)uAW?%WCLcAF zKp62|KW&-n#hZO8pN=mad+6ctgs?{cX0tfkVY5Q7RZCtKxXBN?We1g;IYnM?YQHQi za~)@b{4qLaHfi~F2e>;s&Uyk1OMy|Lfj$YLba^h>ocd>kiXut`H=f z%l}EpGd;lHmsggy;!CYi3P_Tpi~4mx=uw4Xv)IMcW<4A)p%Ey7@80MFwA zMhn8YFK^9l^G3`tjQg@%Z^J?N%dthrp0OVQMI8x)Xb(x8Xo`x0Dkz9$%&SeaqSOf` zJ(0TKOYM$a^}r33nc6Y4MUn?Y{!`2|3QhI+$gU%+7H#;SU}}LuC3&~v16g&VEL*C> zWNHDWME{S(9vXlDY)mclGpqHTYhs0oZA-9}=}ax7j^aBTQwst<64n|_Vj6oJDi#bH zt`AkWt^v&qh=7PDiXd&?os1wDe5A zK7H%aP6r)c1pbuq@P|TE>tn42mSwR^J-A=xt-FLqRF0nKcXEd8j`}~l($EWwhfimj zasl~&)P}&?NJdL3(uNkIk=;=*_2VrXcHdmz0@Id5v!gsh9u;H1hxwmLQv0m zQF51q(7R~mbs6Z8jyX}Hk?YWk7)mv*yCxiH74`1vP}KQJC6lkiN8 z;kHF~7+$s=R5Cw+`$Qz>K7n{l6XPM9LZ_IXRCU~^RVZ6U#!yi*D;b7`k-qmpFRv(5 z6}*zUlK}oj*bF*@xUJYZ#H4We&{~tuTv?&dp)lOh>HMmxU_Ze=cl|4}pZk`n7S#X8 z9Q^vvJ|g1CnN?43{fbaj^^9o;Kmt`guAELrJu?b^-6WTO7Fb6;Gbv!S9F!L1Tq-o9 zo}JGDNI(*z2>5o50dW#nb6{_s#wG$QN?@2JFCI(i`-3p#c3X-i4V4X`Lvel}i2vhi zaE@Hj+GURs$Pu?+xsp%>fx}h$G>>x%U@r~5hhRoD{1Q>W>T30$SC{)$!c5%w4~z>G zds`9veZFe5s-oh=^O<2TZ_YcJ59a*)ezw5-!Z}Y2EyrSj*K#Luc1_}71?ju_X2{H( zOisZz*}-K|F6(!0(t+X@Lur$HHupUd!_29J;+P7SB$Ci!Q`eBp3UBJlViQ3q=5y9~ zS&w^Nr2uNnwRuK{_ayo(BwE!Qm`+X;kRfYlPq{FKJ^h1w-?jQX{1zZWeLM) zOsc7eiMur$=H6+&OPZ$vY^a(#u_chb--&6oSg7TOhNA+jJ3*_d3flY(+)-Lm3Y1F~ z!4e~FKh^7{XIqFBhAsdG5Vu8s1|cJ>m~1vUa)!Cd;J+QZIZPmKohHYo4m7jq#-Rw! z*n@{aE5{wl_5rg<3vbrFe&{Ixk;38aW2`TP_;x^PL}a;6Nr?2C28UNPgggEXC`_=A zc&DRaj&@LIKwPfE!_RyL)hUEK>6V2kY70K?!xCc_XSpksD$Xbbef?V|>the~{@0Z7 zF;U5quepI)3xyLCM&i_`L6?NH>Xyk!FbPFWyqSmupfn_oya?c~=@ow540CVBeBgA- zD-<=q6zO#s)Wfn zrq}zQR?ZKf1n(hPI$P+q81LvLq-{va{l7{w3c24#n+fM8uqewM7F<(5E$Ro$F?$sc zE9^p&2G{qvf=SE3|58Vd2DK?oM*!Iuv)2jX)GkyxdX|&Ox<^uG(-m*G(ydPl+Wf;d z?+MPx$!~AoE8V~?2{|70mzLSP&OqLDvopsUsz^R142Sx8XS^^4<}yB(#DD{eR|;$*iT1YFJtNi6!|`GucOud`Kq^!t4PA9Eps zx|JraqS7K}u7v&ggPig4ErQES9+n;8Q1%L7RL*h==obsVG89-w3F&lAZrL9K8}UjB zMu_?-NB{5DH0g*rwn)246Vi1k@6kpCN#2hJ?=oWZX(mq>^^mNb3f(p?_ObYz!X8rZ zu-^W2{3cT-=d@*lV2r_@B3{0crV+`^HgpA<=(fMAeD`zkNZcbz4+?18C;0n?zob@H)?lvWO5&|dw5g(>yC{y<-T;7gT-1xBUGsAM{(C1t z;**|twPL;EeBn2_TQ36Q>MS^^d{hjMh;sv*p{J#8v=St^hqcIeOIDc}m$lYB{N;6h z*_$e}_QploDx-D_p981fkdO!1kU-*`)#moPvQnZdd)@TCW=m-GdvxDk#nxzPTlMRU zqk}SX;^zyTUB@}OnmLI>CU)6X8avGSTa4zc(-`YWMt~o>RC&r*6==f8n)>vluHUk? zM+VvF6A!&j?{Fl4O#fN z^|_{)GFm@|LG#C?VPKc?7-)-!I`oj3Zi{wnQE`mA2)VZ@dba-WB=T}(hdkbK zVwX*0yL`cX%^jyT&~BuzJVTz6h=kOQhmC~Yg>Y+~Oj~78Sm@z#(Y{e{4g%|p*<8|gKJkz+(;VA!*c=hsmr+{*)>)ej zLd=!Hx>c~_bSJRu$v^NPiurjMf+lJC0TGEm^7CL@R{E(xTaN5iP!Gx4lA|7y_T*%r zj)*%ZA}-aEV}1|wTy>Y~OiN_$XO?YeVAopvq-e1swErhPK?Z(_R`N>Q3?2VSivRHM zr(y{|TMbaX{^HP`)73xPhGt1a8iHOVR7-KT&KTk8v45$ncV)l-WZd)@jaB`|`4vt*wI_Y!xSEpk z)q=Jh`9S=QID7zttC)FNpo5ra-y2V3#^HGFpEOWuADVdc{A|6Qn+>3!>sO zo@liuXF#CR3!|wpF{df1tNxZp>SH&LsTaK?qX!}Sv1fqeoZ7R0f#W#NC6+7fBfC+Q z1nrI+(!+f8L+T8fl+B?}XLLID_Ik{|H<0jQ8p#q-kd#oxjYLvHgJ&%1B|Z{8sS9`y zK|f0ZNZa~y7P$K{XAv};;*N&fO|veeRmRHk!nNjySC=>VC)9*E)W#uSk-087*R`f! zPia9Z%rQ+6n`ei-c;gfxjW=mf2C~}sI9+n7{*@;A-6`5K&_On3h~zGGegk(Zj$;Df z&$00@;9Kmv9CL35)O)t@yOx_jt`D2S%dS$MYT~{-#kBxNtPj0{(QotmcU6~<4iCy+ z)W zZ`6H`g+wUzXIF=M!^m{{zL?ryr z1fzw%iaj%jmreRSHP=2L#*U|cApKCt?=Sq!UTSJT?~IUpX1gs{WZUP2kat39Y+qxy zJ1*cX68c^ZdNSb3m#C>ZU=+u`*D0uLoikmw@ekSO1j2{RO{jzq=ymF_gUEK=Z+zFJ zxv927-Ty)8{AJ?mpQJ!G*v}c8xXkwlG|N3v#@Qt`wX*Aa19!oC3>#A9jf+x!wx&+%Vh+mYb>+@331 zEd4bBp8N0|ztg-E)ED#LKJnmRsW8b_Q>9Y-jsbS0NhFMC7Oes+*8~;x7 zcAFV$IkYAtEMt*hgMZW0u=CSOvYpq>Ncteq8A97)DQ2)5JB5oDk^WW0>K?LhU}vMgmRAa4hcWABVQVA?doPL+8RXGM)3Z& zjp??RvurCwLjG%S)~~}~Cd=<2-?E92dyT)q5zYM?PzPVR&6*2ay3Zkfo0;|=0EvR_ zf^sR3^jr&GvEOd#?Qh8!K>NYinJC-B4_*5B{P=T|p-peyV`y`b6n`bN9H}j5QiW}P z@=SE{xcjXu29S(`CzIKTJ z<7&v`*8Asz+7+DmETF$_y|Tql@iEGIcDfn;j3Px4w(DxRXN;EC7WDk1v}Q|0;nl4% z-FiAm_eGQ^&$3^?IZ;qDOV!vM=q3qm%`2=5t!mF(5-@f6;$ToQSH!<`9VZs^c2;Gm zuGa^pZhky`&v02rq_yJak^o8eOn*_agH4=qjxxFI<#Wno1BTd$<{sk# z+s)2mJ+ct;>A76}&^{l22RhddC*ZJw+1BuYWKR^yYVmC)xS;f%OK>ona{RM zy$4Z>T;HD{*4A^5-|NYtokcQ?LmaXd*@pHMR*69Y4+rli|H((;`2H=`6QcFS?kM>L z2t3YTaZ?vM=D#OG)_>1ROc_50A{gsyUTtfVpt)MGmwoBeSH=C+uHt}{V*B`4>R^X% zi4a6(T|dzTQT^ewZg%P{X|q#L(M@=y_aAmk=Zv3&q9Uvw{;Ral0oz4HdrI>JxORT9 z_&l-0+lTpBlg?P{-k7u?gWVYc$Ah+<=h?v2g1jy z>jGB~^8<*x89rbm5A1B2zjI!F{LUDRV2K--} zY!quZE1SM9RbQ;OKCP+_nLKrQtLlx)VW*vW{ZpOSrR6DS{NNWBoZuUoBfFS>$<1f4+S$Y*zNoQ& zU%9NLpeDaEzP7e5!wxwbOEMD9xBCj(s{hmGU+m|X;~g58F~ur9BR|C|QR1lZH~A>w zh+Eyu16k=uL`|-#u++oGk zQu89QoC}V}8O`xv-3Ab0ukCPF@J^PdISRjw5v=>cgK^PxlgbbwQ%YppwAiohelMl_1Rm^oEU9Ad zZ0OnRNva0$9taOeg}<=;Qev@U$@oTu2tY`k9QSdY4{%OvuPgOS@vo1NFJ@du__|6{ zoGtA1{Zi}<4zjPJ?k&jMdX4#bcHYNVG1JdGj1ma*iIess4 z=7|<`{3=jJPcEAFb^%jv9(HM|T2?$5BHI`wX;s#gl%#}JU377^5#;>MYK!>u+GY_N&e=1@_>SX*2oG4|Mf+yp;pNOePiXjkGu>E4SvB( z7ayBtvPZF8QgZ5YU`FeD$)ls*ZsR7O$?hhdBeojec=r$16Ucb|Sla$ySe;3y<^M&S z3T_nP^+;##joY&JjTyz6C&9D$SW1QOgck*+xwa;w-8?G=19!cg3pLhh^1-RkgdGjv z-~P{=qWlKP>2Jeqc$?byW2@ww@@r_saPByGov3&A1<@DeiM*<)*RIi@X9)gh}30;l}!(XJgM*p zaXh3k@7pQ<3)KS3Y8}>FmRoQ}LEV_^C+Zp_GDDi5)aGci>LE&zPo;$l?t-k1$!C3o z62S%2HH`1z_{-&MxnB+wK^1~hE7z^GXE#r1q!%^Zq>p)%uJI-KN1x`OfMSKHzMv=o zprFg_6MZ@VhqdpHr@Hy<`}W6u_o&l#uJ`NxdOg?mKF43t?np=>I~};pK}Y$Jb}tdns855xQhoJbp) zl{=JYk^zAHZyC01RtHA@fyjjNBan6;_VBm;%N0TMDyE`8W ztW-djl4ev0;EG!j?z%2pTg+958T}JFaHXBC+^Ti57r$}~Xtr+Xy;$Hr{<-RiqOna_ z_F45l0ks(PuD*g2f%q12Wcu+Ro!*IM|LLP28;9jY5-2}L*yu9wrhnzED(Gp(;y7kz+fO-R2uvRqjwmf#m?{rg1w#SI;NfHN9fLQpjM|2Ef0#vZrea_nwRcxF6U~DRyyw4@buZk>>?Is zmRIUvhEGc&1q092!@lQ3WBUOd9Yq-*^14=MH<6)KKXNv~cSZ*A_k-d2(M||sbRHjr8~l=nNki-Y zgBkBdnh?ArERpWLmjeB(Kp<5V`}-Dtg@_}3cB{4^k%v@_HJK}D$!)G`;pW`;eXNE3 z@cm!=1AOP@-*F!ic0j*>z*F`Ej^jcGhB@j{NMm*C4v6!P8WwqjkzVWMdO+v~ig1Dq zzs7&Zyu;bUh*=FFnnW3V(68MQw;I8n$jIv#G6ZMWf4M|JiP+Iv2B3_Zg)}+JT1OaE zi}g>^% zBedH;&B)K34LqIoTk3c9AEYv9!5=w1a{DK#ALqZPe*chmge)*0r6VU3`*SxY|B(9q zfp&h+bb)ODYwGt$3L;SSy8WAIL0Y&I3ex?Zf`H;*+uO~5TRaZY!t;a;YTSmDm6W#Z z8rTl}jg|0@S;>}<>~muU6=nLY4!-3;%c2tNSqdH{go-?(rf`V@zz@h?%lQs*FI>)69#qA> zb;=U+2ZaBRLw7WdP-VhVv?k9Wmp7prv2b2(n|aPgQAsU)^-PRwiSM z1+TK_szzWb%ZuDUPUA^G0><4;YiQ?J1xFUq4{uvy1Mz(%ra>#QAR6I#vXC$Q_EV z^nGgUD2hz)zf5^aaM>LGbk5XX5MDWS=mhINB)sjclU+$+Udk4MU%9t(L3?bt(%Eh^ zsBW=;cgr|+bX040H`!^A${gg7Jv4_ua>$F@(A6sSjM#vf;ciHBV$Fe##_X02Nq`de zpH8HZx}QB(c@yCn^`XEbhW+If5ShAE^rWnQ2~ppa@3=pEX~6VB%H&3stifY+=vzwvj=c{+Tx`kkfj~qR>H!qsXGAHwD-0QD0 z=ZOhV`YEq1IsZKY0?(oRrD=|1!yYKySu9zgdvv%F%7jyq(GgA71Ggkd!0v(mQ_K_Jb%&5Nq>Qs+3Ar7>6I<6?)Yg1;s%FauFc6M~Dc-)MS zk}cCtv%sJcJpO<@egtJnGlmwL{RiWGoa0?XUL>NFM3`{~m=6>Fs*6vQ%ZZpnCLuov z`8dG?M^y?x1>A2h{T(LId%<@Ghc*J_zD~XU8Z3S7jcv>G z0wAz)F3kjoM=kS*>ys^w;7}Dj?)taq7b>e4=DR0VVJVr!Cr7HL(&SlG` zrBe)fO4}t)>mci8-mmK?eCAl@|EjDNab7((+}i8JM#W3?ar)svY%f*X*uLF5_(1_S z>n+#H4~pQsnf_%(;HPG?EL!d)ju+kcwSddGIImlbuMJyF=&aAAg*uPfuT+iLc&$&q z&j$Ep0atncbX^d9_^4g(ANuOITgj1%NA~*x6oM%X7#e?(0rcO>3conMMdU%| zF=d0`SPkLY|9pWbGzAVa!P6_u8R9750wMpcZaS_n_;xlRE)W+;_9v(N%LN|S_pj{& z&_(utM;Ao900AWS#~C;o#~PvY9UI`+|30lqD|Uh|SAVwjfAvJluL9_Q zc;NA*n$my0<2cZ#e>cA;_x%_qkaBY7=T4Es2ObI8{-=cWq^3%LU)fN08Ki5!uK%wu zN51f1q392{7T`hZua@`k{dF?AKfSU09~sQ$)k2)$JKSqii|Mm$`}ND_>xg)()X}MG zzmx)J|HIyuUZ-*Mtd*|Vjam2pc0S0`^at(Ak5($umZ`KXruTl?HHYVvYqMP1_L^$kT!~kxu<9Powg?zq z*y`<0smrZgEGkpHX<<*baxfn&%@p`FG;LHzQ%|K$$i|37}= zf!{ncWwW=iHhF4fU|{o<4e?q+@TX^yuQl97J>#)+8f9+i63WHDy%zaTZm>QxGmVC6 zJf)Sg&cv(?_;i3F*;Ia?nC9F~S@FVicdnXaK5Eg7P4|hqMb}y?-8-YZT@_0ttCKt< z6`^J}-ekVSm)!EXr?*O$qu+9SCj~wY-&I9~-n z=!e5B;8Q8F&W9Mj-%_ez>lTNN?Sk-WDwqA?D%hdR!A9daY`G;CzSbT4aCch}z8O%p zPYQ3ZI&8FnZ$(rcZj`y~FKsl!50(#SW;TWe4_EMA_GEm&1-QWI^bdB&;V}Fv`26?w zDtNZw;YLcVejxZav0#lu__E8vB%8~W5xlVqmhk;>IlF4#f`SP)ulXEDirm7U{t)&Z z{M*G?_|~ioe79v4e$Y7XX|hSb>g-g+*Cu#aiSx*96KrqO1)g1XFn;5kj-@4hnCfsH zUl1M}>m}voyvN(Py9z&CWrM>asvx_tSYozPl;yT6*!-*)d~dkj<#1|h71YS$a5`3? zy&8O~Z2YiA5H?J8u6{8M?ge%V-ZaW(6gCwwJk`2;^E$-)P|#%u6s`}p>aw$I4WSZ5@;fmIC%W3H}_sL2J=)-SoF8m*U{>Rj}Q5_{i9P?A5s(1jJ76O!C!%3y8gl=K`M$ za4F7%N4e}wtsVxn!w>Co3izM%Mw<`ACp(ZMwX zsgSK**UIELm)(@A!`&)4>O3hynKQ-qKHJ6XSIw#99(h(BtdwRg9TId;K6PCFmObZs zRruWKp=Td_m+dBeV;KG#=li~hl@3u^!IyZ(Et7hErI9Qmo%Am`%Folir_{eI5~UP; zDPe3gsh3jH?DOu27HcpGgj}!n4G_UzxSz0B;hz_hQ%U~%<7S;WZH}NX?Uj8E%kBx( z)8vzP@vGe*Jh+q+9pWUJ)lx@PjKOUK`O18o>~(ZriD}CD@wmCMh{t)+U3Xk9D&1Kz z@tmQr1a$mN*Dc*{y18CL(dV+ex7}28o6cs}6*orkRCi*~S$-Wq;elO4+S)b+@ix?k z$rWz2_4$LR1G(mgOQ+wEw0$vpGcZMx9h4#{HVAq4+n|PoS zm-tBUs##~3zjfci*J%Q|0_=qjj1Nj3e5a{Dxz-`AtM%&$?ycHhHtC9%*&6D}$? z-4&pDK>g(62-ekh-PIdBU&ZFS`@x#m5oO`7j$3^u&`b(R38Mx@@yyRSFB&YTBllvl z-H$NNOa5}&`cX}6b}wUo1xub$vJQOyy;b~lXi6aMne(f&Iob5*WVLyG5+CY0VGqA> zt1k|K7-;c~@v`Jqs0M!6uFMCrjU!+|mF zni|{?{Kpwf!tJuKfET69aMpMFxGGCxjM|S|#D%D5L;P3sZ^TiVieJNTz7w{@L74vN z#raNAbgD5E_xTY5$c+jsF7UkexRP_zQ z*%C)zge~%87|IF`1o{)>K_7jrDIm@xcxe(*C3dg7W6`TG*qrLjxLAtZMc)}(>iro` z_O|W>iAx{f&Wd!PS)Di39uiiedF0t2Ca3va!x!zU5iY&CoJsiMs+lGFPGZ5M7uY1C z9O|?agND}=5(T~H5B$QecjjSvwQL#3;! z@#FaYYcYmzGz*JCO>fLJdX)o#4K+MpzLUuVOjmJ$H+x-^Kv=4IVAbb(Gn<|it*CO2zowa!#2-tiqA1f!q@<9=JG?Zi8T{ZKv5YmfkszDfJ0Bm~ z=m_qhX}5P|Q^Q?PCllW7u6~FgkGhdN@yOv5kq?wq&lTFM%xoOLNK>+TxW|?GuqJ$C zpXTwG+)YWD`UHQ4+|)>)_sJ;+S)Lw!4ev;5u&|q?*jja;&geXDD5~d?B(XvXv8lNt z%{maAo35$Y8i>6_R%9(Fr9&dowasrlw=HBMQNy3G># z_1HB>8avo z^Zjmi!@u~I6$vZe=DsgC_Y~sJvxZ@pMnzJS@T_EN#`$O}j)XnGiwkoe$fbjnGVRtH z(ULs3of2o=nc-ZMb5ZBKz*A!)TB=5jru(|T(u|cT=(kha$=>L61xIra2J}rW9uWwRqSpP;};v= z6pSn3)b8`J)$=*Jc4SL9?w+o%g;cwTAEahw-*j%<@X<@qQY065Zyj8ZBp};gE@(3$ zX(BBn-`yF%NkHjh#4^9LBFbKyNI=9HE!wba$T_{=A=3S+!{TWyNlhe9(*riMt54UC zZdV%_a<3>Z`QbR0YBIit`H@RF+72v zcTp!sw5|VU3IRzhu}oRm471y;$cxP9v$?c$5!@kk?(ysmMM>A5iVjLXw-A~=m}ZR> zS$DVzdtAR$w=p#Os$WpO$b3$EB7L=GEA^Eb-FxCrJAN(Ytf?$EO${l&g5e|;xpOxY zBKdi2@Dx{4Z%i%Om1Zy}gx}h@^m0}tNAePQ@sOgYTmM^dAMc-=42p~&AMQB70TsuQ zmbpa1&Ql81DEvJZ7lIWGY?3sJ8qv>>Ul?VTXFx z_n3D(Vprr_RT3G-Q%PIzV}gZo{pInsPMh%1idE#NNt-`IBF(=c=vp>G5t9DMtH<_-lQFf|jtdD7Hq}N>0`7 z<&7Jevm!nLn*1{{!5dwMTomPP0FHwK-((M|Z`<4Zz7Y8g z!E^D#S~pflv-F}{BdZJvQ}|L+t3CHy`T{aF9G!#d;OU)9#x#=$yypZ`y`^4}u|^ED z?YGQZKm8~;Xd%eXrjs0m%vHBM%viwxA9k6{SJz3I%OU z^ebi}bPKK!?ZGEj^Ue?C5^BS3n&ad}h{B*ZQhDU=(h1{&pTF|-nZ12w#qIHVm{EHR zYNl)_?q?}}W1+euxK8a!OiPumd*zak$??U}_M3j^2GxX|a>=N+RE1rqI+U1kHR`B` z%AenO%xUmck29&+oRc4N{p%Bg=^0^hNA1%)BL!c}yX&_=|0D^qnJ9}^WT^R~@frC^ zY2V^!8XX@V@ckxcBH=NH-D^og>6>e3OH94I}C&qevg8 z;1}LvNucwX$TheX{)}gJYTVJlQ9FN;kmf^WzM2-+TLg8TdOaAGKSo*}EE4HS4L4%Z zVjGQOj?@Viku?}Do){6;HLsWuclc8IdTyt#tBb#Y{}aY`uI-}#{rgQSiD^$h?$YzW zPBDlp9Gl~603=3`@VtuCo|$^14gu$hoL%;rJLPN@WfkJF&jhMHd!q)7ruSi=}eY7 zn?Lfc&d4(^ZlaJVR6TK+QtEs>xDg|Hbd=-Z_h|`OlD$hCPcD}0LAx>nNEG&Qaz$rzvGU;kUg2UF;t3Qes&!?}BORO% z5!@~!?EDV+$$xdDb`k&(1qB}llu5exGH-_ae!g_Lgm419{OomQbHxY2-oHRT0XalP zGdMfO#iEBTu8tlNKVNSgyQb<#!2gyA)S;X4o(}BziNFDJgWO zlELo7pID_D;If7PpQK`M-+vCec{Bbeq<4oM4z|z7R*>I zBj4WzXqhwG+~+>JHpfV+q|lT~7Q%TiwEy}Vrjxd&HXSbH;X)E+gowNIMTCS1<=o2( zi`wR9yK(?H^jTR5MR$P6>3ixl6o$CZuNE5O+H?j~2~gU(NP&Fk{atvI`cTKh!8%Q~DvN*F2WB8B44&>CF_hjFJXf8$aQ@e0!vi?q5xs6Q zmKsDlgR3}Nm`C7I`mTIbEqr2M!+UNAD2v8L6+2PI!HEuD*|hv9s|6K1pVZv==?=ge zhC%|b*vuGP&>>uaoMvD7&6Va@T_>0GZ$0P2slv`4hPx%%`pU0v%Wb~E$6UAt%}PeN zkxCtaCI6y%-773|QH3?n&WYi*P3@H@1O;5vGaDXki;N79IROz|*p zp)@;`liwW%Dl(9iQE9Z-zGGy|YnmOST{gEM|1QAf7~37$-V!KDem>x@S&kw#O7ZXo zEiM0w_zcihj2?4B5afPiko&C_9o2dsiwhg`MO2~bTm+6DXC01P@JK`N^f{&ScjYmC zq$hY1V8Th{#|Kf<{LEA4V@mptST30Qj4!CdRiW_C2=1`sUZ60*y_8J4UE$X<2e{MM zyxvVH+3?jFEK`l#SCJ!R*lOOZ_(#2azgNbKK#3JW$Ut_M&Z}OPVm%!V7M!`qI-nET zGILOYKyRy$XYgx~y7w7CZqX#`8fpcOuct)vGBtZjhwf9URtU--SGDZZr3o+$Bw!f2 z_R*`}T77e*7`6O(r^(|v=C^X+yf62vl$@U^yj|bs;{b!)Bw2ffOQ@&_cH{KpWI`u>+37Bhwum@0C_g4v?n~usW%B7)c(N4Pn=3n``A;^;OnZ}@>fMZkb zbXkKftK$;|ErLJ-Z57e^U7+EgfBf1)$Fi~>xUyWMHi8;s;!jzZkBzQfJvi}v$1 z+Egv2$3+^K$!kx%&@?-p-q|Ciet-PIRjxsRtacLV0sObw+yv~GHeE*}X8a}aj~Xwx zMyS|dgYD7Sa0h}Gn%uJtx)8G{K#}K)U$4yFA+pwRD4MqnqZS@5+Lmf*W`GE9TM=xw zsI-#bu*ps{<)NZ0xy2GID$7-yCZs5rPGG7k zzsc|(^E~1G2)sqxy#Ry0UWO+8j)m}UG)5y0-ZYUSnBUix{l((g>qp=>g}G^)=WLS@ zEQDyH{s`#cB5eLa%cGLY(DaClX9ynfY+!ap%;fRHk6>yd^~sn0jBO_l_F90eqnRyI zxS!`v%@kMYIW8wK2*<`$SR74})h&g~Mm#|Yx}4LseMVcQjsUQQg{(gV?n$IxDbG*K zGMektHwbO78P=otimN_#sk=MiKLgUr@APwy45nsz4vKkzKZyda)j?TSra0mQ*se)`0Y7mfy~OE?za$^xOuw^BEHf zLVvz@tsQLG{HkhV_6&D@uiNE#O@&Qf$Q8zYyu>t3MJikpYGcjN?1}KV%9?XBRcx)4 zPY<<`E=v1>Va0e<5CK9OPI`;tem;l0v{abj${NYOu^6*|MdWCM`>a9rxJmaF}=9#@#e9nxaD7;{ZW?juDUEK)C<=&22M1MBCW}1>tN15;To_Rv3n> zVA0*a1q(Vxr3zwRs+iQAn)s)2j`(ThMr z1FZ%~&OvrgE~^|BV^7No8fPYotXkzhLc}x%0nD#lHzu7!M3S0qzF8YG4MDKvKX#GP`;d)9MR&0yI%6$F)w?k7YX`{H9GH*Xen%@eMNND z(O%Ok1VZ-bgwNmtrK!XTP1det4WT2m_V`|Yw$JDlKY~ZLj*Tg~)mf>b0WJU1Bqs}Z zBv%W8+Zs<=>&iHy%#&d0#k=OMbJKlW49O((rD0@mE;J497;_Tg-5-}p-bZK}bT3vu zV9jvF)D(EaJoNRRYj{2$qfg3QT^4Wc0G{tGAk#D+Im({_pGPVBSLTzw_A*h7rUBxEzi1v>(rD^PA1vyvI=S zzADU*>@77peUOTh$w$@I~;`MUz)9 z7iCmLRn3GSfc;97^|NA$Ij9!`(TJq!kRH+Z{S7*P$s=95oO>BfAp7Bdzk|4Krs8@I zPdL=LFEZ*s*KqVNB17a8L8ypPn2^2kFgWPfA>%rS=tzd>FvYl)c1%! zn6D5WAK}^SS?{JXHVW06127QZA`!LVxHU~PYikh7bb!by$Ztst^*WJ9Ov1pzVa;a{ z`3yGUXrXn@d7Yc30`TW92}p5X8D+W&Dr;F2U*`Jt5#+$?XW8joe^0@vqCpw z8ji;Hi<{Sz28hKJdpSU?MER15z%){8*V+LP(6E^4yn7=chrC;}iVk{1-hDc4&$-A( z)tosZAr5+u1YE57*Z0BoYkt!H3M6LR_>qgy6h5uiRh-6_WO~%J`kIpyZzWpK;e|F7 z*2<+nae|<%9~WU>aX02tVptB8htQ$#7Mpr z771F{&&=Qo^oeS59@hH@wBxb#h)zpdR3;&^TNEixRg}?Egf=iUQaAIrwd=4puFtR7 z2rOiNYxmjS>9ECM>E~cuK6gSwds)TXdn<1C=~;5=;Kyu9HZS3V5RZCq`)_#%6 z_UJpopd?o5oQJ7{=iZM_dE9g^;6806K=lu2Q&z7s-8{{TR=}K))D1F>Tz3CG;crq; z8_#`1s*W@G?=hS7#vlJc<9Tx#8m{Ygv~KEyM1G4QgWxQx3U)9nC;;E^f)^KRW_!Zd z$^=o}Mg_k_;K9LBkdFu45n5kRA%F=16tE9yW!MRlyxaL2>!R(UBc%qH6J%`n$=eLq zc%2*pHaDV+d*{I054znIMEcWa@{p`mGx=j?Ap*>Dg|Th8C83`+^7;nvm!Ffm*qx6Y zRT+tkq954W>sb>TMA9sn-MB~`E4q@|Q;yRqk{P@&YOBW)l4x<9E~gM@APILC-D3sS z?nVFOGV=B6{0f&TI+(V^G9RW{e8wC)t;dgI7|2D3)$Vxx0yY@982e%%j(6 zH)$f{0Bv>BN8y(~y}iHI>1^h#%9${G)~}vyylL!Rvwicb*|(SOm5+87XcV}B4dgDW zm1{9`f|X3}a~!j_6Xfe2xc^8O=#XfZ9mn+MJK$xI}jDcR&;Z}Zr3J_tw_6k^+riAMuQHqT)DgY9Vac{ly(wDACRN5 zzKQmCoNBViS{hh=B6I)C#J3`mJl5+<9A8g!m1IT>lUgjhn!2nU-&X%s^E`2q?RVrs zE2LFqGSe@+XCGmd>^xI%XdP}k;YWq!l?xBweZ90!v z`u?0_Xyhap4&HMnvN;-$01XI34UAV9f|WKZjfL5H%R^B{q)z54xqC`|W4ULIh9+xq zHW8NzBz(&ONYa%HYK7Drp98;@`d$~O?tEJFvG)#f&1DZx6YKLbi}>I6jK7IJWxzLn zb5B-kxcN0h)x6>Qq4Y5io9zxh1kDkza-1)~Ui%n{&P%y1^HJYHRs9eT*LF!#sJG{q zE@znMIWDq|^y=CAX)fGS&-^P~*A9^FH-#&@*m}8=jpg>a6>;oy)C>B8r%%mpMqYCM zZl6nH(_tVqj`Dn5_*O7TH+;j{lzo%C9ww7q1ZHl5gvlp0lWdx}MkGg_Yh$nun9d~E zO5~}-y}I|?PEip@lwN9zz>Nsp(8fYm@`40AjixxjyP5-CymWWKX$xJQufnHPG9l4d zWTeyRHT6+kq}B%OU_h=N4af!dXM~1x+uWRJi1?v830DQMw(p4$Yq55u;Ex<%V(86=v&A|)A}p#?=|%^-jq@9O7?$h0mCniR4vfBHOlB)#a( zj@<{co0fo|X6G86%viZlF%eh9dTlO2LWpGk7s0%zr*|#*>0z&t`R4sf3uRh{NnjYR zH?K6MPvi6$VQF+iX+;I0~_-+dN~w2A3!7sNhQ5devuow9 zaJWsGJ2kBjCDGzZ^lcyKE!vZoG`yrh8rJHHU^N2c@pWwq0QuxOH|-%sJby&y?|-2Y z=?oDwDWo}Y9Vm-opLh0hpXxlX+OJF(Fdr>7E_1&jkzg5%+}0UZUtwVwtpO>VK=`9( z3pZ9bA~Nv86MN()>fpS*Z~7Im;|s7q^y1*VF7g~h<|FZ(g;o+JcAXh=+Ra@^YiM&n zEF$ls99?3YPE%^61}u3QFnCaW**r2}xdW88&V$Op!&3I5Ce{+oC z>>tB$FTCAwEFh{7a@AuZPfoC-XTk#PFv%Bk*+7}_N^r>cUL2cr>YW*3NB7S_##)9t z0vTH)H})Bj`P<23YPg8au>utAcc5T7uJb%H_LM;D&CPuH#w}9drM-*Tu`m`(qqbD2+53H~I^pFt;JO!sTsnBnA@FF5aY?XPgO<+&nfn13f3ANavJw zplkWB$jH?%I{>xKy_c<*IyG4dvP8Gi&D-NmPZ+oGSmd70dOYs&5N@{ocu(6Xh58?K9oiZ_)0`$snj3@ zyql~07#4czC*`%m^6+W@YWWJ!8(~Mw@u0{cdN z^lSzaL=cxx$u@_D)su=Ic-Np(-bzFQsm3ot(+L^-UW%)2dN4Y9?JV}}i7uj?k6i9p zePWO*n8zTb#bcFlgPuObOq#lkTtS^_^^pWo1qOYA{-}d$Sl0FXU+<({=xfDjG>!|+ z)=N`$ry0jZBWyDiSVu9?J43Ilb%%Fk;XaI?=!!BAUm~vZ0H;BccSA;;Y2jNU1>^3b zp^;Vd)P(Ja9y0T=%*yfU&NONH8$$CbGg0JF?Hbu$)y`Fd*fiA-G!Z5bJp>$-uPW!9 zSI)EUgVL+M-4N4`59>r{GHo_8dFjm4`G!cbi~EBf)WXq;TQ%N$%$@M5SNl-m1Dvs*)%!z;x~ybWx>tG(SWm z;x@>^WmMu6JyT!Xn)-%4sq!vHs;tPWD^^sOlb56tsUq|fI0M29lci(aH4`o;i*?SH z>%@KtT_STOdR2Kb@P(wRmqu7Ug--qDS))EwW{TKJbY|0LOLA4H5e~MbS(NUL>5{dv z*il@ijY~N>3>8(q5xmsdieauv-V1cO>By>zGL zBbItC-+O~D(zuRhSu{d!gH&94B~J7+z2&WOIj7#-A6b~%_{6B#>GYyDIV(}^1+@8v zyvWsb#ZEH^!dPvt`;sML-bB}?&#)=_1dAv^hs!#PAH1rYIX%NvM8F@t$iAw<6xn zwHP#3SDq*_(4&mHlvl$g9$VgHx`KOupvQsPbV|O&+cSE}StN67NX)wVuFjlwz__`N z;>IC$6yNG53w6MKCEh2Av$DyjA1iv1tMR_$(RHICfF$eTN;1?G3^LPmERsJ~y>r7t zJh|5VydNh$nMUG8zFl3jn;8fTfRQQc(h{eo6#?m*eygW5E(YbeJ`fN*D97N5H z6J8hmbnnVpa4^fA72drXQ%t~yf~`aedd`3I_PxPeg(k0^^b28P9GR)Nq9l}@c-B{T zra!u@5un_(I$Qkdvwna7eK+z;sl1yLhI(gi>QY*F+Y9JyI7`33h;`Ba{YCDi?!B1X zshDyBeRDGfqjUj1!Zi^OrBjE(_>b;%ot55p6o>`4}vlZIXJJO@>h$gdl_*)HmCT2iIEvoR_b zm<#ZC>)PYZZUw1O9D1ckS<$Vs7!Vw?xR0v1gs{vOqs83&A+X8!N8E!MTSX zi5!Uj(8_0GQsOi`BVo(IR50WfQ62XF9)K?<(}nVz5=l@TCZ(^zl1e4-&qEu$B^cuY z&RAhEMYnzc?G~1U7t*Y!4P~BnCq}!A-T1itE_PJuGoSuX%u1ZeXRvz>)s0(M@-x8YR}PEUJ1NG1PWG}+4^(KP zlzd31$f0~M*HEMZ^<=XgEqeZ+t#cxTDPq5)vzRV?(c+LIvYmaj$=Pr2b=EZb3?#oV z!6E>K1+-j8ZSqFtNWc4SDJ4>M=qF7vX*IMJP`traoVB+JcM`$?(TiL^wa%iJI2r63rYk}rs$bGL&5Pvq8R7UL@; zK?nn4fv#%BNR68Dl2I+F;7rC#y?XCTRJ07sLMA45Y}NV9;KFLaLCQH^7wYX9O`A_K zQN$p~Z6SfBMpQd3;rpqV&7+3O2}530C3gLK@OO-k_{syJlrp*FX^4lBgnIR=NYg3@ z-wLtRA5OKJ!>4T;ZjZ#m`)sesUhsMW6~5%;FomhKwRsrlse64Fqvxeh_n=Y0_4e%U1~(Z(X@{rQMRd?)0m-s&}PTy`m!ODI!GrH7xsO-HDD` z#~|ONrv6of&v^m%D7DvLs9u>e_Z2m+ZXMy^(kt?gelI_fH0XvS(d%Sy>4Y0JFy~Vl zFQIf~FnNlMm#18YQK>e>EUU2|uV+YSJOsU|Jn%O6G{w+qo`F#Fm5sZ)kAh`kdD5qP z4f%{qR%Nx{d>B@!zjBJwRB~HRjnPIitcg~XmLK;~Fr)QbT1A$SxiffkXY2VwJ}uz$ z@kFKQ>z$$0jmf+na`@0g8J!%=A9mpmjw0xGaoM6_U&)@mJz;sM(7>oXQV9S$kP#85 zRWdj)LG)HwPxxxkOGb+afiF&l$xd8&^ICYE^t9p+nlVeAyPz^Kk|$V)DUgr(Jcr@7 zZ3(Sn^?S@xl-O`0`L=&hCn5oNPaIFHWE z`Lqtyz>63z8h7x;Nc!Nm_ijm&=T;)FDqu2}r7Le0J9*y5 zDHpvBOI_8fT3XS&#?M#X^=N}CKfkatosd58!M(l|rjQ3vaVqxOF8ynvL|FVGfd==2 zT26h-!^v->KktMhl=58ktt#qgc99XvqPoRP9t`gZ@u~x9l8i3UtD&pMT!yfdMZa7k znGPM+kxQxA>WofUW$VD#(+?FT$pW%rrDi% zi}n0q?P>h#l0$rR-!1KwzMJY1(RmyJ*NgOTpj3Wv(MdC-5?!@!;6`KnR+VvmG@Ng6Q*db+D z@-i$$mo`S9Ph3-6-~9CYkpY@uA4?PMCoXD}#h}VaOcWNh%)Z36$V<)W9>p_xlh~(O z6mVAh%wsUmzIlBqeIpMiPu*u@lSlme(yml$jl+O6?w*lbCqHW7!_+U-sOPwo^f4e$ zuu;+&Lmv8y3#_5M_x{Gzv1s!28v!)@p>eO7T*i6d$~&hqJwK451U|f~JVDUcc^E!3 zFuwBLE@t!Y3t})*SL$-oeC%4UD{;16pD^cOnp02>x^U(v8t=6{dx)SpQCij)VT|nk z_k5tadc=trAJ=W&liQr!5#rZ3H32DpTV*lp$%tH0Q!Tk;fjW;n->0j7A|ax}i_YKyfD0kCEO^ow>s}Km-G_d%0{r`WtlMo_g1#^M6Un)WmmhXRyEIHB zF&6_v>M2_AwQX6@UK~S+ZD&>n5RyOe)@#rIod&>Lz@oD-5!Qs91H~{P3i0+9NHPTP z(`jfgDcuXp2~{6SP_3geIz`+z6Vm+A`~CU8!99+7d}Skp{2HvNQX>STea7;40VPaa zY!@lNqkZHcHpg1TPG=yO{0s>(OcjD`HYXToys41<>{+Fz-ScwiD59?_TQ-a%mAOs1u&9z%rG4<4umS_|_t`l}xlh5YH2n}$ z$vw$gx0uJj*e*wW5A`Qe;;F<-JbrPHNeEYVpvOt`PFeyry_b$$F_^Rr>ucCew*@Yq z3GM4~Vk5~87`&lGM0iutKClH6az82C(c#NWOm9)mE*Xh&KMX%rf^u&=PGu` z({gMlxAU(unbrF0SBTWVD!rby8g(nqrid#|bDvPT8LI~6qNuR53-`n{z82lXzFu;u{;Vlxz70Ge3)BAh_%BQ?hTNt_MsW z=&v(ntro+%Y$g$LzbV=olJJpl^xNUq^9mbE6UxiFy~+_Xs|C2lERKd$T~(-$<^)6K1d>a zYEQhTx)s!0GL?+cR==z`Uo?sJZggw3%n=g!Z!vPRof*zsK68Ahez-D5yC~f>rAqw@ zs{K1)L1wUEz~0RHB^79MwYMA(8^r%FjghSbL z6ocH8p#GcM#Rj!6MXb@enQyd_5jV-c@c5vm8)QbnE@eS<9z{x(MAeQ?$}LR7CFdR! z!bpd9a{oF8Vvx6(KTWS#Jql=9?@GQP{Ukiw9&)Wf)qB87@3YkaJ(Kat?otMrR#k+T z?(+y6CVxuJ`EwH3hk#Wk`{0%bw1#oos;bU=t2m^UMhpVZ(I8MTDNUaNW^Wpjy}@n!vwC=I-V`j)S%LiD*5yQe+BIS$d$r zvx}C=!%*vSlot05Q}wrH_8;S-OVBk)$}T9$(tj%ooAlq8_cZz7AUl_vdnz=?x=4O2 zOZCOopQ4%1EEu$b+TGrj=H`Nr+xy3#yjp+YvJ+s^vYEHfR<(a2ZUA;=YM2v#L5C*QvNc`M$>=80l9*=_hJt7!AmR+s ztvN3;n?GX7*YZg-gtS$^1cv1e;BM|WigNaReImtE+4KY2`=OyU`_)dSEyP3>AZBUX zceGbnd;`VuzVI4*{NTAfzC!{dF9WH;ThmsF!DP+|=4-$rLR5KpS2lfmRuu=JtxoEs zO97_M*Oe6`RT#(;-9F~pZu0h#jmwb`{OIjQf32*2X|(`tx|G#)m8MbD7xk_5E$9F^ zYH7TY5?Epmq&R#!DazI71$=`g`Ono+i%;sZ_gw}vVgUX;-M*t zI0EAc5x%|vs;4Mc5peo_Pp-dX?CXyL=x#8A%!7GotSY0$UWCgC_y- zogx2ZRX>TlndTe}1(o(a)&xJ7EX5X)Oryc@mZN;+f+`y=*>&L#rji?tioQ5QysE4G zxLb!|nHxcT!gaS<8Q=JI|wx;@-RN^*Z9TQ77Y4k zMPel$%4-B6sSbpWm4Pp0qF@nC3K+cdfhUZa@)L8sasC|l>9=%*OzQc<=;}Zpf*xnl z)iSDS(Pm-}IsD6*e`kEDH)^PA?7Es707W|)^T+kMIHX~N**syI)u)IPyHYYy5vE8& z?gbs8iRvRbwkl7Q7g(1W%#O;{n7hCda*69IGzpMi zlEfsYFW0ByFo-5Sc;`x(0_7i;<&xjv(!LBb)@l~J4I%s8# z7AVF&*SO7950AwZ#6ynK)#Xzgg!{lNG#nf*w3VACu z)w<^EDek@JBaQ>36})gqlK$L)KVeA*I+&~wWIq+==kq$n`F zJ3Dm{OjbD!YGotaMp&eo2?CAJ?&;etDTWc>RIV_#V}#J`zUH{fl9&BFSx-hv?d6bZ zc=+2*KMvou=8ScI{_O{BMR=t3lHLTMNjuF=w0V2)jmyP8!eCGgTK58_Y{lx~vtty( z@>*5&BuwO!nnrv7l2L+S>8>Qb^7|gI;i%bnpg}V(1EV2N{B#6I#ia)?-||_*{*@?p zQBUG6DUfIpu5fqD`#{7XW0&$lKnP-juG~Zcnt*aWMNi@s#`HjPsVc}RmK(}lG$cH6 z;1;RBOe29NRI^D}W@QGK+>!cx{k_2r43@GF4g(dGOlWwT2_&p`Ltma)0`6c<9W`r6 z>f86!PEuidXtn?lV z>n%t9GpxGP$_M<9Za7kEmSG`zMNMNKC#>qa7TLx3;}|YM#=~bVW|JS>a!p&lpIhG z@P1wUi2^8o9-mS_-+QEJI1C!XLl6mDJgDKa8Me{2`_o#q;P&c!g-`ZUS!eSS(lMLy6P z`6?21Fj@<}=OAl28+}+(s$ON`^|uD6te+wKYs$&j!NR!CvU)IGV`?;>|HSDuSm`aHv7OzlQ;;YB)o>=wF zCfo&iOG#2u-w2S<=4zi?hzQ=D4I+2}lBa4{P(m|zDI!0sy9BG=Eo@b@TZ%2tjr_Zu zrvT3I139thTpnVBr|R2W{Y5d)wsuoiDJ)hMl{r4L<~-KRf*R{Cj6_thewu-vh%x5k zDJcjEg&j)>(E329q~h3cu@x>izlt{(Aq><9$DF_v^l{ z>v=t&&+9&g%%;a{2Ivw-;$|L|F%O89rs}r6twWjpqBrV9BWRLvj_Z}KR(H03vPL*d z*SPj2OnyoQN*Ko?G_!Gt(Rhu3@_yem!m}hSD3}D>sXVK^dhxR>TV7883_S$!CQ@bQ zJ?r?L`sFa5&lb;KVe2|nb?tOX!Q4$BgZIn5A=JuEGGS$JT{+X%w5E7*Z~7WP-n;nu z8+*-9pSX45$Ue-Y8-@3!WJZsRM);QpB$iQo8FznypWkzO$~yfxXfrVIyJi1{C12Tr z8^SG5#!%-=Hq(}__Soa(9bU)r4mg{dywI{8IVNEsT$5C;h3Aqg3oS=CoGsi}d&ep= z+y;}wgtzfi^aeHIoRPiLK+Y*NsstqipNDj?SQW{<9`!wCLvN-o@v@(BHic|y6b^MK zeJ#`h{yEo>y+aIpZSX}{lvS#R`_UbQWq8;E5{3bn6f|q|#yd6bZsGrB{>{UHi9-Ps zm$sx2n_V~o(97F($z9D>u}~##P0rfy9Y(K!j4x9|hs%s0PN!IL@#M|)J~=|D6G{-t z(E90&{~|$Ht$V!)!Dm}VwL_bRj{yiAUd_3`ajfu;WA)`iw)MjjvvD*>#UD2Wk5yx$ z$Et@G#~*QHJ~90Ed?ETl!hFpmoHuY;gZ`bAWQ;Z;Rl~Rbeqn18NlP}EIbl7_^t+;h zOHt<)J)3kY+S*ZC1Uuw&WTY=SO}F!H#ChTEw6$)c!?1rn6r_yUMnm#(OuV`{c2+M! zf4G_tlWaAM;dp)r61`ctY|0GbFTmYZcRbE^Sv|yjc=IztCI*$?eItcSU-dm#;11=v zCSa0G@`v%<8uEI4{Fx&pWtli3DWj-V4FPVWDCJ>?F-mPn%Rk@JPO1AoXMF+;wF!?w zKVW0VA5?43*K!zlPbK#iK;xy}5F5t0uR!&6`SSX_BQ1t=;TXQxfnP4d+9c>~rZE(T zb%$X-Tou$Sc;m6wGt>3uJN1E^X$SC*$93qePS<9uiA*cO!3-e>BV}n;(ERFC%m9A}UFXV6SL@N#V{=hU(71&q{- zs)47OOL?P(Yqz&}wUXr2MjikTtXiO}2gRUnc}LAt?s{HdP{9_S`6+Glmx)a*p;f z;&|NP^=&3WaVzRyHV@~c;NL#MXP7oYKjen_XS zDe#cA$EHpCkHBN5+||Ua`hi!UB_CQ-3f@o{(mDM>i7I7K^vroIizDu=*U$M6v20`o zp_y-Z?CzfLF1$@w)-f{FL5&*f7uD`*qi}4g)6xGfQj}SG!AjSUiMlT;kV)FMW4*^^ zn)~##2&T9n(%)#gmAVISNE!zplRseoI&PCy6l;5<@L20Ph9^RFxc07|70TO1Tem#r zKCPu3b+%Tn&r_3D$Oxvp>BwWCLpKuiV4_FWGk=PI@x5ydmA&O}!UHMjEz*ZHo9G)f zcY8i(^i63?(+_wxwdP%$Y}Ut;J`_NIh6a!qb2+pw^%<+Hmgn6*-{mg3COWI%m(x@9 zeZDCx=o~mOfi`HOGZ4YJ9O&L!479v^ESUXcS>duF6Ao6sp7Exe8oyvr+vqogAOs+4 zS9^S}tJywo@hFIG>>@lDuOC0yo#l98#^ix9eNjo-7W0X(RQ3`&7J|piiIU5x4GW*A z)_fkZ4SO#!nE}0mYbDF0tS>=yVYgE*6$Z7$W+D(7B)mxl6I^G%p6WfQ1XXu%16fWY zw3>V)RdJ%^Z)Utq7Qzvgj`~vawf5V=JHigX%4Ogy#Q9`@_GDyes|!|?wlPTW$U6KD zrxpX1Yn^cd#2O4~Yb#_q4B5CoR$&}zm;o1|MnvGV2@On*IPmU%Rlwds+o5FK9c{4E zi@(NdG4pvRt9tKs*WZxtnpAuJG8@yM=6cZ6oPaSqW{~VrdF0tCVnU--oE<2&Lg>R5 z0VZ!H$F>9S9qf=|v$y@&t~(p38S|RGOob8QUYIW@98S(4bBU$*&z@6o$A%Dp?Mh z%Y}23Cv)Rt7`}yEqYP(ZD|T~H0}7o#`!eX7Gb7)rZR=sx!6|i_c?;x50f{j=YHuFd zkrOW;b52k#x2BsgUI$?mDdNL1)lony$R#U6YXlmth;nT2^c@4WL#bu_oR?+cQt|SQ zU7pWL*w9*UphW&`H^?+cO4*DP)uZ)6@wPgRryz57O4Asj@}q@YHTmxDIxoGG4p%tQ zf6AWQ!}aBi)wtI=`;26d|HGO$2wM`YC4{OwJ#njMwb@~l&^^JI$4`>v<0zvJYhe7I z7uw7a2xV#*EsaRi3mUCKHx6|JIF%-VZwAKQ<<%vgZwY~-{cq!ieG27YV@lnSc1Nae zLS(qcrxPKXR)w5tnpWaC{9ur6i;b#-vQ_Ank>ayz`~K;B#{XE=J%PTt*>!%OPgR-T z#ag#B5cj;msjMEqureS8F~zo&v+AO#cSXQhE()VOtT=E14`SA5nbM7_FqDpL%C20B zT&rZvTKKspz_2dJe%=7jHNkH@m2>lM7}6cYuVP?%whcP|-6lDGiIOQ*V}#LEBqg(( z8(?Os+fF+>2AUpdd{hZneWsMZy=+y!7y+D^$NnxWY9p5}JJK?@8#|0x0|MpuGYZ{G zvD^TCV$RgOHcG&II|{l+V_)yBfkF+tD_Loc{&Ok%Y3sbp5LrexKYnRGKg6ippkphO zUaG%*xP(&Zr*EfW2T+*V&+_AUn8xdt&qLKlm3|!_`Y6ql(04M3;pL|vh2SiC&aj_* zc83JV&KecsDkldHAVlNB^`I~*!3siBIN==XvK_&<7d$0@oCW$je6ZtnkYha>uWpcR zY$7%dxXcZu7fFocMU=H*HM(~mmCNDR%4l&ms!oqF#YO{%m;OmpfvN?`#xtW;#Q&~V zC^QJ+G+_wK7}R*x>s8AZ=;k}*L;89H*;!CdX~PeyhqWBSsDAiL{1wA3SZA3DmA9Mp zFTs{J2OMCAvS1(;=5<^%g4<_T_?&sq&vpio}Jf(eKtQ#Ff0i6APptdkTZ3%{ZJ)sd8_AP^Zu$u>fLvO!CVv7*B zdQ(s89W8xT;Eo~6`KZET6G#9C5d{@`s`d@%7|!Vw91`??N^eB|JdB~?JqxgleXy=U zOI?}O5#1cCs_MA~lr+dSOwKdEz@(rHtvE2Z{hlj4KZ|2IO7>heu;Z+~9SaCxuZ`S2 z;RpT_hOs^ZQ2BME8;Ulo9KSGJaq=yZ7T|So$1H9>d8?w@Gg7FjQK<4nFazfvAFm^&vu3mt zUR`c=Xa5VUm$ZNCiJADw%IBKk`e03rtm^S&0Il zpu~Q+-j=U!9MI6~T<`G|__zRuZ#|Qr5+m{SoQGlq94AI{0*G-r9TijvzjI(LZgOfV z@)Ac7o4)N?@hlAuhM7%46Tb`dP6ZCP_X&viQZP*P5HR%G#dda6V6sHFu73J>HW@{& z=U`h5hO%sjvzE{3sS?xKG!PzguA#C~mN*BYO%T1jvXOu|2NQoZH>?-m#1sSkkw8!} z^1W7i{h`nloMj{tNbSkqk@G|f#%G=;OZ9gM?1;7hDvh{c0YVs#{OHAhB`-q|ksu%< zwjFy7LKk>YX_7F*@WG1XZ!@!cNzgY&d@CAIo0n z&~@KTH7ktjvUARmJ$!dQqov?`wG#XE(ocXotJd? zJZebgux5eE!xrMdU~$XnKEAJ@t$XeAku3l^Rugo+4n9=eGr*uHgMm4E74TpJ>@R7n zrbjF$SK(FwXk2W_2BlFLJL_--rvVhAu-yw<@V($?r5t9QAO7joawHTp<1wpiAg8H@u-$HgSLxcUnO9&>=K^o#N>myo7@4C1}_!KgilhOf5F)?(;re*trhe*knKx-f#223(Ar#D1G*vKIqBxy?T#!!Ch}&FIG$!bzh1CDGoe+Jf)ZcWA*?NflLj|terpxpjrVU`hNvNNmYP%+D2T|^EG2k z6UAM7MCAP=ZQ&4UD|fZHuQ(7f>VR9KK{(iy-^($jyG4%7?3_2FyAuiJ=Mh7S_X`gOzE zI01Ajb95?b(6|NDhgb6j#G{=FHLX&mcsw>{oJsdtKqiYV6G^J=nltu|g74-O1sJ>< z@?U#ShE+{+oXMO*;+csbH({Tk33y-hB^<}iKEM~zrFCVmm~*R2=ft@cl~*L@5bqem zLR#>xt$WUx);RPcO2@&rfDr!lA+R_7k>MQ7a*xk9PU!t^x#Fnf-wc@Y*4*=oAZ3ui zY*KfiJPNgIMFGX3nTt*$z^k>C5c?K7#TXs1dc~4=XqEF1&bH zB+SE`e^lwRbRWeDX~ZxsqFUq4xd5&*Z*Y}0SVM<@EY=b{O_n+p;NTPfX0~QV{JI*7 zaI_^DGfMNRS@IBXq)nr=q>9;fcU6>uRdIXR7J=YbkVT3YvNt;f*IxGfsO!e#r8OgqNc54k&P|VBE#S4>CpSD2ar`4O)&d$#)1s;?W!Bz}vVH z>?WRX8k^Cs0%}e)Xa41erIY8EOQ~FS>z-D)hZlXC+8%|6PQS75ynAVS;n9UTc==KL zwL3ihSmU+bb;{>9YTLv2Q|4%oNgM%OeNTwpwau(_%N+O%b1>2TWl5Qx+FAi|%tg^z zZT`T!o?Se7EB#6{Qe61y1kaK$i<%ovTRW--U|bz19froQ=MsqzJ!8pr zgx}w>3#^W0?05w>M*7be9C%2Sz+BX9_4qNO9+bNcn4m2F*btDG%iMxr=CK9UyZ@m{ zI(VV$V0aeZ=>AWZ>4L}2j#chj&Ohz9%LzYealpW;pgrv5LPQ&)99XL|3X~})J}MsC z)NqaeL<$8l3Owz_A3v%}yx7r_1}_tzW1zB>`yKZ6Q?>R>p^6ucQ!;xrWmf+Du49uG z^n=s$4{KG2EebIVZnNV%T`AvnQ{TYvMXAz|BpFRxw*6|HZ5IT6W;f#=}CRt9l{+R za}`tauJpK74){}?u`fGSaVZQ5)>J*6*8sTbiOX;HUb_`V!J~(mYx%+B^uoK@850~Y zANRyUS|yosUKNmGk2K@}ut~IRD91Nwc%_*%Yjlfs^M}hZW}NflK5k*D$c(hgsG65R zk_VHhB2B&WRBj{N%pcE)C|;S1YuDRxP6+EUaN}tC9bB^&?KwX1sTwnsxk<;$6Mz-i zsHLvSz2I&1YMc=xA?4jYZO;4isZ_Y$ok*9M+Zg^(>z`+202HHh*u{m5X&tr+@QebFdc%|UhX1pYNpKR$3;r3ULq|bi^QH&#OK9MIdv~)Qrb)Zjaysc z`YZ-ZIuA0NG#Jd*^vHKiugk_|fCvTGy?#ii*atN-@1QG<4QhJ9{v3sh|08=>A+qXf?_%jqxW8YC?A~e{`$pkVVWFn>CgXEnvDXFvJP9H}Se_^wNtUwb| zk_n45Sk_RFA+FjBra#MM2b}bNUc5@tM06UeG~yTX#1nuvjYF&FhK=_=#);saPwJ3k zvyRbl6oK3HTZ{H;Nee~W*e(uQb|ZOkjg+qnJwyOVvYZfB%>X+;OPtBOrwbdTeDL@C zK@Qk*kFll9z{JD9k3V{hb1Qjrn~50Q55&)hrj`9`dHC?DC;!#d{Tfqaao^t#Asuq! z+E|93stV@bvn-RFpR(mtr)1pz)WC+qk;nH6aRsu`L-LJd8*4$N+88Ols-N4M&mYjM z9|y+2Xl%4_J#r+7-gEO6^=r4Ey<0xbk3BlTQxdU*g)dZgmK$t{e9#MW!cjB4DrYn> zd2w7VP=l@024GKaBeSJ0w_pqF&h3v=IQYhS-Z_8)q6%!b*~RE(pp7K|rvl=j0zzjI zZme1w%#dNK(1>^umc`(AKP z8e!dJt%KhJ?*ulvL9odQ6PqtN9lQsJ2~pPjYlRZmmvZVz8aS}-x*O->y3K8`2wFx@ zpei&XDuY#B_+P;HK~ekdwJhkxh~ho7T#(82AS9G1pw(1@R`Z+>Z%g!EkC74+rpuzU zq(dEtt6Mn790ex9j1F5lMQ}6H8|M%}50tSt$nww56#T{}PGIR|&GLnmdj+q|l%7nE zeFoPNw`a52&4u9a$DE`Y*+GsKL*&>Z?FEi>Onh@r*!VkrER)X_VlnbzRIE<1c=UZ< zF#uGtp$tiPJeu299C$Yo&xbVNJGHmq`FI}}AU`o5r{{E&$tQZ>zc}@YCo%%Zqz1#2 zI6dtA!%c)JeB>0RXO+qzh<70=15CZ!v54gg&ClJmy~=q#B^5j`sp5Msw1Oev$qjyp zcvd+7wWqkQBuNSopJVIfPJnY*J`6^&__85{C^ec5H~@+2z+RftbL^esFB_fd5M)hl zCIx@G#cqd1?JFU$knPl;CN%!H$fw{_bXhPIo>8%8E2`nI@CV$_%tIMLeAA zU$zhz-uQ?ZG3ZCHh7kfcGD_N+c3Xk?FRN*$*xX0kHOHjanRCi$cSKAhA5k0^z>k5yvD1+G$#gTZrwseic{vE?`X4 z=p8TQ2QooIBrh(8e&cjt+~-^8!)A{}wY-qpoq~P;q|JU6i8yLZQW$4NQ!)K7QSoyGXNVdwQ z9I;dEm#rf|4-dUT7sPZP9yN8 z*%njrVcFzm0jS=u?I_4|{ z;yPfCCpt^im*B6%NF=A0si02{Y`JOw^?-#T9x#$d1)n6c9qM5RK$gZwb~fw1sC(tv zO~{zNq(PQWiQ2KM+yrJnOiHMNm+Y@ISEQ_VaLf5x6ZCDnfWRLLLK#vJ5}+UymG&SX zY{&l6@X(@I2|T{y0zRCi7C_1?5FjqA^~?Lit*F8|Nd7sj9w~*(i3C!w2n$}mPRd&A z)`_ZZhE;1hh*GX7u?v?jygB_O}RK$5iM+u5cpN@5GLwKnJz7- zFp^v|4qvvat3RIYwQ?m>w4K7VMZOChA05I~XaqzrR>5ZLh+{W}mk^v$-S`y05s4VS|BeBMzGlAIL!n2BdK>^>inW6L8M} zUm-<@0O)b*Y6egbpeIm@&P5pmQAke!l(|kzonM8*CGiCXhU@;sdlNvN4k^WYs%Dog z8=juXzKzf#-=4n8m)avEA$0YB5Qgg}bA!E#)&}GKjcDh-GFy;SJf~pX{7(2ci_3Ql z#P)K4$?i~28NYQ&rW)|(R}7TCAlsex%-2o|q~F`FZ~kfp0lyj$ykO$fP43Ysh@l@- zL|Pd2!sP?@-~MGSQ?iL8U7sX&vQ`uHW^TJSr41Jek?L7b!>RNud7z##NrQd3lh72` zS)vTOG)R4(eSnDtt`y#Ut5bX>dM&UG%9jY8pd0yeKzPwq@84iuYBjsQV_JNUe5Qb@ z3Eh+TIuJ((V1u>EA)|;Tt*O2*!;v2OGI5q&dhjHs;YET39Vw$FiSBSKlJG`yqW}E; z!r@+~)|X-tm0QBD{=6e%1KZzZXVQPhNhlb+nM_6mKNdIqqPKl7%C2* z`vQ#lFc-(TsO53xo%4~5Nr96D8D-RjCf$Vn)HTCHhciuXDBO{?$6uzwWr-{EEnZeD zNFZEY>XPb(t$s!@q1Kd#|M1HK%@)W3QzW$a^wnMViDo+1FBCO3pF>QMiC?F6QhL52 z!dd+tkC{3Ap||Vu0ZuvUzQtM)vmG+dP{iOU?#z7^bgYBma$T!t`0*=mkCR`#DR86& z*D@Hq+Kzkqyl{==fOcwmbC$va;tXE+#bjPkkyyXOK4#AjQny8Y@9p(bs`2RfiP4L2 zxFO}Ebi&oiY_{1^|oAq_HJI?G7{l_)tNeKOs3KtA^(Q*rGBWi7Y)57{%sZ6Y&qL7wtJanGA+jcY_zn0RwuUyozLBe$<+Dfq~d8e}Ai8b?R&-{s@=0ZUCi1pTP^ zjz>qQ6}18N>+#O(q=is#cUcAKV_|;Q7@41?XcKxe{PgS-q8$U{xss!kix-#(C>7>E zgK=`lvJal89|yEwi1Kd5)|0s?M=Tk5e)Kr;uFcTJ=6tL7(1p3;z?3qP@u8xJtC+Pf zqbVl|wNaICTHPksCYoB|Y+3`woP+ZjNmoVme2I@^JU*B4vps#~DNb-C8@(K(yZDwi z$_WN2$=%Nvphx#pS@6&onP$6^Dn6QVJ~;}LZ#>1VrV@)NL{*8ldmUFUodYv5^q8O0 zv3f-To_OSG?m76wIaKrA$Y0GO5ZVj3+xhopkCkAC(;7<&6`1p5E(;98tmL4g35>3&u0DtV zf=s&$6n1AkdlRz$kBRf=oBg})<7Ee*=U~d-Q`SB4Q751*jXM_ztay~LAj&B@aD=__aA~35NR>yZqznxwNo-I6UZA1>?dq5-?)aZJXHPV zYMFvhU%QM9V_ux?Y-q(kwX-+!l>MS93z#}dRVU^vn-?Q}m@K%+Z@bRV9nRM4yqTZ% zjL%WRE>1vPO>(?pJhQAus@3$DU(!|>HLsF}AxChTf_kYpOi0!!_5ZtvQc6%N7Ff;!nMbrKGmlQue zIAS&ZlPkn~AamJdu$7f}h2{KU_wQLUO^7?FL8_y(IRBx1QbLKN`#jL6rsc0sRxnthU zt%r%BNRI1(k!5ZQ*ViK@$1`SrM#yJC2Q;CmuWId}Gy4{GUKq9FvUbu|Q3V#2ghdDR zd#N+7pnaZ@#YDto9g2&U=_>B18Iek68mVN<9Z?Vd=H6#sHVYp zhu*kaks|+Zp~Lt7!cP!7WCqN@Y;~s_XMX8wN%N6BTzjoWekI^@j(sBTi^QgU+1pSA z7q>q}-inAe!*x3Q7oGJjC#}UCJYHg`c{JqVkR3QuJstDmsA zOt+k5ak+aA3m)Gmu24Krhs1I$veoLSZG-#Qd%N14)EuYTCq8(NVbM@;IyX$mGNH(D zHZe-deCb33xbx024bSoal1~2+G|4P@19Yo%=Q(OSR(`FzQsYU8^iT{Da!D|e^X-8Z z4tGIx(dz4N zqp)j{KPT}qU2B1X7)_-balFG)e^mRCLU|(j!GwbAcd}0h{#dw7`k_+$ykte$RDQ$? zv~VAi8QqVRX!Q0O@(MV`(j7h3fySRU<~g(>bW-16+lG>#bnu*0=dE>5N1tquC#&n6Af5@x=<*) ziQ7iPRQYJ_*>}VusjC!s#D3I0ra(1uEWiK&hel-Ic+ z>kTWV-l^l#-MKM?+bT6Cx6Q8+{AXP*_i5USHr12<9U_@Drb{tx8=6}LJD^MOirmQC zLOzx+h?N~aSVYbHoy`s+n`IlHSg1ZSNNKxotp~xr-hg}}VmGj#iqz2&BOA6cCKkEY`5q** z#4?fE4l5GSG;7u`#nOw7HwF2i$Eg!>hu#Nt73?jXsxz(3vWd(~Y%f23kk)CFC?97W ziQE6MvyR+US-O>*J|JAksVV52mnqEF(vBPz@v(Ql6U1x7M8OQv2n|9joI!0y2hx8t zBOi?QZ#1rxOBSnP^T3tbfEiFvBojJ=t$xby>XuPV`0Dxc)iXiAX^Bhx`Agk0x>rQY zd@^N7c?sx7NRqlrc;s@D)O`t5V9dkf^$?jUqqV7~A(qJxJGb(k^x$h03O{Xi=w{BN zLz%Aj1Y!_A1g&{kZQ~;Zn(@i|^i^}OeNZD3t%%@gZZj&mp8t%E&|KNSdxE`k7Q@9X zZyQ1&N{0l$So2z%2NjvHq{N$ypz~>c_&VZ#S^=))>oyZ4A^ib^2!fKM$yang?tnx- znA_|Z_|@5}Fv*#@VcjdaVPcs!%20h1%&KIGq55__PJ&!qLYx7o^~W21!5ct>Xcc-A zsjwbT%9}%jYdw-wQSj9Pg83zVt-S5}33* z5-fUZ_pzQOh&jEXJZ9nLC~~-d@^vCX{D-h-`q9JvKi;fGpJ$Wu_I+_6|B!XyyU7uu zz}AAPlMlHEh*yqgsYQyttsN6KKP$1=!@<_;ltFV$L-yPsi7WBRb2zvvwP7DuWNltXbLqL!he@58 zOFIx3$tdV;%}0F3(oB~2bkw!i$svA+E)z*PYdBILvaor8JLDR9CAl&Afyt@yi8#X( z<12jckNU$n{PqHWqA^EKrzWoOSdBcE!H%9F%27EXWdFD#7k$9l2ETW=NQsKI=mcq? zN$fc2>N1kT4%0`dGxkk{s1&^4xhxVftdy2S0f`G~-pGL~w6hCQc2JQCf}tWCvxkxF zdbw*PvGHaPloRSZn*9=W_KQ}qT3>qi2a-VB_3BknqPp*AWkIB_#eKQnrH765Qrai| zE#TzbyugX<=^!*7@rG|bUH*t09C%ijX?nX*Wo*K=BZf(xbs8BY!2VpbWtfIoG3PP( z408mDbhoohKcg29m^;|kL&oz55GqYIB!Mqjy?to#LS-S|tB`XI9~rzK^7YD>|H**HJWx;eQAM$H50 z7X{|BU0(6MDdf=euwr-EFZS|55{Yc1*7G90J4^@%e%e==wE^l#SV<1pAm zsVjQ;FlSNdi;!+*TZ~JliB0m2wtV}#d-oj zF)_2I8s(!+)w&gZK5exV5Am6oegYSA;ZXElu5UelsTrXd#di8J!+kA- ztM^!n=2@VYHI1XZTt-iJ^ku%Y_nV>7v-_h;S!YMEfz5iFY+`eZyTH>;NFH|;EC%y z8A5K%nRmOijBliE;S&Q#@Hey2XkudV1}qV&Rf~p|NPY@jE34)Q5d=04wjKVcl)9*t zTpX@lj`U`3PsdQeF)bA{99&IBxSG!x6A3jLl7|b!*6g*OJ&B$!5V||f-44uvu&z;z z^3nRU?)yZqb=oKGVCGt`^|T3}^vmF^t}4@3d&`}K13Q+gmxOS2R7k9jAs2+dgQfne z@8+S-4$Xi<>nHp4u`9~AlFJFLX*E$?O&xDYEo9Tl;DskKOEbU1oAfz}joV+`YMW&y zW1dIZ@>z{HQ>EZ*&z%v{#7dbbl}(LxpD*DJIBYyzE(Xv7{!xDWOT31060X}#U-e!J zuBDFas7e;O@%y|<%SyhH@dXjuakrCwFmT}l4TGf5hYN9@TrM2J6l$z(@K{A{7O54^ zQ4@s=ObIPyP)#K<_E17WHiUos=3A4rb?@4sLZkmVY_qLTD!_?<$PHuQNA_vVbp%6v1aRxnU?#wVa#B zKI>sWW3;$#z^SOF_p5r7lMucAlC`Q$2*^KwxA{ph$8WuUakfnf1wTR;0*_bJ9?ioA zv&?@tj0-6B(Fh)}-G(Sy*oK#nwpQ1KMIernFSUAF4;OLgznMtjz7#EGx90G0F;+}J zAxAph)(&2Fpr^C5+XP$L_SX!Lg#e7dI8I!wVEyuW@tW$BAqQNHV;&R}w||f0CThYY z6Sjvq#)zvt;i~MQW#0Hnl$509#~-ej(nqY49?8&j$AeJq_)o2?w>-ckjD7rs<@5cI z5@f+HxsE85qfd%|;kwe0)ht1@CH(CjV$K?UZuri;(GHZDhfrlWgx_d|fH3sKdSrf~ ziz7`7#G;~c!WZ|KBrc9tLy%Zlg&h?;J}r3pX{B-On`ZPoj^MPqkQ91->_lh75iN_{MTEMned6DQ1T^&b^o(EqTlby4kW(h2=Mh3-N00P@>45l?qI!}%gzXT%sr;-n!~csGrEyWeW*>H&uP$q7oGsKV|tk&NkD=> zFRVManuS6_gNRT}+=w_Ye6-?|89hIjNG z8^|!kGQ`#bAqqZ$l(a~qZURs|s&T@t@K|8@!IxvL0T|VcT#>U!&zacdHV4pCWUAWy zw@s*gpGHM(gc#sKv}wLR20c|-Mmr*rF^zwc^dw@0Sb+&yyzjtNEQv7I)&XAQFvU?k z8X4xZ2@TKDm|5*vL;3-f|8bI8FGoE zZq}6W8qnU2tMf}?D8#ilWpviCB$=?Z@fs>eaP5KtjqScVLe&`1;lmFOa~Fn9Uz%vT zQ#=D4JdED&7eTYT&D=Ty3BLAD^^D%5Li@l#Mxex@!LqF~^M+^^F8B;X=LRHKsB^AU zn7}@f_H5gmQ_7)GK;;}mJlnDBVptNxWojPyv;B7=Taz^p#BWbW9!YGs7d(_e3m$u^#&p&mMK^ zh)chfO;q>D*^^hDfdz7f4UYi_-3SXB=E0Gc1^SY2Z#eX^);2ot-bQE&Q@%4*e?W$Y zUX%l(WqTrR)`LUemO2?1a5!esFCt!@nh*`ECaLn%?{~Sc*@I5)`_ouVTYj$-IFBc0 zF=25>{%5B^2(@UrtuT$%>ic%ddM_HET}I=P>7QpCmT4p6*kI;tWht{q{*6!gkH(s= zorbiwDhDrXs&>Oq6%A9`KCb$X%qqyMqd#So9$(SAyZI&jNSDIh#pQ;Qi@`(A_7RRK zYDb?7S9{7w$f~6eIP)!)0SE3ofSnds$iunVy;g)tOq_h^Dbwl&Nx`~}!qih!JgZ9|E2RU0Tej$mN^LcpMx)c9>eH$9n9oL&qH>v^*_ zDsik74{2^=PutK}NT9P`dv#>#_tf%JhA69u;yl2%{CT*jq0SLcfQtI*+9r@8gv^X$ zWz&_2c5?)!Sgwg5m&79VUKdk$uCjTPl~6s$JwG_*?(j?2;NKRzAk3Qd{v^04_?Y z3por>@kV&-!C_?U6f-XHyAcH9a1o*A^ltkI&#)wO=22fCI>(CCL4)sn96UA>R?0`) z&YF{mr}ok9w9X=J(?`fGiR1t*w)J<01j2b9lxf2Z%f3LkxFi$KD!JgjO10{)882rQ z(K(xhtB~WdQIAL!noZK#FTSq)xA+Ay|G-T#DoV(Qz~nQ6+nBDXXktCsaqDK(XCM~E z7xb6J@x6SrNQpvV-6?5?<#o~`z4(d6hE}8a2#r-bwR?pEv&_cI(bmcdZ5_wO4dz>IKs#?Z*@?&G_YSgc_U_lEy4WVBXnV!v?^~)5m-OTR; zPIqqUJpDd_=esuVHEjZKKC3mQ11WX4zcx47UJohLtmb6ROLJ)E)W+R7Rnw`;PqqK)d$86mTNv+`2_P^-E>=%y_y2w|l>BsDCO?wb7zH-D)9CTq)XuLZSN9zWPUJ)t;+A{6vs~=}>j~v$WqhdfQKt5r*9_s+#!J+KL z7(83R{BE}E4C`xzsfTg&?eNCWhleon*$|~cHo`*Z4R{183dqMI9_Z|siZNHB`tWT? zvp9pNm{Kb7tH&ysvJVl9v!)#cSl1cy^faVhE1fO)yuvJyb{~`dz3mMrKOC^Zbsx3H z;P=yq6bjT!>3%2Nz3=5bYR`oKUHIOw-8rX1GUJgYmyWpr=88<@F(q^6$xA?8p|v>- z;g!7&d0}xob5hJ2L!Bf)k~Zl=2H>=@Q;VeO4q%&{GO-}gvDzs924@=Ks~@LWzZgWV z!*7b~G-nVWlD6$PdjL)IgXY{}I|s*M8eZjueIV9sf>;BIWt8`OWVh~nQVGG>*kSwc ziE{R@+Y|#LZ4511H;zlw36_yBqf(&rR4XFO2qscv8-m`jPF)Hsl}Czg>KPj9JX#Pf zxL*fZPYPMjNs2mLKVHre*STU}T)bkhoG=tZ^b#02$2Agy45(s%Ch(Wvo*F6K_bXZ5 zmqSHRh1%xzP|)~JHKXzG>B!K2GBonR*dGBhNS&La4~&E}CA~WOMk~*ir3p`8!GZ=; z^&|Q01HXt^dOt+Niv*fR_MwnHI{G`Kh*{wE+ru_E#|TuIZ%T9_N$bQGW|RkFJqlud zTXm2wMiUDuM1zh|S`tfgkvoteDT-UHVwU5@9iq%n{)MBOseQyiyCs#OU(`C~{iA}t zE&~H`RP4h=UBbrig>q`jx9-<`5Zx_~zQR3KxB1ca%<+OfM#<){PYsmsQ;YJ32d5(% zi=h_XWciI$#X5q(QObDLLbk}}FYwp{-gP;uT=MC~Y(V@mGb5<0cFE=6tV$1*5;Awn zTfDAX;%B;We@w!bnnlKFVpCeiU96t*nW?03MQ}u;+L4a7TLGF+92~zT$5PlVR3Sv6 zyRN{h`fsfu650;8Yrzm=b*-gxc^;a>%q*BqX-<8?AX#!-U3q=A?PzO|7H7_E%x3RH z?yNpmx=VJ<*nNM6X2&5ke*It+c@T$wLhgLMKT${jVQYvnv#97=zr;ofmu&{Zs7$}3 zWN7Cl6_Mwk*tMk8NNt}1X`**Ds<4Z8@4NZ>iX3L)yxK9;yh8uX^>$}nv~iwuTM`%D ztCG-xQAP{1EJH&cF5iHpNdbFSq^+2LT+hJXuZa%?)W6%Z@Vo^0#0(AvI{kA&KaCF( zGA$#kL*un6Gj;AzJaOK=Iln>y&-dNvIaCt!S-*o^1gH-Z>U;gAX}kt4p_q?v{XR3- z$7GTiu?4^2^DNhDk^$vO^8LCToR>gB80ma~fC?7vM|6|riB_W|T&I#Xrh3b%J)pFL zxVer#P|BgZj-J9_Ex}q*rS!NYogk=3s0WSP>vui4^a&3MFke$_%|q1%0y%K;P^#`a z2%{zR?@o7+681yJAw=kyANY8of+dvgGIBe0Q8KeLl~;ZpQ*pf#shLI;I3F=7bm z4Gc^&?vO-a-ISf3V+oD1n%;@O;-v{!a|K5A9&`5K9BC7V!8HE)J|vq(Zyxs}CpnhV z6h~%8i2Cr9h%?ZFZ2Usdevo92iuu_8Zg=szLRf*~-sNFx5FVz@^tS3cJpE9KT8X^q z>wDeztqsBy!1fa^ozS;S5*IK`F0a5-y*lR9ztHD${FRr#nn5j7r}L9f9*D+RAy%Ee zak>KYYf|p?MIsj;bgCV(GsfCcM{@juy@-(Hb@TD1WeG(pTQ(_Yll8cgdF$_*$=U5F zJC`0OmsyLSx#ymYd%a6lk2EC-c#x!B5UolL55_!|?t#jI7a6K`rLx=fM}4sCI8{-o zaBK4p0v*u>G%jlG7zWpMDQZQ4H1|&fO7d;UKhTDW=gh;EE$ye68n=jg8A>WHZbHk+ z8i+uf3XVYLy189K?M(P9$A#q+a}{-jEbuxClIxDjbYLL7>9--gDT9BGcQO)oAcYQU z^Y#UwNy-jPJQUETfZ`~{_Kwa}MQB?hSgE7H2*OfQK*-W-|3gBsDD?^lozLBl;^203 zjV3ZQMr>9QLdCsC3=2!gZNbuAK|c#Ej7R^bW%lP^*46fRW0I}&aHh8HC{kDMP`_km z;bi{Nv2f+2=qggXg#>L0I>96my1NgOJoRvB)VGv5rwC{oS=_ASd;-KFn(y~zwLC`3 zE42H(pzGd5lFILACEON}Ig*;YPZ-#V-4LXthzcFB>$syF745vwW+CCv)w|LsQKEM0 zV%<0V#w<_4%)SWu0;v2RD(A5t*`@3OPcy#PfQBJDKC#p~l7S#dM_{N@L{lOfNgzihSBcK$6oE#OrB+X+J$rJ>X8d3D88;er=CEfJd`r77Ov}Tm*Yu`q)IAXEou2mjndC;5}(7D^$QrwK8LCL>Vk} zzP&|hme5(5#T?+?YwB{h?bxj`q)GB|=F*(am;ohMeln3v4O1J1@ZYo)&AFzgHH*hZ zuC*g?i7}aq%;hp?fIq3Kzw;lP@WuO%`xGd-p){vt1xy8;Cs21RZFKYgw8mdfQNe@is*%jdfmIX?lq*z)$rEXI^OKj<$uM+Q23R z{tc@ZdCvdowU%|Uk)cXyt`g$a()+ErLId}%-|Dm5TIGS_6&jih@#Fr${gQ2dC9l6D z;B_#o=^Wo3rYjWnZt}aNYu)E#|D(Uo#kM3!Qm5U12Js zq&ojU4Rd19z9#16)WbQuO9#F@RCPxzOhppITtxY&K)vgQeb2~L`| zoex78SH5o$feEBvG9vxL>5;SnIQq9|cuX|b3fE!Ag=M%EPeKp04`H@paff&&jfD-> zKCwTrPNZr2jK}h5ROL*xwd`?DYG6QB$Duv7wxS8>Y0J>&Z)Kgcrrd+zY1{K&GQ34? zN#$I9mgmvO>N6Xht&~Un1|r3wWNlr4uHbW++7I|2AV+~WNV3HD@?NDhPf7VgD*Ex2 z*X0|9xG$VUw^h33ICm!i@lxCXDC*lF*IsCIO-S9YAT0dg%_GXr2%=cRG!ddx82v*|}oJ@w#%*-$O2{=p9sH#W3!@kY78 z-1D$~cU%oHUYW&T^hP)ZM(X2a4(QGo)$csaBFYc~&)E)4z3OyBejQ;YAY2~|O$=_< z-g4tfokz_n>$dv;_&q-OZiu|Z35fhZy1qM*%J=>M*n1v(WN#s|_p!6%2xae?$Vlkm znAuzQ$W{^w*)op3M}*225<=APKE3>VKS(ad;?XI3>^P}eme}b zleC^s>zrOme#lRigFW!lB(e$j#j;XDrBC-=J`6d-i~-I1z%p18MT!+KBb&Y1iSx$hOM&<<@{d)_8 zOg9}H7~6h8$LZ)Tr(Wk%jUxq%C~ykFea8?SPFlDYgiG`V(0Rv!h-I0AMSO(IBnuI= zHctA8ILD;x9?KQzmTuBhT}X%-Jq?$A7ia$!7ahHDjGslud?Jg2n86XFC`w4SOWms0~_g0Gj5z6 zURLE7!0)BYTJcI$3sMN2Lwpdvk}mJ;^gYhzFox01O3=5{HH~^yc5pBAI;#rCe`jX~ zd+1stIY@fz{}X;5cLbRz{Yj@#U~O=$9ON-X*tD%xF|1*1o%nYkk>AfFDw_zGKuh;e zx92twM1)ENT}`9+YWi6Vj!ATXvHkI^`M(RXlDGZ^k;U)ROP3BJJtZBBEKpB~ z#_R=jzgG7Ak6}c%QY-0n(xUDTfo@#jqP`K(csWAbR?&Id#DXb2B_Ru9@&E(~tsbSi zfVCz?h2(U_+-7_8IT(NU6T06h)i_YmiNSa}w3d$Nj;Pk`Q0{LrR+C-oeQVjC)aN-v#ox8>S9y9(f47Fu-S6!pD?inq?v0HDotr+J&2+qaP4)w%yYGy} z;~ibKw+Pz~rjUS%wx84yt3VUb?>JBHM-;bqpt(_C|d&IM`q!7x(gvn<&0`pKB~?$jfTsdz(@DUx>|ay?%J z^NZAH;)$gBqKo_;Myp*<4QB*A%O`&XB51`j9Q_U{tG+z1x&0ItK(RoC$B=gNOe~W7 zkWz0|vF|c(gN{KM1}*I(B1=b?P2-vt<{ALQBnl;0vN)eB3a4^04yi8 z?{ZNdPCKTavY_eC@A?2-5&AU{bn;mF6BH9df!HP}CUhQOX{TU`Hv9=y|3L@c;VoSR z>DLa(ab+3)RuejeJmx1reBD>^kV^%W41X|pvuoSi4`PVkNMhw6qVp!+{63&lqXf>V zXlst__1AVT&xj#^qsf-&T~~w}NbGv8pS%K9PC4uwxAinq(APNt82{b}l^doT>JA{F zJTq?sBQ1Kj9H^rKe2=c}JKnz+c?-FbWg~$l_i`6eZJZ>yR{B0TfCl3CFqu^lA$&c& zusl8qBLyhyKke@)!RnKhC>0$&^!2g!4?4y)IS_3^RL&5?RWOd&a?M9@XO z*WI$p&PQ6OBZEZ)D7t{kK`fz{y4RXyQRV(FqU+mzFs%rcac2b!$DH>w27*Rn9YgA` z@*rSUlkHEvELD5MUC4#oz2a9JHU5;i0fZjlxqru^fgs5mv|MWMy=X9AkZMAAd^5~h zRlj_}A~LVhnSBi4Pm+O&m~U?CncVL<5+$IJ5O=(Z^v}DN>;uc7iov9cz@#|fOKBvf zdZ3^`(MuQ$gd^>Rn-&Tx5Z62~<=t=HA!BeV1wf|m*T1P}R@_*0#RC}*$n+xmPR<|I ziS{JW>-t}}S~hL8wNqbo$q)Ku5EC!;3uu@z2D8l)IfNfs`t&KC^tBU71jxa1&-B!2 ztUtOq=t%2xC-58YgI3AXKPOv(CmK|hg3{XPX*1O_Y>-yeemJ7n?LdE%*Z=ON= z2biSbCRRvCyy}Cy4fWv)t`KkAQBI8v*3w)9d}($SRMGeR+!*RFNMCi*pZ;H*p#wHX z`QjRS@OUFqSH#^W>7VA3OX+RbQxeh#(`n{!i1zEHZyV*9Rsk&LV8m!ssLmwYc+3QY z%!MsgA*jB}G^Mm5NS9lRIWUwaw`=QZF!Jhzwxa2^sb&3_oS|=RrgC$t7<|HEt9@}s z+EG%HDTT`M=~}j!;_4fq4ANvwpRS-v>RLsJ$NIs~09vme-_D9Njf7PsGvBOO3sPA7 zQ+|Do?D@qkwTSICe-p2~s&BRM+FR+hX$E$7VS0uwsq9FWExK%#a@3NogK^*()p%vq zvT{cwrVN|gmUAuM7SQ`mXuplK<)x4akns<@WmKZBWFIyVY}L6WfDfNgcJUIEY0Qlt z(5}LhG2xD3`sZoG4shz_ne?jI)pkx@1hgJogN7afu6B({{!S3(fmK{Z`r?9BTy=(a z+DtL!RxyN!^RGF2xjIlJXS$Pl)#!Ljcis@i(@UrKsv1BTsnO&niF+NVVtB#WRyFr= zq;ki?L3J^=ZnV?pHz|_`rj+}$a1eZYdCli^DHj9|au&EF>>N_EAPLFRUI2vc6L;$l zo1h8YL3mJQc6?$^4KoiAo$g>xyAq9qH_D5l-a`5+?c{$70uBw__E`ckMRzwD(0R~)Y?GG_a*zt zoZ()kZ1x`OHC)jJ7CD*hbBU!9mum^$_2KQj>oGohyym!+vGx=pYf5ige*EbVnw2b0 zB&GWMp=6H0sGqIr1BOM@N`@DPO%>dpBRA(1x<@TLRNpGnQ7f$1A7kao(1o}fD)cCo zqg+pKu(x&p+E5o=5f@YucYj#)ctgs~{rJ5=XJo>MFJiATbGBNojZDhnPVdxov00;i zp#0>$W%fNaaCLER{FCkx>=_0Q%a@k3Rd)qaBQWvlvsEfk!$SSUj_m;={7pk<_VL9R zt|@A4R0O{YquZ_cQl!|-qM$tdt)q4W^Xcr}iv?^zb0lvC-8$sMwy1qJ8K!k9YoWqZs zQ&VvfdE8SbEeRLjz@6zCS(=XJc$-YkvSeyz(G@rRz{sIR_V-SCjg_+L*v)1{PFDQ` zBmZ$gCx~yqz+M{n{|n>#0wT79ZipHcxu8LBnY0=}hV>d~F6kIvSJ)@LctdLd;-3Dn z_hrW`_q@QYgQMx99h^-1K?^TXOn&NFmh5ON(WORXzX~h=OY$SnY=8Ye0yC2FEf9=p z3ONpunvvQr1mBtozE!Ax5{p(K6-kDS8|KR6_qlTq9??&04?wlAlbZ!zB#FlzSJPNi z5q4?P*jx9W%l-Y{lJ?h+*EsM@ErMSec^m7oN>x=oSX37OhMExWaM*k^%W@+A-8z~* z1h*3;$^PR!vLyE$>9hCP>onmL${oB|*WnTL4k9&%Y;FzHQ57^1@&4FoPAy!>?ZxTLeE(mdJoDr@$(^Bc-r$>Vrl* zL&c75Y({D`jgCEQgVs1a> z)B3_rbS$6pt9)-?QmzzF!iL2CLEn|i^^V|=0T-HZGHV=r`Zij)Qcd|uD^hJ1(%gFP z{jMk6vVTf>s#mP7C#sGaYci!KT{vyIW%JU?rE&d}q`5|o;QlA&C4nfj>YiTj>l*?oLwhE7% zJe(d^yoUwtp!%K{hEQmopSIGs`3X>Bodn z9hGuo@&QnJ2jo+csXDPg^VzZ^bYt*HO($i%wbMy{T*nIvliZ{^R`%Rh{Hdf`9J>Sq zyAWN+N7lIxA`+x=^5Av2y^r>QXw$$OC=zMgc7MWO47~*eAmss**^qT&B?Pbr0wiE0 z#nD#Q%mqUzt3o0eoXFD-B(NyC6o)5km;9;8Q309|r0&8L1{g?~#4n04PR8N1Ct`j3 zQ|SdYM3WbrJVp)z+;UP3H3EpM;>(IXgQ(^}@N+~vNs|n&M3uaTb1;+(Qk3_1_L0CD zL;h3(wE8NDS$%o2G^x#$U>S&MV)XG-g!*cO!X7JB00Jb<$o(8|Vnj=Tsbsz(&xk3j ztZ?y-(NC%mp7GbPi7ASU!d3!ME-O#kz=xtLn#|fPITsu1-B((-X9J3BzQT4gm7Z=^ zTMQVAk=(}5J3<0g1I`*1*nIXHHrpaLY<^n9G=bI)bRs3$c>62}nk}P$|LO=CL<}c-3t@;}roQF+01BiTlb4Ck~{#eJX)c4Q0o_1!dbbc&dW3l6OdZqrJ=> zZUlWo4o1B_)&c8K_1!~ZsDJpPk54_QVU&17_VMw|c^T^L6C$0ggyDPWv&C6#?>L#I z3;w2G?8>R%k~*Wd&4dBC0dhO4N+6DYuvX-0O}g?ig(igZb?u$33zH&=0z9M;Blfi>1JC%6EQe^lg(s)6{~GT*Dt=Y*lE-lVXe1o?H8kc8uu|AoSBa-C(myW zu&Hz3&3$R|aJmU2m~p^fUX><>PweSH5Q39xSFl*Jti!;uBOB-`VQA^x7-lCX!Xo@* z5tWIr+MjPkrIP$$)8GsraVe$w?AL#Bnz=h(Aowi{LXcyE$NGpR$#@};CSF+!-bFHa zRoII{%?z{W7*b*pa2+i`xN^rhi3|XxE~So?&&EleDh&)Lw3*@`z?A2$tp8>kzO(3f z%T=8 za@XaQ1MUF+?9qQeIN02NQd|j9Akor7Nkc{uR^<0bFaY)d>?5{dryqy8DtomB znybJH--w60iV1BQN$>>f(~1&;P9nH3zyDUJ)hkWo7Xx+mUwagyK!FvDdz*ls%l>+a z^C*UJQBoXxHEqEE&@92tl{>)u#|+ix@2wicGks^d8aQITa|kLU)$nyg}mMXlCHq?o&nPvAuy}1cl9L(OR&&<*XOv| z_`jZ+)b7&;!xaXEE&!*_n{yl?pgy`K`{o-B&UzDIb)_utS2X(mht)OacM(iR351C6 zRcRiabfws-dOJisq%79qxgCxvSfpfnSLs2gD7iJz+Q~rAXY&nx{^>9;wx%$YoOBQ$ zoZ6EYC=8oBx8XfV?+a?RIk$p(fyzXao1i=ajBoVGW!==p&Xih2o%dJ*&RRu|i&4G75e0Ad_tDGi|`jHV+V)|`&u-zBE> zbOA3P2YBcpeCL2|`#02;uKP6oBbN>v-i)bBrr}~Oaz?zYTY-xap`Y%APzWf7_Iqm{<0T8-9ATayH{@865 zbbZuN6#rXYezSGTZ1S2{5n>Hj2+)pOb#GOK&is)X#hSQgTDn{ymi%?I=e~OhBs^%yWRX@2!jmDGtV zFnsHWzeaHDLP;vza`8|)!a(J>wX;_J^W85k=Wia!7l^egx*q(x{_i712OGH(kHlS2gWr@Nx{>PV*_v@ zEQE($|)fPwX-Ef^>UMd!mH|HdoC z-)9=0l4G^wiAXt4iRH6yB&T&&;) zKZMhmAbNW4)jkpiNhVT)bZ`F+2hop|`{$7k(IZVt>f)oUrk;|*Vq4#}Px;cmB_Z$u zC4J=M88OExcR5y zXc5pX@Zrgx(Y#{b_~Tp3+% zSVTL9h=rx=F7}^qhO>WkyruK#u;PA0&nB+2?eknY&4L34<>)3G2;G3tv?f2>-mr5Rxd$d2=m<{R(oJesC>hBP^x36Vk#PX#(s;U9zUO=bCY=NfeP{p7CJ*TJPuc`Mfg&3HjpCMRy5zgAGz<2X zW>mY+)vfqXQ~I6gT|Uz7GX4}zPFo4Q(0lLknD*eY#|0?)=bz_$eOsrkm7t~i^kyU3 ztpF8WGh&UbPe3Qcj;TdljsSwpdy$IYO_3C4)?N6UVpO10Z_Rm; z@P^}cQ5PYPV+~rhIW{33WHu%SiLLcVLvHSw=3Uj|Z@7yO2DlnmJj-9+eEd-KYAM9G zIJKQ~H^*qLT1#tPKdq5kqrer5Z|%bMz4W%*vJzq9_&?JINwt9D!u{aIC1NRSn*vfA zpCUW^&og*j??$qpXIv2rQ%wW|{`+Wfzjk_hc?d?F;kJ)Cq^t@Ox3>)e;5CtpEqMe% z1caki6asLJB2WPY$eyy=U*iA_Bk1|_ad;9on9RJ<*u8rqT(RY`!BvGgStPwp$HzCJc?ldl7%ahp7belqz;C18Oq_Y!=dTuYJ|uDY4);QsPTK`RDt; z&nrJL=zYa_W{P288r58W;O;|)6DQ{ldM3LUB;VOD92glZB*McL%)O_6$bCTZs4r0iF`xxm?*!cPMkrV-&s~yQ$ zN6xqAgdlCfDEYu?pOvMHpqR%X&ihMYLAL;D=m6OZKm&w6njZiZ^h~g=y$9?Mb=SdT z(#_}(ZwTET@A$B6oDJA|!=H@R{2maRSvnuIuaaOjeY@ZG5HpXQW5NF^7@S19<>mUf zysH|OHx+&{W1Ca3hNnQZibF_8q(yL*=jD?t8xA1u)>e0=$HXbx%jPR zRdBUsj7yu4uL6Q-=a(-N9(@YZdU~%bEQ3zNIr%z;^V-A6s6RI^+x4sQ3>reZuVkbP zFGUk*{DzehT$C%l#IBdU3z(GMP)4gmfYF`uA68JO6kyWfz2zX^;+Ah9bi^y9HT!hi z)7lj1ElA?u!?bbqB5CZG6hJ~tZ7#sIZs zpe$x~50>#(vsl%SAYzrhReTj(g8zty{Z~Dauji{5fCvaxKt1~+8sCqCo$RIf`?&h@ zyHBf7VA!7hY%%|0-mycNX&hjIR$4I#0+x}5fnuiB|2#8H8|M?yVY55V2SXCydUX^3 z(Cc6TfRp7u+hDWcsOlc@vPW!sVeUT>=&ygPYSfV>b8r4e;^gXWHQY@8`nSlM^q><7 zTl-8ZBZuQJ!-$;DcF5@0E^sYgE!u^+@%%w7Br zSPuntqh~h1A9f$AP<&3T=_z|r5VV;55Qgmdir;@$xZgxyU@p*WR(Th+8WmCid;0Ye zob{}-O7=<*<1s^d%GB9NrHEZKtu1{`?QIPk;`!c(^|xkpN!pI)b!s|+^pvjdO7jbw z0ZGtp2bo$m;*M=q&0T~;HVj_^3f`Wzgv^(1&7cnpa>L!6xwGXRp=}k4;=_sf`Sp~;@e(~W&jiRLi0P^mTtdJkOGVh03K>SxHT-? zF}L%A2A@KP&kg}lE(&NnZa-g_;SkeKqpxmn>mkOmS}(?TGbYY>7mW$vYxwSC+SgJ4 z&D(T;RD{4lW7FRCH5#uyN2$9}hEzWEi9Fvk5*=2qKMO_$Kmg8#xl^l&9q?_V9~675 zyoF-WnJE^&DPY9Z?Vm7YeI z#$h-;@yDRUTUr9Be;??L2_-E>nD4v#K6sgE8wTXf6(&JBKKQi^JUR4v>@fq&;Pcqi zi!9DRB8D-Pbx4?XG7`^JYMGj*nW@vHtO*r}W!f!+e0~trO(=i`q2Z_V01f0gzpK&C z%D%_+f+!$oxegQLt0zaGxrNT)nEcifeo#jT&u-5rf0|6OO+<^K17Fj+79$RLvy>bf zShg@gw&VmvlF`j6&_)IbHqNpGcgc=_z$C$);q_!XuA~tIJP#0M{(Y`7ahWf|bJ)Kw&pib?#Gp0y06=fQ}4D z7Z}M5fOWOq*SDeXK#12(4OjTIB7a1T2 z(sS0u|3NK8bsp!ve43&ZFQ|fpg+{ftdVs`)5gH!2;%Ms{PhPG}DPK?QAO``q`wMdH z8_HUSYS;;dSH_N--^UOI@SO-j0K!vM=fxE*QgVK5&#C-B{EDc73xS^gAsGsaAac^Gaq~{&Crt_c} zZU#neicz~cqlQqtjDkAX`Ee^HPnnfp?*!ekymbP!u-VE^w(Ts7Zqx&OKCY*(m=q^g zyt@qsz+eNy3fU@qHKeez{=%aaz8#LK1oU2Hx2ffm2+UN}JMQA3HB(R{)6aB#uu4rRr8PtUG9h4Rivtw9q#j^osxG%oW%K0Zm5#k#z zP@wn>xFPj_sQf_K1n&WjJsGJrIDZg2^m43}W1^{^-6XTms}`5{xn@G?Ib_rC7#q%J zO)$Rd1ey=Snqfgj?!Clq--dzc8nLWcv1v>LNbW1i>WfNIkq%kRw?cFHZmjnhJyM?e z2DER4qWZCKfn$QOyh5b#i@7|H^}}n6qDrD$(0WqK5W{6pLfPg|pM-?5Ca2+RN)>cL zV!&WwTM!9T`Z+3L#7JOJN}Sw~03}AM(7n!KMVKx@o*zrc3_haJ8l zAplg9X5uC2Zq&d2NKK*+o29F?x^_L5n!_oWgMG z95W5+t`15;lzemukkIjgwv3jkmR9pP2G`zLbQq-vCYSq8*dC}B-{9h1^(ZT)xgrm2 zCWLUMeaiwRk`^qf-601ht@Lc_@>no>n|S?};L{o#TbkS~J&{Tx(zc^4;PyZ>aW-!Ne= znG~){)~j;$pJgDK)EZ#mxp0t>;08n_!S{J5Bb=H%xnn+{yq#J{D#^V!jKBo%%L!7@ zhhT~6D5-WNRBk_g9Nl{F9&4rncs8dy3ag@HV9R))vK;gu?`&9?R;{{Oc*7*@K>OWe zOw+E<1g%6c~LpH_w?ZKsvZrGnDBeRhFT zZ~m<8Y@!BFwRQsikf5~sdPc5VM%KXjlQR7=MAevM#dELlsP*!Y6fESt<5~6x<2vFK!P{>W;uxlD_5DRX7iMAKqmo5PgWSz1Cz)77Q_pRPzAk% zcxh#NPcfdxhfxFC{CGTI(~|V(!9{NN1G-v@V&YMU&oPV9+@0qmVm7;MQ=&-EK=Q6?3!9`ENH zq2Q;X?kKw!xOcnE%zn*#k}nA|boMDPA!-AZgocnx>`8aga%s6{Kq zdx%jq3gJm|{tm+jeGXPwjuLjxQ5F*g+##k;RO_6T-ChfsOI8|VfKQP^pp3owT@{30 z>@_;j^?jF8g8zES>r`+FJt%J_c)5%6*)fte2Ig~hHx4}fz%o@URZ{~Kt6a) zaI>XkTB>6HyN=C4dqVzJoX>4A*6@kh>c+XPyUISAy&kKnfAB&n)Lo3GvEq%a8=TM- z{p~c1*n;S9udCpH8j-r4THVQRPeRn@h(lAP#QInedCj`(T#g2C8}WAq?|>>Z{+}1A z^q)~ObWq_1cowc>fM+2L9zFdvZ!cFCwRoJR`$z{jR>Gu;iOQrb@l@f#C=ymbC`OGL zQKKrHMp9)q!Wcfx_*2MW!10IdNbtz(_&SMiC?g4fAgwMXu5&)%L^styDa zv7=)Wd=E?t_nq8Yal(>%)#W<5CpryMCkjrXjr5r>$w47&rS~ z2_%;8dJ(yM5;yEsBusk{5$5@KgKYlKb7{wJu(qh9S{uu@UqAi-I+e}bm=tW$I#q=&zYiR0;=elOxW z_fIhd0+s{8$q_}+#PTyb5gNaJVQ~40c6;r5g=2VS;v~DiK_3SuKe9qCQgfiqQQVq0L_M|L1$# z3L>NU8IQcqsMm+w3Z8MIP!nhyv2zI=E|cR{QQgg|T8`g%e&181j-O~4>JX1lvL;3i zLkcPbLqTPZxbzGGLs88gKCM4-f~+i53Y&<-X&HP};*&|5GV!K6-n?L%Q=ld^b2~@` zR~jbO-XMBaFk_R%d3R`;L5W>0n7l>$zTQtjTOWYLdfA5B`rmyi zy|@)eQ@DyzzYXZ+2v6CGz%ut-K7$XyUTUMhj-G69Vu1kopF@`Sy0ON?m?l<+PA>Hp zLm|Fdc(KCvJK)UBkV$<1SyJX&W)ElJ#J%JsLh&UWjs+>uKDWZdgS&XPhuq)HHJSTg zn+E>T1>6V}>VC6Mb;_y(3>3bSuXvI8W=N%fy*LrY*;lVNv+#v4*Qb_8S65H2zHTc1{&rrjc-h~$-r|0> z?*F9wh0Tw|fPf3DU)$g16MqNFP2ZZ|FCGgD$3q3Et}5qrV&xn~Gm*g^9*NXHRk%xX z4JPrKjjCJ4LR_j~)5aEu%*G^f{U)lE0QxF{O{$fNIVFytN!vJRw}v8xtnk3MT;HBqQxWT7MN@2B!DJUE`W@)mZ{?MdXOd0FMF?H15G^d@gTddr{^?^m$Ww zIsuipT7mIqb zApD2i_ETnrUi7!7qWBxTm{j#$!cPRlO$Ekd+V3HDwB3^3X=0c$_K=U>gIdo09zE*# zg|0XDVzP~$k*hO}y!HZqu45NNWBn=>fdRu2o&dA#WvUKi*w=q8Xk(gVTN63DzCo1l z-T5^5P`{pUoZyD-QX=0jb3N(RcQYqj92pyC$GrDU^VV*!^+1^dTL1`0TQYjZ@fsap z(3gCES&?h`bGnp6;PUE0^2zF1zPIPKh1WdgFHDC_+nmeEWP(2%xIH|s?BGFB=6w*3 z`kc;q3H_1JXIWCBc={cdJwo_LmY(BbhF$;T72=G8z2$H_cB`%%#WsD?pIV&U`hYC` z>Q>JdgvVaM%XRE-TM^k3vPz@ak%>ceKIchiO$_BzYszEV$ibKB)Wnb{kcD;Yx>p#@yu=8^Gf^N;(* z_o*N^+3qUaJw{>Txx!|R?CRqwwuO6GKg`n)!5RlBnFNg`Y2{jl)6!dFrumQ zqvGa(FtyyTfq?q_=d`PXA7yl}dOq*Z+ZaVf)OaaMxfkR`-7(R~Egab^B%{=O;@XuE zl+;D)@DQy%c9oZ_kpvXsMbFD(k6Yycq}R*XRH=`^3`>KkRa2};iN55+taF*hv$dc| zym62NWYmp1+dS!mE~w=sS%7%G>PHY}vcXAo+#Dy>u>=RDn$qwjrU?sZHT7a)vNi@( zG>Kr5pAL1Au)>X-Ivq=wpZ}~05+a9i_PHXgwOZs?gM|xz-*O~)RmbjM8cKb!Y4&Ge zEv?BRQ)4N_p62ubmNwMCX%m`HUMq34aYb1{7!h^leJJEuFTqBdvlipMwh|guOq%b! zQ#8v%jzRYG`FGrWe$m!!eoVRg9}qb<{s{n8`M*3m#78#zV@IwyLKv+X@`Kj1(ofWA<8Q!M1nEVz;b*h#;mG7}C^w*nl z#=v=DwMg(2$8?6*&zV(bR-2jHb4Slk*G^wdQ$h5jDOUWj5gLAu19G_wtD$gLTO2ts zF!?s9xYGH-8f?L{_t4LF#7plT*;76Fc3^)kR>seDX0om)Wc!^>c`UIk++Iw7fI)6E zXKd);!}5q;2Q{u78%=<{4{m_e3H3EILx}$U^ajiTFu{$(vBqpK_gj~tR;=nrf`wQB zX9UlYzRY62N9*p07yK*aV^M`2&od>z-<9dhH)pQ{sKz7uDkDDodD^*GhZ5#yo3Feh z1kanV!k*535VKTyE-VaDWTOeO*E#H|3_b$ep>G;>S?8nf>_7426`~-i_N-E#L~$>( zC-Gdl)=Ny$(CSjQIjT6Jz&!Ka7W7SL6!X;M;Hgd^hJ7G}A@5tEeZ?HDHnS>i(axkt zdzCHb1udyC#QL?T{ZUg+wEqKx+$FRsGgV)#XU^=@~bzQL45Oy_8oO_otdRN)k9ReNzQz+ z*z5L*0z;HbUhCFC@!9B&Ku?_x)Cl{|*jN^08hsOYu2CBIPh@xy-<(K>9;~#_BxVFwVMt`eu~}S36|Cebu5wvK*_uBaQ1M+jgzo{n4}V zd=_APt2{MCigS0`Gd=Vf6~fJY#@Nko^v1j{u;Eqhh+~_kkrbmk8R!@ycVJd&OmU&N z9h1A&pJYfMS%ng%s_z?j_>J@9j^OXvHPjC@X9zQ>EfsmNKuZ z0Mb=4oc!lHJzY5)qK=;JIC-7ONll?fQzgw8U(JZ@$2u>Il|7rE&hHUI6Sc-%clEIH z`uA$2v9D4JmNUP9UH%rBnqU&usUJOexz)&VR`i5>2vHD2eTnq#Bm3#kRyAZAZE`ss z!jQm{+pef>7h+(xG^~H!?9-9S5}sn3@8z`2#=g3u6eL={bqn9Y^nILWJ%r{JKfp+` zV-_ZHDe+z`3392>Lm?5SkQ6u* zZs6I>50hP_U6#CT#6mqC(5b3hilV!g0M}$6nx}oWLgDk3JQDgj+CVE6xi;r89inQniq~@37PWk zu3U;EyD$#gIZ`u=(!aTOpC!;tFDYbR%mKHMU-XVOykSm*520VdpzwBOH~L`W+qpQ` zrdk}Ge}7?95`<-R@AX(OVNkbBZ&aQv*)h?*acC8_d}B!w@IuEoZzf7~X9ixxkR^g7Fpmx2(SL~DsG-DPqZC3>{dDv*Ywp641UUGm`ALmY z&O2i{!i1`CtZMCRasP|HY~vJ(z6TWQE594PboR1&5BPR3bb*G<9f0hX&ABM6;|2|V z>(;{ssGHN%@0KjtPf7{rk}4@<+hvj$=p|WNijE^2coJqNiDHL_UeNuX=pGgQBGa~| zJ!C1hQCK&1Dar}tf1}f9rO8}@^C@ccNmJ;`$`|hvEdIqw0v)Dz=&dE#SS(*Hxo^{| zC;_(jy7?zv=3OXu(9W572c6-FusTv{NQN-Tw)Q9!`66QAXZN z3%ho@M_R~T0PX;EdGD1HaMtpf9Q$lYPk%wh)o(hl#yJG8ZLLk`=f_YVBYic=WSxS% zjE~r`71{2717|Y?eKvVmYRGfWE7P?u(>7%ySbrGItU+~yO?t_~YGuQ&`RV-7-LGU< z(WhRsSvUzo@EDWie?QkwOSRB?L_s8X`wj$LFFk;5lV2xv_;$1Z!I4sd#URpN7v?I)vSoCh)W&vJ7#D>k5&#&E zx2-l;1h}l~aEwa!|KQ07)JYIXOs7&jReK1)vnp|$KmeYVHF&ed7UQp$J`n!Xt~hLB z{y;~YhAsK|wp;v}*B}9o5Fk#j0>aOp3Cj;WA-ID{3IC*jW3Ueg(C7VCmlN}9(fgsl za{O7CQ_9j1KFzBn4o1TymEUsGP=Nu0U3Y2Q-^8WO8O6~&5Xh^_U7j4R(j4+D(GY{y zMc_9jKh+F`kY9q%SeO3Ill<(>@Vou{tPy%O8cc0a0=m`m*h2xUl$B0!aunaDeZmqq zr&iq{`1XwD>KV-?2s6Q&hjhz)25VmO@MMBxdAQ?N zWpNAKQ-L$8P-AosYT2XXFuk!7JC5g6F0_7|oo^n~%g0AF7a`j6+sj?II+f3ir8x@7=b(SWJ3D!` ziu2Jp)b9H6>Y&A5F4^Yp+~*CVBQ?R}G`ANLjpb1v83ncg()gO+{wI!elIAG(NS5O| zu+QZr$H=YB2`qBSDX3cCHJe;Yt&aop0GKxp@F-8BJ_w*taECwfp>gta9(%3CUMeCJ zUTk_Zp*rga3RpNaHUAm7yPO*%-?xQgy5xfD=Shg#j_H}KU;Jy-?<7NjN!igsv`Uo`>-dUPwdh-+3ZCX{-(K!iMt;x zTxU#;W%69FOXg+9CA6gGY^`Ctbq(#< zHt?w5k6cdkbL!o)Xa~OlL^d5g=b8bi6-3VpXwXY7h63Br2aNTSxLhb<+L(;v@%0RA zpws5aZ6X4ljmXY>G&k!0(4H}2)XT03_^n0sbT1+wY-=E8E)tVzQ){MC59UMJy@cu_ zn%@VlJUTsh^$>~rDgg6-rd#8MpT|cCuYF> zjS@RiUFz-H+W9Ro-UNft50!e}L z$hc`xkJITQW=cHJ%Z)U|gWXdgo$G71ZIQ;i$3^a5`rbZ6b$}(z5oo?C=au@122Pf^ zZMx`T!4e62}Zmp!VWK&!oo1FKC7SxfRgXJPixOJQF4CF`!i&KZ_94TNB zvp45lnPpJM%ZldOp^90*{>|Ef7rtL+UwyZlMZS~{jNNfuh%fyqFb=iklJ}oKTrHXz zd$Ma!7zh(Q)=a^amkTHe<~A7zCo11u?3W(S!$%Wr(U=8vjuB+Q=5Sd~wI}FUs3;^q z8&#)vYUqg^7S;5WX9$ight=9`cEpheNd=-0Y(w>m&2<&=phK!zElICc?mkM-ovQbI z@{&-2w*>qC?sX^QUJNCEmiE^&t2C@L&2CNKZr-M;>Vsa4E(_GV5*qbnrU>u?o3_S&2 z9uVTr@~yS+F)06u%>$aJSZr|Q_p*NFd;z5n80*iCzA&9Eh|&#nEd2WppYmi+c8}Er zA%lw~h^-<#XImU4o4l_f^BqLDm&K!;)eOEm;oEk29$q2_jv}6Yatw2QHA$&zreRQP z4WN$T(2RG!XpR+BHZdU}G~?I`t3Dk%g0#42B!$5Qv15p_AGqp+oG7fjh5Vu0N9_gm zgD_))SQ``U2Osy)52lKL(R$doIf5O0%E!ohHTgrqA)ZyjCUj&uynXyAx#|S7xjpFD zj;aHWPw{eIyD%8~_66@{2i?~KKFjYVFZqGq)GUrw`K+Wlo;KY`FbFxbIX-E)gZ;BH zT6w*yV)!IQU3-2Tm%1;WVC%L1dkquo)gD5pDE(Tej7(ZA7C)T<6y=60Zh=h7dmj6k zvCWrSX@O#!RNg=-Mml%KA-|IPi|Wd^MK!fVr3D$I23VA(gE5H=+l9kc;oGL{j!gj%oL@(}ZL=xojkKcC8wU@T2d?YSgCjv&s{?}KFC|TD;nz?yf#@-J zzXS#$gXJhN9;EoTmmh}>tXWj~H0Bjeh}Xf#wTqu-C41m*9nt-rXSop0axLe8ig78iz8>!tqr=1r*`#8WK`C`gBvecNl#IsGZRkx1;m&v^?b`KF5Q??ds+Ng zdeqtPjMNT|X-omf|J{l4B>rrbK_UL+L@``%9AFl&Lj{~cV3VQcR0tEWBQc&&6UyNP zbMK7N(2-lUdi(ng=0wI|c%jn!G(le?LgV=xWRr!r)wufsmp;7>VnASaw?ybHUc7x+ zNkX@fyZ4Ol$MgUuiK|rOKawRD6_sXRWU1$$-sBm64kvzXUMh9}R175ju`Tc3@e}2H z9&RrT>(}an5V;?EX)yZ@s=M0CED?y>Ax5Cna#oI%)OcoZY8%*sFh*gLIO0X3OMHl6 zm@S588Lm?9A{H3^TUa*=vHdNiT7Sxp5#fvj3=;zMX@ZE!`J;0%s-A28FRs2jp6d7g z{~UWCl0A-585wVs2=?*YkQlpVxh7rqtfNJ`9~-PDugV`h*r~Y4@-OPkejoKS*|BHV2^+Qh4upe*&6%f$ym!CtA@-JxnrM^L& zOe|lqj>kwGmEbD-K{35bXf#c?+9(;}_-Xc&YwvyD+{PxZ9x7vU3MM$E9)UiV0uB0D zE{>YVLq}O5+uP6MQnJ-5uWCg8^4SRn*EaQ5>A%)+>r_~eFtG(Rg6+pvaj9Y$C$7{X ztYi9yT9u@uIuYW`y=hSJ{7R4dwbk!3@-?eJV=T?JB#QxO^pC1q;yXN!_1qg5n)@|} z$*)LsMR8nBVYoa&xXIgu{Bm1y^zeITftdyo(rIwhV}@zjC6?R8HU}=HGvHWqll-U& z(qTy}Yj>$aYO&eNhy!c*bZa3kwCS`{Fvq&q{TfEbH>|&4>5qcZ$m>aIP&L!n)%C-u`KV*YUxs9o#$Fzp(!Mt^`bLF>ytv zuQgIZfsp{Sm3u*pN~?Tqbt0ztu~cL#R4fmK6gpQx^+=Z8flxsQKm~nYU-9zYOHe<} zcda_aWXk*e6sr1f*e(|GV^$f<+k1CN-8Sj6516_2MDU$m)F?3a0bU*n+8m43%C^CNX-`Wgbd|%1V zRSH>U8%fdCLrVzJ8!OKjg~s*nlvX%!2SN*?y2P*B92E)sF_h^Ebs}@`LuU541Wu_x zJ35G~{a@;jIO0f3l`Mz87*cdZqexg0sPY3>Da9&BN}5;JWPyS!kfIcwiM5Z2tZ6_S z2ej%l{kSjKq;K48ETnfD`q<+;^>TZ`W0c3mKUB!5${^{VNT^v2WbvCoa-6Bsl$u~j7PEX(^JwU{^^zPpgpENs>Kj`Y^Ti%yA5=ItV zUhzhCjf`0O5=i76C$wb?*g43mf+d_)$MzIxoZ{g5MfgzR{pQ2EUUUgcT)dR%lukb( zN6A$1&I7v-vft}jz}O-iUn{tkcNWx8WGj#@3e3)j!jsvqY~5H%JIwfP+C7k64mkC} z!8MBS;LnF-fNokzV_VJ<&rv-97ZV~z6^TEubl0sM))8vnTTX0lz~2wr><~WD&=WLO zsF+w{&d=s&{hSGrdF7A|P@-zBN4?x)&h7ck{{+Q5hm`qUC+x}qmwoI1y#34X9Z#D8 z9g58FJ?JHke>yak^ZGXK%Qkm!qM@{D!(v)4H9j;2|9s3n`axJHma!G|W%Za|0H}r7 zw?Yi(>{0h=8S$NY5JKxG@$_3pma{`5$m_5sh>;pyP7yeI7(=SWs~ub#SQW4WLo%1r zQ!AApsgTVMhB1iT1@paB7b)G?z|K(*13QNT>>MS+&Y@K1lx7S?*by5|Mn_$FE>a$s zF5?&6pHD$L|#ztrPvO}xhWHz6o&VF!3kFn>q+YQR8xCxXjR!wA<`@4PwDcbbp z|6~;#TMDZFsGPB0`Zm;$>5nz<(n`iHuLl5n_z?bycJ6r4_FCWf$_oWAeKE*tz&@n# z@E2L;viBdWTY4O*-r`X7PVD`$UXMhfC`(2xyPrD+ZukFWiIc4fc8OyHS2lVP8LXgr ziy)$T+&lv%M1u!Er+-{K6KLQ(@gn%46BDC@nkNJjQBId*I`&Td_ZL8V&V;|r@5I`u zmVXB`G@$j}zl@r&W}sG(ys$Xa78Vcc=(g(A)9f2hD7i=r25kAnGZyTUndCi$!Qv^CcuGlpc!o% zmLl;Z>}?#loi#s-6Onr#m$~`#v!Tzh7cmiDP$l5?Oy9JvL&WMd|jAe*Qc2Qjpu$J(9(sKS2BIjkk)=Wrd{D>OLg!W}a= zNh?2y-**uuL-K;2LOen3AU7b4Uc};*kRfb7dN!1DB~Wn)fQ}CF3vj@I>q-7pF==>8 zL`J@8OhXag7!W7R7^Dfs5qF*yho)D zU7&ro)#|kuwAI2CL2_6{pe@uUbm5E*ZyNg-&`^U2hM&iR=klRER~P?GmpSZ%!?FZ^ zp9`>P3I1<>0qtnLr$)M~lu{KcvVsq7L{I4IMDMS=Yg47 zB!3bgHNvNj0@zpLg#fu($9Cf^xU6eaQrLZECU1H3;}3CIHq}J0{5t?0r@>`8AuaA( z-A#mp<`8w}pLR-jdg+ILIx+0vpQBRH!(eM}gP(AA)8lgA&E?;`+<(LH z#Af#^@jnn(+}R=gfS+dKN4%-gm)-^HOjm|a9WItjLx+4oo!*2XJ$mVX1CqiuIRu&79~{S+ zz8nuuo`&yu&xR@>N3U*dKA(x@i^MZBQX|WK{%yusP+vD-2Af{kNUNLs;am2Ov;g4c zNgy6sNg=Lh-H{D=d8qRj{NihF4OM|1L&igg=Bo}gW|FkPKt!c3DCLV|EiLoNy{%<} z@>l)Gpx)k#Nq_X4={G}$$M;??B!Yy{`fi#~Pn$qJU0z=@WeK1Ylp@d=;(J#PP}iGO zOvv>`@8_vjTW}|wW`P6t+g_ z;p_+txy_d-A%@AxquQxlhrj2)eXuPHSWs0HP`&5@ByhUJpVM=LAqR8z9su@gr`{PQ z;_ABUkw8rU~jtP&}*Xc%_MEsrMCIW3OdOrl+?R$ILs61P`-nn~Sd~VZheIoA@0y+)? zwm2=)xSYHiF#1+BF}27MoA{W3j&`&^eS(_&MZW1f;7Z%W&#C+Dh~1H@rJ)xbpOBQY z;WvC9Uby)PFpL?|sC{zhQ3ZaR()|Zs)8s8Q|OrQeMw-6x?* zACJiEUu`0fI(nlgPxdd1)Gpi`pBFN#S)%N|^{E3EmtXBtv&7e-dkg$D3{hsX?jwt- zhKWtR){d3#jP?ObA!fg^IES8=xz?a`)9Iut2V5UYwq;G;=~Bhaz#0ug$dtIPY%b`q zX4TsV_50Y^GMu(U1w&-OT+AQxT8ERQzx-wg{h(T0&U@wfXR#zoLK!48=Z@BXuKgrt z`LJzunLc?oi{}$0tnc%CTK-3h0#!VMPQ4U){>6!|ib7))%bsC8W5#nG;50Sw^qlO% zw(E(3kYGVG3dtqyioIN`*eS@M+AkgdxZD>$j>@cfTeHuwh8X$vm40fmX@Soz@gxti zt(#9!diR_4hv`rc;YYJ=&YynS;l9{QqefjYY$(TDc{Zq0y0rZuU23ZrrBGzDDBiYz z%7@2vn1n{rd|uw*mI*AmoNtk9YPg-L^zbmFp_qZ>HETdxG1_99RB3gL(Zi5BxZIO| zP!dtGWJfaFabnHEfmp3vC9DqYy9C0(yq#Q{3y!%7svWamIYq$8)3k5IM69CP_SmJo z1<7x{KgN3B7y8y+C!-VOFxza-vVwaZ8m98L3y+9AJTNqwZiV{z>D>>~ALgD_nPZ1e zCW%|IL0&r(7nrdJI^OywezDGy(_hJFQ&LgEB{GDsm0U4d6tZLc=F27hR(1gNiqkqb z2aH+oBfa!ZHbcD1YurncDP_;pDACF7%x4Y;XTDQ77v6r^>8nPtK<71#x?c6A`M&or zkQd0)KX=b>C!Y@!7bxKgFMpbu-Qh9cSK98r6$_9wpgnke?mSWqwRwYH<4 z6l7tO(Dyr<74AL%^D$LW7LELCoYJ*B_e#DU&phsmLSL`kd|5JsE2DA3XQ44Zku=Dg z=OuPoJa6NtABcoISiHP8qcMh$eK0mZy^&uPP`cZB^!(am?=Z)w9ixxE-q4T&=j`7Q3tzir4AWZz$dO@{8bagBK|E!QD_QTQ0v z54_ZXZ9h6tihpHGUq5Wh23!0xrqugmBID|s)4|oy#?h~2^oOEAFOB-pY9vJ;m|$H` zW6*2fK2Ge(LLDe*23e;3wxHtq;}P=GyKC%$wVlv;qbg?f7hY^q(H9uv>2DNnX$?5; zmdOt=7jRa+lZRk;qTeZOBQCw)X+F?4AVUa^W0z9N;A5iSMz%@dBCU3QcL#QR$WBAc zk#u}U1?>3d{Af;u-q7Z?p{U-Dkq+&8s%4?;l8`f%s8=XYRmN6E;P-x7-)d+P1=?aE6RCf=(YTX$w zm+VCQdL4saOKZ~e6udsyKhO^*z1Yi;^~$%?ZNj0&+(;fX`K;0j+Fexo%DFo+^L$h< zp~0Myq|B-D#Kh_FSip%~>5BZ2u!EP(i8XPRraf_T9&PSJ2l_no%MBtgRR6JM7v~?m z@mxma=PyJxL@}bAls9Q)ur9I;ng>!Qy{+mjIm%O1!O}J#0!!9qLVEM;2VF55jlWI@ z!0>}$I9;!APLip2&O3!I#mW*UN!%;PRKpD=jTJli0jlR!5Ms*9vFD> z%Pe>RBn7P1N_4^8fEsI|su?z^e3tx6EBW^&xcJcn1C@(7%}ip%Dy9xy^`Q>^?)71F zzK1H&UMt!C-7v6G@g8!mu(hI171U${|30Vm1K8kHn5^CBUP0y1tUB_fLa)8@NB9#k$4zm{4ZqIG3JA7z} zcyTC^mp@5P=Hq6R#O+5pa>orW3^-=yrm$$6Cfrda^XRL!rgpz(CuxhMbqj|GX=j;& za;ec*jz;jD|PiR9W7-tJNqba6~<3NIoOBK(MqcimM!sZ9lh?i zvDb zlK%Ks{q+xh0~P7spZnLHm0+|^_%Lq%;cD>*MYDUg8y-Hn|CF4sIVE`<3^OxpfZx;B=-?hJ`&7ccA!;oMt*A=5L?eQMqmE1}bb48i(IK;&O?0D>2|2ID>lS^uHzcAFBPxqidve+Y|Ea zsPgn!_^z2}7c@j3ims~rl&>es6@SQSi*KJx=tCYB2s#Cc%TgDQ^uH8pvbV!7y0 z*CnU9LBK942ZtKzka>_MJriUY)7ag-Qeu#0?i(!g&kay+L0{C5;%Y-2f|R3fP(7fs zS5p4AJ)W|qzg~ylx#1}RUxB!FTH{ix6iMeTh~`u>x1-d;X!UXE)jr&SZyZ1n6j~B= zYTstxq}`ec8LhG+;aE&ErBAL3$qDC!v8Zl6rlHL_`vCG-j+h>7Oq;+2E0D|d&1ZAA zX)oDPD=MI$jQBBpP$cAkRPCagxdMO+Rt4oho|0=}<`>rXe{Nppz84p8Xaz+Ifi8`l z0ySE-u<(i*Z@V^~PyP@42vIsDH7_>%p~E5pgX+M*@-Knq=RC8yMR7M-bbH(5!g}`@ z47NzXIei0aJ%=7c+Kmq2>td&$8hAfiWn;0iH4PNVIO~0mf*2U_W@HOV5A_h1Ses|XXy zfP6wJJfX(1PSPbbsIWoGRv?=1D|mg1tA0}xDVoSZT3Xfe6mfa}x>FF4b8;R!KtRqx zQS=>p*=7O!9B|;2ng0&Lu0~N(<=*rex}!KyZkxr!FG<2S6pa$bv(!uNxT`bfR9B0O z<7mz`#NW-n$!!fS_z8399VX5iI&R+Nd|Gnv&Wd~El5fI^^~Ht469Xwe@({<`Fgk`cQ> zjVj+g7yNDbR_N{&FQm&}I*Ks`JeAk&`A7q_%fd{=4Ftd^;J4d~a z_U_0ZJ=mnYqkq2Hjk+8>(fF__iByPv(pbm>&PM|XaN>f9ofl=WqsiMj3Q6Hl-qgXh zROVd|Nhw}C^KI|`{>io8fm}zl$tfSbuCH*4rzf|+A7n607y7U!B!IiA*SBao*wHfD zmR_qr%%EC|q91G}Po>-8-4xAl9^~%4r{qyhH{q}0A0FnJ`f6YMcAHint8TuX>`j$i zOR>R9-wRDPl)ip|!~J#*;K}~ncqG`u0g&@b%=DYI(3#lL$0DJZh+Ha%qmX1;CUOSP z?mtqU1I75CGRC}!M!Qf+W>L@I6$dP8Z!cc0e||tWWEXdLK=v6wd7R)J7OKxYvvJ3J zqM)jmBReAOwOe*)q3s-zUoBO(CTgTfz>X2^t$^D)nv1M#K%mJ$byksZ2$DXuk1+T3 z8#Xl|0_8az*XPXE`T^qZ3|M|N*Fz%rHZUCvptMFC0<+cKMx<5#d+(e?iCW|DN*af|0!r(3f>t;iNWUHLMm;^%mW+V;aY zp|R;DPcm-MmW5;e{4{>aI*)m3lqeD+lC)RQGz*4EI^R6kQT~pS)zAJgx@gYEXtCUH z(|g{dGYVZ|Y0(&WKp}L9i#Nyf$nSH4ye~iudRmEdzJ$m6tw+O31ur3 zx^=HNO)C^o{ye?jLnooS8U>$Agv{udO>{Z+DFqY@yr$_Th5c2x9mZ3|FycnK!H;%k zaj{4nZ{>tQvS1lRYbOBoJc19%mDYccIQz?Xmb>Glzd4h*8rkJ{Z@Q2NYdsuKWNu88T}^L_fCpnS*$kK*$r5uJshCXnPJN_xY-5}EjI7#$su_%fk9yQ|Qv zg`|om+HhMjtFOaOyJR`e_CQlf&4NaFp1(>)@v*%dvUBbNz6tD46=zqf=57PMeit7;%PC$Qx2C}e>3?K=Z3}5K6pg2v3Dz<5 z>E^&)8=5C)X~wqCSNGmRM7x0UE5ZCkk4T5A77S?k2I}318VpNDeA+qev|s7wvE_vV zEDj}LaR|WTq8iuqJ|}pBfPW+G1uLo!Zy~+@0Wz4B`Aa$u^hI9W5#Pjx-6f}tt8e`% z13|^4Iiq;;LEACZl0)NwvAhTsvI;fx>niMnAqQs)3MZ6+Xu&t}-N*>19wAeqK=x zGaKhKHn1MyXu|jiB5OsJ{3mu=Z3pnJrb81?J zn50-Z9%2fc;zM&R1p#1~Y{Z(+t~GN@5thQkYTx0TmS;sN z${eelD6Us>7ubX*ysKXf!MH)TPe;Df(&lu zYDdZ_3fevGTS@EKat-i(@*%^l@CW60mbXD5DDL##6Q$4^S275=LQZ;-0tAH}aYRUw zniQn}y=n)9m--1?PWEK|R2nzJU*t>d-~djO3qR%x$T1Vp{Uuu6po9_tN@zkveT+fxquByYTZnS9 zD8)|YLUb4eKtp4QLgVzCwlbzMeTL}}!+PRD3mtV#KO$mI z(i@udjtlas)}MaODOQJ7yPpgcbFfP6NHU6*M{GQ!m*B6UBoMIglhxkBe4eoE!2snj z=LKOi?iQ{6u)dd1qDP+`%cKO?6pI@VRiz0AczkE2apmHNX|PKFNwRF856<5dK5i!^ z#4@Kb?IfYs70rKf=JTUV;*2C2dI^81JL`VQ^16l`DsUr5<}!X>l|6GhNJsmq{bm=L zqPV3?wRrqXuYnseY8KFEn@}FlwLjTU4)QF?n51;5Mni@~oT_H~F~Zr#abk9^-KKVH}r|p7Fp}j?nw`+Gh5LNe=)$W1a$WJh?}dmAtlC>7{)= zl>;2W!sqNdK_-#|NYur?27BASYyDw*)l!QDfIf-inet}K%I+k&T8@NVO%`3;UVU>w zjpH60!g9%~zka~$ESpk8S(9y~>t=yf%TBw}cH>TIk|PbuPy|m=@kn76Lr?UF<#Zdj zv7prbGPUYko<+;!c_-QlK=epDXsy4-nXAqoQv>kDCmH2Lj?6=yj~p8C@&O{}C8l5p&~&VGs%qE0W?5^V(}L!YN|@(N{$siLnw zrM~vGhCb4sC-f*ighm;3)SAQGXOwNk1Sr1b1(Ssu7;7(31h6fRZ~0} znWIq_oJ&^JWG?O@-*}%y0aJGTsFQP;ASM~=!EiVA!?cQ_G-bcWT_sInPv!06Tj1eO z{`2T^_ByF$tHw>`3{%Yx?V{nAZeOVl1Ja%>$$maOGUik823^-{0rt(ud+XO7O$G+V zZES9QS1a+c$5!01dZ#QH_@$ld`FPsi%PSU!BCFf9ROE{ouovY_d^_o4oq}fBMvh46 zxCQJulzxLH<%qdK z9;c8B+A;FTd&Y!UyP}*d(z|AwZ81%Y93|6!qgCVpwLt9Fcoi>As`HpgK$6QrS9g!l z)irXyQYiFlZLX)GcfP9VuYXGG&$x*C_mXuyf8`IT+E2?L6*vuU1;H^A+e7egW!;V&{oDS%CoahL`_i zMtQ=oP#DKK$H%4;*!{L)?Rkh>5qFc}<^3mh{>>Sa53AFv^AVqezv)Lkg;P#X1H$A# z^ggyd-?Lio{OG&0pSg0J9f%{i(*A>y9G;~?mzUHa=fX+;>4Ut!Mz0e^x~<2);yc&a08C(j+dWep~z2wJ51JXk8Lf?yKdHOxG@ zi|*$+>7$~SKFX_S>VoKecNQ}TiL%})sD`&!Nk2~rwarN?r_FkJuaEHLh@K-kw-zh@ z48{p|VS($&dR>!Tsi>PHHeyc!zaOB{5joF#d`AUnyM~*ajRw+RnmJ$zOx+!^q^p)f zlbii}>PG-(dwR!BHUXHezl#_^r9anM5tpv`ZL@k6sZz=P+6I*%U%%|Lp8jZJR;blDb?dDe(Uir13<=s3~E^QH0a#m0cS!fVQw>o*16U$un8;WlNMw0gXX+E z?V5?M$|mslN@cuHS<+W6O{C3iFeS@8>(3$6DP%#G?{LxepLrH4f^*FNb6}J6Uf<-73bS+pfrDpQTpd3z?h2$tws{3cb&v?oEj3u>t6(@!PiPT(S@8lEfhJvyx~UUMr>w}5by zmNzF2=l3O+0cxNH7Rw}UjlQP*2@YR;#j4?;ra>g#XElPb&LV7AuEqM@b2H9QeGX4E&-SUl_p044K8-rA8p?o>NDqzazE>5zHbV!Qe=MnQFqHJ7=I|lXHH1-X zhoiTgPujM&{(>qXR>~&e|pTbp1Z=;}C0Ru#4tjexg&aa*yu89q}x{ z=FCNm`b1{(FAJxMaw_QATFgmUXV&^1kB5`{lsBXS;ffrJLd=0} zLPY;XF1|ICc|Zm$-z`rGrq;p$QtlEUw3Gq?eQL2sBy|~nJ=3F(6SUlH5yiyjc_;jU{j=rh%(eo26EAD%YWa=)g3u(UpJfH)kClbZ6rtmW zk*E=fob0NKr~2daka)+%*6u(Dt;PM5FXbuJ#PMcjODIzAbFAX615#-110w;VP_kNpHa)1~VW5fwMTnxP zc-o;9wAB}b9}S%ynctfK^fBk`+{SO}@70SzV7pNQnn20KcQM$pK2{Mg4AH^>pnnMf z{TG0>lX;#74b~;s^gHc^1f#KDVxOY#UJ^+Gzu^waiZDmBq4a*FL&Qe>UT>PErfuMV z+UO`6e5n(>W!Q8x0!X?`LF=rPlTkGxcmZQG!GznC5#@!ne7ok1|IicKE_&YcPuTKw zY#xSm7`OY!1p=ZYPoxF+>tK#9@&~nY|T zny;q^82=C2VVYDPeQzRfC=FF6Vs}YpXIsp2fh2>02|j)Z=(#`%ha^`y{Qr5kfztv* z&WrH|J>zF!GRR<=4kD8WZTHsGG1?CCL4< z)%!Swa2XEq>%F|}iIZl>)O8uyX;-eyV6OVWN0owD&E&(_2i&iMewEUg2K0G0@teIu znuxAj?!p4De<+u#Gf&kC-f!#zOTWr9<2|%5FLh0*HO(rJtBcvw$7jnJ&PYs9s8_Vp zQ0097jt34U_Zu8M0MWPM?mvMg)!E|nmi{>F?mJ{jhn+b`M32FM5T}AS2|R#pS`Abo zaB=aKM1F=JW(Gv-R?$@6bw4hZD&8c!ni+|3^skrzxph3ZW&*K*9`I z$ERMK1D+3knB^)s8xi-Xu7~3ZTDZKY1Um-16h?+VTTH&h3V+2RJ~y!ST;{?VzaYZ< zD}2Nt9#Hu?-hOL?mEa4}2SDwNV~~Cq6?#v+q$ZpSu76b2`?}@mm3N1RWh2ENus9$D zs+xchi|~GC!Fg61eDur9W(&N8jath&di-i}90E?A0`UCXNddA zbz8`?FttI~1;q{hdik`y_{%3r*7z);cZVvLgOI@gpmI^Dq*wg6;WVYr3)E1N3=Ej- zu_FjBk#P$2bieEZ?+!qpah-C0gm`}c3GthV9F!_HR7~e;KrK~=sVCJVMFQ&KojW|( z;cpNr^fGRNzGiijUkH>Q|9F`BbRnEr>eQ(*#}Zr3plS54yk7jR*D`Sxo#ydJ1`vZ_G|_|$V%_^c5pC}R(fUhnJiLde z=K(S}F_6Lk6l@D{C1m%DKxk(KSbsZ+mN7Jx;|l^YiC2i|1^$VuCUhJXq|5;ZI3GyY zSS!8yoGHAXOxqfwe7j2;Rr`7dkN{hkKmCAy^3&J_oHv~&3=8v~`<}prd`ZFUxz3H) z-hU47E;SlE(7!pjnQl|?Ca~7|7Rt&72&Ob6BW8#Ok(u>dplQJb5?F6CpFgbkQsBcQ zPUkUkMklkyj}!7lC$`-(+Gvd&;!A5(}+Z8I&wcOK_3 zayCrZm#HZ!R@WQ*p;f!G#F>38mcn9vRQ*xxA02qN$(vIUMpMhve91rWC zj5T(bJcdx5LUM2QLsCAkI*aKh^>By3`6Lp^fe{-}c7e zSQXO9JNq;2%vao_+8)$jk}?g>c6R>GsE<7-7ngn3CUN0h-aOV8;TF%^tBZ=uOsXmb~Q; z#Bd)H7YxS6&)54M2{Q(dv+44debBoT%-hLU3)_3m;q2E_)U0=NE+qxZEjHa{!lyjq zcvlYc<4}hw4Zg5e@ySf)zpcu`mJEW*uD){~N&5L#e#GgL-HD~o|Y+n3aNB%w9dm5;BFko_u0wyQo zevsH#QHGVWK!)a|2QDYrrcx^5>-$Hl@GZ19g_o0}vj^Jzdw&y?AqWY}ua*KH!uU^< zewtNj6=w{{Stu<2@Nk9kNLyaDSy>bR z%Zvng|2{t8DqJYN2S$@;n*iH&6B3&@bn+ZluM7I|g^mbLq{RiXLzcM5zZt7b8fKMt zZsCkw;~NP{t9SZJmoo~xH!z004fOQ=G@e}nCbNjNdq-;hS_vizdVTc89ZQd3+fl%! z!g5wRD~GxHjWch-!sTz>0dHo6l>F&abHrNXjsFDvBjS~rk&19{{sILDn&8o@*t-q{ z#Vh_!A5a1%eHU}ba5K-l`hZHDg0_K$8qL|EeCW0&5hhTWDllQ_J5Ra_S$Sl~JQ%ee#6(lxjh!zq-eY9WY++T1wDG&Hi`{pPMN${n-0W8uvx| zDLkDNbp3ygWnB20@HCJU)sN0PNBlJg7*-yAbz&po0cbq%?#n}Tem1@ddPr+fDEp#w;VeAvxU+?8-UNI zkKnTbY))icb&pI;T7QtPhK4e-FV|T~;Iwu>ac#MD$LP!ys%V%cvF%(9H(jpkUVg(x zn%s+aNt}MattVx~2ZC3wNep}UKp%ABnqYOi_&?@2cZEtzvi|-5_&q@B>)YXhKS@V_ zwc=BLe^HPe_Qz$(I#qco9;MrA$Trdn{s|2f@4|bi}T%Eau|8m>~P5#SMUF1)&!q6UiV~UhJFLL zSaw+KL+5wyCZQ2_-w&zMXz2Jl@k!jT^QKRXUB1KEPz(2Z##Dku{jy)nn}Gqo5#Zx_ zZu`cW4IEQA`S;D=LcDGVSOqY0Pm~8;fy{le-}*izA#Ih9dV$X0xf{-9HUgZYp5J#9 zxTHUE-pSn(|4^0)ywq^)2kavUcW;)j z5Ge?aFD|8qaT8pX5@&oK4SS?#XP35N?Zlxzr$*5fr>*Q-Ac$VUmF}pWy8}UswP@Of zgU;Y4ZrV@?ac(avt#UQ4~kmVx<6W<6}tkW{PG!*O~@7k=O)BS_x z$@gZ<&VJXXD={kz1@%q-LP%sUPPZDjv^C=gG|Yd%iIVyG(fvu-17l0a0?LR3MO)kA7>Z=Q+xc1B;4nh0*w-;N1a|yOzu>(u3u|b zCP>x~#$S#D*$kr$oayTwneHG@H$o$d#q;P4SfD(SmmUFj5W?&8$xnXrw_3W~Bt-Bt z&MbVrP+%7VO3ohl;9^+dBO%C_3-oA&U0=igtM5! z!^LqJJsw7@ZHJY}i_>RGU+_>5NaB{Cw|j3$!!+y}$0ewBjzoI(yA6Oe&gHxG9PB0h ziyQeI#m=K1+9A48*y;5du{S}+Z2fw$wG8;!grr8nZ9r~FHxa8@MT0PTbRP2ib(u7(K)jYO>| z!Kz3G=U>KoFsKW={z|K^CO|PHHYmAwKr~!G%FAziUt#*c4Hj%O*R?o)Q{mKgQpGUa-|>BrHb!aMh|>p%S++38Tpb9G`^n$y9GOO$+O1QjM7<| z%QNo$o2}!703&&`&-0T2Av_KQw{FiU-CsnIcnq;Ef)J zxTIAB$HcT8owf_lf2C&6on-Ht}ZQrc=T;6-O43>8#i<@4fsE(!Wi6i$nOMQEcT7hVJR>wo4QmI5cpB6fkt)`YKB>UV&kbq@AOW1K$8=>S6#Q z!LEKepydtmxlK4h`WtkAffK=^`kGHY({TR#>m5}_$k(pL{t*`xT$9=lM_5*szN*No zfMcz&WD1;FGjl+k25?lv7me{K?l~$fal}U#J7XUi*xj4H*1yY9a-MM`gl5jp+h_UA zRPi_iM9xTb6_|G?*=sn0x!8v}Y30o4{o-$YvB$A^$}Bxm!(PRonPB~)7eARz>hmuW zBHyUk@M7)x!x%?+T{96yR9|SmBI@$i0bNSa$Qn}V!w;IgQ0w~n3 zyvrYEC0-p-G!yp&w=qPL&oy{d!HZ$GbrO!(FS>wmX(Eqo>ZQ&vFAO=kCUJZd96%#x zCIftje;GE|9`cffI*(Jt4}c&%YqP9?6CNiaCli;33DR}YxXHF^@S!vb#4XG5kyyu> z)xJ`ruq-jRp8U7dezy74K8829CmN=Yy*CA>FWB9ll*NN+_)7I~v~c0qE9ME{#U`_~ zmI#Wb6?wV1`pVG;j5&A`sHtWP&z?>R3;TQlaaYBw0A;Oi$GovQB_H)zWIb!U%9F~! z&}H{Ld7kkZVR&J+)0J3mb+7_db5GElE&xE=-uCwFg9$L#Kuc&%KPuhdl)R$g5Q)yN zp~G=@F+cR-8<@|?2Y~ibD^T5PmV{}lm_r;^g)%1E9!HJD>#%7F1}|JI>l^U;x;i!h z9_&-T>)fhx_@V(SsK%lAgWzAgkC$=e{YYS~tJ=% zyH5c>$0#kt$JYv0Z1Ky2ICJ4BkTb~Ni<~O{zAKp4rHr@<5G(wZRG`_lxW9R_q zh#(gH^_-gZ$LLUB8`7gvh+AQ|GRUXVJv~^JI@2*AYnu}qMYCWy#t1xJ1|LxBc;3wA z93TYV&T#AvsL`R{`vkC91nC#u^m~-net5VxSIE*g4SY4Y#r5!V{=HULwwgfw;qOP= z17gC*WN2sLx?ZhL9R_sJ8Ll7acaND=YGPo{m;630UQ9eClYvA;jBVqB{23usKPTFJ z#F~f`oKDJ%ggrdtJK6r=cX=Tc0Y)od>3YLGogoBcH|~|_=8{(-;IwG4e>g2pV+>*9 zCeOw%!GwUKOo)g~9H&(XFv@0DMZ)(Vr~+a3z^Arz4G<AHa0hCI^_#`YirZa-3kR zpJixv{rz4}SOy4AE=RkT+q60V8ZW*>KjPF5?dZ$r6lR0o&J7M1pqh9eTcfa2=ngOdDfZ}oX(pD{;+*WI$v-!eeynm8_a+IW*N%b z_}?iW`C%^%*hV*i-b|0EPET-SnmhKl&$DcRY+@q?RiCxUH?{Nm3<6nt`YKaY?teu@ zf0cD0`lEkZinAjB}!s%KgCr~U{4Qx2-E<$MABFJ<+N{mEuA|( zK-6>nAViAZrJCF;_#;FL6vl)_%BhMieh<=u=8@=zoX(8H@1LG6+I-^^x#wXJbu##` zM_%?S{5JK8`cyWnL~sa@%pcWCRP!q|pnV+xT76m#F2Sy?`NtDy%SMV4IQ$o z5npc%0kJ3Y5>}ZTe2!M@VOA6u%W&&A5ZF&K;s^z0lF2KAr&ZZgtkPebaLXyr5N`;M zyisA&Cmbl0Z2S!L?_?G$Tt3(QS4UJQ>9e8+g0UmnGuajrM0{)q{1!L-ItI4WnX{K+ zwDOMyF2q81ijm?M72`Vzv7Gh;=@x2RyT4Mth|n1f;)>r=w(zI3i%$-u{VUNTcJGXy z%=UiIUox=>D6|-YLW>~;<{pWM$Y5m*NsYp=aS>^e``a@{aHWg;&3=rJ}lGk7kHBRKU{C!-Qp+3ivdm*z{nc4)-jkT zLh^lk>epkmPou9q-ixJ@|GO@ZY}*YcCPw}tpt5w4Vr_z=4kroXnwwKKnivAHc3M}eLh0JF3^!i5+3E#s#cRH3hJC=JOB?? zD@N{FT$z|=ebP+TBQ!0;@Z{zO;Ld;OSc#jGkP{OA)%Ha-e>b~)1ovQo5aC19nRa3_ z1eNMP7jxa_XFv9-j0(|%4ro^38}D5ZG*$*$cY(Ut(I5xNxK~f=0FnBGchMegcfp6~ zQFy|AE#C2e=J1d7>EsYi4pDm)9^pc#@yg0Qu^WQ~>nqZoH3y2yHHTalF`EkY3(*Cu zjo{;`^r{AzcDv9_8Rl4!vP!y}Kj=7D&b(HO-wVsgMC-?hG|NkY!m;LGiwZ&753E#v&F#}+9%GSJXab_l;Ru( zxmUi!e;5c~t(g5pEmI$iv5RS|zc+3obL?%CgpUCy(v95gnpubl(QhhAPk#MirQRSr zc7J-A=9Am5_Dd}4ksk=3E7q2H^cEtU;HMXx;_0&NPKd2+ez5CRJhP)vtImUnDWe@^ zq&IUr@Z*$1j;1AuOleMlT%u-dy^fs8>3qPArP41|9ydusfKt;M9 zzrd3nwrq@nUDs28*i^NmoSJ1>1q;?)osPbbol9c$e9bcBQVfFYvYh`42%VMFqkg_E zk(#2E`w5I=8%E`(k6}zW_zu46oT~un>%Exiczg+YqpU%LuV+?vZrb!p!k}Ds5`Hdb zi@iUhlEX8bO_CF?`2moF1= zf8agwdZnzef-O=Q{?JIK+pdmSWOo&iSfE3#R^*-ku%pXxt_qZobcphi4pBbR0hH_x z%12T6Dy%8Vk=x4T`41YE1*VWBpOO_6zrK9+sCbXK9@=5?gI?lfIqZ{ej+>r0id!&v zSGy&l^)rW_a;6v7L=_--Y?f9i=V?ke7vpT{JCobdR44u1ZD`L7^I|T!A)-~Ts(ouH z)hNYm>1+5^YC(%I>r1&k=3A5{#+Lix&z+_FtmlniEYj2|OlFVG8Z_RUrX{pPGJmZE3H*U%7agzcxMVx&|QC^?S=cgFgZy$5q#sTqmlY zVuR%}zC1+%0#EEazOG~uZc$PE{;7@n!)x; z(&RQ>_k^*bSJw|JMv~4ON#37SKJb}qi{iH*b{e4s6-KJDeV8~f!<7}D(Ts@KZK{-o z^?!)mcUz|>5u`(inL>K=t;<(slyX^wDtMB7MgM+{fkVaO_bR|nLOjd<&^`DMX z_@DDm7GKM?cDdD5mxc5og1+rtQq-{uSD>dzzx zjT0v~o1VSuoDnEzLV1Dd4;*I_FiD)qtgWW@9))qs3y0h?fg4dK&iSX;)9?XJgZq>8IrDaxhAh3Q! zvfj8!dDBxoUuyjB7~C=9s5mjv%%ck_Aqq(e+cbe3?5Dw6*5$sA@lVF7)B~`BT8pvZkzvZL!)wDN&yswSLX>H5ilv9+xT_Jjo>Jj^Y#MH zQF9ct>ST*{T@o{nSaIsAdf6>xUX7lVkc3@~Ikc(o-g6hQJ%w(=_mk3U=XcJ<^rEy1^I+nJ1nR{R7U+RU0Rn{Ws;aChTOKf@(?eP7C_YDGXcJV;f z#n*Uz1kiscD8ThLWJZO?!8QE73Nh@mcUjvJxOAc(HwM7(LnU&94pNHzLC zm<9Oc4cSJk66uCYSskzk1)j2-i@&uMMNn6mafHBfA-ZUfSOSuySOq@ex;8i0H7AVF z%g#j;Mp-yS-jF42i=DmatQ+3$mI?8#b30Q-wGceChSs%Lzp^C zlRjJ-zb@#UY1$?%qI9`?eUVDC)Z~XYouZ=StR+TL!RNX-uJks5m^PT=zD`{c5tK~w z6>vP37(3^g>Cu%3l4MXOzu!WtEX2(1t$WoAKoqm^}JHg{aEb=WuRNt0eWDgD24PaawGo=JxPIeY((|zYyG601yX4=H&Wt0D{~26Q`|A`T<$2 zSL$n4DNk21VwTI(h~gZ!Rc}x}i_4dSHOkCDB6H1Ef8yLZN#=nP+Md;Z^+wVdT@}!> zkOu9R@&n7;YT8i*lNdP<+pyc!gi1Y%v$n0On1T@;({KHl-wXZFN8>t$B%o}R_iHZH z^!LqN#-*qC@c1;NS+dW%b$g(l1)BkX*j8k9gyC7X69PaxqdD@FlPVqRUc&re)gCRT z-=8KpO2;PmFD6N)BEHQr{D&TfxX4tsZ-S?YGAd@%dtz(nBxR4vCkfb+vreBj7 zhT^BQ9i{tSUUhl9EiBC?h0PAcd)mjr1mIfomr@@1k&eoSDNJ1w6|0UA=uV3U$iV^k zM_L-})k8XjphCPQIh8`Z{;zL|-nR`o&6%wOX6v~&ua5>kdvZn7Oi$SUL&QJ;zGnF% z`0$^FFJ#*V+!vn#Uk(O=Khfp!(;+G3S4x2jE;0#wnQw`^MXqWVI`CU9cX$`tDSgGl zQ&!#J+c+2(LqpiXxwG&Um-Ck(uSnqX*JPT;4;Pug(YS-$vvZRZ&C`pW1S)@?R&zsro+dOv`B40&WS z8y~FlJ|_1K&g0VeG>51Cx*Y1gc`a`ISKqB8YEyom{lmv=^zSkVxc7MCMqDU(?_9gp z{2mBZD`+&BewTq(vHj&k^mOf-PbSD^vv}#1fB9o3Pu5_z<_O=C&aeqS^cPd|w#_)+ zX)Zv|#iVLH=RL||-hGKC%tRCYY>VmmIbet};qr!jN1H=y6+Zc_1z;@{C*Y!-bb?`U zA|k{0fu1$x5M3FhAEg_{#j)<<6fm+Xe%YMU;Kmb7e&2A9c^m_=^3mUXHqnU|L(_Yf z;1=1186Si)hX(ZezwRqi+;jly-> zn?8l`KZhos-;#&AOaKD`aV}v7S^1Wl99rdG2kU^NI>b8QhUKzx zd!#{L*}P^sF5ZU#ks3}pMs^&$Z3Y4Edj^*KaZS?=pIe>=f3k7|CR>Cu{a$wWdofX( zTEweEWZG^>5%?!}SssCEQW5}!;11x3L}9YyF}ArGIBNvqAXou>&ntE!o7{W zXusgQwCA2GX&b$>e@5^OL}?9~zc!t>^%oe)pEXU?9~W9S;&oS@g8pw9!rc>hOJxH< zG|q&G#u*XOI193m!rED74t?q8ak>^)ek}Y95q)A&Ml!Z$Z(9?dO3@QpJ&xTS8)uMD z^8@%mlRMIQF9N0GPf0Uo84;^3Zy#D6lJbmMqu2>hwNyZ1TK38x;M?w?_4( zrI?+vJ7w?Q&v4Dh(f%4UEfo_NTUrZ-i9}rsrVT?fP6zzG+f`jD3$9Q6<^k{yk#K=n$va|GO zQ@?Se@e(fdm z-J!lc(d`Nav-bN>+{2n*7nIh)fFNjmoOv>;gkJOyNx_Qg37}t63jatZ-l&q?yQnS5c$d$8Rx2R|BuxTQso>uROIQgpQ@0ie)x+D3_=wHd*4x4e zNi07&ru|;lvv#?YnyqJpWPB-BxVPCtu?aKYU2JfXZNbb8NI6d+`GxNyXbwRneggyx zgnczyZ8suPL%`?jBI3Ez3BrExK-ZB6M+qWBkRzugw)Vv*ZAPXf-aS-vK`%{F=#1Qv{=93ewJ*5V#s zhoSKf!zG_oyng+NxNtiS&&PS>PIbG{Z_?{ik7>tiR*sv*Xn)wIqs5;!&n<*W-5lVx~*8^^k|Om()% z(zgvzU2ib;xML+Q7N?Kb5WT!hgnhAHi$4G?xOfQ>9SR}iqH9b_VrLU$)CO9>mHQW0 zD3$KrJ?qVc6dG<5Q+tM)=kFAhQan@O#Ix|4<#b*>N>enFZ4iPZuMgYDyHPTD=Ca`x zOA^XdyZpZ6_sYsXDG^qLPV$XNk767UmQvlR(ql0jI6;|;GP)AvEWSNR`S;-oDV&YA zB9d%zgfkvLNknsA3Ve-;{`x87-bJ#&GXcY;X6E^8gdn+<Ic2>e`iwNL$HM#eWu^ydWdgV2)c_gXk;V)UAlZ(EsPw6dnE9Rz&G<5GBMq zi%ALYJu`lYuu$6v@1d8PkFnkp`Ax@L|Gy0hh!UiM4keHto&VQ*!JTm{WDV#QLj-Zd z${%*fJ_P|2<9q6uwg)=PvwQ6<;>R66lIVK01w$?~7xV*Dz017OSy3 z@U(UP!a$+8GCUg8k&+hX)toPDs7MCVQE8d?g)PkQtFzF~F5B_5=EsG|;!WJU4%N13M!&vG%EX4G{lrDQioJA5|@7MvtQ@BDP^W zK523z>C)Hh>-*AgXTP3Cvlvdwf(`WmaFF?U^|hr8zTsG?m8te~(DL!V+a;mxI&_(j zYLwpNU2}ROKHYU9sWlLM$*;%MvbV9n3`dq&vKUob_ zFFXGP%7nF1Vj7nM%(D_**YqF!mP*P$3QyhQ$?og9+r3())e*)+B=4j^Octnp-1VeK zc5?@y~_UsX%_315ig zZkGflzo(f%)U~j1W7_$O`>JN&$56V-RK=hRCMJ&ebR}Ll^OPyu;1(1kdXdJMf;FvD z=H2fQUKmka4BX!Hp#PJ$dq$!>zhs2At`s>_+G1}ut-{NXY&LGbZml|u`7P@FF*=Xv7 zC2!a-)jZ?)nn;r^Zor(AY#{w%7WnOB|9AF%IA;8x*w4`AOfl`lOzs;n5tZS~qWL{V zh*-V#41A1P)ay3Kipt;<)w@kIAD8(RjfluHisi1;YyDgPdCRF!yxR6u6d&=f5j-lU zHOj=O`XH=o}FaG3EZf8r=kKiNOc$ZN6>_^+|= z#QXx9$M7zH!HA8p>UEUIB_hf@HkR?lbfu&kb~L|S$0V%!2ZkD&e4zFgba|lx;1YYQ zU+Tx3h9%qEX#zJfVo`VmBDkJj->=)nGVS%+@@A6vnyif^2JDV8G^O~&MF6`&zUB16 z)?wt;or=oL4@tk_p0U1izrsj0WEH1hjJI*jF$O&=Xq!~>PB!OluWxQ{bdkm7UO`L; zPd&}gP)?^~P!?T?r%N49lE7qKNhhB+SxYI`39)hAPo$`#}q~~g`(f1C6lW%uA z$l5qBUbBsfPPA&02nNU~qbS~5J>o@e%_g#6W} zuGY6_O#F_${OWF6znO&cDUmQ+HH9|T-A@ zR0O&c=ee+{9c3kx_iUXK?-X||&qz8y>r%nv=iu);Vdn>&*j5^ox(T%@1Bu;X&i<>F zJddzWWeha*GmogEEK<}eB=|RSKmJ;BleWFiNja`kW@~K!Y9V$HGUGN!2EUkiTs_W9?RQ1$P&dX?$mlu0bydO~1Z1C(=<9=9 z(i_|YoI}|HZH#wS%WUUC%TP5+IT!XVaUj7j7g1p zDZoB;@crY>EB6bH`nb72rJWgejC`T0H_*@bo;mzIW%1o1Pz3XhP%Eif3XIlt5?csf zSx3P@234~;`<$^K%bv*RDD%l$O$6|@ z5H>VtW>9>P-Bo;%jTjM_!OP^R7^&r(KTY9&AD0Mt$@ROgZMp8*%fA zJ#R&qIVMDM`kNaWf?O%%Iz=xXbum|aeEqoOO=L>I->LIHs`+zou?bEbr#<}m5CtF} znXf*3CFgI;gibhKDBc6rvZ8I2$J*S0!1$8-%hQvFGJL=#U|SYlxm+oYn*XMOfqZG< zQqxt>pDdM{RZ#0jb;4({_JL}+&++T=dzUwjQ|T!C{`EY{mkDtvFUv=g76a0_N~ggV z&-h%3rREPCcM-mEDDtSPjK z1y19b_NQ7}2(O1}J<$yl>9-4)b#CsO)zwMwr;`su&E)5OuUTK*p@UTjP_|;Z<8W`` zsCWZTl0{8$SC-<~_!2?4=arGB0I9t4`cBiJ4e++Qh#D4DeWj-4PsdzwbX&)W=`hJ4 z=Pat}^NDoKr_Wobik&Ak8QJ$J7EUr%Pp-F<+utkEb+*seebvJy)QT6-=;mGK_1o+B z;_s7!-<#jPj@N&4+`Xi^k65u|T`K==`=q{fy61eW*UA2`FI+j2TfneTLl?iedhO=$O^dF92-|$?M2J;yCv^* zVzURNIIlWI3b{Od<<-Vww- za^LmuPtQ)7`Qq87%r7ALEIJ3|f#XXZ-z5~=%eq2J2TE>mfR*QSPy0(BKHAZ8q8~aa zlR$r(UEg!G)^U9N{rlX`H^l-ujO6nLALE9x*X}ET4^NuI72?imY+zxZO;$~?62Ff@ zxvGHeRXj}fp`)Q;)uzf^html6S6#>IwgMA*0q)gy!KbL;C%b*vSHWXAq-FUMMRwK7 zuI4MAVL2T)nh|^Sw;I#hmF_ezT;UB+Ubg+>p+;Z`PrnG#gI)n8ALtb5vhEANf~@gd zP-!O6A%<$WL@;B>dfM*F{p_|&Dq=&E)rz0k?U1>lnw#~i|IL^dC5E!>WAf^xw zr$20wp4!Ah30{2#*`pA=+7-o>8%_dt`4*j}d{RT=tQRZfzPdYxR!Rgc03EX5)vKRI zv;w@5SYWYVulA6aU$EreH?DEVzBRq1Lo7kP0M5^GXz>vj1TTz=r%~3)`Fk^=pPz;? zp<9ll4ziQ2xxqEx5!nc2-v%oy$0a1r?=0@pF3%J$b7o=ZvR!kO?t7_p$i4N79%{@~ z8`mY7(AP%!%ymZ%oUB5zB}b7j6KFhGn{6U!QC17)gxX%cyMFPH4X*X;b)U^2zbMk! z#rtmXRi%U{P$}x0garT-oi(Z3%OEj8o3nFuCkh zDZ!Yi?N$M-;}hRBE33uz2ma+V7jxO3o>+;;VnzZrXw#PgF8|kTw_=N)|JgVC_8ATSMNw4@GR)Q6!LvD0=Yw zUg@H>t<<3~f1#?u*5u^d9a2TFQ`iYxxBO0WfHP>$6e&h%?V^1)bc0{-QR^idg%i!# z91l$KRbf!?E*8OVmLJd#qP1v=?F7Y_P;C;BYI9IjUe8#)YGv48^m+}W8Yzs3(suJu zQq>f0BS0ARRi+ZpS8`i1%P&S2^FShqOkk3cwBIE_4JWn0dPyhP{+*Ziu}kHe2^!LQRB{Nqfii)T0{?oHun^l=>v9zA&$SL)<{2ar5!jQaeNzHF`z!Zb zmw&ZpdE%a%Mp9TE*QHIj4FNsB*JmyO={cPG6CcKS`onKHL~Z=||5f&SqOza_>d~R9 zw-az87F7vpr`4TLmRLVCGmEy!&%X5*{BAy$3pq7(1IUB3xh_#+WWz?VL?$Of(SmoK z$U=>AVEfAF6Hz|!XkxL%<)fvf8cH?1Iy-O20!koA>B&f5Jg(m5*gO^~ZZhiMR7CSLNZf^n;}SMGFWS~lEs!f#Jzxj&NKmddBN^z?LEvgjQ&wQz5T@-~5y zoq|e%+;`UWDbbq6J`NSrm!=;*e0~;ZnAUntjLmw}Zzq#xVH-56x|yGXF2v?PTv_W* zcwqan^vGMFh9zz!8>FR+z+22AS7xB5p2xnf-p>;%NbX?_*&?|0 zPWJmMamNAz?eOAM>29;40=dshA(M=_{|>wydwi}|#%TeNKms5D2OLFYkN~{qiN|;E zdB;Fq=9(qB&2Egdf5GYR)-ssm^i&4I*GxcHbnAm7e#I1-&F|AJ)FN{%7xwRqZ@YMO z&_I$C6@UvtSS**VIxF{39@KYe$9f`VBH9ChrsJR^Y;O*LyO(d8YYfe>qkU7(Gw3Dk z5hl~mDeHqJ98qGpDW#R`(wtq@%851HPeLh_Q}?AiC5;ikiy`pX%^vz{;Ml#EJhVDX z<|F}z`Sw*AOo0Fx&5|}PGVmaQ;?Q*IZXvD^Xt}mUFN=ELdq#uY?;<2^;w-4=UvyW) zzejH5a+XJ{|I0|4)q>A%J~X=&^Rjh~Wv=;=vRL-T&S6YnhbMb0w6NF3&r<%|Q`$bR z9gi{e9YETZFYrG3F!&=lhTq;XQQkuohA9CcCKY-x1Whu^IO$Dn;b*~Ng zs7+(yNq-+6>R;>oMlwiONzD^^__5~x;`Op(HDh)nKFLzLxJJcIOtz-HA1o*;KKDb~ zKi_oO>rdZB?0^pF|2&i^&fw0(RHsD58B4v|6g%W!;J0t`QFJah-nx{A!A}!8F^Vds zjVpoaSR#|8xbJOYv> zT#c%c3C1j%V(dHO#2L%A&=h@{&ofW0i}15Hc|q&rLfN)-E%CDSORwsx~R)<7c` z4NZXNPL6efdp}PFI1WlDjbRDo)J;{s#`Pv!n}+K3kN#!Bc_@ei%rpvAe9yMv+d!*4 zjtfV(|_)g+EAHDa$>_UomL^ikoe=;DRFssm>=eXf)g- zIWy0?+y(#Ib7i(`s5|H=HOArRgu{j6|Ma~f6NLTH#h?PzOYHjBXat~zB&l@sl(B#i z%#<$JKi=Rn{oHlsHd;cQFU+zsi?AQnS$qUt^?do>2TT0n=i&SQ#V2A#@SX%xzT*K#o)J_}shwS^!iNvZ9w6Do6!wihBUnfKrb2l?RX@^z7fYld}i*mZO zOxSrCHZI5yOk$x~SDm>Z*R2TmVGHq~3*?-&zJp^uoa7{62I<-ARq6omd;F=XoeTx9 zqR6jf7v%#LoonghjZtCes)H4K_#YlwS#G7H>NCw46dN8<4IW%X<}rmZZbd+_qo0+- zxWpIhj>VUA)&fgh1!@*_bO3oIxhKbmnK+;q)rD5G1A9HDabcxe8>Kx5A@|FitT5p ze-WX@Y2fh}$6@lX_WT{8Z%BiO3%0lxex@xy+gLU#N*(o~lRmTasy7S)bV$jqg*w$j$sx@xp)v#di4So?-Ci3}@HlzTFMD1zC9j5(Wfz zI)cQ$y*oAX&z=WRShmRHfSTxaS<=9eAE*tESPyKk{kO%bkIpmt4W6JSF^zD5A@Una z>qm!qxpu}H#3N-KpW+Ob)RvF|(WsI{Ae9L^PU961Y(|!_0m3n~& znDH?%QlxxzlXwJBEPfnuC>EagsoSY!8AXZ@HNunFjN57i1Ve<^L%Fg}yzZ{Q&w63;aa><#Gm(tuwG|kg4?f&nz{#oa7~f833iUr4 zs7K%^xJhgPR9zu=rp^F^)Olq>WI|2SyE!}L!5uPXscG@11V1snVOG@-uME7{8)yD z0G|{MR{1pHF9$>_&=F7Wg#eYjH)vSa?)P1e#u#x00DxQ?vN)Ti#yGxx{BLcg9dDha z?FBt0wiy$5WbKvH>Kdn!U%O(A0`XcAKrNF?K^uQZ+7N|3s=9!H(woH8XZb`Cz`z$P z;Zy{`N4ypg+2`FbULi1bK!E)B(&PrBpS}Q}#>lXz1k)qvY5#}Uh3AzC0wtliV76oj zH!fdw)alr4qo7f0XAyL7xiqVB6^jPH8x4A0TNnbA07GV@8Y(utO2#&0qgG}IeG;U$ z-B)wxx&07e7COeH0CiXZ{Cv%#1XTU?LawX6irOQBk;M(tu4w!KYP!ci^rC|)699u? z_5HI8Ke`GVA>jp|=-2II_9PZ?-c$IZ;V$7 zg`i7K`d0CSZt;R#LmnL~4AW$fC5TN4gv6L%$eeszB(XQw>6mNfx+<3Ud!!WGHeKEu zyv}U5wH5&aw$;s!H5M>G>Xv5LLSx0{s%RTx z!UV}VG(M@7c^kiZQ*dyJ%UiNTmku{nmD0BAjPHft*tTlUI7(NYZ5>xP1Xp`}Pg%>m zgfyc=?c;Ws2R}k)9MsBE;Drh!FVusW%s;wsnN2p>pgUyR;mZBq<;Qa4Ojo0Bfm;@O zppy0szQqeVTVcI`zFl*GC!Ez7S7p5n;XC=OJ1PQJ3e}vWS_v4)&dQSO>m?{R53Sxu!vu~fps&%9fu`9(|dVUHH46)=@Q9tytk z+7A8>Wi^DU#{UZn%fHunK>Wo&x@h@@EW42qU*a3}GQwz%oHJU=z?1ZQK=h!3}>p^F5TRFGy#K?YaRRVix0iEbaHVHlobFmR=ePkhl- z6lP1}by^6NYS<+YFB20Z3Q}CSK+`sURZ1xx9SQVp=8vrY3DZ@RD+O(q__yLCvn zZ4y2H9qqI%U+Vb~OTEG$WXpD1k;Q}P&T}wk_C)i4%zmREm3Dzb2-bjz`?))WD zv#*$?cT|SBFmF{yGkWAhE?n#y+#>gxIP?)3@|)>^dj;Vb(*hf=kWE3h(bi>W1X%hW zIA84{vkN^cvCNd*eq&3-1)(&&l#*S1n}e<2MeHz#$E*SQ?b_5~=A7BkMU!HIU;f2% zN?zkG+pP1llC?#QaSMmXCA%bpiDAYp9xacLZZ6jj_qK-?@vahnb@vM$k!at@9di5L z2H&(Zu_3Tb6B3i3_N5Uyn%`3qbOgY<*TE{;*tA##U6>8l{m1WW)fks#C2s{D>tum1 zlH-@%E4qqvx)ggq(;3GqW|G^#*oEiX%;EfMfU>A?x#IE1c!ASXAd4ziM*}qZv9N9M zU4tMjXnpnC2hqmU-&MSxCb0fLU$vw)NdN2uT^>V$qZXL>VuuVD@CKP|W8xA6oA#My z>!waOUDx^w&%2OVpEBJpMsnj>SG6a+B7q7p(%T&}*+&fR^xw%!CmY;r6{hBcAMx8( zC1A2@j?LuUsIYl86~+ntc;!2@8+&kZ3x<-i(yWH8X9-$hRH-O2e8bYs@C;0Zf(X7V2>7nir9~nFJ4%}2l8GYy#Q=yvbk-oP z^i4Ls%~E(UA3CI<<;TRLO4>g5_@U1=*hDZ{0ibDFl@z%BKZ&SwuGf>=@93vDfGCbt z8IlNyVprH;R2@u=q7ptB6iJ3gU5OlS0jRB%zR4lK&}(#!xeSi0AXZp|*cYJ^(2c`(Yv>@URd;JWUkMjU45fkO@fHvy}qRo<;y{92c zGcpG+&feYq=cM(dZ$HvOzV6rLBrvCHG-ob*7LQsBj@Q5w5_@2G?{6#v@Sc6j! zP+J3!2jBbwlI+8{k!MQJ-rGKR4IZfQOs&?Q&=%=skdp<*<}lrRHLYn`LjMkAonU5e zEA&q$cJ|&v*+|#j4BRc{edHUTN)&IsSOh_oh!#8Us{a%orPk4GSce-kRDFl2Sk)&^H?*hjfB;vd zvX8J0=|su4kWTc;-%gY@4%t}1BBc5#h$w&QqP%anNBfJC6_metE>UbhtNh~`sl{y^khdp!Hg`gtc zz3e>%pqh+&Cj;w+YeKSwPWHn|tdMx-P1YD%P!65#+g9CYt)>gdO!El^b9C#46c(#7 zCp)H1674?M)Xtvmds&Pf51MQoc_E&C@X3ko{#JObrej-0=yB#9+G&J5#Kt9(8<(tr zX68=`kr|60aqPOt6z2WnUSvKB9$xHN^fDkr7zbCVv1580b-DR^5&0?6h$ljDuz2@R za3GoZoq{xhE%IIP`nDk71tZmeYo-q##A}w1gFEE<;BI6GxB*#LeDWKt5yLU5N4|N} z=sZ59Mv>=pE{=#_x(U54G3>{(J5MU|9$>gR!t^k3zM?H)!{x^s*D_tszZrs3pkxY% z@go+LT8IgGh>7UkYYeS97eZ%E?G5`|`?NKD{>4I#z1SzoZw5v&J1kv{l*r24nDweh zik;a~I)f8-|AP0*~bQhggrtb`o z5qG`NrmO9P=twQ?SC9Bn^%X`zLFeI9Ya6N?B&PwU}Sf z4E+1;uNdO$e)MXk+hwSOx1DXoxO~@bnGN*m43e&ww|ra>fcrr`9!ZF<({g|27$^B0s>ujE{79z*lKnd0C&)3i-Rjnr7vC z1A9_XMlF}w3_9szAOS8qRJBhK3kIr&7?l)@c=xvrwlB9XP;{n0bP;w>q3^W47jS0Y z0p!{WgNbWS<^~_Q`mRdF4J|u&e@9+-uof5<-2tPb{=UuM-tlc=P#DcI4e0TYk$a^N z(oR5D;J&TxdKidV7X%09;&>)1ebL=^}55KTI>=iD{yH%qJ4GCUpi%&NP1kH}GwYhh5A z!k`{Ws~=N=_NG6aWX=lmqQJ1@>n(mg(@!u<^B<=+z6~~HDk7W&5DzFTK8k~1#;U(h zVAdf^0i3vhwsMfYZ7^TCP{t{6y{{n~Zk;?kd@ly;xtB_r8^ac#c7LogxliY~7sa&P4%u(>1Uq>2WG^FG4rij#aG83ci4 z@S)N#%wLTiS9Ut*=kjV?2(GA>xh5y(^G>zJ{n4&pe@*Z}&lFP|#{Xm0Ph2c1(n>!i z{+<0ZaJgMvx&|$~n=wIH@$VWGBf}7o(_lbO`E{mr{tmle#{>b%I6Z~N%sh5}wz%Q# z#qDO3L)-04-+ACgf zgz&oL#*+;#Z)`Xs(F+`ay~VeaOq+Og0H^;&StfBP8#@L}qDV!uzqw@D)S#bYEl2Z> z@e%!nqXGkts$2Ir`1DMDHQHas9=!Ij=9N&q>KB^`Ddz8kePcyZ_gW}C?$Z0bv>KRw zdn+;(?yOntJv|d*wE!4h+GI^uOoQ+okWI|*u zx0J5>(I5tWs^np5Tn|8XKs*1|CN!??qIq#75tZ{t_AEJ!FNGR1z2k+(wF-(Yu4+r2ASTRdZ`IOQp01X-w>`JeSK``;;x_dsq7Uz4U3xK(PWps5;>c5<){`wC z_fD~(SNB0A!@F9nA=|qn-9I7(i%pI0+um1@cP5*-@#g#4`fQ;L3Zbj$q)ylF=#<^| ziz^ns!<#QB_`GT*$4nYsHF~DVI#b#XH~|XD{pR5o-gXae5sV{oBHl%=JSP8 z;bhr|D3yq+gj8!wNovJt&QM9};@}~+6?_GS+o5+=?o8Z$EobTZm0)xx$o&3?{oecO zUO%}*BI;Fb);2YjaedPUF36PHx;gVRi^#bDJWo^9F)bU5Z&RWbRE{57eDIbjcIcsXLxAt!RZ7qqd}1%rKZ@2QRZrOE275 z;eJ=u>`IrGZh@?yc! zQ_S>%3$pePFw!FoUo39ar{9S{d!a|??Wjh}V7kL5i%P+nEgQ}m#BSIs7VrTlnBmL~B-rBwW)5)-F2T4cidl_`FK-Qi@x zpG*wnU7|{Vpui-%-~_$+cT5GsgBVe`>@VV{IB*7MOPWW=816=OjNKXKEU>$f&DZ z*BWeTe-#}QE{leo{|Y82@9ia9c z2Ql_zzCLg>VKLJQ(X$!w)#lDU=U&6wAMzMmY&LSctgo(xfH}498qrMq+*%Gj=dEh$ zs;?Y7W`gflcQbSHrrTc?Bux>`Y%3h7;}=Tb|7fO0L2i=KD@;6(-<|9GuCGhADQ;n& z<=)-6E{dXr+AXR6vbQ3kb^_^Q*IO!XaP!J7or$eh8JFsfXb8zHpsMxF9LVPtqWG%G z(pp(Rk?78KGRta$#|_?|3stl={tAY#yhs z3H144IwY`Mq>NQC|8U!*=q^09HjB+^UxX=0q>s8QpIcPn3V!{D;>h@d$;>(bD735o z=dM^?^QN*|yHzR>sW_8j)9#FNLgTBFOD@EHqhlm_^YYHNQAHN-m=BfWF^5V?zLdC~ zviX{@$_)&aB{RCg7HucAnS|^)W#(QZospWAHuwD$P6yA{Y`=iI%)BElHmC5|SJBt6 zmq(8cEv{)g$f2v``qRIdBOM$5xG6|F2Du{XopdYymU9T#h7l&PK)&&6ik>fW;f}H& zrG1hGNbOGer*lzr!b&$*PUMoD@e`|6l#Vfq&%Zaew!Xw5Khj>*VI~~YW=0pR^vu~c zYt`9)p}PMq+e!IJliyl$kh);<_jKVUstKAO@vu~E;4>Zh5i2cn%anM?6gShVP3gfo z;wh&nLz8=NJZ=}x`;(pb%{V{19zWXkBVKK<{Dx2r&CrGpTM+%!>aNd5QIa~20$coz z<-DN=^^h{#u)(tVBVNPVVPZq!9OAdq0)aRBp8B(OIKPz^`98p*P@-qXHzcDrBXC)? zpfN&6O$=|A36te|gyGp6JJosOIr0-Y;WXDD?9=Aw=kCt57`DCYj{lNjTb!O%Q2)hT z{vH_x4Z9rfBF{1Y8(1IjI(BO3H z;B=mq#_nA<^NxH;`>tY3D-uq^8)30u#1!F=%;a`eOHT4n+#9 z+I>uM&3?F1`CcpZ`?PT{EuWU%!$IBqa|*4ulNzmIh&6G&ZWsK&!}Z7yy;pKfUif1w zoQ@=|tf*>PBm-^GMq z>F$=0?nb1gK}0qn(y#$RknWOhY1lLy1SF)TyF?n4mM#f7!}Gl7``&YY@C%sxzSpdE zt!vi0W@eUv)bOMm!O;F$2N5k^&E~j-q0J0J)Dn|nHdPkVC}~Re4BLXOrS1piDPVz& zc-6N3;sZuVODu|`T9@(o&yW)V{EW2m$|okmLhc`wbsHMW1ltJ((>v!;wg@ybhRJCc zh%&ryGl@lVBN&BeWT(hZJ^~e1HCxe0Y(jeTLSfv+EbSkco)*SO-qg&AHooBC#7xmKdFeD4K?dY5OIwHSbJ|o!{?u@B6*+pL^}Idt@5)TXRxJqwfC_@)7E+hAWsjKtobwL z8;;$5cF_ZZO6;9ZtVU12&wiUSfJnY4?(^uFQiUER%`iIg7^16}zia0TI&IDSK0#5r z{=v@I^gnHFC43K=m@b+^jN&rEtk#d%o zjp1FuU2!*d_>cWU;V&`z6sT=T zrNSXXVxBJF`$@vTbDe)X`{fz{njcZ!^1`q`UNRQMG>RELnTEu&79=oINI;Xf0A!Y2Uh?(~94FbWspk70^(^Cif$zwHdmp*K zy$nUyw9f-q#3($9Q#|T{_f8%ql{x*yG#cBJfRwp!snWLK<^WO{$eJ=k<=zs#fE7Ks zHof3_04tZ!fKiI9747rBq~X0P+gu>Ne||r@W%>=nGs~SNfY?X6W2aEed2lx%u_yv} z+FLB6bp0bnhGBytMTX9~gP`PBR&E-l?-G@g63%w@)grbTVxx$HBX9`bHG|aZPb(q~ z!r#$@t!rJSe5UiAui^yVPpe#fX@%t$<5w@mB&9QmW;@3BCk5Q~aYL2PE&8q7ZLm#^ zvsyp%(+LdObzEsh3{%sOY{$y~Kz=tq#KRVS9c$tgjceDc73-Iq)b&U{)0(1r=FgW_ z|KxMStx(Ut_UykM>|w$|*;2%0A~CQ?%><305)zv1uh}oqH48EerW!|DH%M(E*b4`l zm4BBGe14Dy4q=x4M5R&jG*=$_sdHSnzffem#K&e5DN}A^CTR>anc&xUs&6P8K7T1K za>|lJpJlP5%ZWIfwvCsxu-Fh_agFU)Zy48tHpTB-ZZ!ZxNj1xJ+JV}v zJ*^H~Ya#1K$VDW7+fvo2|BjAZwk0J-ba%uq;%hpQWAP^cex7#L@YA22*@bq4>PG>j z0f{B{H$rjZuKyeNM82h?KZi?2mW)#3hVRtsvP&kWS56cbpq6z8(B~lYYVz?*sOm81 z=RD3R1py7*C2dW@_WCA{TF>AMHq_63Q*MbsBTIcW!2wgF%Xzh@mUTd}sTc9?CUDy>2!H{&wD{$*>$hh`Zbb-^i?%5#3A@|bNp z?{Ih)&%Pk5;xa`@Y<^c<{O$(Bn0LJh4vDO12t#O1H$@o3cr(_YEqKQ7GZ)OE$;Oq^bPXkcOfu>^#EM=G_-@uJ&%t zI9@~e!v3mDurO6jzXZ2i3(X6+|8M+cTno7UCEv6|!Ec(-;&S^k_n;u!A*cnv=NDxr zUjcnOd1_X0RndH8^f}+dnh1aD#b~#C@+BXP(}HO_I7~GHfl<5#A=Hcp!A*y{!|MDA zU-_TAd72b#KOOj~e4VlGp0lknoH#6~X9McztwD^g(9qV259O4WoO;)?w@Gh`=a6co zg1_e4JP1xT^o)sIa|T!JxomB-6Z#E5O_QWK0^{C-ais;fn$h@-8j$79D)Uf7i^U`oRAXws*nuWyq{sss!FwN+!L=-U&qH@xu!j@aa)gg90@4E_C8 zT=8o-c=5nptl-yxsJcOr)43Kt=2hw6T;xB-a9I}w*F1yEI0air)vYNm9b&$Up}g8r z1-LwX#`P;obS$S>2y@HoyDW_Ai4w$1^~EtmX7VaCb5|4-X5eEFvete~iUZb#vfg$y z-Z#F(*d|+LXuL)Zr*dZ8vDj)4Uf8sn_OcIEX{opW1dV6f#WDbU$j;sIvAq>u>T+6? zsu{$yvtSGnhoOjS5P>C=$f9Qiop1l7qccknozKV@2WR9<6=HPCnuJfvjB(?L^;N2% z*(GM*!ZPb*;9S5!62rC8=u@FfnhveL2vj~UP7`ePR8b2siBm6V(x#u|pYq&fA+Rtb zMJrSR??B@ts_E*km1@7`aN9<=i>tOO3H>A9WfB zH6)0v<{|>Mv0q*D2O~s^jWT!*^52@_huX_neo|kU+)0$EeST1O@zL$)->m)Ol@AzM z@GmE-L@7bVNft44$5A{M>-~6v-&LWxNi%&?5u2v-&T>W#hu)>-6PBs=X?YGi8V!>D zB<42XAoSjLDos;<2$&uYpZ_jzPbjKgL+7N}x$G-tT#fJXGY)8+jWf3nzqJ@h9= zzUpAU;j-!}zk9R{%DsGyvij7Q#~a+E)DngJam`tax2Rn(f|s11OuJZjMn6-sGiL!` zH_`>FW$Ll+GE)$;+AKMAK^WMmzR8@c8X@y~ov1}nuLpEc#c~0X+1id4;o8FO!$O;l zl@^0p!#EZnJ^*KA=<;WHx5@?ow-NP6Tc}n_^Sjmun!ZmF`_&gRf_$Qf2HcTxt+Lct zym2f;?THFDkeWBzdA;q!8*j8!%rplM}J^?btm#-T5mClR%M8kJtUUjTTBc)G2w;Jvq zkcZO;W%_Sj`(1n6``M(T_d6>Ti^YR4u(BOZ#Z4Saz^OKN&Uk+=&#I26nV?BSsG zl!Rhimu?IPf*4=K$$>4*Nj#WGZVBB(Kndb1q7<@JeMa7I^(iDem&%-lIWXGmS|+qx zSe=dsKqbmm9Q!3lFAtuCU7m;~mAZmbTU+nzL znsgSyVcptLUaD~jFU#KX#m+3p`v`QpjbWCCPkC9&VU!uCTOVcCi?QC)@VE%Ln>>cr2zk&ud1aU8B=!Uj zvOMw6kFCRyo+eJ_NtSs2wknpzLyJSQ1uvr+t6RvC4f-qeX9vnNc0yq$ZE-EjRCLGf zLNS@a-L=r`jVFjiCaaTZLPiZO^t*N;i|1u;Kn~yy-g#+*rqsOh=92*~Fjo&Smq|n@ zZ}Od756_QTE-FE@UzP?2d7AVLmIk{lf}2@(Ds-lIaUx~@Aiv0fJTPu`&Ms&l@RoAi zY90?4Dr7<1Vr$Y&Z0CGcrHfpk6mvb38!9%+RXV_bn>|$3$D5W1fl&#V{Yu;6xP#je zB$la0JBD|S6rv1?hs8QG9HBnhKk^4LM#oaF8Sx6+bdHW?$iuR<9MMErekvgwA!u<3$jN%sgAgjF!R5a*&>v>49Y_WWRm04v1+J+iS;J;JWX*v}4ZMiYW1r>1`lZLp zME)Y%0g|+5$@;WpE*b zOVxhlAmiHF8uMqix$w`!dSZ)*#$hNu&O$IwI|Z=qUZIq*xof6o2-yyl6Tsj_U~rcp zFgOh4mC4Q92al*JSm_!_?`5L|cHXCCEMhM6h}#kqwV=ej-ib zSkJ{+#yY7oXH#Cf3*EB#&GSyvSXYj=1YG6URx+lO0y5Uyqw(ZKvc-piHmNk}b#`pCr0rQ()?_L5znEPtVASSrxw-h~<6tl_Aw@ek^!Gm`?st$)g9VfwRoa(|%=QOM4W$`dvAN$m;V7It>aZelGT)6XA5WSOW92R$3fu96yFDx_)8z6w9!fBk$7@6 zW9g2=yf|~HqfUV^AH!4J2rb5OaLg5dO}ratVPvCSr*Nt2o@~rCI={)@px#kpU^Xqq zOyrMexKj=8L&qOURyY$P=Kc)eF#R2M;3nJl$+W$l60W?pn*TOtFi(jhC0NNbJo~Nm zOgp8cq%mY|@SA9s#x9Fgvkl&R9r#9pW-^-8{-jrO2Y}2Y066dUPdyyCj#N8i@nh^1 z9hR+sq#U4tyXLAl0N{(zbjdW)?&`mX+xPZC!b^7eF-2F`d;wh;9{pZwAL_LYu8cSd z!gvqwrl$3+HdyTrpk4(5bOnf%RJrK#B=2ALDv`zQ(<*sd|>YzYIsO(2HEJfO_bhy*}(x)ohLNiO`WM=3gE^gO`ld zS2aT&%GQsUZ7NfOX#evV8s|sD$e;A~ug1&1IUeV|8PGWDbZL#nkEW1%M*AtfrX#HR z(I>9%m3IgS2V#Hf&7k6tPJAD>`Dz@mk_%g(2 zG5=f<;n@<3isn6XZW4wJ5jHZN$2){^RVV`B2?&*&cSznMxqABu6J?~2hUnT0=)yrd znU`iP^2*N5sp?S~MhkCF&duq5&(nQ_<0nh-JXN)y5Z}LfaPhOFUgP7oD)L*aw~4fE z_gq)11EXThFUV(8qZ|>D0#?EDW95pYJ{zrd3|#EhysV9kuc*wuPp1oS-%_-a(K37 zF1>4|#xIxlajnhN)tUt1*EWlccK{uNS_H!MrA*xrvVT)xu^7VO?rVR2H+(G)4}aSi zQM(6DwAoJW$K8_Sl<KKvJ)(qNr7aw@-&QTD5^p9;{uKdMVVl|Mbj^wVLu z?Z4oqB4`oxU#0q6A$Fy@_u6lER`OrZ;4b?W239pWcV+jo#wTLZ!%jSst6$RQ(Z|+S zN=+~=jpn7!6{86|nuiO)d0AnE2Ou(Y*%y|brD2(uoNqM*frDS9L6P3g8APE=0YdgE zakqoD99=3K-?U3)4?%p}Xe7B$a zXsa8q8hvJR*=DXk60`a&K)JkkJvU3ubgenI`yc1^vT z_Uf7u380)ZTnqLP6Cwm?HgaismhvtK0+Ufa0vq(v@K0evgd!_^>x@kte=x2L>kOin z{-@@=L{cO=eYc(N`|c;Wh= zi=`eZEKFvL&{@$`6HiZNh|m#*1k&y52YQ!HwWYg)oKGdQZ=s!@ssH@-_idH$nCM9( z&;3dE!S&IE{!CFo01_HBukJU81w1BceSI-VA&xg~)`YSGN?#Yx#zpS3NXe;8tB zo{@f-tdr8Wf$v%l?dMnm2`}C&W1Wbpv9#@6Oio;}x@I9im9MMV^zXLQ%6HhIQZp-h z8fQ~ZzOke_&2@-ScF+x$|t_*uQx?1&bM)rQbQM{C* z1Sr~q3MjUaw=7`U#eG2Wr0allmeN_Q4-t*{TfrQw7b{nS<69V?##~u2nr({3|2wMj!Umcwa_= zG(SG#PjY`Q?=L_6J-olBZT~xW|92&yN$%kOFYi6^@%9Dnk?QdM8Ljl(hV*MPKG~fg zQdx0X*(hLXWh{#`l)}C(9uSzu_x+ z<4t@A^K2bpu9b1rcqX7U!edO@R8yh!)^pO#!<8Ylz;CIyqx5&-Ibqqq%oT9rN@igv z<+NgEfy>Vnk1jZTrlWu3_i4v`xiJp2Zzgklc@}RG^7hO-$oQxW58n%96LXMFQfFGl zb8|sVzay)(+rIcU1n3Sct7X5qd0z=D=P`2161Z+>DH0!47o4syI>3hN&D-Y&q93MS zEUy$gUQ?nzVbD|SSxKW7XpvY2+~x{!8^4FbmSsKHE$)zAWo7#g90=&YyhLYlOT0-@ z`t$|c0#M?v6)W=9>X-Xwv_yE8wkBd*&dq~jRE%!bugSAh`aagB$gpJokQg;PB*jYY z=E48JrIz%W#g;6+eV#D=p^V*`6_K`lKszMxE`;U~cSVQ$%$9r*6qc~GQYsPF_Htcw zk?6p}BWq}fW6QOH-zbb z&Y!&pY@+Y#{d>)I(dcWmFX$C8lcRJ{Pk&q!Jv{zeFO;SLj`()lx?^%-BVa6k6}=hg zyxt;znlI|xs-U<6tJe2V-J-_yoPQC1wKj@bT6=BPx3-7Os-4=VN%r|S{LlBEX%`}l zmj(9cQrA}!@5kyZU}E0aBEvD1#oVpf$|s4=Qt}3)%6|B=njUPU${ASRA~nd~fEwih zK>~QuvqDQZDL3`cg%{sq@=Wl@BQ9kbj>V)Tl_OS}%VSp0WtSo~$4tBQpJpKvIJ|AZ z%dL7i#QuogeMbO6Z3(5{^pYZhn$GvN4MGnOJ^}y;e*h4)%QOsQ;N&g zmn(k8V}q=y5IpUi!yGK!`1)Zs)euc~x)KF4FDBM{qr8nBXls%PMS&(WmX^ndC6iba zBsJ>>>M)=T9AgIpfR_b{Lrb5QxIQBcJ7L%lAqhM+VJ9h3AN5MWaAX zgpo>J?`OqGMX*JKFfh-oGi>tND-MCJG7iz$c{&x|jr>$*nHKEDp-aI*5g)W4<74(H3b0Iqw$=~t zmI36q>`br4SJcIqk}=h;ARB;sHWTEWZs+2nc<$cWH!5SR{Wy#Qkqg(;PwDlZcK0J5 zaseHgDX(;sI}E{K`ZX`=++iI*WEu8F#9ej`Dz!i4XfpMcZw&pjh7qPAG`Z8i5$L~t zZTs5ZuY;}xBaJS+>~ zK#4KjlEWQ!@TVm0%aL?)hqn|5)Vy_332PxX>(WT2%T%oiDC-CuP}J#-p}nE+xG@5HnUb~e6tS)(-y1S7j2KIFuH^s+J zC4ydRpO2VEg}f{eXW6s$(KX*ldR^Og+!`fZ@B9_Q_KZ|A`S5u5`;OW~#7jBX6FbB1 zU)pZ)(4u7nQ8vp^_oC7g`Qz6F3%TJ9iXSoG>K6~3=9V^k_)Nv|p(w&QBbVD-bG(Z5 z4oP;N4F@q?_{mJDLbZ}+g7UxOV?~Bqm9T*)6xXE8+%Qn29t1O>#O;wlF5KLr@ZUep z)lKR;kN$ljH1xFp_+W17DONAir zeQ9_CP1HPcmFlimOfB$9fCnIvkZu4q2fxg~EShG29L>tUr)2+4jd%Goo#Hf z-uCB!SUCu$ryAPB=`0nfcRzUtC&4LlwqXN`sjA!GW}5wh^gmKY9pjsaKQ)q5zaOE| zMh1c}B`^75^w~eFt=uz)$D-sGOfF)4mWSwMpzo#xRs+dOccWUQ2RP4P#mosPY)o?B z_)Ahour{`b(I=AiP7YWzl4W!W)uh|+6nvNr`}Wpi%B|d4Vg5&%H^<0YL^BR@O5%_V z8qsEL5H->5xPB54aIUxN4z{^;lA-%-x_p}ySDC6#?BSp^Qg>=#n zEKaR{Q*%!>7T(BiM)6<-J1m1-b@e}K3izHPt>1R6|>>ug7On3ElvcmW|_N6Z6X=R|)p3v%|kzsD52%ktcE&=vBh|XpFzuxVDX zT&r_2ER17HA@MFw>|Y{$GL0@6V(O;2$98*vrRV_+nQHA|j;SuX`oKZu}@4PQ@xnT`L2G2B8zr6iiC2C5avQ2zt zc=nF~^d7DyE&kn`M9C*Qz)`g!)juIzmF3dlLhM3Xx!2|d4g35HTA!ygE` zBKsoyAUv5NOEAJg>mkDCjVP1FFNOKDu7}WgOtn3l<<4Au#JxKC0G!^^Au(wD`cHO1 zS2)~l49d&cz8S(NM|Z47d!8mU2;BMa(w+a;u8&2^p&*>lvLjJKEv(E}L+sKf9j&A2Q4 z)}2M1h~FoGtl>?N%*MAd0t>~~#S2pnKWIYb3#*NA!*!bE9~Q$^@1=V`H59qUhD#<5 z%2`=?mA)NA0h!x`-n;WNdqrK#y=`gj@}6E#3EKbWIdlcrT4oH8RAr5thy_E0%ryxB z5Xlj^Ce2~;laDL=jM)(ghU|U&QK(3JO{R2}H%-qsw(;6i!OWxOZ3exB_S~!C_3ude z(~lGmUz$s~D*tRyfRTnk0(PT}!Oz^`$G8z;j;(@bfqJ9`LvKYM33L1z1h23H^A| zp3Ul8Zt=f5jO(-#?RN1Zu0_I(E@R!ehqn(TNJyL`!ipke*_%jf;+z`3Lfvfg#wBb(#v4lg_45RGGGrkpx zFVif2Tx#8q=<4TVYM-_U7oCTA3J!XNp2gN#JiLBg=TnZxP7nUZP8z^mZou+&qx@E$ zn*cKdk+8%S0pv)Tq?xeVXfU5|>WKv@t`~lf+qy_9u%ggQzRRXdyj9>zbbt^fbuD3^ z2bZ?Z+x{SxAf&(lY>_k2 zD0SXPKD3Ig+4o)VGjlx00_xrDyuVW5^l^WByiq-Lc~H_Ew~K9II`^~ADvV+A$XBZS zaG0#qL|rRp?#lf;cC(5YwSZ>sTKtdm_473~J<@{>VhZHaq*wgJY^M?psj9Y^xu$Q| zm0r6g!IMiGw-{e~^Sly&sthB|@m{y}aPC3}hThr#m%BQpIKzhM1GQc80rH6G%mkQy0?sZk-buTfGon>n>#TRF7l5Spzo#p*@ z`^D2=|FEH()I^1!THV$(L|4XZJeE}8{AQrrxz*Lj ?RSuwY72(!X>`-e&hS^eWi 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

!^vejx`;2VQ!<6| z<3x6nXUehK4ik5+$%SI)OIdG?X^aMwkwh-R?hnCVG{-#1m8JW7T}D;s1Qho@+nk0u zGOkg92tn$ohM(Ek+<`M%9XaXp;iPj*c)kyw&M@TZ9Q9`03Q2b2 zf>egs4oH%=^YEa?>nbQPvLfl=mR~^#x~*{RM~JP#Xh#0uB!sPl|HO6-4;Ptg*!?%5 zWysnb5-^ah2`F^uZasI|Py-L(&Dsa2Pb%A|$wx1U>GytD^`#U!`B42o$vAklwPi9x zNrHj>dQ?C!W z|CEJS_wuXIxJ+$T*2+Tj!6yX*`1g=**|{c9^S{Bu1uv)6pBrV1w3Vr=KyCapJDl~Is5DtjU1qGvulkQ-6|j-dA#uW~VH zj{g5J<^MRrGkMYX#MG6%ImNI>JF?xu=q$!tMw)RS?mjNX<Tfl3Ma=FUm`2cN1pX;F@+xnQfDDk3?%f{Ff!><$Zef!#S5)du+1QzKj&O}#U z(*u6e+oKrXDOBIw)IED%gU$WsWX_96ggv!ANcN!$&$NjV&3~qxV^b4MVKC$rqi`!X zf378bHdUP(K6at5Zz6^|?0a$Gif1ArJRkm?u%=T4#dq$0mxrZ%<3xScNA*7>*1k(m z^)i%CIc_O(3#->vP@ycJ$CrW0wG2oU1F+n++|f}B?#Nft(ZoxdV2Gzrb_eX+&Q6Nr zEk)RZQJYTgwiK!EPQ81C)PCSd@BzC-n@nDtj%(SO$x?QUiOaEOjOkNfqQD*7Nj{y` zT!S*faQoA|e}K_H>1b8I!+Ot%SslsJ#Ujyv*ANhW3JVcwpgc`_U*E?nLYcdj=_vd0 z+KDV@m9GA8z&x5cTom3DP%G2VRu$-85gubMT&63O69@j?zZrnkE2Ft7VL~8tNMztA zJ*87e>O;#NMk7W6BS;4q=My+=q>-GQZj2=q@t&M zzY6jIrVr(_)a-*-VUDm>r+-?ub9xdf5dm@Q0YF4CfkD;bOu!&KQ58Yfd++W(kG=fn3$~kh`19NWQudxU_ zC~gRI1Tcl$ZdJK#B4bvN(Za>gV%3*ZqCFd`#@IHKa#v$Yde=Lh=>EZI@-ljH<|SS7 zjTH-)$H)yM1<@$Qy{w5Sg*^mCXLfT!To%6`Y?q$hFnC=)Sw$S+1+iFd>`5xM`+x3x z+toZGD-XPXO|i}pKqx%E<&2vV#xJZ^*HDMHP04q06x1V&zFDN@cn$P_EMdffECL8} z2Kh?v*&;>dx>ycAM}&&=h{_Rg5!;sY?kXUH*`ecMPQRsm?s&f?K+y$?nIO2aPE;E8 zvlWu2nojI0FjsmI<8^BJWdogw=7{pt5KzpNOGpA!a3oQ%&psbx9=B?}Hu;Khckm^F zJ9!~G^SC7=Lzj&Kh3O-&#;%Oja7XV+3U>2uJ^WI!=b;GMKoL^QZbJ(s@B?Rue@s5^ z*$rnZ{_{|std?klQJg|NnVfxQKctEG2G#1zp03r${ZuzZtNs8o*wLIv(MKl^HkWE_ zrcu@I6=^VhwF0SkIY%IxvpBgI{4)viBWG ze^Mc55N`!*L;BSI>VJAF{j2C=<$00G*MHa1mCO3h3kH_Tkyix%Y5{q@Er>|z4(ub$ zRlJgMSw1fYt^^`{`mYi^-xtN?EYK&oX#{$9{7U`cz*=6H}$O3@zZC9tn`|>4evRCs8-bV9| zF=6K>%Q0qvgQou|k?3#yv0(e*t2g9Sg;#H6YZM84{kvU<$nQ5F8(1N92%@(B5*czM z5jyA!}iy4N=fd{98A(r%0A$DpW-~_lv>*h~O!X`Y_J2w>I~moWHeJHXCyI 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π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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ca41599 --- /dev/null +++ b/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + com.ningdatech + ningda-yw-road + pom + 1.0.0 + ningda-yw-road + + + UTF-8 + 2.6.15 + 1.8 + 1.8 + 3.5.4.1 + 3.0.0 + 3.0.3 + 1.2.9 + 31.1-jre + 2.11.1 + + + + + + cn.hutool + hutool-all + 5.8.18 + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis.plus.version} + + + com.baomidou + mybatis-plus-extension + ${mybatis.plus.version} + + + com.alibaba + fastjson + ${fast.json.version} + + + + com.google.guava + guava + ${guava.version} + + + + com.ningdatech + nd-swagger2-starter + 1.0.0 + + + com.ningdatech + nd-openapi-signature-starter + 1.0.0 + + + + com.aliyun.oss + aliyun-sdk-oss + 3.15.0 + + + + com.alibaba + easyexcel + 3.1.2 + + + com.ningdatech + nd-sms-send-starter + 1.0.0 + + + + cn.afterturn + easypoi-base + 4.2.0 + + + + + + + + spring-plugin + spring-plugin + https://maven.aliyun.com/repository/spring-plugin + + true + + + false + + + + + + ningda-yw-api + + diff --git a/开发指南.md b/开发指南.md new file mode 100644 index 0000000..725b646 --- /dev/null +++ b/开发指南.md @@ -0,0 +1,18 @@ +# yw-car-manage + +义乌公路 + +## 常用字段命名 + +命名原则:尽可能简短且能见名知意 + +- 备注:remark +- 修改时间:update_on +- 修改人:update_by +- 创建人:create_by +- 创建时间:create_on +- 表主键:id +- 身份证号:idcard +- 电话:mobile +- 车牌号:car_no +- 驾驶证编号:driver_license_no \ No newline at end of file

g?m@&Fq#_0W`F!dMQnwKcyFUv%V* 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%0D1g*mq|-c-O5HHDwE2@PWTDN9k1B01(C0 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�#I#-lnP+#CXm?-@q4m=GI}-c}us#4p&a46%hH8 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 $Za1^;eS^|t`A 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 s0SrlkKLxZ3WGb}Xaa4aLmpu3D@6AU*b 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�tGmvV51?LJpC^t-h))$gs4m@)uX# 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 S^|JfrM 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