From 26f9a97231f327ca049f658b3ecd02d35015e6f8 Mon Sep 17 00:00:00 2001 From: Fleury Butoyi Date: Wed, 18 Dec 2024 09:38:52 +0200 Subject: [PATCH 01/13] Clean existing analytics data in order to generate freshed data --- plugins/wfp/management/commands/nigeria/Under5.py | 6 ++---- plugins/wfp/management/commands/south_sudan/Pbwg.py | 2 +- plugins/wfp/management/commands/south_sudan/Under5.py | 2 +- plugins/wfp/tasks.py | 4 +++- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/wfp/management/commands/nigeria/Under5.py b/plugins/wfp/management/commands/nigeria/Under5.py index fe4c69d9c3..9cdf79fd07 100644 --- a/plugins/wfp/management/commands/nigeria/Under5.py +++ b/plugins/wfp/management/commands/nigeria/Under5.py @@ -110,13 +110,11 @@ def group_visit_by_entity(self, entities): ) def run(self): - children_type = ["ng_-_tsfp_child_3", "ng_-_otp_child_3"] - entity_type = ETL(children_type) - type = EntityType.objects.get(code="ng_-_tsfp_child_3") + entity_type = ETL(["child_under_5_3"]) account = entity_type.account_related_to_entity_type() beneficiaries = entity_type.retrieve_entities() - logger.info(f"Instances linked to Child Under 5 program: {beneficiaries.count()} for {type.name} on {account}") + logger.info(f"Instances linked to Child Under 5 program: {beneficiaries.count()} for {account}") entities = sorted(list(beneficiaries), key=itemgetter("entity_id")) existing_beneficiaries = ETL().existing_beneficiaries() instances = self.group_visit_by_entity(entities) diff --git a/plugins/wfp/management/commands/south_sudan/Pbwg.py b/plugins/wfp/management/commands/south_sudan/Pbwg.py index a36bf3a4a2..2a6147d0c8 100644 --- a/plugins/wfp/management/commands/south_sudan/Pbwg.py +++ b/plugins/wfp/management/commands/south_sudan/Pbwg.py @@ -13,7 +13,7 @@ def run(self): entity_type = ETL(["pbwg_1"]) account = entity_type.account_related_to_entity_type() beneficiaries = entity_type.retrieve_entities() - logger.info(f"Instances linked to PBWG program: {beneficiaries.count()}") + logger.info(f"Instances linked to PBWG program: {beneficiaries.count()} for {account}") entities = sorted(list(beneficiaries), key=itemgetter("entity_id")) existing_beneficiaries = ETL().existing_beneficiaries() instances = self.group_visit_by_entity(entities) diff --git a/plugins/wfp/management/commands/south_sudan/Under5.py b/plugins/wfp/management/commands/south_sudan/Under5.py index 826e2ac19b..05dc1ce4b3 100644 --- a/plugins/wfp/management/commands/south_sudan/Under5.py +++ b/plugins/wfp/management/commands/south_sudan/Under5.py @@ -140,7 +140,7 @@ def run(self): entity_type = ETL(["child_under_5_1"]) account = entity_type.account_related_to_entity_type() beneficiaries = entity_type.retrieve_entities() - logger.info(f"Instances linked to Child Under 5 program: {beneficiaries.count()}") + logger.info(f"Instances linked to Child Under 5 program: {beneficiaries.count()} for {account}") entities = sorted(list(beneficiaries), key=itemgetter("entity_id")) existing_beneficiaries = ETL().existing_beneficiaries() instances = self.group_visit_by_entity(entities) diff --git a/plugins/wfp/tasks.py b/plugins/wfp/tasks.py index e6ca96e572..690dcd83f1 100644 --- a/plugins/wfp/tasks.py +++ b/plugins/wfp/tasks.py @@ -14,7 +14,8 @@ def etl_ng(): """Extract beneficiary data from Iaso tables and store them in the format expected by existing tableau dashboards""" logger.info("Starting ETL for Nigeria") - account = ETL(["ng_-_tsfp_child_3", "ng_-_otp_child_3"]).account_related_to_entity_type() + account = ETL(["child_under_5_3"]).account_related_to_entity_type() + Beneficiary.objects.all().filter(account=account).delete() NG_Under5().run() logger.info( @@ -27,6 +28,7 @@ def etl_ng(): def etl_ssd(): logger.info("Starting ETL for South Sudan") child_account = ETL(["child_under_5_1"]).account_related_to_entity_type() + Beneficiary.objects.all().filter(account=child_account).delete() Under5().run() logger.info( From 6d967fcbfe7360700812a9e4011da66973d30a0e Mon Sep 17 00:00:00 2001 From: Fleury Butoyi Date: Wed, 18 Dec 2024 10:16:05 +0200 Subject: [PATCH 02/13] Delete PBWG data before regenerate freshed one --- plugins/wfp/tasks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/wfp/tasks.py b/plugins/wfp/tasks.py index 690dcd83f1..5e55a33083 100644 --- a/plugins/wfp/tasks.py +++ b/plugins/wfp/tasks.py @@ -37,6 +37,7 @@ def etl_ssd(): ETL().journey_with_visit_and_steps_per_visit(child_account, "U5") pbwg_account = ETL(["pbwg_1"]).account_related_to_entity_type() + Beneficiary.objects.all().filter(account=pbwg_account).delete() PBWG().run() logger.info( f"----------------------------- Aggregating PBWG journey for {pbwg_account} per org unit, admission and period(month and year) -----------------------------" From a1e158d2a81f73347f3fdec967e1cba23573ea3e Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Wed, 18 Dec 2024 14:08:34 +0100 Subject: [PATCH 03/13] IA-3741: reformat message --- hat/assets/js/apps/Iaso/domains/app/translations/en.json | 4 ++-- hat/assets/js/apps/Iaso/domains/app/translations/fr.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hat/assets/js/apps/Iaso/domains/app/translations/en.json b/hat/assets/js/apps/Iaso/domains/app/translations/en.json index 8760d6b6ed..c256d71302 100644 --- a/hat/assets/js/apps/Iaso/domains/app/translations/en.json +++ b/hat/assets/js/apps/Iaso/domains/app/translations/en.json @@ -1214,7 +1214,7 @@ "iaso.snackBar.copyVersionSuccessMessage": "The task has been created", "iaso.snackBar.createDataSourceError": "Error occurred while saving the data source.", "iaso.snackBar.createExportRequestError": "An error occured while creating export request", - "iaso.snackBar.createExportRequestErrorNoFormMappingError": "The form doesn't a form mapping to export to dhis2", + "iaso.snackBar.createExportRequestErrorNoFormMappingError": "The form is not configured for DHIS2 export", "iaso.snackBar.createExportRequestErrorNothingToExportError": "We found nothing to export, change your filter or force the re-export", "iaso.snackBar.createExportRequestErrorNotSupportedError": "Forcing export isn't supported for event tracker", "iaso.snackBar.createExportRequestErrorNoVersionError": "One of the instance had no version specified", @@ -1577,4 +1577,4 @@ "trypelim.permissions.zones": "Zones", "trypelim.permissions.zones_edit": "Edit zones", "trypelim.permissions.zones_shapes_edit": "Edit zone shapes" -} +} \ No newline at end of file diff --git a/hat/assets/js/apps/Iaso/domains/app/translations/fr.json b/hat/assets/js/apps/Iaso/domains/app/translations/fr.json index 1ae8623fbd..a83510ced0 100644 --- a/hat/assets/js/apps/Iaso/domains/app/translations/fr.json +++ b/hat/assets/js/apps/Iaso/domains/app/translations/fr.json @@ -1214,7 +1214,7 @@ "iaso.snackBar.copyVersionSuccessMessage": "La tâche a été créé avec succès", "iaso.snackBar.createDataSourceError": "Une erreur est survenue en sauvant la source de donnée", "iaso.snackBar.createExportRequestError": "Une erreur est survenue en créant une demande d'export", - "iaso.snackBar.createExportRequestErrorNoFormMappingError": "Le formulaire n'est pas encore configuré pour l'export vers dhis2", + "iaso.snackBar.createExportRequestErrorNoFormMappingError": "Le formulaire n'est pas encore configuré pour l'export vers DHIS2", "iaso.snackBar.createExportRequestErrorNothingToExportError": "Nous n'avons trouvé aucune soumission à exporter, vous pouvez modifier vos critères ou forcer le re-export", "iaso.snackBar.createExportRequestErrorNotSupportedError": "L'exportation forcée n'est pas prise en charge pour le suivi des événements", "iaso.snackBar.createExportRequestErrorNoVersionError": "L'export ne peut être créé, une des soumission ne spécifie pas la version du form", @@ -1576,4 +1576,4 @@ "trypelim.permissions.zones": "Zones", "trypelim.permissions.zones_edit": "Edit zones", "trypelim.permissions.zones_shapes_edit": "Editer les contours géographiques des zones de santé" -} +} \ No newline at end of file From 511b1684e63000459648720aaabae44083eb4d17 Mon Sep 17 00:00:00 2001 From: Christophe Gerard Date: Thu, 19 Dec 2024 11:54:33 +0100 Subject: [PATCH 04/13] hide columns --- .../Repository/reports/Filters.tsx | 4 ++- .../useVaccineRepositoryReportsColumns.tsx | 28 ++++++++++++------- .../Repository/reports/index.tsx | 3 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx index d943151273..44b9279828 100644 --- a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx @@ -30,7 +30,9 @@ export const Filters: FunctionComponent = ({ params, redirectUrl }) => { const [filtersUpdated, setFiltersUpdated] = useState(false); const [countries, setCountries] = useState(params.reportCountries); - const [fileType, setFileType] = useState(params.reportFileType || 'INCIDENT,DESTRUCTION'); + const [fileType, setFileType] = useState( + params.reportFileType || 'INCIDENT,DESTRUCTION', + ); const [vaccineName, setVaccineName] = useState(params.reportVaccineName); const [countryBlocks, setCountryBlocks] = useState( params.reportCountryBlock, diff --git a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/hooks/useVaccineRepositoryReportsColumns.tsx b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/hooks/useVaccineRepositoryReportsColumns.tsx index 26029fb1bb..5c8798a5ee 100644 --- a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/hooks/useVaccineRepositoryReportsColumns.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/hooks/useVaccineRepositoryReportsColumns.tsx @@ -3,10 +3,13 @@ import { useMemo } from 'react'; import { DocumentsCells } from '../../components/DocumentsCell'; import MESSAGES from '../../messages'; -export const useVaccineRepositoryReportsColumns = (): Column[] => { +export const useVaccineRepositoryReportsColumns = ( + params: Record, +): Column[] => { const { formatMessage } = useSafeIntl(); - return useMemo( - () => [ + const { reportFileType } = params; + return useMemo(() => { + const columns: Column[] = [ { Header: formatMessage(MESSAGES.country), id: 'country__name', @@ -19,19 +22,24 @@ export const useVaccineRepositoryReportsColumns = (): Column[] => { accessor: 'vaccine', width: 20, }, - { + ]; + + if (reportFileType !== 'DESTRUCTION') { + columns.push({ Header: formatMessage(MESSAGES.incidentReports), accessor: 'incident_report_data', Cell: DocumentsCells, sortable: false, - }, - { + }); + } + if (reportFileType !== 'INCIDENT') { + columns.push({ Header: formatMessage(MESSAGES.destructionReports), accessor: 'destruction_report_data', Cell: DocumentsCells, sortable: false, - }, - ], - [formatMessage], - ); + }); + } + return columns; + }, [reportFileType, formatMessage]); }; diff --git a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/index.tsx b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/index.tsx index 5987f8dd7f..95cca2cca7 100644 --- a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/index.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/index.tsx @@ -40,7 +40,7 @@ export const Reports: FunctionComponent = ({ params }) => { const redirectUrl = isEmbedded ? embeddedVaccineRepositoryUrl : baseUrl; const { data, isFetching } = useGetVaccineRepositoryReports(reportParams); - const columns = useVaccineRepositoryReportsColumns(); + const columns = useVaccineRepositoryReportsColumns(reportParams); return ( <> @@ -59,6 +59,7 @@ export const Reports: FunctionComponent = ({ params }) => { extraProps={{ loading: isFetching, defaultPageSize: tableDefaults.limit, + columns, }} /> From 324167582fff90ba19df49022feafa9df7a0fa42 Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 14:19:58 +0100 Subject: [PATCH 05/13] POLIO-1803: add model methods to return single vaccines - On Round and Campaign - Includes subactivities scopes --- plugins/polio/api/campaigns/campaigns.py | 19 +++++---- plugins/polio/api/rounds/round.py | 4 ++ plugins/polio/models/base.py | 52 ++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/plugins/polio/api/campaigns/campaigns.py b/plugins/polio/api/campaigns/campaigns.py index 82d75145c5..847e4c7a90 100644 --- a/plugins/polio/api/campaigns/campaigns.py +++ b/plugins/polio/api/campaigns/campaigns.py @@ -141,6 +141,17 @@ class CampaignSerializer(serializers.ModelSerializer): account: Field = serializers.PrimaryKeyRelatedField(default=CurrentAccountDefault(), read_only=True) has_data_in_budget_tool = serializers.SerializerMethodField(read_only=True) campaign_types = serializers.PrimaryKeyRelatedField(many=True, queryset=CampaignType.objects.all(), required=False) + # Vaccines with real scope + vaccines = serializers.SerializerMethodField(read_only=True) + single_vaccines = serializers.SerializerMethodField(read_only=True) + + def get_vaccines(self, obj): + if obj.vaccines: + return ",".join([vaccine.strip() for vaccine in obj.vaccines.split(",")]) + return "" + + def get_single_vaccines(self, obj): + return obj.vaccines_extended def get_top_level_org_unit_name(self, campaign): if campaign.country: @@ -410,14 +421,6 @@ def update(self, instance: Campaign, validated_data): log_campaign_modification(campaign, old_campaign_dump, self.context["request"].user) return campaign - # Vaccines with real scope - vaccines = serializers.SerializerMethodField(read_only=True) - - def get_vaccines(self, obj): - if obj.vaccines: - return ",".join([vaccine.strip() for vaccine in obj.vaccines.split(",")]) - return "" - class Meta: model = Campaign # TODO in the future specify the fields that need to be returned so we can remove the deprecated fields diff --git a/plugins/polio/api/rounds/round.py b/plugins/polio/api/rounds/round.py index ec33772d17..cbbe59a5c7 100644 --- a/plugins/polio/api/rounds/round.py +++ b/plugins/polio/api/rounds/round.py @@ -35,6 +35,10 @@ class Meta: # Vaccines from real scopes, from property, separated by , vaccine_names = serializers.CharField(read_only=True) + vaccine_names_extended = serializers.SerializerMethodField(read_only=True) + + def get_vaccine_names_extended(self, obj): + return obj.vaccine_names_extended @atomic def create(self, validated_data): diff --git a/plugins/polio/models/base.py b/plugins/polio/models/base.py index ac6cee363d..0cfacfb375 100644 --- a/plugins/polio/models/base.py +++ b/plugins/polio/models/base.py @@ -380,6 +380,32 @@ def vaccine_names(self): ) return ",".join(scope.vaccine for scope in scopes_with_orgunits) + @property + def vaccine_names_extended(self): + vaccines = set() + subactivity_vaccines = [ + subactivity["scopes__vaccine"] + for subactivity in list(self.sub_activities.filter(scopes__isnull=False).values("scopes__vaccine")) + ] + for subactivity_vaccine in subactivity_vaccines: + vaccines.add(subactivity_vaccine) + if self.campaign.separate_scopes_per_round: + scopes_with_orgunits = filter( + lambda s: len(s.group.org_units.all()) > 0 and s.vaccine is not None, self.scopes.all() + ) + else: + scopes_with_orgunits = filter( + lambda s: len(s.group.org_units.all()) > 0 and s.vaccine is not None, self.campaign.scopes.all() + ) + for scope in scopes_with_orgunits: + vaccines.add(scope.vaccine) + + if VACCINES[3][0] in vaccines: + vaccines.remove(VACCINES[3][0]) + vaccines.add(VACCINES[1][0]) + vaccines.add(VACCINES[2][0]) + return ", ".join(sorted(vaccines)) + @property def districts_count_calculated(self): return len(self.campaign.get_districts_for_round(self)) @@ -781,6 +807,32 @@ def vaccine_names(self): vaccine_names = sorted({scope.vaccine for scope in scopes_with_orgunits_and_vaccine}) return ", ".join(vaccine_names) + @property + def vaccines_extended(self): + vaccines = set() + for round in self.rounds.all(): + subactivity_vaccines = [ + subactivity["scopes__vaccine"] + for subactivity in list(round.sub_activities.filter(scopes__isnull=False).values("scopes__vaccine")) + ] + for subactivity_vaccine in subactivity_vaccines: + vaccines.add(subactivity_vaccine) + if self.separate_scopes_per_round: + scopes_with_orgunits = filter( + lambda s: len(s.group.org_units.all()) > 0 and s.vaccine is not None, round.scopes.all() + ) + else: + scopes_with_orgunits = filter( + lambda s: len(s.group.org_units.all()) > 0 and s.vaccine is not None, self.scopes.all() + ) + for scope in scopes_with_orgunits: + vaccines.add(scope.vaccine) + if VACCINES[3][0] in vaccines: + vaccines.remove(VACCINES[3][0]) + vaccines.add(VACCINES[1][0]) + vaccines.add(VACCINES[2][0]) + return ", ".join(sorted(vaccines)) + def update_geojson_field(self): "Update the geojson field on the campaign DO NOT TRIGGER the save() you have to do it manually" campaign = self From d40e273543782eb8b36d88212a65918e9e1ab51f Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 14:21:15 +0100 Subject: [PATCH 06/13] POLIO-1803: fix vaccine dropdown - show individual vaccines for bOPV & nOPV2 campaigns - Include subactivities vaccines --- plugins/polio/js/src/constants/types.ts | 2 ++ .../VaccineModule/SupplyChain/constants.ts | 15 +++++++++++++++ .../VaccineModule/SupplyChain/hooks/api/vrf.tsx | 10 +++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/plugins/polio/js/src/constants/types.ts b/plugins/polio/js/src/constants/types.ts index c8694e6b9f..50cb69f58e 100644 --- a/plugins/polio/js/src/constants/types.ts +++ b/plugins/polio/js/src/constants/types.ts @@ -260,6 +260,7 @@ export type RoundDateHistoryEntry = { export type Round = { id: number; + vaccine_names_extended:string; started_at: Nullable; ended_at: Nullable; mop_up_started_at: Nullable; // date @@ -308,6 +309,7 @@ export type Campaign = { created_at: string; updated_at: string; deleted_at: Nullable; + single_vaccines?: string; rounds: Round[]; org_unit: { id: number; diff --git a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/constants.ts b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/constants.ts index 29f4495c8e..30c570e8da 100644 --- a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/constants.ts +++ b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/constants.ts @@ -22,3 +22,18 @@ export const defaultVaccineOptions = [ value: 'nOPV2 & bOPV', }, ]; + +export const singleVaccinesList = [ + { + label: 'nOPV2', + value: 'nOPV2', + }, + { + label: 'mOPV2', + value: 'mOPV2', + }, + { + label: 'bOPV', + value: 'bOPV', + }, +] diff --git a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx index 1ed21eb288..7801c4efb4 100644 --- a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx @@ -39,7 +39,7 @@ import { CampaignCategory, useGetCampaigns, } from '../../../../Campaigns/hooks/api/useGetCampaigns'; -import { apiUrl, defaultVaccineOptions } from '../../constants'; +import { apiUrl, defaultVaccineOptions, singleVaccinesList } from '../../constants'; import MESSAGES from '../../messages'; import { CampaignDropdowns, @@ -133,15 +133,15 @@ export const useCampaignDropDowns = ( label: c.obr_name, value: c.obr_name, })); - const vaccines = selectedCampaign?.vaccines - ? selectedCampaign.vaccines.split(',').map(vaccineName => ({ + const vaccines = selectedCampaign?.single_vaccines + ? selectedCampaign.single_vaccines.split(',').map(vaccineName => ({ label: vaccineName, value: vaccineName, })) - : defaultVaccineOptions; + : singleVaccinesList; const rounds = vaccine ? (selectedCampaign?.rounds ?? []) - .filter(round => round.vaccine_names.includes(vaccine)) + .filter(round => round.vaccine_names_extended.includes(vaccine)) .map(round => ({ label: `Round ${round.number}`, value: `${round.number}`, From cab5073f6114c038d802107e3271c9604d5f6f98 Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 14:31:14 +0100 Subject: [PATCH 07/13] POLIO-1803: update vaccine filter dropdowns --- .../CreateVaccineStock/CreateVaccineStock.tsx | 4 ++-- .../Filters/VaccineStockManagementFilters.tsx | 7 ++----- .../SupplyChain/Filters/VaccineSupplyChainFilters.tsx | 7 ++----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/plugins/polio/js/src/domains/VaccineModule/StockManagement/CreateVaccineStock/CreateVaccineStock.tsx b/plugins/polio/js/src/domains/VaccineModule/StockManagement/CreateVaccineStock/CreateVaccineStock.tsx index 1ccda60f0b..b84062dfb2 100644 --- a/plugins/polio/js/src/domains/VaccineModule/StockManagement/CreateVaccineStock/CreateVaccineStock.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/StockManagement/CreateVaccineStock/CreateVaccineStock.tsx @@ -12,7 +12,7 @@ import { SingleSelect } from '../../../../components/Inputs/SingleSelect'; import MESSAGES from '../messages'; import { useSaveVaccineStock } from '../hooks/api'; import { useGetCountriesOptions } from '../../SupplyChain/hooks/api/vrf'; -import { defaultVaccineOptions } from '../../SupplyChain/constants'; +import { singleVaccinesList } from '../../SupplyChain/constants'; type Props = { isOpen: boolean; @@ -71,7 +71,7 @@ const CreateVaccineStock: FunctionComponent = ({ name="vaccine" component={SingleSelect} required - options={defaultVaccineOptions} + options={singleVaccinesList} withMarginTop // isLoading={isFetchingCountries} /> diff --git a/plugins/polio/js/src/domains/VaccineModule/StockManagement/Filters/VaccineStockManagementFilters.tsx b/plugins/polio/js/src/domains/VaccineModule/StockManagement/Filters/VaccineStockManagementFilters.tsx index d09ea52993..dfdb50568a 100644 --- a/plugins/polio/js/src/domains/VaccineModule/StockManagement/Filters/VaccineStockManagementFilters.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/StockManagement/Filters/VaccineStockManagementFilters.tsx @@ -6,10 +6,10 @@ import { FilterButton } from '../../../../../../../../hat/assets/js/apps/Iaso/co import { useFilterState } from '../../../../../../../../hat/assets/js/apps/Iaso/hooks/useFilterState'; import InputComponent from '../../../../../../../../hat/assets/js/apps/Iaso/components/forms/InputComponent'; import MESSAGES from '../messages'; -import { polioVaccines } from '../../../../constants/virus'; import { useGetCountriesOptions } from '../../SupplyChain/hooks/api/vrf'; import { StockManagementListParams } from '../types'; import { baseUrls } from '../../../../constants/urls'; +import { singleVaccinesList } from '../../SupplyChain/constants'; const baseUrl = baseUrls.stockManagement; type Props = { params: StockManagementListParams }; @@ -46,10 +46,7 @@ export const VaccineStockManagementFilters: FunctionComponent = ({ keyValue="vaccine_type" value={filters.vaccine_type} onChange={handleChange} - options={polioVaccines.map(vaccine => ({ - label: vaccine.label, - value: vaccine.value, - }))} + options={singleVaccinesList} labelString={formatMessage(MESSAGES.vaccine)} /> diff --git a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/Filters/VaccineSupplyChainFilters.tsx b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/Filters/VaccineSupplyChainFilters.tsx index 611dd30291..4555bf7f7b 100644 --- a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/Filters/VaccineSupplyChainFilters.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/Filters/VaccineSupplyChainFilters.tsx @@ -6,10 +6,10 @@ import { FilterButton } from '../../../../../../../../hat/assets/js/apps/Iaso/co import { useFilterState } from '../../../../../../../../hat/assets/js/apps/Iaso/hooks/useFilterState'; import InputComponent from '../../../../../../../../hat/assets/js/apps/Iaso/components/forms/InputComponent'; import MESSAGES from '../messages'; -import { polioVaccines } from '../../../../constants/virus'; import { apiDateFormat } from '../../../../../../../../hat/assets/js/apps/Iaso/utils/dates'; import { useGetCountriesOptions } from '../hooks/api/vrf'; import { useGetGroupDropdown } from '../../../../../../../../hat/assets/js/apps/Iaso/domains/orgUnits/hooks/requests/useGetGroups'; +import { singleVaccinesList } from '../constants'; type Props = { params: any }; @@ -83,10 +83,7 @@ export const VaccineSupplyChainFilters: FunctionComponent = ({ keyValue="vaccine_type" value={filters.vaccine_type} onChange={handleChange} - options={polioVaccines.map(vaccine => ({ - label: vaccine.label, - value: vaccine.value, - }))} + options={singleVaccinesList} labelString={formatMessage(MESSAGES.vaccine)} /> Date: Thu, 19 Dec 2024 14:47:48 +0100 Subject: [PATCH 08/13] POLIO-1803: fix minor bugs --- .../domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx | 4 ++-- plugins/polio/models/base.py | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx index 7801c4efb4..8684c50f6e 100644 --- a/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/SupplyChain/hooks/api/vrf.tsx @@ -135,8 +135,8 @@ export const useCampaignDropDowns = ( })); const vaccines = selectedCampaign?.single_vaccines ? selectedCampaign.single_vaccines.split(',').map(vaccineName => ({ - label: vaccineName, - value: vaccineName, + label: vaccineName.trim(), + value: vaccineName.trim(), })) : singleVaccinesList; const rounds = vaccine diff --git a/plugins/polio/models/base.py b/plugins/polio/models/base.py index 0cfacfb375..1a8738fa6f 100644 --- a/plugins/polio/models/base.py +++ b/plugins/polio/models/base.py @@ -53,6 +53,12 @@ ("nOPV2 & bOPV", _("nOPV2 & bOPV")), ] +INDIVIDUAL_VACCINES = [ + ("mOPV2", _("mOPV2")), + ("nOPV2", _("nOPV2")), + ("bOPV", _("bOPV")), +] + DOSES_PER_VIAL = { "mOPV2": 20, "nOPV2": 50, @@ -1099,7 +1105,7 @@ class Meta: ] campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, db_index=True) - vaccine_type = models.CharField(max_length=30, choices=VACCINES) + vaccine_type = models.CharField(max_length=30, choices=INDIVIDUAL_VACCINES) rounds = models.ManyToManyField(Round, db_index=True) date_vrf_signature = models.DateField(null=True, blank=True) date_vrf_reception = models.DateField(null=True, blank=True) From 13be3f8478aaa997016f6e8f8ac1274e1f18140d Mon Sep 17 00:00:00 2001 From: Christophe Gerard Date: Thu, 19 Dec 2024 14:58:02 +0100 Subject: [PATCH 09/13] adapt reports and forms repository --- .../domains/VaccineModule/Repository/forms/Filters.tsx | 4 ++-- .../domains/VaccineModule/Repository/reports/Filters.tsx | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/polio/js/src/domains/VaccineModule/Repository/forms/Filters.tsx b/plugins/polio/js/src/domains/VaccineModule/Repository/forms/Filters.tsx index e72f9c48d6..869ac233de 100644 --- a/plugins/polio/js/src/domains/VaccineModule/Repository/forms/Filters.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/Repository/forms/Filters.tsx @@ -14,7 +14,7 @@ import MESSAGES from '../../../../constants/messages'; import { useGetCountries } from '../../../../hooks/useGetCountries'; import { appId } from '../../../../constants/app'; -import { defaultVaccineOptions } from '../../SupplyChain/constants'; +import { singleVaccinesList } from '../../SupplyChain/constants'; import { useGetFileTypes } from '../hooks/useGetFileTypes'; import { VaccineRepositoryParams } from '../types'; @@ -101,7 +101,7 @@ export const Filters: FunctionComponent = ({ params, redirectUrl }) => { }} value={vaccineName} type="select" - options={defaultVaccineOptions} + options={singleVaccinesList} label={MESSAGES.vaccine} /> diff --git a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx index d943151273..4c4e9449a4 100644 --- a/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx +++ b/plugins/polio/js/src/domains/VaccineModule/Repository/reports/Filters.tsx @@ -14,7 +14,7 @@ import MESSAGES from '../../../../constants/messages'; import { useGetCountries } from '../../../../hooks/useGetCountries'; import { appId } from '../../../../constants/app'; -import { defaultVaccineOptions } from '../../SupplyChain/constants'; +import { singleVaccinesList } from '../../SupplyChain/constants'; import { useGetReportFileTypes } from '../hooks/useGetFileTypes'; import { VaccineRepositoryParams } from '../types'; @@ -30,7 +30,9 @@ export const Filters: FunctionComponent = ({ params, redirectUrl }) => { const [filtersUpdated, setFiltersUpdated] = useState(false); const [countries, setCountries] = useState(params.reportCountries); - const [fileType, setFileType] = useState(params.reportFileType || 'INCIDENT,DESTRUCTION'); + const [fileType, setFileType] = useState( + params.reportFileType || 'INCIDENT,DESTRUCTION', + ); const [vaccineName, setVaccineName] = useState(params.reportVaccineName); const [countryBlocks, setCountryBlocks] = useState( params.reportCountryBlock, @@ -133,7 +135,7 @@ export const Filters: FunctionComponent = ({ params, redirectUrl }) => { }} value={vaccineName} type="select" - options={defaultVaccineOptions} + options={singleVaccinesList} label={MESSAGES.vaccine} /> From ce314ad17f5d4d85e7cb76cfc3c3cd0f7c685cc1 Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 14:59:24 +0100 Subject: [PATCH 10/13] POLIO-1803: add migration --- ...213_alter_vaccinerequestform_vaccine_type.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 plugins/polio/migrations/0213_alter_vaccinerequestform_vaccine_type.py diff --git a/plugins/polio/migrations/0213_alter_vaccinerequestform_vaccine_type.py b/plugins/polio/migrations/0213_alter_vaccinerequestform_vaccine_type.py new file mode 100644 index 0000000000..d6a5dc5c6d --- /dev/null +++ b/plugins/polio/migrations/0213_alter_vaccinerequestform_vaccine_type.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.17 on 2024-12-19 13:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("polio", "0212_alter_vaccinerequestform_vaccine_type"), + ] + + operations = [ + migrations.AlterField( + model_name="vaccinerequestform", + name="vaccine_type", + field=models.CharField(choices=[("mOPV2", "mOPV2"), ("nOPV2", "nOPV2"), ("bOPV", "bOPV")], max_length=30), + ), + ] From 692421174ef112013d8d52aec422ee19c5d0204f Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 15:07:50 +0100 Subject: [PATCH 11/13] fix: getDisplayNAme handles undefined user --- hat/assets/js/apps/Iaso/utils/usersUtils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hat/assets/js/apps/Iaso/utils/usersUtils.ts b/hat/assets/js/apps/Iaso/utils/usersUtils.ts index 15da01c30f..8a9cb7533c 100644 --- a/hat/assets/js/apps/Iaso/utils/usersUtils.ts +++ b/hat/assets/js/apps/Iaso/utils/usersUtils.ts @@ -1,4 +1,4 @@ -import { LangOptions } from 'bluesquare-components'; +import { LangOptions, textPlaceholder } from 'bluesquare-components'; import { useQueryClient } from 'react-query'; import { OrgUnitStatus } from '../domains/orgUnits/types/orgUnit'; import { Project } from '../domains/projects/types/project'; @@ -89,6 +89,9 @@ export type User = { export const getDisplayName = ( user: Partial | Partial, ): string => { + if(!user){ + return textPlaceholder + } // Some endpoint have user_name and some username (without the _, fun) const userName = user.user_name ?? user?.username; if (!user.first_name && !user.last_name) { From e936f38423337f9841ff1f242869f2ecb6b34cda Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 15:32:19 +0100 Subject: [PATCH 12/13] POLIO-1762: remove empty lines in vaccine repo reports --- plugins/polio/api/vaccines/repository_reports.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/polio/api/vaccines/repository_reports.py b/plugins/polio/api/vaccines/repository_reports.py index 27e1095034..d9b2dc7298 100644 --- a/plugins/polio/api/vaccines/repository_reports.py +++ b/plugins/polio/api/vaccines/repository_reports.py @@ -6,9 +6,9 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.mixins import ListModelMixin from rest_framework.viewsets import GenericViewSet - +from django.db.models import sQ from iaso.api.common import Paginator -from plugins.polio.models import VaccineStock, DestructionReport, IncidentReport +from plugins.polio.models import VaccineStock class VaccineReportingFilterBackend(filters.BaseFilterBackend): @@ -118,7 +118,7 @@ def get_queryset(self): if self.request.user and self.request.user.is_authenticated: base_qs = base_qs.filter(account=self.request.user.iaso_profile.account) - return base_qs + return base_qs.filter(Q(destructionreport__isnull=False) | Q(incidentreport__isnull=False)) @swagger_auto_schema( manual_parameters=[ From 9838c3a83736d358fc2b5adb8218e99a81ba4a26 Mon Sep 17 00:00:00 2001 From: Quang Son Le Date: Thu, 19 Dec 2024 15:34:42 +0100 Subject: [PATCH 13/13] fix typo --- plugins/polio/api/vaccines/repository_reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/polio/api/vaccines/repository_reports.py b/plugins/polio/api/vaccines/repository_reports.py index d9b2dc7298..a40cb3abc3 100644 --- a/plugins/polio/api/vaccines/repository_reports.py +++ b/plugins/polio/api/vaccines/repository_reports.py @@ -6,7 +6,7 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.mixins import ListModelMixin from rest_framework.viewsets import GenericViewSet -from django.db.models import sQ +from django.db.models import Q from iaso.api.common import Paginator from plugins.polio.models import VaccineStock