From 53ecb9853f880ad1432fa091abf03fd8a1259518 Mon Sep 17 00:00:00 2001 From: huangjin <huangjin@lucahealthcare.com> Date: Fri, 25 Oct 2024 16:38:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=A4=E4=B8=AA=E5=BA=93=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E6=B4=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pilot/config/MongoEnUsTemplateConfig.java | 38 + .../luca/pilot/service/EnUsPlanService.java | 10 + .../service/impl/EnUsPlanServiceImpl.java | 684 ++++++++++++++++++ .../pilot/service/impl/PlanServiceImpl.java | 12 +- src/main/resources/application-hj.yml | 3 +- src/main/resources/application-uat.yml | 3 +- src/main/resources/application.yml | 2 + .../java/com/luca/pilot/PlanTaskTest.java | 10 +- 8 files changed, 753 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/luca/pilot/config/MongoEnUsTemplateConfig.java create mode 100644 src/main/java/com/luca/pilot/service/EnUsPlanService.java create mode 100644 src/main/java/com/luca/pilot/service/impl/EnUsPlanServiceImpl.java diff --git a/src/main/java/com/luca/pilot/config/MongoEnUsTemplateConfig.java b/src/main/java/com/luca/pilot/config/MongoEnUsTemplateConfig.java new file mode 100644 index 0000000..5bd091a --- /dev/null +++ b/src/main/java/com/luca/pilot/config/MongoEnUsTemplateConfig.java @@ -0,0 +1,38 @@ +package com.luca.pilot.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; + +/** + * @author Wong + * @date 2024/1/6 14:17 + */ +@Slf4j +@Configuration +//@EnableMongoRepositories(basePackages = "com.luca.pilot.entity") +public class MongoEnUsTemplateConfig { + + @Value("${spring.data.en-us-mongodb.uri}") + private String uri; + +// @Primary + @Bean(name = "enUsMmongoTemplate") + public MongoTemplate enUsMmongoTemplate() { + log.info("-----------------------Backend Init MongoBaseTemplate Success -----------------------------------"); + return new MongoTemplate(enUsMmongoFactory()); + } + + @Bean +// @Primary + public MongoDatabaseFactory enUsMmongoFactory() { + SimpleMongoClientDatabaseFactory simpleMongoClientDbFactory = new SimpleMongoClientDatabaseFactory(uri); + return simpleMongoClientDbFactory; + } + +} diff --git a/src/main/java/com/luca/pilot/service/EnUsPlanService.java b/src/main/java/com/luca/pilot/service/EnUsPlanService.java new file mode 100644 index 0000000..503a4a6 --- /dev/null +++ b/src/main/java/com/luca/pilot/service/EnUsPlanService.java @@ -0,0 +1,10 @@ +package com.luca.pilot.service; + +public interface EnUsPlanService { + + + void synchronizePlanTask(); + + void test(); + +} diff --git a/src/main/java/com/luca/pilot/service/impl/EnUsPlanServiceImpl.java b/src/main/java/com/luca/pilot/service/impl/EnUsPlanServiceImpl.java new file mode 100644 index 0000000..99da0ed --- /dev/null +++ b/src/main/java/com/luca/pilot/service/impl/EnUsPlanServiceImpl.java @@ -0,0 +1,684 @@ +package com.luca.pilot.service.impl; + + +import cn.hutool.core.map.MapUtil; +import com.luca.pilot.bizEnum.TableEnum; +import com.luca.pilot.entity.*; +import com.luca.pilot.service.EnUsPlanService; +import com.luca.pilot.util.CrfUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.BulkOperations; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.util.Pair; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.springframework.data.mongodb.core.query.Criteria.where; + +@Slf4j +@Service +public class EnUsPlanServiceImpl implements EnUsPlanService { + + @Resource(name = "enUsMmongoTemplate") + private MongoTemplate mongoTemplate; + + @Resource(name = "mongoArchiveTemplate") + private MongoTemplate mongoArchiveTemplate; + + @Override + @Scheduled(cron ="0 0/1 * * * ?") + public void synchronizePlanTask() { + log.info("-------------- en-US synchronizePlanTask start----------"); + String nowTime = parseTimeFromDateTime (LocalDateTime.now()); + + SynchronizeTime synchronizeTime = findSynchronizeTime(); + + String lastSynchronizeTime = null; + if (Objects.nonNull(synchronizeTime)) { + lastSynchronizeTime = synchronizeTime.getPlan(); + } + + Query countQuery = new Query(); + if (Objects.nonNull(lastSynchronizeTime)) { + countQuery.addCriteria(where("lastModifiedAt").gt(lastSynchronizeTime)); + } + long totalPlanTaskDetailsCount = mongoTemplate.count(countQuery, PlanTaskDetails.class); + log.info(" en-US PlanTaskDetails 鍦ㄥぇ浜� {} 鏃堕棿鍐呮湭鏌ヨ鍒版暟鎹� {} 鏉�", lastSynchronizeTime, totalPlanTaskDetailsCount); + + if (totalPlanTaskDetailsCount == 0) { + return; + } + + saveSynchronizeTime(synchronizeTime, nowTime); + + long skip = totalPlanTaskDetailsCount / 10000; + if (totalPlanTaskDetailsCount % 10000 > 0) { + skip++; + } + + long totalPlanModuleCount = mongoTemplate.count(new Query(), PlanModule.class); + + BulkOperations bulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, PlanModule.class); + + for (int i = 0; i < skip; i++) { + countQuery.skip(i * 10000L); + countQuery.limit(10000); + List<PlanTaskDetails> planTaskDetails = mongoTemplate.find(countQuery, PlanTaskDetails.class); + log.info(" en-US 绗瑊}娆℃煡璇� planTaskDetails count:{}", i + 1, planTaskDetails.size()); + // 鑾峰彇瀵瑰簲妗f锛屽彇subjectId 鍜� randomId + List<UserArchiveMapping> userArchiveMappings = queryArchiveMapping(planTaskDetails); + List<UserArchive> userArchives = queryArchive(userArchiveMappings); + // 鑾峰彇椤圭洰鍜宻ite + List<Project> projects = queryProjct(planTaskDetails); + List<Site> sites = querySites(userArchiveMappings); + // 鑾峰彇璁″垝鐩稿叧鐨勬暟鎹� + List<PlanTask> planTasks = queryPlanTasks(planTaskDetails); + List<Plan> plans = queryPlans(planTasks); + List<PlanTaskModuleRelate> planMoudleRelates = queryPlanMoudleRelates(planTasks); + List<PlanTaskDetailsModule> planTaskDetailsModules = queryPlanTaskDetaiMoudles(planTaskDetails); + + // 鑾峰彇妯″潡鍚嶇О + Map<Long, String> relationNameMap = queryRelateMoudleName(planMoudleRelates); + + // 鑾峰彇result,鏂规硶涓垎鍒煡浜哠cale锛孮uestionaire,CRF + Map<Long, Map<String, Object>> resultMap = queryPlanTaskDetailResult(planTaskDetails); + + // 鏁板瓧闈剁偣鐩稿叧鐨勬暟鎹紝杩欓儴鍒嗕笉闇€瑕佺粍瑁呯粨鏋滐紝鍙渶瑕佸啓鍏ョ洰鏍囪〃鍜孌igital id + Map<Long, Map<Long, Long>> digitalMedicalEventMap = queryDigitalMedicalEvent(planTaskDetails); + Map<Long, Map<Long, String>> digitalMedicalTypeMap = queryDigitalMedicalType(planTaskDetails); + + List<PlanModule> planMoudles = new ArrayList<>(); + List<Pair<Query, Update>> pairs = new ArrayList<>(); + + //浠� planTaskDetail 鍜� planMoudleRelate 涓哄熀鍑� + // 涓€涓� planTaskDetail 鑳藉搴斿涓� planMoudleRelate锛屽嵆涓€娆′换鍔¢厤缃簡澶氬皯涓ā鍧楋紙闂嵎锛岄噺琛紝鏁板瓧闈剁偣锛� + for (PlanTaskDetails planTaskDetail : planTaskDetails) { + UserArchiveMapping userArchiveMapping = userArchiveMappings.stream().filter(x -> x.getPatientCode().equals(planTaskDetail.getPatientCode())).findFirst().orElse(null); + + UserArchive userArchive = userArchives.stream().filter(x -> Objects.nonNull(userArchiveMapping) && x.getId().equals(userArchiveMapping.getUserArchiveId())).findFirst().orElse(null); + + Project project = projects.stream().filter(x -> x.getCode().equals(planTaskDetail.getProjectCode())).findFirst().orElse(null); + + Site site = sites.stream().filter(x -> Objects.nonNull(userArchiveMapping) && x.getId().equals(userArchiveMapping.getSiteId())).findFirst().orElse(null); + + PlanTask planTask = planTasks.stream().filter(x -> x.getId().equals(planTaskDetail.getPlanTaskId())).findFirst().orElse(null); + + Plan plan = plans.stream().filter(x -> Objects.nonNull(planTask) && x.getId().equals(planTask.getPlanId())).findFirst().orElse(null); + + List<PlanTaskModuleRelate> relates = planMoudleRelates.stream().filter(x -> Objects.nonNull(planTask) && x.getPlanTaskId().equals(planTask.getId())).collect(Collectors.toList()); + + List<PlanTaskDetailsModule> modules = planTaskDetailsModules.stream().filter(x -> Objects.nonNull(planTaskDetail) && x.getPlanTaskDetailsId().equals(planTaskDetail.getId())).collect(Collectors.toList()); + + for (PlanTaskModuleRelate relate : relates) { + PlanModule planMoudle = new PlanModule(); + + planMoudle.setKey(planTaskDetail.getId() + String.valueOf(relate.getId())); + + if (Objects.nonNull(userArchive)) { + planMoudle.setSubjectId(userArchive.getSubjectId()); + planMoudle.setRandomizationId(userArchive.getRandomizationId()); + } + + if (Objects.nonNull(project)) { + + planMoudle.setProjectName(project.getName()); + } + if (Objects.nonNull(site)) { + planMoudle.setSiteName(site.getSiteName()); + planMoudle.setSiteId(site.getId()); + } + + if (Objects.nonNull(plan)) { + planMoudle.setPlanId(plan.getId()); + planMoudle.setPlanCode(plan.getNumber()); + planMoudle.setPlanEffectiveDate(plan.getEffectiveDate().atStartOfDay()); + planMoudle.setPlanDuration(plan.getDays()); + } + + if (Objects.nonNull(planTask)) { + planMoudle.setPlanTaskId(planTask.getId()); + planMoudle.setPlanTaskName(planTask.getName()); + planMoudle.setPlanTaskdescription(planTask.getDescription()); + planMoudle.setPlanTaskType(planTask.getTaskType()); + planMoudle.setPlanTaskTaskCount(planTask.getTaskCount()); + planMoudle.setPlanTaskFinishDay(planTask.getFinishDay()); + planMoudle.setPlanTaskLoopType(planTask.getLoopType()); + planMoudle.setPlanTaskEnabled(planTask.getEnabled()); + planMoudle.setPlanTaskIsCirculation(planTask.getIsCirculation()); + planMoudle.setPlanTaskBeginDay(planTask.getBeginDay()); + planMoudle.setPlanTaskCirculationDay(planTask.getCirculationDay()); + planMoudle.setPlanTaskWindowPhase(planTask.getWindowPhase()); + planMoudle.setPlanTaskEndDay(planTask.getEndDay()); + } + + if (Objects.nonNull(planTaskDetail)) { + planMoudle.setProjectCode(String.valueOf(planTaskDetail.getProjectCode())); + planMoudle.setTaskStartDate(planTaskDetail.getStartDate()); + planMoudle.setTaskEndDate(planTaskDetail.getEndDate()); + planMoudle.setTaskCompleteStatus(planTaskDetail.getCompleteStatus()); + planMoudle.setTaskCompleteTime(planTaskDetail.getCompleteTime()); + planMoudle.setTaskEnabled(planTaskDetail.getEnabled()); + planMoudle.setTaskCompleteOrder(planTaskDetail.getCompleteOrder()); + } + + if (Objects.nonNull(relate)) { + planMoudle.setModuleType(relate.getRelationType()); + planMoudle.setModuleId(relate.getRelationId()); + } + + if (MapUtil.isNotEmpty(relationNameMap) && Objects.nonNull(relationNameMap.get(relate.getRelationId()))) { + planMoudle.setModuleName(relationNameMap.get(relate.getRelationId())); + } + + if (MapUtil.isNotEmpty(resultMap)) { + Map<String, Object> planTaskDetailMap = resultMap.get(planTaskDetail.getId()); + + if (MapUtil.isNotEmpty(planTaskDetailMap)) { + Object result = planTaskDetailMap.get(String.valueOf(relate.getRelationId())); + if (!StringUtils.isEmpty(result)) { + planMoudle.setResult(result); + } + } + } + + if (relate.getRelationType().equals("DIGITAL_MEDICAL")) { + if (MapUtil.isNotEmpty(digitalMedicalEventMap)) { + Map<Long, Long> eventMap = digitalMedicalEventMap.get(planTaskDetail.getId()); + if (MapUtil.isNotEmpty(eventMap)) { + Long eventId = eventMap.get(relate.getRelationId()); + if (Objects.nonNull(eventId)) { + planMoudle.setDigitalModuleEventId(eventId); + } + } + } + if (MapUtil.isNotEmpty(digitalMedicalTypeMap)) { + Map<Long, String> typeMap = digitalMedicalTypeMap.get(planTaskDetail.getId()); + if (MapUtil.isNotEmpty(typeMap)) { + String eventType = typeMap.get(relate.getRelationId()); + if (Objects.nonNull(eventType)) { + String tableName = TableEnum.getTableNameByType(eventType); + if (Objects.nonNull(tableName)) { + planMoudle.setDigitalModuleTableName(tableName); + } + } + } + } + } + + PlanTaskDetailsModule module = modules.stream().filter(x -> x.getRelationId().equals(relate.getRelationId())).findFirst().orElse(null); + if (Objects.nonNull(module)) { + planMoudle.setModuleComplete(module.getModuleComplete()); + planMoudle.setModuleIgnoreRemark(module.getIgnoreRemark()); + if (Objects.nonNull(module.getModuleComplete()) && module.getModuleComplete().equals(1)) { + planMoudle.setModuleFinishTime(module.getLastModifiedAt()); + } + } else { + planMoudle.setModuleComplete(0); + } + + // 鏄惁绗竴娆″叏閲忔彃鍏� + if (totalPlanModuleCount > 0) { + Query upsertQuery = new Query(where("key").is(planMoudle.getKey())); + Update update = buildUpdate(planMoudle); + bulkOps.upsert(upsertQuery, update); + Pair<Query, Update> pair = Pair.of(upsertQuery, update); + pairs.add(pair); + }else { + planMoudles.add(planMoudle); + } + } + } + + + // 鏄惁绗竴娆″叏閲忔彃鍏� + if (totalPlanModuleCount > 0) { +// CompletableFuture.runAsync(() -> { + bulkOps.upsert(pairs); + bulkOps.execute(); + log.info(" en-US bulkOps 鏇存柊鎴栨彃鍏� {} 鏉℃暟鎹�", pairs.size()); +// }); + } else { + if (!CollectionUtils.isEmpty(planMoudles)) { + mongoTemplate.insert(planMoudles, PlanModule.class); + log.info(" en-US mongoTemplate insert {} 鏉℃暟鎹� ", planMoudles.size()); + } + } + + } + + log.info(" en-US synchronizePlanTask end, 鑰楁椂:{} 绉�", LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - + LocalDateTime.parse(nowTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toEpochSecond(ZoneOffset.of("+8"))); + + } + + private SynchronizeTime findSynchronizeTime() { + Query query = new Query().limit(1); + return mongoTemplate.findOne(query, SynchronizeTime.class); + } + + private void saveSynchronizeTime(SynchronizeTime synchronizeTime, String now) { + if (Objects.isNull(synchronizeTime)) { + SynchronizeTime time = new SynchronizeTime(); + time.setPlan(now); + mongoTemplate.save(time); + } else { + Query updateQuery = new Query(); + updateQuery.addCriteria(where("_id").is(synchronizeTime.get_id())); + Update update = new Update(); + update.set("plan", now); + mongoTemplate.updateFirst(updateQuery, update, SynchronizeTime.class); + } + } + + private Update buildUpdate(PlanModule planMoudle) { + return new Update() + .set("key", planMoudle.getKey()) + .set("subjectId", planMoudle.getSubjectId()) + .set("randomizationId", planMoudle.getRandomizationId()) + .set("projectCode", planMoudle.getProjectCode()) + .set("projectName", planMoudle.getProjectName()) + .set("siteName", planMoudle.getSiteName()) + .set("siteId", planMoudle.getSiteId()) + .set("planId", planMoudle.getPlanId()) + .set("planCode", planMoudle.getPlanCode()) + .set("planDuration", planMoudle.getPlanDuration()) + .set("planTaskId", planMoudle.getPlanTaskId()) + .set("planTaskName", planMoudle.getPlanTaskName()) + .set("planTaskdescription", planMoudle.getPlanTaskdescription()) + .set("planTaskType", planMoudle.getPlanTaskType()) + .set("planTaskTaskCount", planMoudle.getPlanTaskTaskCount()) + .set("planTaskFinishDay", planMoudle.getPlanTaskFinishDay()) + .set("planTaskLoopType", planMoudle.getPlanTaskLoopType()) + .set("planTaskEnabled", planMoudle.getPlanTaskEnabled()) + .set("planTaskIsCirculation", planMoudle.getPlanTaskIsCirculation()) + .set("planTaskBeginDay", planMoudle.getPlanTaskBeginDay()) + .set("planTaskCirculationDay", planMoudle.getPlanTaskCirculationDay()) + .set("planTaskWindowPhase", planMoudle.getPlanTaskWindowPhase()) + .set("planTaskEndDay", planMoudle.getPlanTaskEndDay()) + .set("taskStartDate", planMoudle.getTaskStartDate()) + .set("taskEndDate", planMoudle.getTaskEndDate()) + .set("taskCompleteStatus", planMoudle.getTaskCompleteStatus()) + .set("taskCompleteTime", planMoudle.getTaskCompleteTime()) + .set("taskEnabled", planMoudle.getTaskEnabled()) + .set("taskCompleteOrder", planMoudle.getTaskCompleteOrder()) + .set("moduleType", planMoudle.getModuleType()) + .set("moduleId", planMoudle.getModuleId()) + .set("moduleName", planMoudle.getModuleName()) + .set("moduleComplete", planMoudle.getModuleComplete()) + .set("moduleIgnoreRemark", planMoudle.getModuleIgnoreRemark()) + .set("moduleFinishTime", planMoudle.getModuleFinishTime()) + .set("result", planMoudle.getResult()) + .set("digitalModuleTableName", planMoudle.getDigitalModuleTableName()) + .set("digitalModuleEventId", planMoudle.getDigitalModuleEventId()) + .set("planEffectiveDate", planMoudle.getPlanEffectiveDate()); + } + + @Override + public void test() { + + } + + + public static void main(String[] args) { + String yim ="2024-08-30 10:14:45"; + System.out.println(LocalDateTime.parse(yim, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + } + + private String parseTimeFromDate(LocalDate timeStr) { + LocalDateTime localDateTime = timeStr.atStartOfDay(); + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return localDateTime.format(fmt); + } + private String parseTimeFromDateTime(LocalDateTime timeStr) { + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return timeStr.format(fmt); + } + + private List<PlanTaskDetailsModule> queryPlanTaskDetaiMoudles(List<PlanTaskDetails> planTaskDetails) { + + Set<Long> planTskDetailIds = planTaskDetails.stream().map(PlanTaskDetails::getId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(planTskDetailIds)) { + return new ArrayList<>(); + } + return mongoTemplate.find(new Query().addCriteria(where("planTaskDetailsId").in(planTskDetailIds)), PlanTaskDetailsModule.class); + + } + + private Map<Long, Map<Long, String>> queryDigitalMedicalType(List<PlanTaskDetails> planTaskDetails) { + Set<Long> planTskDetailIds = planTaskDetails.stream().map(PlanTaskDetails::getId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(planTskDetailIds)) { + return new HashMap<>(); + } + + Map<Long, List<ClinicalTrialsEvent>> eventMap = mongoTemplate.find(new Query().addCriteria(where("planDetailsId").in(planTskDetailIds).and("relationType").is("DIGITAL_MEDICAL")), ClinicalTrialsEvent.class) + .stream().collect(Collectors.groupingBy(ClinicalTrialsEvent::getPlanDetailsId)); + + Map<Long, Map<Long, String>> map = new HashMap<>(); + eventMap.forEach((k, v) -> { + Map<Long, String> innerMap = new HashMap<>(); + if (!CollectionUtils.isEmpty(v)) { + v.forEach(event -> { + innerMap.put(event.getRelationId(), event.getModuleItemType()); + }); + map.put(k, innerMap); + } + }); + + return map; + } + + private Map<Long, Map<Long, Long>> queryDigitalMedicalEvent(List<PlanTaskDetails> planTaskDetails) { + Set<Long> planTskDetailIds = planTaskDetails.stream().map(PlanTaskDetails::getId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(planTskDetailIds)) { + return new HashMap<>(); + } + + Map<Long, List<ClinicalTrialsEvent>> eventMap = mongoTemplate.find(new Query().addCriteria(where("planDetailsId").in(planTskDetailIds).and("relationType").is("DIGITAL_MEDICAL")), ClinicalTrialsEvent.class) + .stream().collect(Collectors.groupingBy(ClinicalTrialsEvent::getPlanDetailsId)); + + Map<Long, Map<Long, Long>> map = new HashMap<>(); + eventMap.forEach((k, v) -> { + Map<Long, Long> innerMap = new HashMap<>(); + if (!CollectionUtils.isEmpty(v)) { + v.forEach(event -> { + innerMap.put(event.getRelationId(), event.getEventId()); + }); + map.put(k, innerMap); + } + }); + + return map; + } + + private Map<Long, Map<String, Object>> queryPlanTaskDetailResult(List<PlanTaskDetails> planTaskDetails) { + Map<Long, Map<String, Object>> map = new HashMap<>(); + Map<Long, Map<String, Object>> scaleMap = queryScaleResult(planTaskDetails); + map.putAll(scaleMap); + Map<Long, Map<String, Object>> questonaireMap = queryQuestionaireResult(planTaskDetails); + + questonaireMap.forEach((k, v) -> { + if (map.containsKey(k)) { + map.get(k).putAll(v); + } else { + map.put(k, v); + } + }); + + Map<Long, Map<String, Object>> crfMap = queryCrfResult(planTaskDetails); + crfMap.forEach((k, v) -> { + if (map.containsKey(k)) { + map.get(k).putAll(v); + } else { + map.put(k, v); + } + }); + + return map; + } + + private Map<Long, Map<String, Object>> queryCrfResult(List<PlanTaskDetails> planTaskDetails) { + Set<Long> planTskDetailIds = planTaskDetails.stream().map(PlanTaskDetails::getId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(planTskDetailIds)) { + return new HashMap<>(); + } + + List<CrfAnswer> crfAnswers = mongoTemplate.find(new Query().addCriteria(where("planTaskDetailsId").in(planTskDetailIds)), CrfAnswer.class); + + Map<Long, List<CrfAnswer>> crfAnswersMap = crfAnswers.stream().collect(Collectors.groupingBy(CrfAnswer::getPlanTaskDetailsId)); + + Set<Long> crfIds = crfAnswers.stream().map(CrfAnswer::getCrfId).collect(Collectors.toSet()); + Map<Long, String> crfMap = mongoTemplate.find(new Query().addCriteria(where("id").in(crfIds)), Crf.class) + .stream().collect(Collectors.toMap(Crf::getId, Crf::getQuestionJson, (k1, k2) -> k2)); + + Map<Long, Map<String, Object>> map = new HashMap<>(); + crfAnswersMap.forEach((k, v) -> { + if (!CollectionUtils.isEmpty(v)) { + Map<String, Object> innerMap = new HashMap<>(); + v.forEach(crfAnswer -> { + String questionJson = crfMap.get(crfAnswer.getCrfId()); + if (Objects.nonNull(questionJson) && Objects.nonNull(crfAnswer.getAnswerJson())) { + try { + Map<String, Object> result = CrfUtil.parseCrfProblemAndAnswer(questionJson, crfAnswer.getAnswerJson()); + if (Objects.nonNull(result)) { + innerMap.put(crfAnswer.getCrfTopId().toString(), result); + } + } catch (Exception e) { + e.printStackTrace(); + + } + } + }); + map.put(k, innerMap); + } + }); + + return map; + } + + private Map<Long, Map<String, Object>> queryQuestionaireResult(List<PlanTaskDetails> planTaskDetails) { + Set<Long> planTskDetailIds = planTaskDetails.stream().map(PlanTaskDetails::getId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(planTskDetailIds)) { + return new HashMap<>(); + } + + List<QuestionnaireAnswerRecord> records = mongoTemplate.find(new Query().addCriteria(where("planTaskDetailsId").in(planTskDetailIds)), QuestionnaireAnswerRecord.class); + + if (CollectionUtils.isEmpty(records)) { + return new HashMap<>(); + } + + Set<Long> recordIds = records.stream().map(QuestionnaireAnswerRecord::getId).collect(Collectors.toSet()); + List<QuestionnaireAnswer> answers = mongoTemplate.find(new Query().addCriteria(where("recordId").in(recordIds)), QuestionnaireAnswer.class); + + Set<Long> ansowerIds = answers.stream().map(QuestionnaireAnswer::getId).collect(Collectors.toSet()); + List<QuestionnaireAnswerOption> answerOptions = mongoTemplate.find(new Query().addCriteria(where("answerId").in(ansowerIds)), QuestionnaireAnswerOption.class); + + Map<Long, Map<String, Object>> map = new HashMap<>(); + + for (QuestionnaireAnswerRecord record : records) { + + List<QuestionnaireAnswer> answerList = answers.stream().filter(x -> x.getRecordId().equals(record.getId())).collect(Collectors.toList()); + + Map<String, Object> resultMap = new HashMap<>(); +// List<String> keyValueNewVos = new ArrayList<>(); + Map<String,Object> keyValueNewVos = new HashMap<>(); + for (QuestionnaireAnswer answer : answerList) { + Stream<QuestionnaireAnswerOption> questionnaireAnswerOptionStream = answerOptions.stream().filter(x -> x.getAnswerId().equals(answer.getId()) && x.getQuestionId().equals(answer.getQuestionId())); + Optional<QuestionnaireAnswerOption> optionalAnswerOption = questionnaireAnswerOptionStream.findAny(); + + switch (answer.getType()) { + case "CHOICE": + keyValueNewVos.put(answer.getQuestionName().replaceAll("\\.", ""), optionalAnswerOption.map(QuestionnaireAnswerOption::getOptionName).orElse("-")); + break; + case "SLIDE": + case "DATE_SELECT": + case "NUMBER": + keyValueNewVos.put(answer.getQuestionName().replaceAll("\\.", ""), optionalAnswerOption.map(option -> String.valueOf(option.getNumberAnswer())).orElse("-")); + break; + case "MULTIPLE_CHOICE": + List<String> optionNames = answerOptions.stream() + .filter(x -> x.getAnswerId().equals(answer.getId()) && x.getQuestionId().equals(answer.getQuestionId())) + .map(QuestionnaireAnswerOption::getOptionName) + .collect(Collectors.toList()); + keyValueNewVos.put(answer.getQuestionName().replaceAll("\\.", ""), (optionNames.isEmpty() ? "-" : String.join(",", optionNames))); + break; + case "DATE": + keyValueNewVos.put(answer.getQuestionName().replaceAll("\\.", ""), optionalAnswerOption.map(QuestionnaireAnswerOption::getDateAt).orElse("-")); + break; + + case "SECTION_NUMBER": + keyValueNewVos.put(answer.getQuestionName().replaceAll("\\.", ""), (optionalAnswerOption.map(option -> option.getLeftMin() + "-" + option.getRightMax()).orElse("-"))); + break; + case "TEXT": + keyValueNewVos.put(answer.getQuestionName().replaceAll("\\.", ""), optionalAnswerOption.map(QuestionnaireAnswerOption::getContent).orElse("-")); + break; + } + } + resultMap.put(String.valueOf(record.getTopId()), keyValueNewVos); + map.put(record.getPlanTaskDetailsId(), resultMap); + } + + return map; + } + + private Map<Long, Map<String, Object>> queryScaleResult(List<PlanTaskDetails> planTaskDetails) { + Set<Long> planTskDetailIds = planTaskDetails.stream().map(PlanTaskDetails::getId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(planTskDetailIds)) { + return new HashMap<>(); + } + + Map<Long, List<PatientScaleEvaluatingEntity>> scaleEvaluatMap = + mongoTemplate.find(new Query().addCriteria(where("planTaskDetailsId").in(planTskDetailIds)), PatientScaleEvaluatingEntity.class) + .stream().collect(Collectors.groupingBy(PatientScaleEvaluatingEntity::getPlanTaskDetailsId)); + + Map<Long, Map<String, Object>> map = new HashMap<>(); + + scaleEvaluatMap.forEach((k, v) -> { + if (!CollectionUtils.isEmpty(v)) { + Map<String, Object> result = new HashMap<>(); + v.forEach(item -> { +// List<String> sb = new ArrayList<>(); + Map<String,Object> resultMap = new HashMap<>(); + if (Objects.nonNull(item.getScaleResult())) { +// sb.add("result:" + item.getScaleResult()); + resultMap.put("evaluation",item.getScaleResult()); + } + if (Objects.nonNull(item.getTotalScore())) { +// sb.add("totalScore:" + item.getTotalScore()); + resultMap.put("score",item.getTotalScore()); + } + + if(!StringUtils.isEmpty(item.getScaleCode())) { + List<ScaleQuestionEntity> questions = mongoTemplate.find(new Query().addCriteria(where("scaleCode").is(item.getScaleCode())), ScaleQuestionEntity.class); + BigDecimal totalScore = questions.stream().map(ScaleQuestionEntity::getScore).reduce(BigDecimal.ZERO, BigDecimal::add); + resultMap.put("totalScore", totalScore); + } + + + if (!MapUtil.isEmpty(resultMap)) { + result.put(item.getScaleCode(), resultMap); + } + + }); + + map.put(k, result); + } + }); + + return map; + } + + private Map<Long, String> queryRelateMoudleName(List<PlanTaskModuleRelate> planMoudleRelates) { + /** + * QUESTIONNAIRE 1 + * SCALE 1 + * DIGITAL_MEDICAL + * CRF 1 + * COLLECT_FLOW + * + * INTELLIGENT_DEVICE + * EXERCISE_MODULE + * + * E_DIARY + */ + Map<Long, String> map = new HashMap<>(); + List<Long> questionnaireIds = planMoudleRelates.stream().filter(relate -> relate.getRelationType().equals("QUESTIONNAIRE")).map(PlanTaskModuleRelate::getRelationId).collect(Collectors.toList()); + Map<Long, String> questionaireMap = mongoTemplate.find(new Query().addCriteria(where("topId").in(questionnaireIds)), Questionnaire.class) + .stream().collect(Collectors.toMap(Questionnaire::getTopId, Questionnaire::getName, (k1, k2) -> k2)); + if (MapUtil.isNotEmpty(questionaireMap)) { + map.putAll(questionaireMap); + } + + List<Long> crfTopIds = planMoudleRelates.stream().filter(relate -> relate.getRelationType().equals("CRF")).map(PlanTaskModuleRelate::getRelationId).collect(Collectors.toList()); + Map<Long, String> crfMap = mongoTemplate.find(new Query().addCriteria(where("crfTopId").in(crfTopIds)), Crf.class) + .stream().collect(Collectors.toMap(Crf::getCrfTopId, Crf::getName, (k1, k2) -> k2)); + if (MapUtil.isNotEmpty(crfMap)) { + map.putAll(crfMap); + } + + List<Long> scaleIds = planMoudleRelates.stream().filter(relate -> relate.getRelationType().equals("SCALE")).map(PlanTaskModuleRelate::getRelationId).collect(Collectors.toList()); + Map<Long, String> scaleMap = mongoTemplate.find(new Query().addCriteria(where("id").in(scaleIds)), ScaleModuleDetailsEntity.class) + .stream().collect(Collectors.toMap(ScaleModuleDetailsEntity::getId, ScaleModuleDetailsEntity::getName, (k1, k2) -> k2)); + if (MapUtil.isNotEmpty(scaleMap)) { + map.putAll(scaleMap); + } + + List<Long> digitalMedicalIds = planMoudleRelates.stream().filter(relate -> relate.getRelationType().equals("DIGITAL_MEDICAL")).map(PlanTaskModuleRelate::getRelationId).collect(Collectors.toList()); + Map<Long, String> digitalMedicalMap = mongoTemplate.find(new Query().addCriteria(where("id").in(digitalMedicalIds)), DigitalMedicalDetails.class) + .stream().collect(Collectors.toMap(DigitalMedicalDetails::getId, DigitalMedicalDetails::getName, (k1, k2) -> k2)); + if (MapUtil.isNotEmpty(digitalMedicalMap)) { + map.putAll(digitalMedicalMap); + } + + List<Long> collectMoudleIds = planMoudleRelates.stream().filter(relate -> relate.getRelationType().equals("COLLECT_FLOW")).map(PlanTaskModuleRelate::getRelationId).collect(Collectors.toList()); + Map<Long, String> collectMoudleMap = mongoTemplate.find(new Query().addCriteria(where("id").in(collectMoudleIds)), CollectModule.class) + .stream().collect(Collectors.toMap(CollectModule::getId, CollectModule::getName, (k1, k2) -> k2)); + if (MapUtil.isNotEmpty(collectMoudleMap)) { + map.putAll(collectMoudleMap); + } + + return map; + } + + private List<UserArchiveMapping> queryArchiveMapping(List<PlanTaskDetails> planTaskDetails) { + List<String> patientCodes = planTaskDetails.stream().map(PlanTaskDetails::getPatientCode).collect(Collectors.toList()); + Query archiveMappingquery = new Query(); + archiveMappingquery.addCriteria(where("patientCode").in(patientCodes)); + return mongoTemplate.find(archiveMappingquery, UserArchiveMapping.class); + } + + private List<PlanTaskModuleRelate> queryPlanMoudleRelates(List<PlanTask> planTasks) { + List<Long> planTaskIds = planTasks.stream().map(PlanTask::getId).collect(Collectors.toList()); + return mongoTemplate.find(new Query().addCriteria(where("planTaskId").in(planTaskIds)), PlanTaskModuleRelate.class); + } + + private List<Site> querySites(List<UserArchiveMapping> userArchiveMappings) { + List<Long> siteIds = userArchiveMappings.stream().map(UserArchiveMapping::getSiteId).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(siteIds)) { + return new ArrayList<>(); + } + return mongoTemplate.find(new Query().addCriteria(where("id").in(siteIds)), + Site.class); + } + + private List<Project> queryProjct(List<PlanTaskDetails> planTaskDetails) { + List<String> projectCodes = planTaskDetails.stream().map(PlanTaskDetails::getProjectCode).collect(Collectors.toList()); + return mongoTemplate.find(new Query().addCriteria(where("code").in(projectCodes)), Project.class); + } + + private List<Plan> queryPlans(List<PlanTask> planTasks) { + List<Long> planIds = planTasks.stream().map(PlanTask::getPlanId).collect(Collectors.toList()); + return mongoTemplate.find(new Query().addCriteria(where("id").in(planIds)), + Plan.class); + } + + private List<PlanTask> queryPlanTasks(List<PlanTaskDetails> planTaskDetails) { + List<Long> planTaskIds = planTaskDetails.stream().map(PlanTaskDetails::getPlanTaskId).collect(Collectors.toList()); + return mongoTemplate.find(new Query().addCriteria(where("id").in(planTaskIds)), + PlanTask.class); + } + + private List<UserArchive> queryArchive(List<UserArchiveMapping> userArchiveMappings) { + List<String> archiveIds = userArchiveMappings + .stream().map(UserArchiveMapping::getUserArchiveId).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(archiveIds)) { + return new ArrayList<>(); + } + return mongoArchiveTemplate.find(new Query().addCriteria(where("_id").in(archiveIds)), + UserArchive.class); + } +} diff --git a/src/main/java/com/luca/pilot/service/impl/PlanServiceImpl.java b/src/main/java/com/luca/pilot/service/impl/PlanServiceImpl.java index 1691b66..2120ffb 100644 --- a/src/main/java/com/luca/pilot/service/impl/PlanServiceImpl.java +++ b/src/main/java/com/luca/pilot/service/impl/PlanServiceImpl.java @@ -49,7 +49,7 @@ public class PlanServiceImpl implements PlanService { @Override @Scheduled(cron ="0 0/1 * * * ?") public void synchronizePlanTask() { - log.info("--------------synchronizePlanTask start----------"); + log.info("--------------zh-CN synchronizePlanTask start----------"); String nowTime = parseTimeFromDateTime (LocalDateTime.now()); SynchronizeTime synchronizeTime = findSynchronizeTime(); @@ -64,7 +64,7 @@ public class PlanServiceImpl implements PlanService { countQuery.addCriteria(where("lastModifiedAt").gt(lastSynchronizeTime)); } long totalPlanTaskDetailsCount = mongoTemplate.count(countQuery, PlanTaskDetails.class); - log.info("PlanTaskDetails 鍦ㄥぇ浜� {} 鏃堕棿鍐呮湭鏌ヨ鍒版暟鎹� {} 鏉�", lastSynchronizeTime, totalPlanTaskDetailsCount); + log.info("zh-CN PlanTaskDetails 鍦ㄥぇ浜� {} 鏃堕棿鍐呮湭鏌ヨ鍒版暟鎹� {} 鏉�", lastSynchronizeTime, totalPlanTaskDetailsCount); if (totalPlanTaskDetailsCount == 0) { return; @@ -85,7 +85,7 @@ public class PlanServiceImpl implements PlanService { countQuery.skip(i * 10000L); countQuery.limit(10000); List<PlanTaskDetails> planTaskDetails = mongoTemplate.find(countQuery, PlanTaskDetails.class); - log.info("绗瑊}娆℃煡璇� planTaskDetails count:{}", i + 1, planTaskDetails.size()); + log.info("zh-CN 绗瑊}娆℃煡璇� planTaskDetails count:{}", i + 1, planTaskDetails.size()); // 鑾峰彇瀵瑰簲妗f锛屽彇subjectId 鍜� randomId List<UserArchiveMapping> userArchiveMappings = queryArchiveMapping(planTaskDetails); List<UserArchive> userArchives = queryArchive(userArchiveMappings); @@ -256,18 +256,18 @@ public class PlanServiceImpl implements PlanService { // CompletableFuture.runAsync(() -> { bulkOps.upsert(pairs); bulkOps.execute(); - log.info("bulkOps 鏇存柊鎴栨彃鍏� {} 鏉℃暟鎹�", pairs.size()); + log.info("zh-CN bulkOps 鏇存柊鎴栨彃鍏� {} 鏉℃暟鎹�", pairs.size()); // }); } else { if (!CollectionUtils.isEmpty(planMoudles)) { mongoTemplate.insert(planMoudles, PlanModule.class); - log.info("mongoTemplate insert {} 鏉℃暟鎹� ", planMoudles.size()); + log.info("zh-CN mongoTemplate insert {} 鏉℃暟鎹� ", planMoudles.size()); } } } - log.info("synchronizePlanTask end, 鑰楁椂:{} 绉�", LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - + log.info("zh-CN synchronizePlanTask end, 鑰楁椂:{} 绉�", LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - LocalDateTime.parse(nowTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toEpochSecond(ZoneOffset.of("+8"))); } diff --git a/src/main/resources/application-hj.yml b/src/main/resources/application-hj.yml index afb4d3e..f1ac565 100644 --- a/src/main/resources/application-hj.yml +++ b/src/main/resources/application-hj.yml @@ -5,7 +5,8 @@ SERVER-PORT: 8181 MGDB-ADDRESS: 47.92.245.13:30606 MGDB-NAME: root MGDB-PASSWORD: 123456 -MGDB-DATABASE: luca-mysql-copy-en-US +MGDB-DATABASE: luca-mysql-copy-zh-CN +ENUS-MGDB-DATABASE: luca-mysql-copy-en-US #MGDB-DATABASE: luca-copy-uat MGDB-AUTHSOURCE: admin diff --git a/src/main/resources/application-uat.yml b/src/main/resources/application-uat.yml index c984d1b..5a5b84c 100644 --- a/src/main/resources/application-uat.yml +++ b/src/main/resources/application-uat.yml @@ -5,7 +5,8 @@ SERVER-PORT: 8181 MGDB-ADDRESS: mongo.luca-common:27017 MGDB-NAME: root MGDB-PASSWORD: 123456 -MGDB-DATABASE: luca-mysql-copy-en-US +MGDB-DATABASE: luca-mysql-copy-zh-CN +ENUS-MGDB-DATABASE: luca-mysql-copy-en-US MGDB-AUTHSOURCE: admin ARCHIVE-MGDB-DATABASE: luca_uat diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5026fde..ddc1fcb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,5 +11,7 @@ spring: uri: mongodb://${MGDB-NAME}:${MGDB-PASSWORD}@${MGDB-ADDRESS}/${MGDB-DATABASE}?authSource=${MGDB-AUTHSOURCE} archive-mongodb: uri: mongodb://${MGDB-NAME}:${MGDB-PASSWORD}@${MGDB-ADDRESS}/${ARCHIVE-MGDB-DATABASE}?authSource=${MGDB-AUTHSOURCE} + en-us-mongodb: + uri: mongodb://${MGDB-NAME}:${MGDB-PASSWORD}@${MGDB-ADDRESS}/${ENUS-MGDB-DATABASE}?authSource=${MGDB-AUTHSOURCE} diff --git a/src/test/java/com/luca/pilot/PlanTaskTest.java b/src/test/java/com/luca/pilot/PlanTaskTest.java index f2b58c9..4341fc1 100644 --- a/src/test/java/com/luca/pilot/PlanTaskTest.java +++ b/src/test/java/com/luca/pilot/PlanTaskTest.java @@ -1,6 +1,7 @@ package com.luca.pilot; import com.luca.pilot.entity.UserArchive; +import com.luca.pilot.service.EnUsPlanService; import com.luca.pilot.service.PlanService; import lombok.Data; import lombok.extern.slf4j.Slf4j; @@ -23,6 +24,9 @@ public class PlanTaskTest { @Autowired private PlanService planService; + @Autowired + private EnUsPlanService enUsPlanService; + @Test void synchronizePlanTask2() { @@ -50,9 +54,13 @@ public class PlanTaskTest { @Test - void synchronizePlanTask() { + void synchronizePlanTaskZhCn() { planService.synchronizePlanTask(); } + @Test + void synchronizePlanTaskEnUs() { + enUsPlanService.synchronizePlanTask(); + } @Test void contextLoads() { -- GitLab