diff --git a/src/CompositionRoot.ts b/src/CompositionRoot.ts index ae82f98..7186693 100644 --- a/src/CompositionRoot.ts +++ b/src/CompositionRoot.ts @@ -16,13 +16,13 @@ import { ModuleD2Repository } from "./data/repositories/ModuleD2Repository"; import { DataStoreClient } from "./data/DataStoreClient"; import { ModulesTestRepository } from "./data/repositories/testRepositories/ModuleTestRepository"; import { GetSurveyUseCase } from "./domain/usecases/GetSurveyUseCase"; -import { GetFilteredPatientsUseCase } from "./domain/usecases/GetFilteredPatientsUseCase"; +import { GetFilteredPPSPatientsUseCase } from "./domain/usecases/GetFilteredPPSPatientsUseCase"; import { SurveyRepository } from "./domain/repositories/SurveyRepository"; import { UserD2Repository } from "./data/repositories/UserD2Repository"; import { SurveyD2Repository } from "./data/repositories/SurveyFormD2Repository"; import { SurveyTestRepository } from "./data/repositories/testRepositories/SurveyFormTestRepository"; import { SaveFormDataUseCase } from "./domain/usecases/SaveFormDataUseCase"; -import { GetPaginatedPatientSurveysUseCase } from "./domain/usecases/GetPaginatedPatientSurveysUseCase"; +import { GetPaginatedSurveysUseCase } from "./domain/usecases/GetPaginatedSurveysUseCase"; import { GetPopulatedSurveyUseCase } from "./domain/usecases/GetPopulatedSurveyUseCase"; import { NonAdminUserTestRepository } from "./data/repositories/testRepositories/NonAdminUserTestRepository"; import { DeleteSurveyUseCase } from "./domain/usecases/DeleteSurveyUseCase"; @@ -38,6 +38,7 @@ import { GetASTGuidelinesUseCase } from "./domain/usecases/GetASTGuidelinesUseCa import { ASTGuidelinesD2Repository } from "./data/repositories/ASTGuidelinesD2Repository"; import { ASTGuidelinesTestRepository } from "./data/repositories/testRepositories/ASTGuidelinesTestRepository"; import { RemoveRepeatableProgramStageUseCase } from "./domain/usecases/RemoveRepeatableProgramStageUseCase"; +import { GetFilteredPrevalencePatientsUseCase } from "./domain/usecases/GetFilteredPrevalencePatientsUseCase"; export type CompositionRoot = ReturnType; @@ -74,11 +75,15 @@ function getCompositionRoot(repositories: Repositories) { repositories.astGuidelinesRepository ), getSurveys: new GetAllSurveysUseCase(repositories.surveyFormRepository), - getFilteredPatients: new GetFilteredPatientsUseCase( + getFilteredPPSPatients: new GetFilteredPPSPatientsUseCase( repositories.paginatedSurveyRepository, repositories.surveyFormRepository ), - getPaginatedSurveys: new GetPaginatedPatientSurveysUseCase( + getFilteredPrevalencePatients: new GetFilteredPrevalencePatientsUseCase( + repositories.paginatedSurveyRepository, + repositories.surveyFormRepository + ), + getPaginatedSurveys: new GetPaginatedSurveysUseCase( repositories.paginatedSurveyRepository, repositories.surveyFormRepository ), diff --git a/src/data/repositories/PaginatedSurveyD2Repository.ts b/src/data/repositories/PaginatedSurveyD2Repository.ts index 0d9f0a7..54d4879 100644 --- a/src/data/repositories/PaginatedSurveyD2Repository.ts +++ b/src/data/repositories/PaginatedSurveyD2Repository.ts @@ -8,7 +8,10 @@ import { PaginatedSurveyRepository } from "../../domain/repositories/PaginatedSu import { PaginatedReponse } from "../../domain/entities/TablePagination"; import { getParentDataElementForProgram, isTrackerProgram } from "../utils/surveyProgramHelper"; import { + AMR_SURVEYS_PREVALENCE_TEA_SURVEY_ID_CRF, + AMR_SURVEYS_PREVALENCE_TEA_UNIQUE_PATIENT_ID, PPS_PATIENT_REGISTER_ID, + PREVALENCE_CASE_REPORT_FORM_ID, SURVEY_PATIENT_CODE_DATAELEMENT_ID, SURVEY_PATIENT_ID_DATAELEMENT_ID, WARD_ID_DATAELEMENT_ID, @@ -188,6 +191,36 @@ export class PaginatedSurveyD2Repository implements PaginatedSurveyRepository { }); } + getFilteredPrevalencePatientSurveysByPatientId( + keyword: string, + orgUnitId: Id, + parentId: Id + ): FutureData> { + return apiToFuture( + this.api.tracker.trackedEntities.get({ + fields: { attributes: true, enrollments: true, trackedEntity: true, orgUnit: true }, + program: PREVALENCE_CASE_REPORT_FORM_ID, + orgUnit: orgUnitId, + pageSize: 10, + totalPages: true, + filter: ` ${AMR_SURVEYS_PREVALENCE_TEA_UNIQUE_PATIENT_ID}:like:${keyword}, ${AMR_SURVEYS_PREVALENCE_TEA_SURVEY_ID_CRF}:eq:${parentId}`, + }) + ).flatMap(trackedEntities => { + const surveys = mapTrackedEntityToSurvey(trackedEntities, "PrevalenceCaseReportForm"); + + const paginatedSurveys: PaginatedReponse = { + pager: { + page: trackedEntities.page, + pageSize: trackedEntities.pageSize, + total: trackedEntities.total, + }, + objects: surveys, + }; + + return Future.success(paginatedSurveys); + }); + } + getPaginatedSurveyChildCount( parentProgram: Id, orgUnitId: Id, diff --git a/src/data/repositories/testRepositories/PaginatedSurveyTestRepository.ts b/src/data/repositories/testRepositories/PaginatedSurveyTestRepository.ts index ad721c6..5fe3f91 100644 --- a/src/data/repositories/testRepositories/PaginatedSurveyTestRepository.ts +++ b/src/data/repositories/testRepositories/PaginatedSurveyTestRepository.ts @@ -7,6 +7,13 @@ import { FutureData } from "../../api-futures"; import { SurveyChildCountType } from "../../utils/surveyChildCountHelper"; export class PaginatedSurveyTestRepository implements PaginatedSurveyRepository { + getFilteredPrevalencePatientSurveysByPatientId( + keyword: string, + orgUnitId: string, + parentId: string + ): FutureData> { + throw new Error("Method not implemented."); + } getFilteredPPSPatientByPatientCodeSurveys( keyword: string, orgUnitId: string, diff --git a/src/domain/entities/Questionnaire/Questionnaire.ts b/src/domain/entities/Questionnaire/Questionnaire.ts index f7a8b4b..0986b07 100644 --- a/src/domain/entities/Questionnaire/Questionnaire.ts +++ b/src/domain/entities/Questionnaire/Questionnaire.ts @@ -152,7 +152,12 @@ export class Questionnaire { const updatedQuestionnaire = allQsInQuestionnaire.reduce( (questionnaireAcc, question) => { - return this.updateQuestionnaire(questionnaireAcc, question, question.stageId); + return this.updateQuestionnaire( + questionnaireAcc, + question, + question.stageId, + true + ); }, questionnaire ); @@ -240,7 +245,8 @@ export class Questionnaire { static updateQuestionnaire( questionnaire: Questionnaire, updatedQuestion: Question, - stageId?: string + stageId?: string, + initialLoad = false ): Questionnaire { //For the updated question, get all rules that are applicable const allQsInQuestionnaire = questionnaire.stages.flatMap((stage: QuestionnaireStage) => { @@ -255,6 +261,8 @@ export class Questionnaire { allQsInQuestionnaire ); + if (initialLoad && applicableRules.length === 0) return questionnaire; + const isEntityQuestionUpdated = questionnaire.entity?.questions.find( question => question.id === updatedQuestion.id ); diff --git a/src/domain/entities/Questionnaire/QuestionnaireRules.ts b/src/domain/entities/Questionnaire/QuestionnaireRules.ts index a9a7203..f1ec837 100644 --- a/src/domain/entities/Questionnaire/QuestionnaireRules.ts +++ b/src/domain/entities/Questionnaire/QuestionnaireRules.ts @@ -115,10 +115,8 @@ const handleRuleFunctions = (condition: string): boolean => { if (match) { const innerString = match[1]; if (innerString?.trim() === "") { - console.debug('The string between "fn:hasValue(" and ")" is empty.'); return false; } else { - console.debug(`The string between "fn:hasValue(" and ")" is: ${innerString}`); return true; } } else return false; diff --git a/src/domain/repositories/PaginatedSurveyRepository.ts b/src/domain/repositories/PaginatedSurveyRepository.ts index cfec7da..97cc2c1 100644 --- a/src/domain/repositories/PaginatedSurveyRepository.ts +++ b/src/domain/repositories/PaginatedSurveyRepository.ts @@ -23,6 +23,11 @@ export interface PaginatedSurveyRepository { orgUnitId: Id, parentId: Id ): FutureData>; + getFilteredPrevalencePatientSurveysByPatientId( + keyword: string, + orgUnitId: Id, + parentId: Id + ): FutureData>; getPaginatedSurveyChildCount( parentProgram: Id, orgUnitId: Id, diff --git a/src/domain/usecases/GetAllSurveysUseCase.ts b/src/domain/usecases/GetAllSurveysUseCase.ts index 88b1f27..7969944 100644 --- a/src/domain/usecases/GetAllSurveysUseCase.ts +++ b/src/domain/usecases/GetAllSurveysUseCase.ts @@ -82,7 +82,7 @@ export class GetAllSurveysUseCase { }); }); - return Future.sequential(surveysWithName); + return Future.parallel(surveysWithName, { concurrency: 5 }); }); } } diff --git a/src/domain/usecases/GetFilteredPatientsUseCase.ts b/src/domain/usecases/GetFilteredPPSPatientsUseCase.ts similarity index 97% rename from src/domain/usecases/GetFilteredPatientsUseCase.ts rename to src/domain/usecases/GetFilteredPPSPatientsUseCase.ts index 555147a..918c754 100644 --- a/src/domain/usecases/GetFilteredPatientsUseCase.ts +++ b/src/domain/usecases/GetFilteredPPSPatientsUseCase.ts @@ -6,7 +6,7 @@ import { PaginatedSurveyRepository } from "../repositories/PaginatedSurveyReposi import { SurveyRepository } from "../repositories/SurveyRepository"; import { getPaginatedSurveysWithParentName } from "../utils/surveyParentNameHelper"; -export class GetFilteredPatientsUseCase { +export class GetFilteredPPSPatientsUseCase { constructor( private paginatedSurveyRepo: PaginatedSurveyRepository, private surveyReporsitory: SurveyRepository diff --git a/src/domain/usecases/GetFilteredPrevalencePatientsUseCase.ts b/src/domain/usecases/GetFilteredPrevalencePatientsUseCase.ts new file mode 100644 index 0000000..e880cc3 --- /dev/null +++ b/src/domain/usecases/GetFilteredPrevalencePatientsUseCase.ts @@ -0,0 +1,65 @@ +import { Id } from "@eyeseetea/d2-api"; +import { FutureData } from "../../data/api-futures"; +import { Survey, SurveyBase } from "../entities/Survey"; +import { PaginatedReponse } from "../entities/TablePagination"; +import { PaginatedSurveyRepository } from "../repositories/PaginatedSurveyRepository"; +import { SurveyRepository } from "../repositories/SurveyRepository"; +import { Future } from "../entities/generic/Future"; +import { getChildCount } from "../utils/getChildCountHelper"; + +export class GetFilteredPrevalencePatientsUseCase { + constructor( + private paginatedSurveyRepo: PaginatedSurveyRepository, + private surveyReporsitory: SurveyRepository + ) {} + + public execute( + keyword: string, + orgUnitId: Id, + parentId: Id + ): FutureData> { + return this.paginatedSurveyRepo + .getFilteredPrevalencePatientSurveysByPatientId(keyword, orgUnitId, parentId) + .flatMap(filteredSurveys => { + const surveysWithName = filteredSurveys.objects.map(survey => { + return Future.join2( + this.surveyReporsitory.getSurveyNameAndASTGuidelineFromId( + survey.rootSurvey.id, + survey.surveyFormType + ), + getChildCount({ + surveyFormType: "PrevalenceCaseReportForm", + orgUnitId: survey.assignedOrgUnit.id, + parentSurveyId: survey.rootSurvey.id, + secondaryparentId: survey.id, + surveyReporsitory: this.paginatedSurveyRepo, + }) + ).map(([parentDetails, childCount]): Survey => { + const newRootSurvey: SurveyBase = { + surveyType: survey.rootSurvey.surveyType, + id: survey.rootSurvey.id, + name: + survey.rootSurvey.name === "" + ? parentDetails.name + : survey.rootSurvey.name, + }; + + const updatedSurvey: Survey = { + ...survey, + rootSurvey: newRootSurvey, + childCount: childCount, + }; + return updatedSurvey; + }); + }); + + return Future.parallel(surveysWithName, { concurrency: 5 }).map(updatedSurveys => { + const paginatedSurveys: PaginatedReponse = { + pager: filteredSurveys.pager, + objects: updatedSurveys, + }; + return paginatedSurveys; + }); + }); + } +} diff --git a/src/domain/usecases/GetPaginatedPatientSurveysUseCase.ts b/src/domain/usecases/GetPaginatedSurveysUseCase.ts similarity index 94% rename from src/domain/usecases/GetPaginatedPatientSurveysUseCase.ts rename to src/domain/usecases/GetPaginatedSurveysUseCase.ts index e8838c2..f786f0a 100644 --- a/src/domain/usecases/GetPaginatedPatientSurveysUseCase.ts +++ b/src/domain/usecases/GetPaginatedSurveysUseCase.ts @@ -9,8 +9,7 @@ import _ from "../entities/generic/Collection"; import { getChildCount } from "../utils/getChildCountHelper"; import { Future } from "../entities/generic/Future"; -//This use case fetched only patient surveys for both Prevalence and PPS modules -export class GetPaginatedPatientSurveysUseCase { +export class GetPaginatedSurveysUseCase { constructor( private paginatedSurveyRepo: PaginatedSurveyRepository, private surveyReporsitory: SurveyRepository @@ -68,7 +67,7 @@ export class GetPaginatedPatientSurveysUseCase { }); }); - return Future.sequential(surveysWithName).map(updatedSurveys => { + return Future.parallel(surveysWithName, { concurrency: 5 }).map(updatedSurveys => { const paginatedSurveys: PaginatedReponse = { pager: surveys.pager, objects: updatedSurveys, diff --git a/src/webapp/components/survey-list/SurveyList.tsx b/src/webapp/components/survey-list/SurveyList.tsx index 59fb928..ac0190b 100644 --- a/src/webapp/components/survey-list/SurveyList.tsx +++ b/src/webapp/components/survey-list/SurveyList.tsx @@ -106,6 +106,19 @@ export const SurveyList: React.FC = ({ surveyFormType }) => { /> )} + {surveyFormType === "PrevalenceCaseReportForm" && ( + <> + + setPatientIdSearchKeyword(e.target.value) + } + onKeyDown={handlePatientIdSearch} + /> + + )}