From 5d2c0e3d793aecbf72bd46722547d86bb2fad06a Mon Sep 17 00:00:00 2001 From: Benzer Bett Date: Wed, 27 Oct 2021 12:40:55 +0300 Subject: [PATCH 01/41] matierialized view update --- .../faciliities_excel_export_27_oct_21.sql | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 facilities/migrations/faciliities_excel_export_27_oct_21.sql diff --git a/facilities/migrations/faciliities_excel_export_27_oct_21.sql b/facilities/migrations/faciliities_excel_export_27_oct_21.sql new file mode 100644 index 00000000..c9dfab34 --- /dev/null +++ b/facilities/migrations/faciliities_excel_export_27_oct_21.sql @@ -0,0 +1,77 @@ +DROP MATERIALIZED VIEW IF EXISTS facilities_excel_export; + +create materialized view facilities_excel_export as +SELECT facilities_facility.id, + facilities_facility.search, + facilities_facility.name, + facilities_facility.official_name AS officialname, + facilities_facility.code, + facilities_facility.registration_number, + facilities_facility.number_of_beds AS beds, + facilities_facility.number_of_cots AS cots, + common_ward.name AS ward_name, + common_ward.id AS ward, + facilities_facility.approved, + facilities_facility.created, + facilities_facility.updated, + facilities_facility.open_whole_day, + facilities_facility.open_public_holidays, + facilities_facility.open_weekends, + facilities_facility.open_late_night, + facilities_facility.closed, + facilities_facility.is_published, + facilities_facility.approved_national_level, + common_county.name AS county_name, + common_county.id AS county, + common_constituency.name AS constituency_name, + common_constituency.id AS constituency, + common_subcounty.name AS sub_county_name, + common_subcounty.id AS sub_county, + facilities_facilitytype.name AS facility_type_name, + facilities_facilitytype.id AS facility_type, + facilities_facilitytypecat.name AS facility_type_category, + facilities_facilitytypecat.id AS facility_type_parent, + facilities_kephlevel.name AS keph_level_name, + facilities_kephlevel.id AS keph_level, + facilities_owner.name AS owner_name, + facilities_owner.id AS owner, + facilities_ownertype.name AS owner_type_name, + facilities_ownertype.id AS owner_type, + facilities_regulatingbody.name AS regulatory_body_name, + facilities_regulatingbody.id AS regulatory_body, + facilities_facilitystatus.name AS operation_status_name, + facilities_facilitystatus.id AS operation_status, + facilities_facilitystatus.is_public_visible, + facilities_facilityadmissionstatus.name AS admission_status_name, + facilities_facilityadmissionstatus.id AS admission_status, + st_x(mfl_gis_facilitycoordinates.coordinates) AS lat, + st_y(mfl_gis_facilitycoordinates.coordinates) AS long, + ARRAY(SELECT DISTINCT facilities_facilityservice.service_id + FROM facilities_facilityservice + WHERE facilities_facilityservice.facility_id = facilities_facility.id) AS services, + ARRAY(SELECT DISTINCT facilities_service.category_id + FROM facilities_facilityservice + JOIN facilities_service ON facilities_service.id = facilities_facilityservice.service_id + WHERE facilities_facilityservice.facility_id = facilities_facility.id) AS categories, + ARRAY(SELECT DISTINCT facilities_service.name + FROM facilities_service + JOIN facilities_facilityservice ON facilities_service.id = facilities_facilityservice.service_id + WHERE facilities_facilityservice.facility_id = facilities_facility.id) AS service_names +FROM facilities_facility + LEFT JOIN facilities_kephlevel ON facilities_kephlevel.id = facilities_facility.keph_level_id + LEFT JOIN facilities_owner ON facilities_owner.id = facilities_facility.owner_id + LEFT JOIN facilities_ownertype ON facilities_owner.owner_type_id = facilities_ownertype.id + LEFT JOIN facilities_facilitytype ON facilities_facilitytype.id = facilities_facility.facility_type_id + LEFT JOIN facilities_facilitytype facilities_facilitytypecat + ON facilities_facilitytypecat.id = facilities_facilitytype.parent_id + LEFT JOIN facilities_regulatingbody ON facilities_regulatingbody.id = facilities_facility.regulatory_body_id + LEFT JOIN facilities_facilitystatus ON facilities_facilitystatus.id = facilities_facility.operation_status_id + LEFT JOIN facilities_facilityadmissionstatus ON facilities_facilityadmissionstatus.id = facilities_facility.admission_status_id + LEFT JOIN common_ward ON common_ward.id = facilities_facility.ward_id + LEFT JOIN common_constituency ON common_constituency.id = common_ward.constituency_id + LEFT JOIN common_subcounty ON common_subcounty.id = common_ward.sub_county_id + LEFT JOIN common_county ON common_county.id = common_constituency.county_id + LEFT JOIN mfl_gis_facilitycoordinates ON mfl_gis_facilitycoordinates.facility_id = facilities_facility.id; + +alter materialized view facilities_excel_export owner to postgres; + From 99359411830a03a9d05b135221b1722684cb588c Mon Sep 17 00:00:00 2001 From: Benzer Bett Date: Tue, 9 Nov 2021 15:54:40 +0300 Subject: [PATCH 02/41] chul updates approval - error fix --- chul/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chul/models.py b/chul/models.py index d4bc2102..a7ad1a80 100755 --- a/chul/models.py +++ b/chul/models.py @@ -218,7 +218,7 @@ def clean(self): @property def pending_updates(self): try: - chu = ChuUpdateBuffer.objects.get( + chu = ChuUpdateBuffer.objects.latest( is_approved=False, is_rejected=False, health_unit=self @@ -230,7 +230,7 @@ def pending_updates(self): @property def latest_update(self): try: - chu = ChuUpdateBuffer.objects.get( + chu = ChuUpdateBuffer.objects.latest( is_approved=False, is_rejected=False, health_unit=self From 27c07d483b2a8dec6bf461c113079aeb74df9ff1 Mon Sep 17 00:00:00 2001 From: Benzer Bett Date: Wed, 5 Jan 2022 11:42:15 +0300 Subject: [PATCH 03/41] cleanup facility_filters code, started KHIS-Tracker sync feature (WiP) --- .env-example | 5 +- facilities/filters/facility_filters.py | 8 +-- facilities/models/facility_models.py | 87 +++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 6 deletions(-) diff --git a/.env-example b/.env-example index 5096312a..608ba8ac 100644 --- a/.env-example +++ b/.env-example @@ -21,4 +21,7 @@ DATABASE_URL='postgres://mfl_testing:mfl_testing@localhost:5432/mfl_testing' FRONTEND_URL='http://localhost:8062' REALTIME_INDEX = true HTTPS_ENABLED = false -ALLOWED_HOSTS=".localhost, .health.go.ke" \ No newline at end of file +ALLOWED_HOSTS=".localhost, .health.go.ke" + +# Toggle synchronization of the facilities to KHIS Tracker +PUSH_TO_TRACKER=false \ No newline at end of file diff --git a/facilities/filters/facility_filters.py b/facilities/filters/facility_filters.py index 4a2818fa..3ffbcd74 100755 --- a/facilities/filters/facility_filters.py +++ b/facilities/filters/facility_filters.py @@ -392,8 +392,8 @@ def filter_incomplete_facilities(self, qs, name, value): return qs.exclude(id__in=[facility.id for facility in incomplete]) def facilities_pending_approval(self, qs, name, value): - incomplete = qs.filter(code=not None) - incomplete_facility_ids = [facility.id for facility in incomplete] + fac_pend_appr = qs.filter(code=not None) + fac_pend_appr_facility_ids = [facility.id for facility in fac_pend_appr] if value in TRUTH_NESS: return qs.filter( Q( @@ -404,12 +404,12 @@ def facilities_pending_approval(self, qs, name, value): Q( Q(rejected=False), Q(has_edits=True) | Q(approved=None,rejected=False)) - ).exclude(id__in=incomplete_facility_ids) + ).exclude(id__in=fac_pend_appr_facility_ids) else: return qs.filter( Q(rejected=True) | Q(has_edits=False) & Q(approved=None) - ).exclude(id__in=incomplete_facility_ids) + ).exclude(id__in=fac_pend_appr_facility_ids) def filter_national_rejected(self, qs, name, value): rejected_national = qs.filter(rejected=False,code=None, diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 7b83ebce..824ba910 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -121,6 +121,19 @@ def generate_uuid_dhis(self): ) print("New OrgUnit UID Generated-", r_generate_orgunit_uid.json()['codes'][0]) return r_generate_orgunit_uid.json()['code'][0] + + def generate_uuid_dhis_tracker(self): + r_generate_orgunit_uid = requests.get( + settings.DHIS_TRACKER_ENDPOINT + "api/system/uid.json", + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + # "Authorization": "Bearer " + json.loads(self.session_store[self.oauth2_token_variable_name].replace("u", "") + # .replace("'", '"'))["access_token"], + "Accept": "application/json" + }, + ) + print("New TRACKER OrgUnit UID Generated-", r_generate_orgunit_uid.json()['codes'][0]) + return r_generate_orgunit_uid.json()['code'][0] def get_org_unit_id(self, code): r = requests.get( @@ -199,6 +212,18 @@ def push_facility_to_dhis2(self, new_facility_payload, new_facility=True): json=new_facility_payload ) LOGGER.info("Create Facility Response: %s" % r.text) + if settings.PUSH_TO_TRACKER: + rt = requests.post( + settings.DHIS_TRACKER_ENDPOINT+"api/organisationUnits", + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + # "Authorization": "Bearer " + json.loads(self.session_store[self.oauth2_token_variable_name].replace("u", "") + # .replace("'", '"'))["access_token"], + "Accept": "application/json" + }, + json=new_facility_payload + ) + LOGGER.info("Create Tracker Facility Response: %s" % rt.text) else: r = requests.put( settings.DHIS_ENDPOINT + "api/organisationUnits/" + new_facility_payload.pop('id'), @@ -209,6 +234,16 @@ def push_facility_to_dhis2(self, new_facility_payload, new_facility=True): json=new_facility_payload ) LOGGER.info("Update Facility Response: %s" % r.text) + if settings.PUSH_TO_TRACKER: + rt = requests.put( + settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnits/" + new_facility_payload.pop('id'), + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + "Accept": "application/json" + }, + json=new_facility_payload + ) + LOGGER.info("Update Tracker Facility Response: %s" % rt.text) if r.json()["status"] != "OK": LOGGER.error('Facility feedback: %s' % r.text) raise ValidationError( @@ -218,6 +253,15 @@ def push_facility_to_dhis2(self, new_facility_payload, new_facility=True): "Or some specific information like codes are not unique"] } ) + if settings.PUSH_TO_TRACKER and rt.json()["status"] != "OK": + LOGGER.error('TRACKER Facility feedback: %s' % rt.text) + raise ValidationError( + { + "Error!": ["An error occured while pushing facility to DHIS2 TRACKER. This is may be caused by the " + "existance of an organisation unit with as similar name as to the one you are creating. " + "Or some specific information like codes are not unique"] + } + ) def push_facility_metadata(self, metadata_payload, facility_uid): # Keph Level @@ -228,6 +272,14 @@ def push_facility_metadata(self, metadata_payload, facility_uid): "Accept": "application/json" }, ) + if settings.PUSH_TO_TRACKER: + rt_keph_t = requests.post( + settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnitGroups/" + metadata_payload['keph'] + "/organisationUnits/" + facility_uid, + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + "Accept": "application/json" + }, + ) # print r_keph.json() # if r_keph.json()["status"] != "OK": # raise ValidationError( @@ -242,6 +294,14 @@ def push_facility_metadata(self, metadata_payload, facility_uid): "Accept": "application/json" }, ) + if settings.PUSH_TO_TRACKER: + rt_facility_type_t = requests.post( + settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnitGroups/" + metadata_payload['facility_type'] + "/organisationUnits/" + facility_uid, + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + "Accept": "application/json" + }, + ) # if r_facility_type.json()["status"] != "OK": # raise ValidationError( # { @@ -256,6 +316,15 @@ def push_facility_metadata(self, metadata_payload, facility_uid): "Accept": "application/json" }, ) + if settings.PUSH_TO_TRACKER: + rt_ownership_t = requests.post( + settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnitGroups/" + metadata_payload[ + 'ownership'] + "/organisationUnits/" + facility_uid, + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + "Accept": "application/json" + }, + ) # if r_ownership.json()["status"] != "OK": # raise ValidationError( # { @@ -272,8 +341,18 @@ def push_facility_updates_to_dhis2(self, org_unit_id, facility_updates_payload): }, json=facility_updates_payload ) - print("Update Facility Response", r.url, r.status_code, r.json()) + if settings.PUSH_TO_TRACKER: + rt = requests.put( + settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnits/"+org_unit_id, + auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), + headers={ + "Accept": "application/json" + }, + json=facility_updates_payload + ) + print("Update Tracker Facility Response", rt.url, rt.status_code, rt.json()) + if r.json()["status"] != "OK": raise ValidationError( @@ -281,6 +360,12 @@ def push_facility_updates_to_dhis2(self, org_unit_id, facility_updates_payload): "Error!": ["Unable to push facility updates to DHIS2"] } ) + if settings.PUSH_TO_TRACKER and rt.json()["status"] != "OK": + raise ValidationError( + { + "Error!": ["Unable to push facility updates to DHIS2 TRACKER"] + } + ) def format_coordinates(self, str_coordinates): coordinates_str_list = str_coordinates.split(" ") From 5a40f5a8184dfec0b74614d734d91dd495ef4798 Mon Sep 17 00:00:00 2001 From: Benzer Bett Date: Wed, 5 Jan 2022 11:54:08 +0300 Subject: [PATCH 04/41] revert tracker sync --- facilities/models/facility_models.py | 87 +--------------------------- 1 file changed, 1 insertion(+), 86 deletions(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 824ba910..7b83ebce 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -121,19 +121,6 @@ def generate_uuid_dhis(self): ) print("New OrgUnit UID Generated-", r_generate_orgunit_uid.json()['codes'][0]) return r_generate_orgunit_uid.json()['code'][0] - - def generate_uuid_dhis_tracker(self): - r_generate_orgunit_uid = requests.get( - settings.DHIS_TRACKER_ENDPOINT + "api/system/uid.json", - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - # "Authorization": "Bearer " + json.loads(self.session_store[self.oauth2_token_variable_name].replace("u", "") - # .replace("'", '"'))["access_token"], - "Accept": "application/json" - }, - ) - print("New TRACKER OrgUnit UID Generated-", r_generate_orgunit_uid.json()['codes'][0]) - return r_generate_orgunit_uid.json()['code'][0] def get_org_unit_id(self, code): r = requests.get( @@ -212,18 +199,6 @@ def push_facility_to_dhis2(self, new_facility_payload, new_facility=True): json=new_facility_payload ) LOGGER.info("Create Facility Response: %s" % r.text) - if settings.PUSH_TO_TRACKER: - rt = requests.post( - settings.DHIS_TRACKER_ENDPOINT+"api/organisationUnits", - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - # "Authorization": "Bearer " + json.loads(self.session_store[self.oauth2_token_variable_name].replace("u", "") - # .replace("'", '"'))["access_token"], - "Accept": "application/json" - }, - json=new_facility_payload - ) - LOGGER.info("Create Tracker Facility Response: %s" % rt.text) else: r = requests.put( settings.DHIS_ENDPOINT + "api/organisationUnits/" + new_facility_payload.pop('id'), @@ -234,16 +209,6 @@ def push_facility_to_dhis2(self, new_facility_payload, new_facility=True): json=new_facility_payload ) LOGGER.info("Update Facility Response: %s" % r.text) - if settings.PUSH_TO_TRACKER: - rt = requests.put( - settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnits/" + new_facility_payload.pop('id'), - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - "Accept": "application/json" - }, - json=new_facility_payload - ) - LOGGER.info("Update Tracker Facility Response: %s" % rt.text) if r.json()["status"] != "OK": LOGGER.error('Facility feedback: %s' % r.text) raise ValidationError( @@ -253,15 +218,6 @@ def push_facility_to_dhis2(self, new_facility_payload, new_facility=True): "Or some specific information like codes are not unique"] } ) - if settings.PUSH_TO_TRACKER and rt.json()["status"] != "OK": - LOGGER.error('TRACKER Facility feedback: %s' % rt.text) - raise ValidationError( - { - "Error!": ["An error occured while pushing facility to DHIS2 TRACKER. This is may be caused by the " - "existance of an organisation unit with as similar name as to the one you are creating. " - "Or some specific information like codes are not unique"] - } - ) def push_facility_metadata(self, metadata_payload, facility_uid): # Keph Level @@ -272,14 +228,6 @@ def push_facility_metadata(self, metadata_payload, facility_uid): "Accept": "application/json" }, ) - if settings.PUSH_TO_TRACKER: - rt_keph_t = requests.post( - settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnitGroups/" + metadata_payload['keph'] + "/organisationUnits/" + facility_uid, - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - "Accept": "application/json" - }, - ) # print r_keph.json() # if r_keph.json()["status"] != "OK": # raise ValidationError( @@ -294,14 +242,6 @@ def push_facility_metadata(self, metadata_payload, facility_uid): "Accept": "application/json" }, ) - if settings.PUSH_TO_TRACKER: - rt_facility_type_t = requests.post( - settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnitGroups/" + metadata_payload['facility_type'] + "/organisationUnits/" + facility_uid, - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - "Accept": "application/json" - }, - ) # if r_facility_type.json()["status"] != "OK": # raise ValidationError( # { @@ -316,15 +256,6 @@ def push_facility_metadata(self, metadata_payload, facility_uid): "Accept": "application/json" }, ) - if settings.PUSH_TO_TRACKER: - rt_ownership_t = requests.post( - settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnitGroups/" + metadata_payload[ - 'ownership'] + "/organisationUnits/" + facility_uid, - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - "Accept": "application/json" - }, - ) # if r_ownership.json()["status"] != "OK": # raise ValidationError( # { @@ -341,18 +272,8 @@ def push_facility_updates_to_dhis2(self, org_unit_id, facility_updates_payload): }, json=facility_updates_payload ) - print("Update Facility Response", r.url, r.status_code, r.json()) - if settings.PUSH_TO_TRACKER: - rt = requests.put( - settings.DHIS_TRACKER_ENDPOINT + "api/organisationUnits/"+org_unit_id, - auth=(settings.DHIS_TRACKER_USERNAME, settings.DHIS_TRACKER_PASSWORD), - headers={ - "Accept": "application/json" - }, - json=facility_updates_payload - ) - print("Update Tracker Facility Response", rt.url, rt.status_code, rt.json()) + print("Update Facility Response", r.url, r.status_code, r.json()) if r.json()["status"] != "OK": raise ValidationError( @@ -360,12 +281,6 @@ def push_facility_updates_to_dhis2(self, org_unit_id, facility_updates_payload): "Error!": ["Unable to push facility updates to DHIS2"] } ) - if settings.PUSH_TO_TRACKER and rt.json()["status"] != "OK": - raise ValidationError( - { - "Error!": ["Unable to push facility updates to DHIS2 TRACKER"] - } - ) def format_coordinates(self, str_coordinates): coordinates_str_list = str_coordinates.split(" ") From 379310b9b56cde084620f1f2dbfe4c6d7c1de47b Mon Sep 17 00:00:00 2001 From: Benzer Date: Fri, 14 Jan 2022 09:55:37 +0300 Subject: [PATCH 05/41] Create dev_requirements.txt --- dev_requirements.txt | 95 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 dev_requirements.txt diff --git a/dev_requirements.txt b/dev_requirements.txt new file mode 100644 index 00000000..18d3b84f --- /dev/null +++ b/dev_requirements.txt @@ -0,0 +1,95 @@ +amqp==1.4.9 +ansible==1.9.6 +anyjson==0.3.3 +apache-libcloud==0.17.0 +apipkg==1.5 +backports.ssl-match-hostname==3.7.0.1 +billiard==3.3.0.23 +boto==2.38.0 +cairocffi==0.9.0 +CairoSVG==1.0.22 +celery==3.1.19 +certifi==2019.3.9 +cffi==1.12.2 +chardet==3.0.4 +commonmark==0.8.1 +coreapi==2.3.3 +coreschema==0.0.4 +coverage==3.7.1 +cssselect2==0.2.1 +defusedxml==0.5.0 +dj-database-url==0.4.0 +Django==1.11.27 +django-allauth==0.39.1 +django-braces==1.13.0 +django-cors-headers==2.1.0 +django-debug-toolbar==1.8 +django-environ==0.3.1 +django-filter==1.0.4 +django-oauth-toolkit==0.11.0 +django-redis==4.0.0 +django-rest-auth==0.9.1 +django-rest-swagger==2.1.0 +django-reversion==2.0.5 +django-storages==1.1.8 +djangorestframework==3.6.3 +djangorestframework-csv==1.3.4 +djangorestframework-gis==0.8.2 +djangorestframework-xml==1.0.1 +docutils==0.14 +drf-extensions==0.3.1 +ecdsa==0.13 +execnet==1.5.0 +Fabric==1.10.5 +filechunkio==1.6 +flake8==2.3.0 +future==0.17.1 +gunicorn==19.3.0 +html5lib==0.9999999 +idna==2.8 +itypes==1.1.0 +Jinja2==2.10 +kombu==3.0.37 +Markdown==2.5.2 +MarkupSafe==1.1.1 +mccabe==0.6.1 +mock==1.0.1 +model-mommy==1.2.6 +oauthlib==1.1.2 +openapi-codec==1.3.2 +paramiko==1.18.5 +pdfrw==0.4 +pep8==1.7.1 +psycopg2==2.7 +py==1.8.0 +pycparser==2.19 +pycrypto==2.6.1 +pyflakes==2.1.1 +Pyphen==0.9.5 +pytest==2.7.3 +pytest-django==2.8.0 +pytest-xdist==1.11 +python-coveralls==2.5.0 +python-dateutil==2.8.0 +python-openid==2.2.5 +pytz==2018.9 +PyYAML==5.1 +recommonmark==0.1.1 +redis==3.2.1 +requests==2.21.0 +requests-oauthlib==1.2.0 +sh==1.12.14 +Shapely==1.5.17.post1 +simplejson==3.16.0 +six==1.9.0 +sqlparse==0.1.19 +tinycss2==0.6.1 +tox==1.9.2 +uritemplate==3.0.0 +urllib3==1.24.1 +virtualenv==12.0.7 +WeasyPrint==0.42.3 +webencodings==0.5.1 +Werkzeug==0.10.4 +wheel==0.33.1 +XlsxWriter==0.7.9 From f34cbad910911370899658e25dbe2143157e7b42 Mon Sep 17 00:00:00 2001 From: Stephen Waweru Date: Mon, 7 Feb 2022 12:40:01 +0300 Subject: [PATCH 06/41] add satellite blood bank to khis facility type mapping --- facilities/models/facility_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 7b83ebce..b351f30b 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1247,6 +1247,7 @@ def push_new_facility(self, code=None): "55d65dd6-5351-4cf4-a6d9-e05ce6d343ab": "mVrepdLAqSD", "79158397-0d87-4d0e-8694-ad680a907a79": "YQK9pleIoeB", "031293d9-fd8a-4682-a91e-a4390d57b0cf": "YQK9pleIoeB", + "4369eec8-0416-4e16-b013-e635ce46a02f": "YQK9pleIoeB", } kmhfl_dhis2_ownership_mapping = { "d45541f8-3b3d-475b-94f4-17741d468135": "aRxa6o8GqZN", @@ -3042,4 +3043,4 @@ def validate_unique_infrastructure(self): def clean(self, *args, **kwargs): self.validate_unique_infrastructure() -####### infra \ No newline at end of file +####### infra From a1afaaaba77c7c520e81cf8caa122d62e36338f9 Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 11:42:07 +0300 Subject: [PATCH 07/41] get facility keph level count --- facilities/views/facility_dashboard.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index bd30e59f..ff727e15 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -12,7 +12,7 @@ Owner, FacilityStatus, FacilityType, - Facility + Facility,KephLevel ) from ..views import QuerysetFilterMixin @@ -369,6 +369,25 @@ def get_closed_facilities_count(self, cty): else: return self.get_queryset().filter(closed=True, ward__sub_county__county=cty).count() + def get_facilities_kephlevel_count(self,county_name): + """ + Function to get facilities by keph level + """ + if county_name: + keph_level = KephLevel.objects.values("id", "name") + keph_dict = {} + for keph in keph_level: + keph_count = Facility.objects.filter(keph_level_id=keph.get("id"),ward__sub_county__county=county_name ).count() + keph_dict[keph.get("name")] = keph_count + return keph_dict + else: + keph_level = KephLevel.objects.values("id", "name") + keph_dict = {} + for keph in keph_level: + keph_count = Facility.objects.filter(keph_level_id=keph.get("id"), ).count() + keph_dict[keph.get("name")] = keph_count + return keph_dict + def get(self, *args, **kwargs): user = self.request.user county_ = user.county @@ -389,6 +408,7 @@ def get(self, *args, **kwargs): facility__in=self.get_queryset().filter( ward__sub_county__county=county_)).count() data = { + "keph_level" : self.get_facilities_kephlevel_count(county_), "total_facilities": total_facilities, "county_summary": self.get_facility_county_summary() if user.is_national else [], From 67735aad8f0b261130ba8b16670fc96ebe5863fd Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 12:39:11 +0300 Subject: [PATCH 08/41] keph level bug fixes --- facilities/views/facility_dashboard.py | 29 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index ff727e15..0f820367 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -1,4 +1,5 @@ from datetime import timedelta +from itertools import count from django.utils import timezone from django.db.models import Q @@ -373,20 +374,34 @@ def get_facilities_kephlevel_count(self,county_name): """ Function to get facilities by keph level """ + import pdb + if county_name: keph_level = KephLevel.objects.values("id", "name") - keph_dict = {} + keph_array = [] + keph_details = {} for keph in keph_level: keph_count = Facility.objects.filter(keph_level_id=keph.get("id"),ward__sub_county__county=county_name ).count() - keph_dict[keph.get("name")] = keph_count - return keph_dict + + keph_details["name"] = keph.get("name") + keph_details["count"] = keph_count + keph_array.append(keph_details) + + return keph_array + else: keph_level = KephLevel.objects.values("id", "name") - keph_dict = {} + keph_array = [] + keph_details = {} for keph in keph_level: - keph_count = Facility.objects.filter(keph_level_id=keph.get("id"), ).count() - keph_dict[keph.get("name")] = keph_count - return keph_dict + keph_count = Facility.objects.filter(keph_level_id=keph.get("id")).count() + + keph_details["name"] = keph.get("name") + keph_details["count"] = keph_count + keph_array.append(keph_details) + + return keph_array + def get(self, *args, **kwargs): user = self.request.user From c50d85a59ae6f6d820186306d52cefc71aed011f Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 12:39:44 +0300 Subject: [PATCH 09/41] code cleaup --- facilities/views/facility_dashboard.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index 0f820367..3556f004 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -374,8 +374,6 @@ def get_facilities_kephlevel_count(self,county_name): """ Function to get facilities by keph level """ - import pdb - if county_name: keph_level = KephLevel.objects.values("id", "name") keph_array = [] From c52244a48137d2a8b91d20f141934e24bec20395 Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 21:35:43 +0300 Subject: [PATCH 10/41] fix keph level bug --- facilities/views/facility_dashboard.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index 3556f004..f026a895 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -383,8 +383,7 @@ def get_facilities_kephlevel_count(self,county_name): keph_details["name"] = keph.get("name") keph_details["count"] = keph_count - keph_array.append(keph_details) - + keph_array.append({"name" : keph.get("name"), "count" : keph_count}) return keph_array else: @@ -393,10 +392,7 @@ def get_facilities_kephlevel_count(self,county_name): keph_details = {} for keph in keph_level: keph_count = Facility.objects.filter(keph_level_id=keph.get("id")).count() - - keph_details["name"] = keph.get("name") - keph_details["count"] = keph_count - keph_array.append(keph_details) + keph_array.append({"name" : keph.get("name"), "count" : keph_count}) return keph_array @@ -420,6 +416,7 @@ def get(self, *args, **kwargs): total_chus = CommunityHealthUnit.objects.filter( facility__in=self.get_queryset().filter( ward__sub_county__county=county_)).count() + print("--------------- >>>>> ",county_) data = { "keph_level" : self.get_facilities_kephlevel_count(county_), "total_facilities": total_facilities, From 505445e18e6be14ed68ae536cecbfa4ed61ec5fa Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 21:36:06 +0300 Subject: [PATCH 11/41] code cleanup --- facilities/views/facility_dashboard.py | 1 - 1 file changed, 1 deletion(-) diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index f026a895..0c7eb568 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -416,7 +416,6 @@ def get(self, *args, **kwargs): total_chus = CommunityHealthUnit.objects.filter( facility__in=self.get_queryset().filter( ward__sub_county__county=county_)).count() - print("--------------- >>>>> ",county_) data = { "keph_level" : self.get_facilities_kephlevel_count(county_), "total_facilities": total_facilities, From dca50496e62f7a4a9ea55fccc1c7e57f680daa3e Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 21:38:57 +0300 Subject: [PATCH 12/41] code cleanup --- facilities/views/facility_dashboard.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index 0c7eb568..31be1864 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -377,19 +377,14 @@ def get_facilities_kephlevel_count(self,county_name): if county_name: keph_level = KephLevel.objects.values("id", "name") keph_array = [] - keph_details = {} for keph in keph_level: keph_count = Facility.objects.filter(keph_level_id=keph.get("id"),ward__sub_county__county=county_name ).count() - - keph_details["name"] = keph.get("name") - keph_details["count"] = keph_count keph_array.append({"name" : keph.get("name"), "count" : keph_count}) return keph_array else: keph_level = KephLevel.objects.values("id", "name") keph_array = [] - keph_details = {} for keph in keph_level: keph_count = Facility.objects.filter(keph_level_id=keph.get("id")).count() keph_array.append({"name" : keph.get("name"), "count" : keph_count}) From 2b900acad752446030d232cb7705110d2746e35c Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Thu, 2 Jun 2022 22:45:19 +0300 Subject: [PATCH 13/41] bed count per county --- facilities/urls/facility_urls.py | 2 + facilities/views/__init__.py | 1 + facilities/views/static_reports_view.py | 92 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 facilities/views/static_reports_view.py diff --git a/facilities/urls/facility_urls.py b/facilities/urls/facility_urls.py index d089fec4..0618f953 100755 --- a/facilities/urls/facility_urls.py +++ b/facilities/urls/facility_urls.py @@ -284,4 +284,6 @@ url(r'^facility_depts/(?P[^/]+)/$', views.FacilityDepartmentDetailView.as_view(), name='facility_depts_detail'), + url(r'^reports/static_reports/$', + views.StaticReport.as_view(), name='static_report'), ) diff --git a/facilities/views/__init__.py b/facilities/views/__init__.py index 8ec7bc40..1f9defb9 100755 --- a/facilities/views/__init__.py +++ b/facilities/views/__init__.py @@ -3,4 +3,5 @@ from .facility_setup_views import * # noqa from .facility_special_workflow_views import * # noqa from .service_catalog_views import * # noqa +from .static_reports_view import * # from .facility_human_resource_views import * \ No newline at end of file diff --git a/facilities/views/static_reports_view.py b/facilities/views/static_reports_view.py new file mode 100644 index 00000000..d374a542 --- /dev/null +++ b/facilities/views/static_reports_view.py @@ -0,0 +1,92 @@ +from datetime import timedelta +from itertools import count + +from django.utils import timezone +from django.db.models import Q + +from rest_framework.views import APIView, Response +from common.models import County, SubCounty, Ward +from chul.models import CommunityHealthUnit + +from ..models import ( + OwnerType, + Owner, + FacilityStatus, + FacilityType, + Facility,KephLevel +) +from ..views import QuerysetFilterMixin + + +class StaticReport(QuerysetFilterMixin, APIView): + queryset = Facility.objects.all() + + def get_chu_count_in_county_summary(self, county): + return CommunityHealthUnit.objects.filter( + facility__ward__sub_county__county=county).count() + + def get_chu_count_in_constituency_summary(self, const): + return CommunityHealthUnit.objects.filter( + facility__ward__sub_county=const).count() + + def get_chu_count_in_ward_summary(self, ward): + return CommunityHealthUnit.objects.filter( + facility__ward=ward).count() + + def get_bed_count(self, location): + import pdb + if location: + + pdb.set_trace() + # for keph in keph_level: + # objects.values('Category').distinct() + facility_beds_details = Facility.objects.values("number_of_cots", "number_of_beds","number_of_hdu_beds", "number_of_icu_beds", "number_of_isolation_beds","number_of_maternity_beds","owner_id","county_id", "facility_type_id","keph_level_id", "sub_county_id","ward_id", ward__sub_county__county=location) + + return "keph_array" + else: + # pdb.set_trace() + counties = County.objects.values("id","name","code") + facility_beds_details = Facility.objects.values("number_of_cots", "number_of_beds","number_of_hdu_beds", "number_of_icu_beds", "number_of_isolation_beds","number_of_maternity_beds","owner_id","county_id", "facility_type_id","keph_level_id", "sub_county_id","ward_id") + my_array = [] + + counter = 0 + for beds_details in facility_beds_details: + for county in counties: + # print(type(county.get("id"))) + if beds_details.get("county_id") is not None and beds_details.get("county_id")==county.get("id"): + my_array.append({ + "county_name" : county.get("name"), + "count" : beds_details.get("number_of_beds") + }) + print("wwwwwwwwwwwwwwwwwwwww") + + + + return "keph_array" + + + + def get(self, *args, **kwargs): + import pdb + user = self.request.user + county_ = user.county + if not self.request.query_params.get('county'): + county_ = user.county + else: + county_ = County.objects.get(id=self.request.query_params.get('county')) + # pdb.set_trace() + print("*************** ",county_) + + data = { + "beds_by_county" : self.get_bed_count(county_), + + } + + fields = self.request.query_params.get("fields", None) + if fields: + required = fields.split(",") + required_data = { + i: data[i] for i in data if i in required + } + return Response(required_data) + return Response(data) From ecf0834abd056d479d274c8546d10ff1a1acc7f1 Mon Sep 17 00:00:00 2001 From: abdimoha-dev Date: Fri, 3 Jun 2022 11:19:27 +0300 Subject: [PATCH 14/41] fetch bed per county --- facilities/views/static_reports_view.py | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/facilities/views/static_reports_view.py b/facilities/views/static_reports_view.py index d374a542..205babea 100644 --- a/facilities/views/static_reports_view.py +++ b/facilities/views/static_reports_view.py @@ -47,36 +47,36 @@ def get_bed_count(self, location): # pdb.set_trace() counties = County.objects.values("id","name","code") facility_beds_details = Facility.objects.values("number_of_cots", "number_of_beds","number_of_hdu_beds", "number_of_icu_beds", "number_of_isolation_beds","number_of_maternity_beds","owner_id","county_id", "facility_type_id","keph_level_id", "sub_county_id","ward_id") - my_array = [] + counties_beds_array = [] - counter = 0 - for beds_details in facility_beds_details: - for county in counties: - # print(type(county.get("id"))) + cobedunter = 0 + for county in counties: + for beds_details in facility_beds_details: if beds_details.get("county_id") is not None and beds_details.get("county_id")==county.get("id"): - my_array.append({ + counties_beds_array.append({ "county_name" : county.get("name"), "count" : beds_details.get("number_of_beds") }) - print("wwwwwwwwwwwwwwwwwwwww") - - - - return "keph_array" + final_sum = {} + + for county_data in counties_beds_array: + # print("---------", county_data.get("county_name") != final_sum.get("county")) + if county_data.get("county_name") != final_sum.get("county"): + final_sum[county_data.get("county_name")] = county_data.get("count") + elif county_data.get("county_name") == final_sum.get("county"): + final_sum[county_data.get("county_name")] = county_data.get("count")+county_data.get("count") + return final_sum def get(self, *args, **kwargs): - import pdb user = self.request.user county_ = user.county if not self.request.query_params.get('county'): county_ = user.county else: county_ = County.objects.get(id=self.request.query_params.get('county')) - # pdb.set_trace() - print("*************** ",county_) - + data = { "beds_by_county" : self.get_bed_count(county_), From 05eecfc40dd15ae72887a6aad40ffc0ae211337e Mon Sep 17 00:00:00 2001 From: Cynthia Chebet Date: Mon, 6 Jun 2022 11:53:42 +0300 Subject: [PATCH 15/41] changed the format of result given --- facilities/views/static_reports_view.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/facilities/views/static_reports_view.py b/facilities/views/static_reports_view.py index 205babea..f1f386cc 100644 --- a/facilities/views/static_reports_view.py +++ b/facilities/views/static_reports_view.py @@ -57,6 +57,7 @@ def get_bed_count(self, location): "county_name" : county.get("name"), "count" : beds_details.get("number_of_beds") }) + summary=[] final_sum = {} for county_data in counties_beds_array: @@ -65,7 +66,11 @@ def get_bed_count(self, location): final_sum[county_data.get("county_name")] = county_data.get("count") elif county_data.get("county_name") == final_sum.get("county"): final_sum[county_data.get("county_name")] = county_data.get("count")+county_data.get("count") - return final_sum + + summary = [ + {"name": key, "count": value } for key, value in final_sum.items() + ] + return summary From 240aaece4ff893f994ccf296e72ebb0903f20e79 Mon Sep 17 00:00:00 2001 From: Cynthia Chebet Date: Sun, 11 Sep 2022 17:40:11 +0300 Subject: [PATCH 16/41] user creation --- users/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/users/serializers.py b/users/serializers.py index f11cec03..c32e8378 100755 --- a/users/serializers.py +++ b/users/serializers.py @@ -133,7 +133,7 @@ def create(self, validated_data): county_level = self.initial_data.pop('is_county_level', False) sub_county_level = self.initial_data.pop('is_sub_county_level', False) permissions = _lookup_permissions( - self.context['request'].DATA + self.context['request'].data ) validated_data.pop('permissions', None) From 67cc382c955db9a556179b20805d613fa9ecb1fd Mon Sep 17 00:00:00 2001 From: Benzer Date: Fri, 14 Jan 2022 09:55:37 +0300 Subject: [PATCH 17/41] Create dev_requirements.txt --- dev_requirements.txt | 95 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 dev_requirements.txt diff --git a/dev_requirements.txt b/dev_requirements.txt new file mode 100644 index 00000000..18d3b84f --- /dev/null +++ b/dev_requirements.txt @@ -0,0 +1,95 @@ +amqp==1.4.9 +ansible==1.9.6 +anyjson==0.3.3 +apache-libcloud==0.17.0 +apipkg==1.5 +backports.ssl-match-hostname==3.7.0.1 +billiard==3.3.0.23 +boto==2.38.0 +cairocffi==0.9.0 +CairoSVG==1.0.22 +celery==3.1.19 +certifi==2019.3.9 +cffi==1.12.2 +chardet==3.0.4 +commonmark==0.8.1 +coreapi==2.3.3 +coreschema==0.0.4 +coverage==3.7.1 +cssselect2==0.2.1 +defusedxml==0.5.0 +dj-database-url==0.4.0 +Django==1.11.27 +django-allauth==0.39.1 +django-braces==1.13.0 +django-cors-headers==2.1.0 +django-debug-toolbar==1.8 +django-environ==0.3.1 +django-filter==1.0.4 +django-oauth-toolkit==0.11.0 +django-redis==4.0.0 +django-rest-auth==0.9.1 +django-rest-swagger==2.1.0 +django-reversion==2.0.5 +django-storages==1.1.8 +djangorestframework==3.6.3 +djangorestframework-csv==1.3.4 +djangorestframework-gis==0.8.2 +djangorestframework-xml==1.0.1 +docutils==0.14 +drf-extensions==0.3.1 +ecdsa==0.13 +execnet==1.5.0 +Fabric==1.10.5 +filechunkio==1.6 +flake8==2.3.0 +future==0.17.1 +gunicorn==19.3.0 +html5lib==0.9999999 +idna==2.8 +itypes==1.1.0 +Jinja2==2.10 +kombu==3.0.37 +Markdown==2.5.2 +MarkupSafe==1.1.1 +mccabe==0.6.1 +mock==1.0.1 +model-mommy==1.2.6 +oauthlib==1.1.2 +openapi-codec==1.3.2 +paramiko==1.18.5 +pdfrw==0.4 +pep8==1.7.1 +psycopg2==2.7 +py==1.8.0 +pycparser==2.19 +pycrypto==2.6.1 +pyflakes==2.1.1 +Pyphen==0.9.5 +pytest==2.7.3 +pytest-django==2.8.0 +pytest-xdist==1.11 +python-coveralls==2.5.0 +python-dateutil==2.8.0 +python-openid==2.2.5 +pytz==2018.9 +PyYAML==5.1 +recommonmark==0.1.1 +redis==3.2.1 +requests==2.21.0 +requests-oauthlib==1.2.0 +sh==1.12.14 +Shapely==1.5.17.post1 +simplejson==3.16.0 +six==1.9.0 +sqlparse==0.1.19 +tinycss2==0.6.1 +tox==1.9.2 +uritemplate==3.0.0 +urllib3==1.24.1 +virtualenv==12.0.7 +WeasyPrint==0.42.3 +webencodings==0.5.1 +Werkzeug==0.10.4 +wheel==0.33.1 +XlsxWriter==0.7.9 From 3f8f6cf00c9b79674f15fa2517e5ffbaa4fa3652 Mon Sep 17 00:00:00 2001 From: Stephen Waweru Date: Mon, 7 Feb 2022 12:40:01 +0300 Subject: [PATCH 18/41] add satellite blood bank to khis facility type mapping --- facilities/models/facility_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 7b83ebce..b351f30b 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1247,6 +1247,7 @@ def push_new_facility(self, code=None): "55d65dd6-5351-4cf4-a6d9-e05ce6d343ab": "mVrepdLAqSD", "79158397-0d87-4d0e-8694-ad680a907a79": "YQK9pleIoeB", "031293d9-fd8a-4682-a91e-a4390d57b0cf": "YQK9pleIoeB", + "4369eec8-0416-4e16-b013-e635ce46a02f": "YQK9pleIoeB", } kmhfl_dhis2_ownership_mapping = { "d45541f8-3b3d-475b-94f4-17741d468135": "aRxa6o8GqZN", @@ -3042,4 +3043,4 @@ def validate_unique_infrastructure(self): def clean(self, *args, **kwargs): self.validate_unique_infrastructure() -####### infra \ No newline at end of file +####### infra From e1cc81060b9cb155dd6cd1068d1cac60fd2de26c Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 17 May 2022 10:13:04 +0300 Subject: [PATCH 19/41] Modify: requirements.txt and config/settings/base.py --- config/settings/base.py | 12 ++--- requirements.txt | 97 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/config/settings/base.py b/config/settings/base.py index 8e89fd95..4234e999 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -7,7 +7,7 @@ # Override in production via env env = environ.Env( - DATABASE_URL=(str, 'postgres://mfl:mfl@localhost:5432/mfl'), + DATABASE_URL=(str, 'postgres://mfl:mfl@localhost:5433/mfl'), DEBUG=(bool, True), FRONTEND_URL=(str, "http://localhost:8062"), REALTIME_INDEX=(bool, False), @@ -43,11 +43,11 @@ DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'HOST': ENV_DB['HOST'], - 'NAME': ENV_DB['NAME'], - 'PASSWORD': ENV_DB['PASSWORD'], - 'PORT': ENV_DB['PORT'], - 'USER': ENV_DB['USER'], + 'HOST': '127.0.0.1', + 'NAME': 'mfl', + 'PASSWORD': 'mfl@pa55w0rd', + 'PORT': '5433', + 'USER': 'mfladmin', } } # Env should have DATABASE_URL MIDDLEWARE = ( diff --git a/requirements.txt b/requirements.txt index ecf975e2..45139f2e 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,96 @@ --e . \ No newline at end of file + +amqp==1.4.9 +ansible==1.9.6 +anyjson==0.3.3 +apache-libcloud==0.17.0 +apipkg==1.5 +backports.ssl-match-hostname==3.7.0.1 +billiard==3.3.0.23 +boto==2.38.0 +cairocffi==0.9.0 +CairoSVG==1.0.22 +celery==3.1.19 +certifi==2019.3.9 +cffi==1.12.2 +chardet==3.0.4 +commonmark==0.8.1 +coreapi==2.3.3 +coreschema==0.0.4 +coverage==3.7.1 +cssselect2==0.2.1 +defusedxml==0.5.0 +dj-database-url==0.4.0 +Django==1.11.27 +django-allauth==0.39.1 +django-braces==1.13.0 +django-cors-headers==2.1.0 +django-debug-toolbar==1.8 +django-environ==0.3.1 +django-filter==1.0.4 +django-oauth-toolkit==0.11.0 +django-redis==4.0.0 +django-rest-auth==0.9.1 +django-rest-swagger==2.1.0 +django-reversion==2.0.5 +django-storages==1.1.8 +djangorestframework==3.6.3 +djangorestframework-csv==1.3.4 +djangorestframework-gis==0.8.2 +djangorestframework-xml==1.0.1 +docutils==0.14 +drf-extensions==0.3.1 +ecdsa==0.13 +execnet==1.5.0 +Fabric==1.10.5 +filechunkio==1.6 +flake8==2.3.0 +future==0.17.1 +gunicorn==19.3.0 +html5lib==0.9999999 +idna==2.8 +itypes==1.1.0 +Jinja2==2.10 +kombu==3.0.37 +Markdown==2.5.2 +MarkupSafe==1.1.1 +mccabe==0.6.1 +mock==1.0.1 +model-mommy==1.2.6 +oauthlib==1.1.2 +openapi-codec==1.3.2 +paramiko==1.18.5 +pdfrw==0.4 +pep8==1.7.1 +psycopg2==2.7 +psycopg2-binary==2.7.7 +py==1.8.0 +pycparser==2.19 +pycrypto==2.6.1 +pyflakes==2.1.1 +Pyphen==0.9.5 +pytest==2.7.3 +pytest-django==2.8.0 +pytest-xdist==1.11 +python-coveralls==2.5.0 +python-dateutil==2.8.0 +python-openid==2.2.5 +pytz==2018.9 +PyYAML==5.1 +recommonmark==0.1.1 +redis==3.2.1 +requests==2.21.0 +requests-oauthlib==1.2.0 +sh==1.12.14 +Shapely==1.5.17.post1 +simplejson==3.16.0 +six==1.9.0 +sqlparse==0.1.19 +tinycss2==0.6.1 +tox==1.9.2 +uritemplate==3.0.0 +urllib3==1.24.1 +virtualenv==12.0.7 +WeasyPrint==0.42.3 +webencodings==0.5.1 +Werkzeug==0.10.4 +XlsxWriter==0.7.9 From eef575ec4f18bb85f617cba4028bbca14f3250f0 Mon Sep 17 00:00:00 2001 From: eric Date: Sun, 11 Sep 2022 19:47:56 +0300 Subject: [PATCH 20/41] updated config/settings/base.py to match mfl_api_testing credentials --- config/settings/base.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/settings/base.py b/config/settings/base.py index 4234e999..8e89fd95 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -7,7 +7,7 @@ # Override in production via env env = environ.Env( - DATABASE_URL=(str, 'postgres://mfl:mfl@localhost:5433/mfl'), + DATABASE_URL=(str, 'postgres://mfl:mfl@localhost:5432/mfl'), DEBUG=(bool, True), FRONTEND_URL=(str, "http://localhost:8062"), REALTIME_INDEX=(bool, False), @@ -43,11 +43,11 @@ DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'HOST': '127.0.0.1', - 'NAME': 'mfl', - 'PASSWORD': 'mfl@pa55w0rd', - 'PORT': '5433', - 'USER': 'mfladmin', + 'HOST': ENV_DB['HOST'], + 'NAME': ENV_DB['NAME'], + 'PASSWORD': ENV_DB['PASSWORD'], + 'PORT': ENV_DB['PORT'], + 'USER': ENV_DB['USER'], } } # Env should have DATABASE_URL MIDDLEWARE = ( From 3141465db7d9c14c93adb3c40393a18c2cde8b75 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 13 Sep 2022 09:14:35 +0300 Subject: [PATCH 21/41] modified config/settings/base.py --- config/settings/base.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/settings/base.py b/config/settings/base.py index 8e89fd95..4234e999 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -7,7 +7,7 @@ # Override in production via env env = environ.Env( - DATABASE_URL=(str, 'postgres://mfl:mfl@localhost:5432/mfl'), + DATABASE_URL=(str, 'postgres://mfl:mfl@localhost:5433/mfl'), DEBUG=(bool, True), FRONTEND_URL=(str, "http://localhost:8062"), REALTIME_INDEX=(bool, False), @@ -43,11 +43,11 @@ DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'HOST': ENV_DB['HOST'], - 'NAME': ENV_DB['NAME'], - 'PASSWORD': ENV_DB['PASSWORD'], - 'PORT': ENV_DB['PORT'], - 'USER': ENV_DB['USER'], + 'HOST': '127.0.0.1', + 'NAME': 'mfl', + 'PASSWORD': 'mfl@pa55w0rd', + 'PORT': '5433', + 'USER': 'mfladmin', } } # Env should have DATABASE_URL MIDDLEWARE = ( From 97300c4e12b603ebda93138086e7aa082641b62d Mon Sep 17 00:00:00 2001 From: eric Date: Mon, 31 Oct 2022 12:54:28 +0300 Subject: [PATCH 22/41] added support for infrastructure and infrastructure_category fields in api/common/filtering_summaries endpoint --- chul/models.py | 4 ++-- common/views/app_views.py | 5 +++++ facilities/views/facility_dashboard.py | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/chul/models.py b/chul/models.py index a7ad1a80..d4bc2102 100755 --- a/chul/models.py +++ b/chul/models.py @@ -218,7 +218,7 @@ def clean(self): @property def pending_updates(self): try: - chu = ChuUpdateBuffer.objects.latest( + chu = ChuUpdateBuffer.objects.get( is_approved=False, is_rejected=False, health_unit=self @@ -230,7 +230,7 @@ def pending_updates(self): @property def latest_update(self): try: - chu = ChuUpdateBuffer.objects.latest( + chu = ChuUpdateBuffer.objects.get( is_approved=False, is_rejected=False, health_unit=self diff --git a/common/views/app_views.py b/common/views/app_views.py index 0b97c22d..55a072f2 100755 --- a/common/views/app_views.py +++ b/common/views/app_views.py @@ -27,6 +27,8 @@ OwnerType, Owner, Service, + Infrastructure, + InfrastructureCategory, KephLevel ) from users.models import JobTitle @@ -663,12 +665,15 @@ def get(self, request): 'admission_status': (FacilityAdmissionStatus, ('id', 'name')), 'chu_status': (chu_models.Status, ('id', 'name', )), 'service_category': (ServiceCategory, ('id', 'name')), + 'infrastructure_category': (InfrastructureCategory, ('id', 'name')), 'owner_type': (OwnerType, ('id', 'name')), 'owner': (Owner, ('id', 'name', 'owner_type')), 'service': (Service, ('id', 'name', 'category')), 'keph_level': (KephLevel, ('id', 'name')), + 'infrastructure': (Infrastructure, ('id', 'name')), 'job_title': (JobTitle, ('id', 'name')) } + if fields: resp = {} for key in fields.split(","): diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index 31be1864..f6b59c61 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -54,6 +54,7 @@ def get_facility_county_summary(self): top_10_counties_summary = [] for item in top_10_counties: county = County.objects.get(name=item[0]) + print (county, item[0]) chu_count = self.get_chu_count_in_county_summary(county) top_10_counties_summary.append( { From 7f6904873afe82ae3ee5f090b41a28c934a2b624 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 1 Nov 2022 17:08:00 +0300 Subject: [PATCH 23/41] added speciality and speciality category in the filter api --- common/views/app_views.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/views/app_views.py b/common/views/app_views.py index 55a072f2..5f016909 100755 --- a/common/views/app_views.py +++ b/common/views/app_views.py @@ -29,6 +29,8 @@ Service, Infrastructure, InfrastructureCategory, + Speciality, + SpecialityCategory, KephLevel ) from users.models import JobTitle @@ -666,11 +668,13 @@ def get(self, request): 'chu_status': (chu_models.Status, ('id', 'name', )), 'service_category': (ServiceCategory, ('id', 'name')), 'infrastructure_category': (InfrastructureCategory, ('id', 'name')), + 'speciality_category': (SpecialityCategory, ('id', 'name')), + 'speciality': (Speciality, ('id', 'name', 'category')), 'owner_type': (OwnerType, ('id', 'name')), 'owner': (Owner, ('id', 'name', 'owner_type')), 'service': (Service, ('id', 'name', 'category')), 'keph_level': (KephLevel, ('id', 'name')), - 'infrastructure': (Infrastructure, ('id', 'name')), + 'infrastructure': (Infrastructure, ('id', 'name', 'category')), 'job_title': (JobTitle, ('id', 'name')) } From 2e3d9abb8cc5539fb15f78a69bf314dd7197dee7 Mon Sep 17 00:00:00 2001 From: eric Date: Mon, 5 Dec 2022 14:44:47 +0300 Subject: [PATCH 24/41] Modified chul/views.py --- chul/models.py | 1 + chul/views.py | 93 +++++++++++++------- common/migrations/0020_auto_20221205_0904.py | 35 ++++++++ facilities/views/facility_dashboard.py | 2 +- 4 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 common/migrations/0020_auto_20221205_0904.py diff --git a/chul/models.py b/chul/models.py index d4bc2102..f9f6151c 100755 --- a/chul/models.py +++ b/chul/models.py @@ -283,6 +283,7 @@ def push_chu_to_dhis2(self): }, "openingDate": self.date_operational.strftime("%Y-%m-%d"), } + metadata_payload = { "keph": 'axUnguN4QDh' } diff --git a/chul/views.py b/chul/views.py index b2c64530..f2ba0573 100755 --- a/chul/views.py +++ b/chul/views.py @@ -40,22 +40,32 @@ class FilterCommunityUnitsMixin(object): - def get_queryset(self, *args, **kwargs): - custom_queryset = kwargs.pop('custom_queryset', None) - if hasattr(custom_queryset, 'count'): - self.queryset = custom_queryset - - if not self.request.user.has_perm( - "facilities.view_unpublished_facilities"): - self.queryset = self.queryset.filter(facility__approved=True) - - if not self.request.user.has_perm( - "chul.view_rejected_chus"): - self.queryset = self.queryset.filter(is_approved=True) - + def filter_approved_chus(self): + if self.request.user.has_perm( + "chul.view_unapproved_facilities") \ + is False and 'approved' in [ + field.name for field in + self.queryset.model._meta.get_fields()]: + + # filter both facilities and facilities materialized view + try: + self.queryset = self.queryset.filter(approved=True, operation_status__is_public_visible=True) + except: + self.queryset = self.queryset.filter(approved=True, is_public_visible=True) + + def filter_rejected_chus(self): + if self.request.user.has_perm("chul.view_rejected_chus") \ + is False and ('rejected' in [ + field.name for field in + self.queryset.model._meta.get_fields()]): + self.queryset = self.queryset.filter(rejected=False) + + def filter_for_national_users(self): if self.request.user.is_national: self.queryset = self.queryset + + def filter_for_county_users(self): if self.request.user.county: self.queryset = self.queryset.filter( facility__ward__constituency__county__in=[ @@ -63,20 +73,42 @@ def get_queryset(self, *args, **kwargs): user=self.request.user) ]) - if self.request.user.constituency: + def filter_for_sub_county_users(self): + if self.request.user.sub_county: self.queryset = self.queryset.filter( - facility__ward__constituency__in=[ - uc.constituency for uc in UserConstituency.objects.filter( + facility__ward__sub_county__in=[ + us.sub_county for us in UserSubCounty.objects.filter( user=self.request.user) ]) - if self.request.user.sub_county: + def filter_for_consituency_users(self): + if self.request.user.constituency: self.queryset = self.queryset.filter( - facility__ward__sub_county__in=[ - us.sub_county for us in UserSubCounty.objects.filter( + facility__ward__constituency__in=[ + uc.constituency for uc in UserConstituency.objects.filter( user=self.request.user) ]) + + + def get_queryset(self, *args, **kwargs): + custom_queryset = kwargs.pop('custom_queryset', None) + if hasattr(custom_queryset, 'count'): + self.queryset = custom_queryset + + self.filter_for_county_users() + self.filter_for_consituency_users() + self.filter_for_sub_county_users() + self.filter_rejected_chus() + + # if not self.request.user.has_perm( + # "facilities.view_unpublished_facilities"): + # self.queryset = self.queryset.filter(facility__approved=True) + + # if not self.request.user.has_perm( + # "chul.view_rejected_chus"): + # self.queryset = self.queryset.filter(is_approved=True) + return self.queryset def filter_queryset(self, queryset): @@ -84,17 +116,18 @@ def filter_queryset(self, queryset): Overridden in order to constrain search results to what a user should see. """ - if 'search' in self.request.query_params: - search_term = self.request.query_params.get('search') - if search_term.isdigit(): - queryset = self.queryset.filter(code=search_term) - else: - queryset = super( - FilterCommunityUnitsMixin, self).filter_queryset(queryset) - else: - queryset = super( - FilterCommunityUnitsMixin, self).filter_queryset(queryset) - + # if 'search' in self.request.query_params: + # search_term = self.request.query_params.get('search') + # if search_term.isdigit(): + # queryset = self.queryset.filter(code=search_term) + # else: + # queryset = super( + # FilterCommunityUnitsMixin, self).filter_queryset(queryset) + # else: + # queryset = super( + # FilterCommunityUnitsMixin, self).filter_queryset(queryset) + + queryset = super(FilterCommunityUnitsMixin, self).filter_queryset(queryset) return self.get_queryset(custom_queryset=queryset) diff --git a/common/migrations/0020_auto_20221205_0904.py b/common/migrations/0020_auto_20221205_0904.py new file mode 100644 index 00000000..5c5728ff --- /dev/null +++ b/common/migrations/0020_auto_20221205_0904.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2022-12-05 09:04 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0019_auto_20191021_1227'), + ] + + operations = [ + migrations.AlterField( + model_name='apiauthentication', + name='client_secret', + field=models.CharField(default=b'', max_length=255), + ), + migrations.AlterField( + model_name='apiauthentication', + name='password', + field=models.CharField(default=b'', max_length=255), + ), + migrations.AlterField( + model_name='apiauthentication', + name='server', + field=models.CharField(default=b'http://testhis.uonbi.ac.ke/', max_length=255), + ), + migrations.AlterField( + model_name='apiauthentication', + name='username', + field=models.CharField(default=b'kmhfl_integration', max_length=255), + ), + ] diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index f6b59c61..9501ae30 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -54,7 +54,6 @@ def get_facility_county_summary(self): top_10_counties_summary = [] for item in top_10_counties: county = County.objects.get(name=item[0]) - print (county, item[0]) chu_count = self.get_chu_count_in_county_summary(county) top_10_counties_summary.append( { @@ -83,6 +82,7 @@ def get_facility_constituency_summary(self): const = SubCounty.objects.get(name=item[0]) chu_count = self.get_chu_count_in_constituency_summary(const) top_10_consts_summary.append( + { "name": item[0], "count": item[1], From 3b64f13db3bed3dfb06f29dc7581dac17594f320 Mon Sep 17 00:00:00 2001 From: eric Date: Fri, 9 Dec 2022 15:55:57 +0300 Subject: [PATCH 25/41] working in progress:line 236: facilities/views/facility_views.py --- facilities/views/facility_views.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/facilities/views/facility_views.py b/facilities/views/facility_views.py index 74e8ecfd..c6c8cab1 100755 --- a/facilities/views/facility_views.py +++ b/facilities/views/facility_views.py @@ -217,6 +217,22 @@ def filter_for_regulators(self): self.queryset = self.queryset.filter( regulatory_body=self.request.user.regulator) + def filter_for_infrastructure(self): + if self.request.user.has_perm("facilities.view_infrastructure") \ + is False and ('infrastructure' in [ + field.name for field in + self.queryset.model._meta.get_fields()]): + self.queryset = self.queryset.filter(infrastructure=self.request.infrastructure) + + + def filter_for_services(self): + if self.request.user.has_perm("facilities.view_facilityservice") \ + is False and ('service' in [ + field.name for field in + self.queryset.model._meta.get_fields()]): + self.queryset = self.queryset.filter(service=self.request.service) + + def get_queryset(self, *args, **kwargs): custom_queryset = kwargs.pop('custom_queryset', None) if hasattr(custom_queryset, 'count'): @@ -231,6 +247,8 @@ def get_queryset(self, *args, **kwargs): self.filter_rejected_facilities() self.filter_closed_facilities() self.filter_approved_facilities() + self.filter_for_infrastructure() + self.filter_for_services() return self.queryset From f4ebf418819c1db32e2d0af0a5003ac43b75d2b2 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 14 Dec 2022 12:57:11 +0300 Subject: [PATCH 26/41] modified chus to accept basic_details update and facility_serializers.py --- chul/models.py | 29 ++++++++++--------- config/settings/base.py | 5 ++-- .../serializers/facility_serializers.py | 4 ++- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/chul/models.py b/chul/models.py index f9f6151c..b57429c7 100755 --- a/chul/models.py +++ b/chul/models.py @@ -485,19 +485,22 @@ def validate_atleast_one_attribute_updated(self): raise ValidationError({"__all__": ["Nothing was edited"]}) def update_basic_details(self): - basic_details = json.loads(self.basic) - if 'status' in basic_details: - basic_details['status_id'] = basic_details.get( - 'status').get('status_id') - basic_details.pop('status') - if 'facility' in basic_details: - basic_details['facility_id'] = basic_details.get( - 'facility').get('facility_id') - basic_details.pop('facility') - - for key, value in basic_details.iteritems(): - setattr(self.health_unit, key, value) - self.health_unit.save() + if self.basic: + basic_details = json.loads(self.basic) + if 'status' in basic_details: + basic_details['status_id'] = basic_details.get( + 'status').get('status_id') + basic_details.pop('status') + if 'facility' in basic_details: + basic_details['facility_id'] = basic_details.get( + 'facility').get('facility_id') + basic_details.pop('facility') + + for key, value in basic_details.iteritems(): + setattr(self.health_unit, key, value) + if 'facility' in basic_details.get('basic'): + setattr(self.health_unit, 'facility_id', basic_details.get('basic').get('facility')) + self.health_unit.save() def update_workers(self): chews = json.loads(self.workers) diff --git a/config/settings/base.py b/config/settings/base.py index 4234e999..e43e6b67 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -23,13 +23,14 @@ ADMINS=(str, "admin:admin@example.com,"), SERVER_EMAIL=(str, "root@localhost"), ALLOWED_HOSTS=(str, "localhost"), - DHIS_ENDPOINT=(str, "http://testhis.uonbi.ac.ke/"), + DHIS_ENDPOINT=(str, "https://test.hiskenya.org/"), DHIS_USERNAME=(str, 'kmhfl_integration'), DHIS_PASSWORD=(str, ''), DHIS_CLIENT_ID=(str, '102'), + PUSH_TO_DHIS=(bool, True), DHIS_CLIENT_SECRET=(str, '') ) -env.read_env(os.path.join(BASE_DIR, '.env')) +# env.read_env(os.path.join(BASE_DIR, '.env')) ADMINS = tuple( tuple(name.split(':')) for name in env('ADMINS').split(',') if name != '' diff --git a/facilities/serializers/facility_serializers.py b/facilities/serializers/facility_serializers.py index ce49ca45..f4670288 100755 --- a/facilities/serializers/facility_serializers.py +++ b/facilities/serializers/facility_serializers.py @@ -689,7 +689,9 @@ class FacilityDetailSerializer(FacilitySerializer): ward_code = serializers.ReadOnlyField(source='ward.code') service_catalogue_active = serializers.ReadOnlyField() facility_units = FacilityUnitSerializer(many=True, required=False) - facility_infrastructure = FacilityInfrastructureSerializer(many=True, required=False) + # facility_infrastructure = FacilityInfrastructureSerializer(many=True, required=False) + facility_infrastructure = serializers.ReadOnlyField( + source="get_facility_infrastructure") officer_in_charge = serializers.ReadOnlyField() keph_level_name = serializers.ReadOnlyField(source='keph_level.name') From f6417122464ff1e6efa1983397d42d4506d33119 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 28 Dec 2022 17:59:37 +0300 Subject: [PATCH 27/41] modified facility_models.py by updating facility_infrastructure and facility_humanresources properties of class Facility --- config/settings/base.py | 4 +- facilities/models/facility_models.py | 60 +++++++++++-------- .../serializers/facility_serializers.py | 16 +++-- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/config/settings/base.py b/config/settings/base.py index e43e6b67..6a6b43e6 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -25,10 +25,10 @@ ALLOWED_HOSTS=(str, "localhost"), DHIS_ENDPOINT=(str, "https://test.hiskenya.org/"), DHIS_USERNAME=(str, 'kmhfl_integration'), - DHIS_PASSWORD=(str, ''), + DHIS_PASSWORD=(str, 'Integration@kmhfl@2019'), DHIS_CLIENT_ID=(str, '102'), PUSH_TO_DHIS=(bool, True), - DHIS_CLIENT_SECRET=(str, '') + DHIS_CLIENT_SECRET=(str, '4e9a05722-62f4-3e03-287c-74f5ad1aa5f') ) # env.read_env(os.path.join(BASE_DIR, '.env')) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index b351f30b..6a2990fc 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1535,6 +1535,7 @@ def latest_approval_or_rejection(self): def get_facility_services(self): """Digests the facility_services for the sake of frontend.""" services = self.facility_services.all() + return [ { "id": service.id, @@ -1557,7 +1558,9 @@ def get_facility_services(self): @property def get_facility_contacts(self): """For the same purpose as the get_facility_services above""" + contacts = self.facility_contacts.all() + return [ { "id": contact.id, @@ -1572,14 +1575,14 @@ def get_facility_contacts(self): def get_facility_infrastructure(self): """For the same purpose as the get_facility_contacts above""" infra = self.facility_infrastructure.all() + return [ { "id": inf.id, - "infrastructure_id": inf.id, - "name": inf.name, - "infrastructure_name": inf.name, - "infrastructure_category": inf.category.id, - "infrastructure_category_name": str(inf.category.name), + "name": inf.infrastructure.name, + "count":inf.count, + "infrastructure_category": inf.infrastructure.category.id, + "infrastructure_category_name": str(inf.infrastructure.category.name), } for inf in infra ] @@ -1587,35 +1590,40 @@ def get_facility_infrastructure(self): @property def get_facility_specialities(self): """For the same purpose as the get_facility_infra... above""" - hr = self.facility_specialities.all() - return [ - { - "id": h_r.id, - "speciality_id": h_r.id, - "name": h_r.name, - "speciality_name": h_r.name, - "speciality_category": h_r.category.id, - "speciality_category_name": str(h_r.category.name), - } - for h_r in hr - ] + hr = self.facility_specialists.all() - @property - def get_facility_humanresources(self): - """For the same purpose as the get_facility_infra... above""" - hr = self.facility_humanresources.all() return [ { "id": h_r.id, - "speciality_id": h_r.id, - "name": h_r.name, - "speciality_name": h_r.name, - "speciality_category": h_r.category.id, - "speciality_category_name": str(h_r.category.name), + "name": h_r.speciality.name, + "count": h_r.count, + "speciality_category": h_r.speciality.category.id, + "speciality_category_name": str(h_r.speciality.category.name), } for h_r in hr ] + # @property + # def get_facility_humanresources(self): + # """For the same purpose as the get_facility_infra... above""" + + # import pdb + # pdb.set_trace() + + # hr = self.facility_humanresources.all() + + + # return [ + # { + # "id": h_r.id, + # "name": h_r.speciality.name, + # "count": h_r.count, + # "hr_category": h_r.speciality.category.id, + # "hr_category_name": str(h_r.speciality.category.name), + # } + # for h_r in hr + # ] + @property def average_rating(self): avg_service_rating = [ diff --git a/facilities/serializers/facility_serializers.py b/facilities/serializers/facility_serializers.py index f4670288..e505ed80 100755 --- a/facilities/serializers/facility_serializers.py +++ b/facilities/serializers/facility_serializers.py @@ -464,9 +464,9 @@ class FacilitySerializer( source="get_facility_services") facility_infrastructure = serializers.ReadOnlyField( source="get_facility_infrastructure") + facility_contacts = serializers.ReadOnlyField( + source="get_facility_contacts") facility_humanresources = serializers.ReadOnlyField( - source="get_facility_humanresources") - facility_specialities = serializers.ReadOnlyField( source="get_facility_specialities") is_approved = serializers.ReadOnlyField() has_edits = serializers.ReadOnlyField() @@ -685,15 +685,19 @@ class FacilityDetailSerializer(FacilitySerializer): constituency_code = serializers.ReadOnlyField( source='ward.constituency.code' ) + facility_specialists = FacilitySpecialistSerializer(many=True, required=False) + # specialists = serializers.ReadOnlyField( + # source="get_facility_specialities") + ward_code = serializers.ReadOnlyField(source='ward.code') service_catalogue_active = serializers.ReadOnlyField() facility_units = FacilityUnitSerializer(many=True, required=False) - # facility_infrastructure = FacilityInfrastructureSerializer(many=True, required=False) - facility_infrastructure = serializers.ReadOnlyField( - source="get_facility_infrastructure") + facility_infrastructure = FacilityInfrastructureSerializer(many=True, required=False) + # infrastructure = serializers.ReadOnlyField( + # source="get_facility_infrastructure") officer_in_charge = serializers.ReadOnlyField() - keph_level_name = serializers.ReadOnlyField(source='keph_level.name') + keph_level_name = serializers.ReadOnlyField(source='keph_level.name') class Meta(object): model = Facility From be2d06519365de369932f67163302aedf11fc400 Mon Sep 17 00:00:00 2001 From: eric Date: Fri, 30 Dec 2022 18:22:59 +0300 Subject: [PATCH 28/41] updated config/settings/base.py --- config/settings/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/settings/base.py b/config/settings/base.py index 6a6b43e6..6bf8ca51 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -12,7 +12,7 @@ FRONTEND_URL=(str, "http://localhost:8062"), REALTIME_INDEX=(bool, False), HTTPS_ENABLED=(bool, False), - SECRET_KEY=(str, 'p!ci1&ni8u98vvd#%18yp)aqh+m_8o565g*@!8@1wb$j#pj4d8'), + SECRET_KEY=(str, ''), EMAIL_HOST=(str, 'localhost'), EMAIL_HOST_USER=(str, 487), EMAIL_HOST_PASSWORD=(str, 'notarealpassword'), @@ -25,10 +25,10 @@ ALLOWED_HOSTS=(str, "localhost"), DHIS_ENDPOINT=(str, "https://test.hiskenya.org/"), DHIS_USERNAME=(str, 'kmhfl_integration'), - DHIS_PASSWORD=(str, 'Integration@kmhfl@2019'), + DHIS_PASSWORD=(str, ''), DHIS_CLIENT_ID=(str, '102'), PUSH_TO_DHIS=(bool, True), - DHIS_CLIENT_SECRET=(str, '4e9a05722-62f4-3e03-287c-74f5ad1aa5f') + DHIS_CLIENT_SECRET=(str, '') ) # env.read_env(os.path.join(BASE_DIR, '.env')) From 212b8990d7f51ce042312f120d927e0fdf6cc969 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 3 Jan 2023 19:35:48 +0300 Subject: [PATCH 29/41] modified facility_reports.py to support report_type filter by beds_and_cots_by_owner and beds_and_cots_by_keph_level --- config/settings/base.py | 2 +- facilities/filters/facility_filters.py | 2 +- reporting/facility_reports.py | 30 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/config/settings/base.py b/config/settings/base.py index 6bf8ca51..e43e6b67 100755 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -12,7 +12,7 @@ FRONTEND_URL=(str, "http://localhost:8062"), REALTIME_INDEX=(bool, False), HTTPS_ENABLED=(bool, False), - SECRET_KEY=(str, ''), + SECRET_KEY=(str, 'p!ci1&ni8u98vvd#%18yp)aqh+m_8o565g*@!8@1wb$j#pj4d8'), EMAIL_HOST=(str, 'localhost'), EMAIL_HOST_USER=(str, 487), EMAIL_HOST_PASSWORD=(str, 'notarealpassword'), diff --git a/facilities/filters/facility_filters.py b/facilities/filters/facility_filters.py index 3ffbcd74..9d5cba3b 100755 --- a/facilities/filters/facility_filters.py +++ b/facilities/filters/facility_filters.py @@ -424,7 +424,7 @@ def filter_number_beds(self, qs, name, value): return qs.filter(number_of_beds__gte=1) def filter_number_cots(self, qs, name, value): - return self.filter(number_of_cots__gte=1) + return qs.filter(number_of_cots__gte=1) id = ListCharFilter(lookup_expr='icontains') name = django_filters.CharFilter(lookup_expr='icontains') diff --git a/reporting/facility_reports.py b/reporting/facility_reports.py index c2302239..c9b8b496 100755 --- a/reporting/facility_reports.py +++ b/reporting/facility_reports.py @@ -150,6 +150,36 @@ def get_report_data(self, *args, **kwargs): filters=filters ) + if report_type == "beds_and_cots_by_keph_level": + keph_level_id = self.request.query_params.get( + "keph_level", None + ) + filters = ( + {} if keph_level_id is None + else {"keph_level": keph_level_id} + ) + + return self._get_beds_and_cots( + vals={'keph_level__name': 'keph_level_name', 'keph_level_id': "keph_level"}, + filters=filters + ) + + if report_type == "beds_and_cots_by_owner": + keph_level_id = self.request.query_params.get( + "owner", None + ) + filters = ( + {} if keph_level_id is None + else {"owner": keph_level_id} + ) + + return self._get_beds_and_cots( + vals={'owner__name': 'owner_name', 'owner_id': "owner"}, + filters=filters + ) + + + more_filters_params = self.request.query_params.get("filters", None) report_config = REPORTS.get(report_type, None) From cf85fedbc2ed7343634f6c2ed0199b415bf0089d Mon Sep 17 00:00:00 2001 From: eric Date: Mon, 16 Jan 2023 14:34:32 +0300 Subject: [PATCH 30/41] Fixed service_filter and added hr_filter, infrastructure_filter functions in facility_filters.py --- facilities/filters/facility_filters.py | 45 +++++++++++++-- facilities/models/facility_models.py | 5 +- reporting/facility_reports.py | 77 +++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 9 deletions(-) diff --git a/facilities/filters/facility_filters.py b/facilities/filters/facility_filters.py index 9d5cba3b..2e339d8d 100755 --- a/facilities/filters/facility_filters.py +++ b/facilities/filters/facility_filters.py @@ -352,19 +352,48 @@ class Meta(CommonFieldsFilterset.Meta): class FacilityFilter(CommonFieldsFilterset): def service_filter(self, qs, name, value): - categories = value.split(',') + services = value.split(',') facility_ids = [] - for facility in self.filter(): - for cat in categories: + for facility in qs.filter(): + for _service in services: service_count = FacilityService.objects.filter( - service__category=cat, + service=_service, facility=facility).count() if service_count > 0: facility_ids.append(facility.id) return qs.filter(id__in=list(set(facility_ids))) + def infrastructure_filter(self, qs, name, value): + infrastructure = value.split(',') + facility_ids = [] + + for facility in qs.filter(): + for _infra in infrastructure: + infrastructure_count = FacilityInfrastructure.objects.filter( + infrastructure=_infra, + facility=facility).count() + if infrastructure_count > 0: + facility_ids.append(facility.id) + + return qs.filter(id__in=list(set(facility_ids))) + + + def hr_filter(self, qs, name, value): + specialities = value.split(',') + facility_ids = [] + + for facility in qs.filter(): + for _speciality in specialities: + speciality_count = FacilitySpecialist.objects.filter( + speciality=_speciality, + facility=facility).count() + if speciality_count > 0: + facility_ids.append(facility.id) + + return qs.filter(id__in=list(set(facility_ids))) + def filter_approved_facilities(self, qs, name, value): if value in TRUTH_NESS: @@ -474,8 +503,12 @@ def filter_number_cots(self, qs, name, value): coerce=strtobool) is_approved = django_filters.CharFilter( method='filter_approved_facilities') - service_category = django_filters.CharFilter( - method=service_filter) + service = django_filters.CharFilter( + method='service_filter') + infrastructure = django_filters.CharFilter( + method='infrastructure_filter') + speciality = django_filters.CharFilter( + method='hr_filter') has_edits = django_filters.TypedChoiceFilter( choices=BOOLEAN_CHOICES, coerce=strtobool) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 6a2990fc..06e24b69 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -2624,7 +2624,7 @@ class FacilityService(AbstractBase): 'CHRIO') # For services that do not have options, the service will be linked # directly to the - service = models.ForeignKey(Service, on_delete=models.PROTECT,) + service = models.ForeignKey(Service, related_name='service_id', on_delete=models.PROTECT) @property def service_has_options(self): @@ -3018,7 +3018,8 @@ class FacilityInfrastructure(AbstractBase): on_delete=models.PROTECT) infrastructure = models.ForeignKey( - Infrastructure, + Infrastructure, + related_name='infrastructure', on_delete=models.PROTECT,) count = models.IntegerField( diff --git a/reporting/facility_reports.py b/reporting/facility_reports.py index c9b8b496..1c9e8b5f 100755 --- a/reporting/facility_reports.py +++ b/reporting/facility_reports.py @@ -96,6 +96,9 @@ def get_report_data(self, *args, **kwargs): if report_type == "facility_keph_level_report": return self._get_facility_count(keph=True) + if report_type == 'bed_type_by_count': + return self._get_bed_type_by_count() + if report_type == "facility_constituency_report": return self._get_facility_constituency_data() @@ -163,6 +166,22 @@ def get_report_data(self, *args, **kwargs): vals={'keph_level__name': 'keph_level_name', 'keph_level_id': "keph_level"}, filters=filters ) + + # filter by type of bed; icu, hdu, martenity and inpatient + + if report_type == "beds_and_cots_by_bed_type": + icu_beds_id = self.request.query_params.get( + "number_of_icu_beds", None + ) + filters = ( + {} if icu_beds_id is None + else {"number_of_icu_beds": icu_beds_id} + ) + + return self._get_beds_and_cots( + vals={'number_of_icu_beds': 'number_of_icu_beds', 'number_of_icu_beds_id': 'number_of_icu_beds'}, + filters=filters + ) if report_type == "beds_and_cots_by_owner": keph_level_id = self.request.query_params.get( @@ -626,7 +645,6 @@ def _get_facility_count_by_facility_type(self): data.append(data_dict) return data, [] - def _get_facility_count_by_facility_type_details(self): county = self.request.query_params.get('county', None) sub_county = self.request.query_params.get('sub_county', None) @@ -682,6 +700,63 @@ def _get_facility_count_by_facility_type_details(self): data.append(data_dict) return data, [] + def _get_bed_type_by_count(self): + data = [] + county = self.request.query_params.get('county', None) + sub_county = self.request.query_params.get('sub_county', None) + ward = self.request.query_params.get('ward', None) + + + vals = [] + vals.append(county) if county else None + vals.append(sub_county) if sub_county else None + vals.append(ward) if ward else None + + for val in vals: + try: + for c in val.split(','): + uuid.UUID(c) + except: + raise ValidationError( + { + "Administrative area": [ + "The area id provided is" + " in the wrong format" + ] + } + ) + + admin_area_filter = {} + if county: + admin_area_filter = { + "ward__sub_county__county_id__in": county.split(',') + } + if sub_county: + admin_area_filter = { + "ward__sub_county_id__in": sub_county.split(',') + } + if ward: + admin_area_filter = { + "ward_id__in": ward.split(',') + } + data = [] + for facility in Facility.objects.filter( + **admin_area_filter).filter( + Q(number_of_icu_beds__gt=0) & Q(number_of_hdu_beds__gt=0)): + record = { + "facility_id": str(facility.id), + "facility_name": facility.name, + "facility_code": facility.code, + "number_of_icu_beds": facility.number_of_icu_beds, + "number_of_hdu_beds": facility.number_of_hdu_beds + } + data.append(record) + + return data, [] + + + + class ReportView(FilterReportMixin, APIView): From f461900692408fa824e8f64693d884af3bf88336 Mon Sep 17 00:00:00 2001 From: eric Date: Mon, 16 Jan 2023 14:45:03 +0300 Subject: [PATCH 31/41] Fixed service_filter and added hr_filter, infrastructure_filter functions in facility_filters.py --- facilities/models/facility_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 06e24b69..0e82401d 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -2899,7 +2899,7 @@ class FacilitySpecialist(AbstractBase): Facility, related_name='facility_specialists', on_delete=models.PROTECT) - speciality = models.ForeignKey(Speciality, on_delete=models.PROTECT,) + speciality = models.ForeignKey(Speciality, related_name='speciality', on_delete=models.PROTECT,) count = models.IntegerField( default=0, From e6cd08edc119d63ab0ef1f5bc82d0be0e419e714 Mon Sep 17 00:00:00 2001 From: eric Date: Mon, 16 Jan 2023 15:03:28 +0300 Subject: [PATCH 32/41] Restored reporting/facility_reports.py --- reporting/facility_reports.py | 77 +---------------------------------- 1 file changed, 1 insertion(+), 76 deletions(-) diff --git a/reporting/facility_reports.py b/reporting/facility_reports.py index 1c9e8b5f..c9b8b496 100755 --- a/reporting/facility_reports.py +++ b/reporting/facility_reports.py @@ -96,9 +96,6 @@ def get_report_data(self, *args, **kwargs): if report_type == "facility_keph_level_report": return self._get_facility_count(keph=True) - if report_type == 'bed_type_by_count': - return self._get_bed_type_by_count() - if report_type == "facility_constituency_report": return self._get_facility_constituency_data() @@ -166,22 +163,6 @@ def get_report_data(self, *args, **kwargs): vals={'keph_level__name': 'keph_level_name', 'keph_level_id': "keph_level"}, filters=filters ) - - # filter by type of bed; icu, hdu, martenity and inpatient - - if report_type == "beds_and_cots_by_bed_type": - icu_beds_id = self.request.query_params.get( - "number_of_icu_beds", None - ) - filters = ( - {} if icu_beds_id is None - else {"number_of_icu_beds": icu_beds_id} - ) - - return self._get_beds_and_cots( - vals={'number_of_icu_beds': 'number_of_icu_beds', 'number_of_icu_beds_id': 'number_of_icu_beds'}, - filters=filters - ) if report_type == "beds_and_cots_by_owner": keph_level_id = self.request.query_params.get( @@ -645,6 +626,7 @@ def _get_facility_count_by_facility_type(self): data.append(data_dict) return data, [] + def _get_facility_count_by_facility_type_details(self): county = self.request.query_params.get('county', None) sub_county = self.request.query_params.get('sub_county', None) @@ -700,63 +682,6 @@ def _get_facility_count_by_facility_type_details(self): data.append(data_dict) return data, [] - def _get_bed_type_by_count(self): - data = [] - county = self.request.query_params.get('county', None) - sub_county = self.request.query_params.get('sub_county', None) - ward = self.request.query_params.get('ward', None) - - - vals = [] - vals.append(county) if county else None - vals.append(sub_county) if sub_county else None - vals.append(ward) if ward else None - - for val in vals: - try: - for c in val.split(','): - uuid.UUID(c) - except: - raise ValidationError( - { - "Administrative area": [ - "The area id provided is" - " in the wrong format" - ] - } - ) - - admin_area_filter = {} - if county: - admin_area_filter = { - "ward__sub_county__county_id__in": county.split(',') - } - if sub_county: - admin_area_filter = { - "ward__sub_county_id__in": sub_county.split(',') - } - if ward: - admin_area_filter = { - "ward_id__in": ward.split(',') - } - data = [] - for facility in Facility.objects.filter( - **admin_area_filter).filter( - Q(number_of_icu_beds__gt=0) & Q(number_of_hdu_beds__gt=0)): - record = { - "facility_id": str(facility.id), - "facility_name": facility.name, - "facility_code": facility.code, - "number_of_icu_beds": facility.number_of_icu_beds, - "number_of_hdu_beds": facility.number_of_hdu_beds - } - data.append(record) - - return data, [] - - - - class ReportView(FilterReportMixin, APIView): From 1882cb6725c5777159ac9a15e891d81528ff7a61 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 25 Jan 2023 13:01:11 +0300 Subject: [PATCH 33/41] Fixed a bug in update_facility function of facility_models.py --- facilities/models/facility_models.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 0e82401d..3646ba38 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1223,7 +1223,7 @@ def push_new_facility(self, code=None): dhis2_org_unit_id = self.dhis2_api_auth.get_org_unit_id(self.code) kmhfl_dhis2_facility_type_mapping = { "20b86171-0c16-47e1-9277-5e773d485c33": "YQK9pleIoeB", - "5eb392ac-d10a-40c9-b525-53dac866ef6c": "lTrpyOiOcM6", + "5eb392ac-d10a-40c9-b525-53dac866ef6c": "lTrpyOiOcM6", # Replace with 8949eeb0-40b1-43d4-a38d-5d4933dc209f "ccc1600e-9a24-499f-889f-bd9f0bdc4b95": "YQK9pleIoeB", "d8d741b1-21c5-45c8-86d0-a2094bf9bda6": "YQK9pleIoeB", "869118aa-0e97-4f47-b6b7-1f295d109c8f": "YQK9pleIoeB", @@ -2067,7 +2067,8 @@ def update_facility(self): new_date = datetime.date(year=value.year, month=value.month, day=value.day) value = new_date elif field_name == 'sub_county_id': - value = SubCounty.objects.get(name=field_changed.get('display_value')).id + import string + value = SubCounty.objects.get(name=string.capwords(field_changed.get('display_value'), ' ')).id else: value = field_changed.get("actual_value") From 0158a0a06aa75e327890219aa11463b1d79fbecd Mon Sep 17 00:00:00 2001 From: eric Date: Sat, 4 Feb 2023 21:34:31 +0300 Subject: [PATCH 34/41] updated kmhfl_dhis2_ownership_mapping in facilities/models/facility_models.py --- chul/models.py | 3 ++- facilities/models/facility_models.py | 28 +++++----------------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/chul/models.py b/chul/models.py index b57429c7..5e0ef2d5 100755 --- a/chul/models.py +++ b/chul/models.py @@ -496,9 +496,10 @@ def update_basic_details(self): 'facility').get('facility_id') basic_details.pop('facility') + for key, value in basic_details.iteritems(): setattr(self.health_unit, key, value) - if 'facility' in basic_details.get('basic'): + if 'basic' in basic_details: setattr(self.health_unit, 'facility_id', basic_details.get('basic').get('facility')) self.health_unit.save() diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 3646ba38..e0cd528f 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1270,6 +1270,9 @@ def push_new_facility(self, code=None): "93c0fe24-3f12-4be2-b5ff-027e0bd02274": "AaAF5EmS1fk", "c3bab995-0c29-433c-b39c-6b86d6084f5f": "AaAF5EmS1fk", "6cb92834-107c-404a-91fa-cf60b1eb5333": "aRxa6o8GqZN", + "2e651780-2ed4-4f8c-9061-6e5acf95d581": "AaAF5EmS1fk", + "30af7e3f-cd52-4ca0-b5dc-d8b1040a9808": "AaAF5EmS1fk", + "d64bbd8a-4013-463b-a238-c346cee66a92": "AaAF5EmS1fk", } kmhfl_dhis2_keph_mapping = { "ed23da85-4c92-45af-80fa-9b2123769f49": "FpY8vg4gh46", @@ -1603,26 +1606,6 @@ def get_facility_specialities(self): for h_r in hr ] - # @property - # def get_facility_humanresources(self): - # """For the same purpose as the get_facility_infra... above""" - - # import pdb - # pdb.set_trace() - - # hr = self.facility_humanresources.all() - - - # return [ - # { - # "id": h_r.id, - # "name": h_r.speciality.name, - # "count": h_r.count, - # "hr_category": h_r.speciality.category.id, - # "hr_category_name": str(h_r.speciality.category.name), - # } - # for h_r in hr - # ] @property def average_rating(self): @@ -2067,8 +2050,7 @@ def update_facility(self): new_date = datetime.date(year=value.year, month=value.month, day=value.day) value = new_date elif field_name == 'sub_county_id': - import string - value = SubCounty.objects.get(name=string.capwords(field_changed.get('display_value'), ' ')).id + value = SubCounty.objects.get(id=field_changed.get('actual_value')).id else: value = field_changed.get("actual_value") @@ -3021,7 +3003,7 @@ class FacilityInfrastructure(AbstractBase): infrastructure = models.ForeignKey( Infrastructure, related_name='infrastructure', - on_delete=models.PROTECT,) + on_delete=models.PROTECT,) count = models.IntegerField( default=0, From 9f5a8a7ce0f33b6edb9505c07d12d31acd0500a5 Mon Sep 17 00:00:00 2001 From: eric Date: Sat, 4 Feb 2023 21:36:29 +0300 Subject: [PATCH 35/41] updated kmhfl_dhis2_ownership_mapping in facilities/models/facility_models.py --- after_disaster_scripts.py | 15 +++++++-------- common/static/js/ace_editor/snippets/python.js | 2 +- data/management/commands/data_reports.py | 4 ++-- data/management/commands/port_data.py | 8 ++++---- facilities/views/static_reports_view.py | 6 +++--- load_all_facilities.py | 18 +++++++++--------- scripts.py | 10 +++++----- 7 files changed, 31 insertions(+), 32 deletions(-) diff --git a/after_disaster_scripts.py b/after_disaster_scripts.py index 814e974b..f47a366e 100755 --- a/after_disaster_scripts.py +++ b/after_disaster_scripts.py @@ -78,14 +78,13 @@ def load_wards_and_sub_counties_json_file(): try: county_obj = County.objects.get(name__contains=county_name) except: - import pdb - pdb.set_trace() + try: constituency_obj = Constituency.objects.get( name=constituency_name, county=county_obj) except: - import pdb - pdb.set_trace() + + try: sub = SubCounty.objects.get( name=sub_county_name.lower(), county=county_obj) @@ -105,8 +104,8 @@ def load_wards_and_sub_counties_json_file(): county_name, constituency_name, sub_county_name, ward_name) except: - import pdb - pdb.set_trace() + + def delete_unwanted_facilities(): @@ -126,8 +125,8 @@ def delete_unwanted_facilities(): for fc in FacilityContact.everything.filter(facility=facility): for con in Contact.objects.filter(contact=fc.contact): con.delete() - import pdb - pdb.set_trace() + + fc.delete() for unit in FacilityUnit.objects.filter(facility=facility): diff --git a/common/static/js/ace_editor/snippets/python.js b/common/static/js/ace_editor/snippets/python.js index ee023b2b..c8cfb76c 100755 --- a/common/static/js/ace_editor/snippets/python.js +++ b/common/static/js/ace_editor/snippets/python.js @@ -1 +1 @@ -ace.define("ace/snippets/python",["require","exports","module"],function(e,t,n){"use strict";t.snippetText='snippet #!\n #!/usr/bin/env python\nsnippet imp\n import ${1:module}\nsnippet from\n from ${1:package} import ${2:module}\n# Module Docstring\nsnippet docs\n \'\'\'\n File: ${1:FILENAME:file_name}\n Author: ${2:author}\n Description: ${3}\n \'\'\'\nsnippet wh\n while ${1:condition}:\n ${2:# TODO: write code...}\n# dowh - does the same as do...while in other languages\nsnippet dowh\n while True:\n ${1:# TODO: write code...}\n if ${2:condition}:\n break\nsnippet with\n with ${1:expr} as ${2:var}:\n ${3:# TODO: write code...}\n# New Class\nsnippet cl\n class ${1:ClassName}(${2:object}):\n """${3:docstring for $1}"""\n def __init__(self, ${4:arg}):\n ${5:super($1, self).__init__()}\n self.$4 = $4\n ${6}\n# New Function\nsnippet def\n def ${1:fname}(${2:`indent(\'.\') ? \'self\' : \'\'`}):\n """${3:docstring for $1}"""\n ${4:# TODO: write code...}\nsnippet deff\n def ${1:fname}(${2:`indent(\'.\') ? \'self\' : \'\'`}):\n ${3:# TODO: write code...}\n# New Method\nsnippet defs\n def ${1:mname}(self, ${2:arg}):\n ${3:# TODO: write code...}\n# New Property\nsnippet property\n def ${1:foo}():\n doc = "${2:The $1 property.}"\n def fget(self):\n ${3:return self._$1}\n def fset(self, value):\n ${4:self._$1 = value}\n# Ifs\nsnippet if\n if ${1:condition}:\n ${2:# TODO: write code...}\nsnippet el\n else:\n ${1:# TODO: write code...}\nsnippet ei\n elif ${1:condition}:\n ${2:# TODO: write code...}\n# For\nsnippet for\n for ${1:item} in ${2:items}:\n ${3:# TODO: write code...}\n# Encodes\nsnippet cutf8\n # -*- coding: utf-8 -*-\nsnippet clatin1\n # -*- coding: latin-1 -*-\nsnippet cascii\n # -*- coding: ascii -*-\n# Lambda\nsnippet ld\n ${1:var} = lambda ${2:vars} : ${3:action}\nsnippet .\n self.\nsnippet try Try/Except\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\nsnippet try Try/Except/Else\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n else:\n ${5:# TODO: write code...}\nsnippet try Try/Except/Finally\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n finally:\n ${5:# TODO: write code...}\nsnippet try Try/Except/Else/Finally\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n else:\n ${5:# TODO: write code...}\n finally:\n ${6:# TODO: write code...}\n# if __name__ == \'__main__\':\nsnippet ifmain\n if __name__ == \'__main__\':\n ${1:main()}\n# __magic__\nsnippet _\n __${1:init}__${2}\n# python debugger (pdb)\nsnippet pdb\n import pdb; pdb.set_trace()\n# ipython debugger (ipdb)\nsnippet ipdb\n import ipdb; ipdb.set_trace()\n# ipython debugger (pdbbb)\nsnippet pdbbb\n import pdbpp; pdbpp.set_trace()\nsnippet pprint\n import pprint; pprint.pprint(${1})${2}\nsnippet "\n """\n ${1:doc}\n """\n# test function/method\nsnippet test\n def test_${1:description}(${2:self}):\n ${3:# TODO: write code...}\n# test case\nsnippet testcase\n class ${1:ExampleCase}(unittest.TestCase):\n \n def test_${2:description}(self):\n ${3:# TODO: write code...}\nsnippet fut\n from __future__ import ${1}\n#getopt\nsnippet getopt\n try:\n # Short option syntax: "hv:"\n # Long option syntax: "help" or "verbose="\n opts, args = getopt.getopt(sys.argv[1:], "${1:short_options}", [${2:long_options}])\n \n except getopt.GetoptError, err:\n # Print debug info\n print str(err)\n ${3:error_action}\n\n for option, argument in opts:\n if option in ("-h", "--help"):\n ${4}\n elif option in ("-v", "--verbose"):\n verbose = argument\n',t.scope="python"}) \ No newline at end of file +ace.define("ace/snippets/python",["require","exports","module"],function(e,t,n){"use strict";t.snippetText='snippet #!\n #!/usr/bin/env python\nsnippet imp\n import ${1:module}\nsnippet from\n from ${1:package} import ${2:module}\n# Module Docstring\nsnippet docs\n \'\'\'\n File: ${1:FILENAME:file_name}\n Author: ${2:author}\n Description: ${3}\n \'\'\'\nsnippet wh\n while ${1:condition}:\n ${2:# TODO: write code...}\n# dowh - does the same as do...while in other languages\nsnippet dowh\n while True:\n ${1:# TODO: write code...}\n if ${2:condition}:\n break\nsnippet with\n with ${1:expr} as ${2:var}:\n ${3:# TODO: write code...}\n# New Class\nsnippet cl\n class ${1:ClassName}(${2:object}):\n """${3:docstring for $1}"""\n def __init__(self, ${4:arg}):\n ${5:super($1, self).__init__()}\n self.$4 = $4\n ${6}\n# New Function\nsnippet def\n def ${1:fname}(${2:`indent(\'.\') ? \'self\' : \'\'`}):\n """${3:docstring for $1}"""\n ${4:# TODO: write code...}\nsnippet deff\n def ${1:fname}(${2:`indent(\'.\') ? \'self\' : \'\'`}):\n ${3:# TODO: write code...}\n# New Method\nsnippet defs\n def ${1:mname}(self, ${2:arg}):\n ${3:# TODO: write code...}\n# New Property\nsnippet property\n def ${1:foo}():\n doc = "${2:The $1 property.}"\n def fget(self):\n ${3:return self._$1}\n def fset(self, value):\n ${4:self._$1 = value}\n# Ifs\nsnippet if\n if ${1:condition}:\n ${2:# TODO: write code...}\nsnippet el\n else:\n ${1:# TODO: write code...}\nsnippet ei\n elif ${1:condition}:\n ${2:# TODO: write code...}\n# For\nsnippet for\n for ${1:item} in ${2:items}:\n ${3:# TODO: write code...}\n# Encodes\nsnippet cutf8\n # -*- coding: utf-8 -*-\nsnippet clatin1\n # -*- coding: latin-1 -*-\nsnippet cascii\n # -*- coding: ascii -*-\n# Lambda\nsnippet ld\n ${1:var} = lambda ${2:vars} : ${3:action}\nsnippet .\n self.\nsnippet try Try/Except\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\nsnippet try Try/Except/Else\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n else:\n ${5:# TODO: write code...}\nsnippet try Try/Except/Finally\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n finally:\n ${5:# TODO: write code...}\nsnippet try Try/Except/Else/Finally\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n else:\n ${5:# TODO: write code...}\n finally:\n ${6:# TODO: write code...}\n# if __name__ == \'__main__\':\nsnippet ifmain\n if __name__ == \'__main__\':\n ${1:main()}\n# __magic__\nsnippet _\n __${1:init}__${2}\n# python debugger (pdb)\nsnippet pdb\n ; \n# ipython debugger (ipdb)\nsnippet ipdb\n import ipdb; ipdb.set_trace()\n# ipython debugger (pdbbb)\nsnippet pdbbb\n import pdbpp; pdbpp.set_trace()\nsnippet pprint\n import pprint; pprint.pprint(${1})${2}\nsnippet "\n """\n ${1:doc}\n """\n# test function/method\nsnippet test\n def test_${1:description}(${2:self}):\n ${3:# TODO: write code...}\n# test case\nsnippet testcase\n class ${1:ExampleCase}(unittest.TestCase):\n \n def test_${2:description}(self):\n ${3:# TODO: write code...}\nsnippet fut\n from __future__ import ${1}\n#getopt\nsnippet getopt\n try:\n # Short option syntax: "hv:"\n # Long option syntax: "help" or "verbose="\n opts, args = getopt.getopt(sys.argv[1:], "${1:short_options}", [${2:long_options}])\n \n except getopt.GetoptError, err:\n # Print debug info\n print str(err)\n ${3:error_action}\n\n for option, argument in opts:\n if option in ("-h", "--help"):\n ${4}\n elif option in ("-v", "--verbose"):\n verbose = argument\n',t.scope="python"}) \ No newline at end of file diff --git a/data/management/commands/data_reports.py b/data/management/commands/data_reports.py index 3eee1bbf..21e272ee 100755 --- a/data/management/commands/data_reports.py +++ b/data/management/commands/data_reports.py @@ -83,8 +83,8 @@ def handle(self, *args, **kwargs): # JobTitle.objects.get(name=jt) # except JobTitle.DoesNotExist: # print jt - # import pdb - # pdb.set_trace() + # + # f_type_name = f_type.split('\n') print len(f_type_name) print FacilityType.objects.count() diff --git a/data/management/commands/port_data.py b/data/management/commands/port_data.py index ee718ffa..fe462ac0 100755 --- a/data/management/commands/port_data.py +++ b/data/management/commands/port_data.py @@ -59,8 +59,8 @@ def _help_create_file( } ] json_data = template.render(context) # NOQA - # import pdb - # pdb.set_trace() + # + # # json_file.write(json_data, indent=4) json.dump(to_write, json_file, indent=4) @@ -2323,8 +2323,8 @@ def port_data(): else: value = obj[field.get("v1_pos")] except: - import pdb - pdb.set_trace() + + if value: row_data[field.get("v2")] = value else: diff --git a/facilities/views/static_reports_view.py b/facilities/views/static_reports_view.py index f1f386cc..19430fa0 100644 --- a/facilities/views/static_reports_view.py +++ b/facilities/views/static_reports_view.py @@ -34,17 +34,17 @@ def get_chu_count_in_ward_summary(self, ward): facility__ward=ward).count() def get_bed_count(self, location): - import pdb + if location: - pdb.set_trace() + # for keph in keph_level: # objects.values('Category').distinct() facility_beds_details = Facility.objects.values("number_of_cots", "number_of_beds","number_of_hdu_beds", "number_of_icu_beds", "number_of_isolation_beds","number_of_maternity_beds","owner_id","county_id", "facility_type_id","keph_level_id", "sub_county_id","ward_id", ward__sub_county__county=location) return "keph_array" else: - # pdb.set_trace() + # counties = County.objects.values("id","name","code") facility_beds_details = Facility.objects.values("number_of_cots", "number_of_beds","number_of_hdu_beds", "number_of_icu_beds", "number_of_isolation_beds","number_of_maternity_beds","owner_id","county_id", "facility_type_id","keph_level_id", "sub_county_id","ward_id") counties_beds_array = [] diff --git a/load_all_facilities.py b/load_all_facilities.py index 593b649f..32f13445 100755 --- a/load_all_facilities.py +++ b/load_all_facilities.py @@ -39,7 +39,7 @@ def load_missed_facilities(): try: county = County.objects.filter(name__icontains=county_name)[0] except IndexError: - import pdb; pdb.set_trace() + ; print county, record.get('county') reg_body = None @@ -59,8 +59,8 @@ def load_missed_facilities(): try: operation_status = FacilityStatus.objects.get(name=record.get('operation_status').get('name')) except AttributeError: - import pdb - pdb.set_trace() + + facility_data = { "code": int(record.get('code')), @@ -94,7 +94,7 @@ def load_missed_facilities(): try: ward = prob_ward.filter(name__icontains=fac_ward.get('ward'))[0] except: - import pdb;pdb.set_trace() + ; facility_data['ward'] = ward try: Facility.objects.get(code=int(record.get('code'))) @@ -108,7 +108,7 @@ def load_missed_facilities(): except: pass - # import pdb; pdb.set_trace() + # ; break return len(facs_created) @@ -117,7 +117,7 @@ def load_missed_facilities(): # # try: # # Facility(**facility_data).save() # # except: - # # import pdb; pdb.set_trace() + # # ; # try: # facility = Facility.objects.get(code=record.get('code')) # facility.county = county @@ -206,13 +206,13 @@ def map_facility_types(): try: facility_type_obj = FacilityType.objects.get(name=new_type) except FacilityType.DoesNotExist: - import pdb - pdb.set_trace() + + facility.facility_type = facility_type_obj try: facility.save(allow_save=True) except: - import pdb;pdb.set_trace() + ; diff --git a/scripts.py b/scripts.py index 0b21615e..89ccef27 100755 --- a/scripts.py +++ b/scripts.py @@ -70,21 +70,21 @@ def move_facitlies_to_correct_ward(file_path=None): try: county = County.objects.filter(name__icontains=county_name)[0] except IndexError: - import pdb; pdb.set_trace() + ; prob_ward = Ward.objects.filter(constituency__county=county) try: ward = prob_ward.filter(name__icontains=record.get('ward'))[0] except IndexError: - import pdb - pdb.set_trace() + + fac.ward = ward print county, ward try: fac.save(allow_save=True) except: - import pdb - pdb.set_trace() + + def determine_facilites_already_in_system(): From 02f7c236bc03037c619c64467136a7722f261675 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 7 Feb 2023 19:51:38 +0300 Subject: [PATCH 36/41] Modified facilities/utils.py; line 287 --- facilities/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/facilities/utils.py b/facilities/utils.py index 9226f60e..c65d46b5 100755 --- a/facilities/utils.py +++ b/facilities/utils.py @@ -282,7 +282,9 @@ def _create_contacts(self, data): created_contacts = [] for contact in contacts: - contact_type = ContactType.objects.get(id=contact.get('type')) + import pdb + pdb.set_trace() + contact_type = ContactType.objects.get(id=contact.get('contact_type')) contact_dict = { "contact_type": contact_type, "contact": contact.get('contact') @@ -293,7 +295,7 @@ def _create_contacts(self, data): contact_dict = self._inject_creating_user(contact_dict) contact_dict = self._inject_creating_user(contact_dict) created_contacts.append(Contact.objects.create(**contact_dict)) - + return created_contacts def _create_facility_officer(self, data): From f9201544285e8790f5a6cb17da0c582d80500973 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 22 Feb 2023 09:49:00 +0300 Subject: [PATCH 37/41] added MEDICAL_CLINIC mapping to kmhfl_dhis2_facility_type_mapping in facilities/models/facility_models.py --- facilities/models/facility_models.py | 5 +++-- facilities/utils.py | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index e0cd528f..89dedb58 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -161,7 +161,7 @@ def get_org_unit_id(self, code): # ) def get_parent_id(self, ward_id): - print self.session_store[self.oauth2_token_variable_name] + print (self.session_store[self.oauth2_token_variable_name]) r = requests.get( settings.DHIS_ENDPOINT+"api/organisationUnits.json", auth=(settings.DHIS_USERNAME, settings.DHIS_PASSWORD), @@ -1223,7 +1223,8 @@ def push_new_facility(self, code=None): dhis2_org_unit_id = self.dhis2_api_auth.get_org_unit_id(self.code) kmhfl_dhis2_facility_type_mapping = { "20b86171-0c16-47e1-9277-5e773d485c33": "YQK9pleIoeB", - "5eb392ac-d10a-40c9-b525-53dac866ef6c": "lTrpyOiOcM6", # Replace with 8949eeb0-40b1-43d4-a38d-5d4933dc209f + "5eb392ac-d10a-40c9-b525-53dac866ef6c": "lTrpyOiOcM6", + "8949eeb0-40b1-43d4-a38d-5d4933dc209f": "lTrpyOiOcM6", "ccc1600e-9a24-499f-889f-bd9f0bdc4b95": "YQK9pleIoeB", "d8d741b1-21c5-45c8-86d0-a2094bf9bda6": "YQK9pleIoeB", "869118aa-0e97-4f47-b6b7-1f295d109c8f": "YQK9pleIoeB", diff --git a/facilities/utils.py b/facilities/utils.py index c65d46b5..785db043 100755 --- a/facilities/utils.py +++ b/facilities/utils.py @@ -282,8 +282,6 @@ def _create_contacts(self, data): created_contacts = [] for contact in contacts: - import pdb - pdb.set_trace() contact_type = ContactType.objects.get(id=contact.get('contact_type')) contact_dict = { "contact_type": contact_type, From 1997d63736822a5f3d54a23f078ecab1e1b8e333 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 28 Feb 2023 15:30:58 +0300 Subject: [PATCH 38/41] modified facilities dashboard to support filtering by sub_county and ward as well as fetch all the 47 county summary data --- facilities/models/facility_models.py | 2 + facilities/urls/facility_urls.py | 6 +- facilities/views/facility_dashboard.py | 223 ++++++++++++++++++------- 3 files changed, 168 insertions(+), 63 deletions(-) diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index 89dedb58..f913ec80 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1227,6 +1227,7 @@ def push_new_facility(self, code=None): "8949eeb0-40b1-43d4-a38d-5d4933dc209f": "lTrpyOiOcM6", "ccc1600e-9a24-499f-889f-bd9f0bdc4b95": "YQK9pleIoeB", "d8d741b1-21c5-45c8-86d0-a2094bf9bda6": "YQK9pleIoeB", + "85f2099b-a2f8-49f4-9798-0cb48c0875ff": "YQK9pleIoeB", "869118aa-0e97-4f47-b6b7-1f295d109c8f": "YQK9pleIoeB", "a8af148f-b1b6-4eed-9d86-07d4f3135229": "YQK9pleIoeB", "74755372-99ba-4b70-bca8-a583f03990bc": "lTrpyOiOcM6", @@ -1246,6 +1247,7 @@ def push_new_facility(self, code=None): "188551b7-4f22-4fc4-b07b-f9c9aeeea872": "rhKJPLo27x7", "e5923a48-6b22-42c4-a4e6-6c5a5e8e0b0e": "YQK9pleIoeB", "55d65dd6-5351-4cf4-a6d9-e05ce6d343ab": "mVrepdLAqSD", + "87626d3d-fd19-49d9-98da-daca4afe85bf": "mVrepdLAqSD", "79158397-0d87-4d0e-8694-ad680a907a79": "YQK9pleIoeB", "031293d9-fd8a-4682-a91e-a4390d57b0cf": "YQK9pleIoeB", "4369eec8-0416-4e16-b013-e635ce46a02f": "YQK9pleIoeB", diff --git a/facilities/urls/facility_urls.py b/facilities/urls/facility_urls.py index 0618f953..e5fcef74 100755 --- a/facilities/urls/facility_urls.py +++ b/facilities/urls/facility_urls.py @@ -84,7 +84,11 @@ views.FacilityOfficerDetailView.as_view(), name='facility_officer_detail'), - url(r'^dashboard/$', views.DashBoard.as_view(), name='dashboard'), + url(r'^dashboard/$', views.DashBoard.as_view(), + name='dashboard'), + # url(r'^dashboard/(?P[^/]+)/$', views.DashBoard.as_view(), + # name='dashboard'), + url(r'^facility_correction_template/(?P[^/]+)/$', views.FacilityCorrectionTemplate.as_view(), diff --git a/facilities/views/facility_dashboard.py b/facilities/views/facility_dashboard.py index 9501ae30..edf08a87 100755 --- a/facilities/views/facility_dashboard.py +++ b/facilities/views/facility_dashboard.py @@ -49,7 +49,7 @@ def get_facility_county_summary(self): facility_county_summary[str(county.name)] = facility_county_count top_10_counties = sorted( facility_county_summary.items(), - key=lambda x: x[1], reverse=True)[0:20] + key=lambda x: x[1], reverse=True)[0:94] facility_county_summary top_10_counties_summary = [] for item in top_10_counties: @@ -64,11 +64,16 @@ def get_facility_county_summary(self): return top_10_counties_summary if self.request.user.is_national else [] def get_facility_constituency_summary(self): - constituencies = SubCounty.objects.filter( - county=self.request.user.county) - constituencies = constituencies if self.request.user.county else [] + if not self.request.query_params.get('sub_county'): + constituencies = SubCounty.objects.filter( + county=self.request.user.county) \ + if not self.request.query_params.get('ward') and self.request.user.county else [] + else: + constituencies = [SubCounty.objects.get(id=self.request.query_params.get('sub_county'))] + facility_constituency_summary = {} + for const in constituencies: facility_const_count = self.get_queryset().filter( ward__sub_county=const).count() @@ -90,10 +95,18 @@ def get_facility_constituency_summary(self): }) return top_10_consts_summary + def get_facility_ward_summary(self): - wards = Ward.objects.filter( + + if not self.request.query_params.get('ward'): + wards = Ward.objects.filter( sub_county=self.request.user.sub_county) \ if self.request.user.sub_county else [] + + else: + wards = [Ward.objects.get(id=self.request.query_params.get('ward'))] + + facility_ward_summary = {} for ward in wards: facility_ward_count = self.get_queryset().filter( @@ -115,6 +128,7 @@ def get_facility_ward_summary(self): }) return top_10_wards_summary + def get_facility_type_summary(self, cty): facility_type_parents_names = [] for f_type in FacilityType.objects.all(): @@ -130,13 +144,20 @@ def get_facility_type_summary(self, cty): summaries[parent] = 0 for facility_type in facility_types: - if not cty: - summaries[facility_type.sub_division] = summaries.get( - facility_type.sub_division) + self.get_queryset().filter( - facility_type=facility_type).count() + if not cty and not self.request.query_params.get('sub_county'): + + summaries[facility_type.sub_division] = summaries.get( + facility_type.sub_division) + self.get_queryset().filter( + facility_type=facility_type).count() else: - summaries[facility_type.sub_division] = self.get_queryset().filter( - facility_type=facility_type, ward__sub_county__county=cty).count() + if not self.request.query_params.get('ward'): + summaries[facility_type.sub_division] = self.get_queryset().filter( + facility_type=facility_type, ward__sub_county__county=cty, sub_county=self.request.query_params.get('sub_county')).count() + else: + summaries[facility_type.sub_division] = self.get_queryset().filter( + facility_type=facility_type, ward__sub_county__county=cty, ward=self.request.query_params.get('ward')).count() + + facility_type_summary = [ {"name": key, "count": value } for key, value in summaries.items() @@ -150,9 +171,10 @@ def get_facility_type_summary(self, cty): def get_facility_owner_summary(self, cty): owners = Owner.objects.all() + facility_owners_summary = [] for owner in owners: - if not cty: + if not cty and not self.request.query_params.get('sub_county'): facility_owners_summary.append( { "name": owner.name, @@ -160,19 +182,29 @@ def get_facility_owner_summary(self, cty): owner=owner).count() }) else: - facility_owners_summary.append( + if not self.request.query_params.get('ward'): + facility_owners_summary.append( + { + "name": owner.name, + "count": self.get_queryset().filter( + ward__sub_county__county=cty, owner=owner, sub_county=self.request.query_params.get('sub_county')).count() + }) + else: + facility_owners_summary.append( { "name": owner.name, "count": self.get_queryset().filter( - ward__sub_county__county=cty, owner=owner).count() + ward__sub_county__county=cty, owner=owner, ward=self.request.query_params.get('ward')).count() }) + return facility_owners_summary + def get_facility_status_summary(self, cty): statuses = FacilityStatus.objects.all() status_summary = [] for status in statuses: - if not cty: + if not cty and not self.request.query_params.get('sub_county'): status_summary.append( { "name": status.name, @@ -180,13 +212,22 @@ def get_facility_status_summary(self, cty): operation_status=status).count() }) else: - status_summary.append( - { - "name": status.name, - "count": self.get_queryset().filter( - ward__sub_county__county=cty, - operation_status=status).count() - }) + if not self.request.query_params.get('ward'): + status_summary.append( + { + "name": status.name, + "count": self.get_queryset().filter( + ward__sub_county__county=cty, + operation_status=status, sub_county=self.request.query_params.get('sub_county')).count() + }) + else: + status_summary.append( + { + "name": status.name, + "count": self.get_queryset().filter( + ward__sub_county__county=cty, + operation_status=status, ward=self.request.query_params.get('ward')).count() + }) return status_summary @@ -194,7 +235,7 @@ def get_facility_owner_types_summary(self, cty): owner_types = OwnerType.objects.all() owner_types_summary = [] for owner_type in owner_types: - if not cty: + if not cty and not self.request.query_params.get('sub_county'): owner_types_summary.append( { "name": owner_type.name, @@ -202,13 +243,23 @@ def get_facility_owner_types_summary(self, cty): owner__owner_type=owner_type).count() }) else: - owner_types_summary.append( - { - "name": owner_type.name, - "count": self.get_queryset().filter( - ward__sub_county__county=cty, - owner__owner_type=owner_type).count() - }) + if not self.request.query_params.get('ward'): + owner_types_summary.append( + { + "name": owner_type.name, + "count": self.get_queryset().filter( + ward__sub_county__county=cty, + owner__owner_type=owner_type, sub_county=self.request.query_params.get('sub_county')).count() + }) + else: + owner_types_summary.append( + { + "name": owner_type.name, + "count": self.get_queryset().filter( + ward__sub_county__county=cty, + owner__owner_type=owner_type, ward=self.request.query_params.get('ward')).count() + }) + return owner_types_summary @@ -314,62 +365,95 @@ def get_recently_created_chus(self, cty): def facilities_pending_approval_count(self, cty): - if not cty: + if not cty and not self.request.query_params.get('sub_county'): updated_pending_approval = self.get_queryset().filter(has_edits=True) newly_created = self.queryset.filter(approved=False, rejected=False) else: - updated_pending_approval = self.get_queryset().filter( - ward__sub_county__county=cty, has_edits=True) - newly_created = self.queryset.filter( - ward__sub_county__county=cty, approved=False, rejected=False) + if not self.request.query_params.get('ward'): + updated_pending_approval = self.get_queryset().filter( + ward__sub_county__county=cty, sub_county=self.request.query_params.get('sub_county'), has_edits=True) + newly_created = self.queryset.filter( + ward__sub_county__county=cty, sub_county=self.request.query_params.get('sub_county'), approved=False, rejected=False) + else: + updated_pending_approval = self.get_queryset().filter( + ward__sub_county__county=cty, ward=self.request.query_params.get('ward'), has_edits=True) + newly_created = self.queryset.filter( + ward__sub_county__county=cty, ward=self.request.query_params.get('ward'), approved=False, rejected=False) + return len( list(set(list(updated_pending_approval) + list(newly_created))) ) def get_facilities_approved_count(self,cty): - if not cty: + if not cty and not self.request.query_params.get('sub_county'): return self.queryset.filter(approved=True, rejected=False).count() else: - return self.queryset.filter(approved=True, rejected=False, ward__sub_county__county=cty).count() + if not self.request.query_params.get('ward'): + return self.queryset.filter(approved=True, rejected=False, ward__sub_county__county=cty, sub_county=self.request.query_params.get('sub_county')).count() + else: + return self.queryset.filter(approved=True, rejected=False, ward__sub_county__county=cty, ward=self.request.query_params.get('ward')).count() + def get_chus_pending_approval(self, cty): """ Get the number of CHUs pending approval """ - if not cty: + if not cty and not self.request.query_params.get('sub_county'): return CommunityHealthUnit.objects.filter( Q(is_approved=False, is_rejected=False) | Q(has_edits=True)).distinct().filter( facility__in=self.get_queryset()).count() else: - return CommunityHealthUnit.objects.filter( - Q(is_approved=False, is_rejected=False) | - Q(has_edits=True)).distinct().filter( - facility__in=self.get_queryset(), - facility__ward__sub_county__county=cty).count() + if not self.request.query_params.get('ward'): + return CommunityHealthUnit.objects.filter( + Q(is_approved=False, is_rejected=False) | + Q(has_edits=True)).distinct().filter( + facility__in=self.get_queryset(), + facility__ward__sub_county__county=cty, facility__ward__sub_county=self.request.query_params.get('sub_county')).count() + else: + return CommunityHealthUnit.objects.filter( + Q(is_approved=False, is_rejected=False) | + Q(has_edits=True)).distinct().filter( + facility__in=self.get_queryset(), + facility__ward__sub_county__county=cty, facility__ward=self.request.query_params.get('ward')).count() + def get_rejected_chus(self, cty): """ Get the number of CHUs that have been rejected """ - if not cty: + if not cty and not self.request.query_params.get('sub_county'): return CommunityHealthUnit.objects.filter(is_rejected=True).count() else: - return CommunityHealthUnit.objects.filter( - is_rejected=True, - facility__ward__sub_county__county=cty).count() + if not self.request.query_params.get('ward'): + return CommunityHealthUnit.objects.filter( + is_rejected=True, + facility__ward__sub_county__county=cty, facility__ward__sub_county=self.request.query_params.get('sub_county')).count() + else: + return CommunityHealthUnit.objects.filter( + is_rejected=True, + facility__ward__sub_county__county=cty, facility__ward=self.request.query_params.get('ward')).count() + def get_rejected_facilities_count(self, cty): - if not cty: + if not cty and not self.request.query_params.get('sub_county'): return self.get_queryset().filter(rejected=True).count() else: - return self.get_queryset().filter(rejected=True, ward__sub_county__county=cty).count() + if not self.request.query_params.get('ward'): + return self.get_queryset().filter(rejected=True, ward__sub_county__county=cty, sub_county=self.request.query_params.get('sub_county')).count() + else: + return self.get_queryset().filter(rejected=True, ward__sub_county__county=cty, ward=self.request.query_params.get('ward')).count() + def get_closed_facilities_count(self, cty): - if not cty: + if not cty and not self.request.query_params.get('sub_county'): return self.get_queryset().filter(closed=True).count() else: - return self.get_queryset().filter(closed=True, ward__sub_county__county=cty).count() + if not self.request.query_params.get('ward'): + return self.get_queryset().filter(closed=True, ward__sub_county__county=cty, sub_county=self.request.query_params.get('sub_county')).count() + else: + return self.get_queryset().filter(closed=True, ward__sub_county__county=cty, ward=self.request.query_params.get('ward')).count() + def get_facilities_kephlevel_count(self,county_name): """ @@ -394,33 +478,48 @@ def get_facilities_kephlevel_count(self,county_name): def get(self, *args, **kwargs): + user = self.request.user county_ = user.county + if not self.request.query_params.get('county'): county_ = user.county else: county_ = County.objects.get(id=self.request.query_params.get('county')) - if not county_: + if not county_ and not self.request.query_params.get('sub_county'): + total_facilities = self.get_queryset().count() else: - total_facilities = self.get_queryset().filter( - ward__sub_county__county=county_).count() - if not county_: + if not self.request.query_params.get('ward'): + + total_facilities = self.get_queryset().filter( + ward__sub_county__county=county_, ward__sub_county=self.request.query_params.get('sub_county')).count() + else: + + total_facilities = self.get_queryset().filter( + ward__sub_county__county=county_, ward=self.request.query_params.get('ward')).count() + + if not county_ and not self.request.query_params.get('sub_county'): total_chus = CommunityHealthUnit.objects.filter( facility__in=self.get_queryset()).count() else: - total_chus = CommunityHealthUnit.objects.filter( - facility__in=self.get_queryset().filter( - ward__sub_county__county=county_)).count() + if not self.request.query_params.get('ward'): + total_chus = CommunityHealthUnit.objects.filter( + facility__in=self.get_queryset().filter( + ward__sub_county__county=county_, ward__sub_county=self.request.query_params.get('sub_county'))).count() + else: + total_chus = CommunityHealthUnit.objects.filter( + facility__in=self.get_queryset().filter( + ward__sub_county__county=county_, ward=self.request.query_params.get('ward'))).count() data = { "keph_level" : self.get_facilities_kephlevel_count(county_), "total_facilities": total_facilities, "county_summary": self.get_facility_county_summary() if user.is_national else [], - "constituencies_summary": self.get_facility_constituency_summary() - if user.county and not user.sub_county else [], - "wards_summary": self.get_facility_ward_summary() - if user.sub_county else [], + "constituencies_summary": self.get_facility_constituency_summary(), + # if user.county and not user.sub_county else [], + "wards_summary": self.get_facility_ward_summary(), + # if user.sub_county else [], "owners_summary": self.get_facility_owner_summary(county_), "types_summary": self.get_facility_type_summary(county_), "status_summary": self.get_facility_status_summary(county_), From 423b0c9b4076987431e2f51e0374874374fdb912 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 2 Mar 2023 11:32:57 +0300 Subject: [PATCH 39/41] Added fiedl number_of_inpatient_beds in class Facility of facilities/models/facility_models.py and made migrations for the field --- common/migrations/0021_auto_20230302_0642.py | 20 ++ .../migrations/0022_auto_20211026_0950.py | 245 ------------------ .../migrations/0022_auto_20230302_0658.py | 21 ++ facilities/models/facility_models.py | 4 + facilities/views/facility_views.py | 1 + 5 files changed, 46 insertions(+), 245 deletions(-) create mode 100644 common/migrations/0021_auto_20230302_0642.py delete mode 100644 facilities/migrations/0022_auto_20211026_0950.py create mode 100644 facilities/migrations/0022_auto_20230302_0658.py diff --git a/common/migrations/0021_auto_20230302_0642.py b/common/migrations/0021_auto_20230302_0642.py new file mode 100644 index 00000000..fc96a803 --- /dev/null +++ b/common/migrations/0021_auto_20230302_0642.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2023-03-02 06:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0020_auto_20221205_0904'), + ] + + operations = [ + migrations.AlterField( + model_name='apiauthentication', + name='server', + field=models.CharField(default=b'https://test.hiskenya.org/', max_length=255), + ), + ] diff --git a/facilities/migrations/0022_auto_20211026_0950.py b/facilities/migrations/0022_auto_20211026_0950.py deleted file mode 100644 index 701e5624..00000000 --- a/facilities/migrations/0022_auto_20211026_0950.py +++ /dev/null @@ -1,245 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.27 on 2021-10-26 09:50 -from __future__ import unicode_literals - -import common.fields -import common.models.base -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('facilities', '0021_auto_20211026_0831'), - ] - - operations = [ - migrations.CreateModel( - name='FacilityInfrastructure', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('updated', models.DateTimeField(default=django.utils.timezone.now)), - ('deleted', models.BooleanField(default=False)), - ('active', models.BooleanField(default=True, help_text=b'Indicates whether the record has been retired?')), - ('search', models.CharField(blank=True, editable=False, max_length=255, null=True)), - ('count', models.IntegerField(blank=True, default=0, help_text=b'The actual number of infrastructure items in a facility.')), - ('present', models.BooleanField(default=False, help_text=b'True if the listed infrastructure is present.')), - ('created_by', models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ('-updated', '-created'), - 'default_permissions': ('add', 'change', 'delete', 'view'), - 'abstract': False, - }, - ), - migrations.CreateModel( - name='FacilitySpecialist', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('updated', models.DateTimeField(default=django.utils.timezone.now)), - ('deleted', models.BooleanField(default=False)), - ('active', models.BooleanField(default=True, help_text=b'Indicates whether the record has been retired?')), - ('search', models.CharField(blank=True, editable=False, max_length=255, null=True)), - ('count', models.IntegerField(blank=True, default=0, help_text=b'The actual number of specialists for this speciality.')), - ('created_by', models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ('-updated', '-created'), - 'default_permissions': ('add', 'change', 'delete', 'view'), - 'abstract': False, - }, - ), - migrations.CreateModel( - name='Infrastructure', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('updated', models.DateTimeField(default=django.utils.timezone.now)), - ('deleted', models.BooleanField(default=False)), - ('active', models.BooleanField(default=True, help_text=b'Indicates whether the record has been retired?')), - ('search', models.CharField(blank=True, editable=False, max_length=255, null=True)), - ('name', models.CharField(max_length=255, unique=True)), - ('description', models.TextField(blank=True, null=True)), - ('abbreviation', models.CharField(blank=True, help_text=b'A short form for the infrastructure', max_length=50, null=True)), - ('numbers', models.NullBooleanField(default=True, help_text=b'A flag to indicate whether an infrastructure item can have count/numbers tracked ')), - ('code', common.fields.SequenceField(blank=True, editable=False, unique=True)), - ], - options={ - 'ordering': ('-updated', '-created'), - 'default_permissions': ('add', 'change', 'delete', 'view'), - 'abstract': False, - 'verbose_name_plural': 'infrastructure', - }, - bases=(common.models.base.SequenceMixin, models.Model), - ), - migrations.CreateModel( - name='InfrastructureCategory', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('updated', models.DateTimeField(default=django.utils.timezone.now)), - ('deleted', models.BooleanField(default=False)), - ('active', models.BooleanField(default=True, help_text=b'Indicates whether the record has been retired?')), - ('search', models.CharField(blank=True, editable=False, max_length=255, null=True)), - ('name', models.CharField(help_text=b'What is the name of the category? ', max_length=100)), - ('description', models.TextField(blank=True, null=True)), - ('abbreviation', models.CharField(blank=True, help_text=b'A short form of the category e.g ANC for antenatal', max_length=50, null=True)), - ('created_by', models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)), - ('parent', models.ForeignKey(blank=True, help_text=b'The parent category under which the category falls', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sub_categories', to='facilities.InfrastructureCategory')), - ('updated_by', models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ('-updated', '-created'), - 'default_permissions': ('add', 'change', 'delete', 'view'), - 'abstract': False, - 'verbose_name_plural': 'specialities categories', - }, - ), - migrations.CreateModel( - name='Speciality', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('updated', models.DateTimeField(default=django.utils.timezone.now)), - ('deleted', models.BooleanField(default=False)), - ('active', models.BooleanField(default=True, help_text=b'Indicates whether the record has been retired?')), - ('search', models.CharField(blank=True, editable=False, max_length=255, null=True)), - ('name', models.CharField(max_length=255, unique=True)), - ('description', models.TextField(blank=True, null=True)), - ('abbreviation', models.CharField(blank=True, help_text=b'A short form for the speciality', max_length=50, null=True)), - ('code', common.fields.SequenceField(blank=True, editable=False, unique=True)), - ], - options={ - 'ordering': ('-updated', '-created'), - 'default_permissions': ('add', 'change', 'delete', 'view'), - 'abstract': False, - 'verbose_name_plural': 'specialities', - }, - bases=(common.models.base.SequenceMixin, models.Model), - ), - migrations.CreateModel( - name='SpecialityCategory', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('updated', models.DateTimeField(default=django.utils.timezone.now)), - ('deleted', models.BooleanField(default=False)), - ('active', models.BooleanField(default=True, help_text=b'Indicates whether the record has been retired?')), - ('search', models.CharField(blank=True, editable=False, max_length=255, null=True)), - ('name', models.CharField(help_text=b'What is the name of the category? ', max_length=100)), - ('description', models.TextField(blank=True, null=True)), - ('abbreviation', models.CharField(blank=True, help_text=b'A short form of the category e.g ANC for antenatal', max_length=50, null=True)), - ('created_by', models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)), - ('parent', models.ForeignKey(blank=True, help_text=b'The parent category under which the category falls', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sub_categories', to='facilities.SpecialityCategory')), - ('updated_by', models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ('-updated', '-created'), - 'default_permissions': ('add', 'change', 'delete', 'view'), - 'abstract': False, - 'verbose_name_plural': 'specialities categories', - }, - ), - migrations.AddField( - model_name='facility', - name='accredited_lab_iso_15189', - field=models.BooleanField(default=False, help_text=b'Indicate if facility is accredited Lab ISO 15189'), - ), - migrations.AddField( - model_name='facility', - name='admitting_maternity_general', - field=models.NullBooleanField(help_text=b'A flag to indicate whether facility admits both maternity & general casualty patients'), - ), - migrations.AddField( - model_name='facility', - name='admitting_maternity_only', - field=models.NullBooleanField(help_text=b'A flag to indicate whether facility admits only maternity patients'), - ), - migrations.AddField( - model_name='facility', - name='number_of_isolation_beds', - field=models.PositiveIntegerField(default=0, help_text=b'The number of isolation beds that a facility has e.g 0'), - ), - migrations.AddField( - model_name='facility', - name='number_of_maternity_beds', - field=models.PositiveIntegerField(default=0, help_text=b'The number of maternity beds that a facility has e.g 0'), - ), - migrations.AddField( - model_name='facilityupdates', - name='humanresources', - field=models.TextField(blank=True, null=True), - ), - migrations.AddField( - model_name='facilityupdates', - name='infrastructure', - field=models.TextField(blank=True, null=True), - ), - migrations.AddField( - model_name='speciality', - name='category', - field=models.ForeignKey(help_text=b'The classification that the specialities lies in.', on_delete=django.db.models.deletion.PROTECT, related_name='category_specialities', to='facilities.SpecialityCategory'), - ), - migrations.AddField( - model_name='speciality', - name='created_by', - field=models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='speciality', - name='updated_by', - field=models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='infrastructure', - name='category', - field=models.ForeignKey(help_text=b'The classification that the infrastructure item lies in.', on_delete=django.db.models.deletion.PROTECT, related_name='category_infrastructure', to='facilities.InfrastructureCategory'), - ), - migrations.AddField( - model_name='infrastructure', - name='created_by', - field=models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='infrastructure', - name='updated_by', - field=models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='facilityspecialist', - name='facility', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='facility_specialists', to='facilities.Facility'), - ), - migrations.AddField( - model_name='facilityspecialist', - name='speciality', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='facilities.Speciality'), - ), - migrations.AddField( - model_name='facilityspecialist', - name='updated_by', - field=models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='facilityinfrastructure', - name='facility', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='facility_infrastructure', to='facilities.Facility'), - ), - migrations.AddField( - model_name='facilityinfrastructure', - name='infrastructure', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='facilities.Infrastructure'), - ), - migrations.AddField( - model_name='facilityinfrastructure', - name='updated_by', - field=models.ForeignKey(default=common.models.base.get_default_system_user_id, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/facilities/migrations/0022_auto_20230302_0658.py b/facilities/migrations/0022_auto_20230302_0658.py new file mode 100644 index 00000000..cb434f14 --- /dev/null +++ b/facilities/migrations/0022_auto_20230302_0658.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2023-03-02 06:58 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('facilities', '0021_auto_20211026_0831'), + ] + + operations = [ + migrations.AddField( + model_name='facility', + name='number_of_inpatient_beds', + field=models.PositiveIntegerField(default=0, help_text=b'The number of General In-patient beds that a facility has e.g 0'), + ), + ] diff --git a/facilities/models/facility_models.py b/facilities/models/facility_models.py index f913ec80..95ede8f0 100755 --- a/facilities/models/facility_models.py +++ b/facilities/models/facility_models.py @@ -1046,6 +1046,10 @@ class Facility(SequenceMixin, AbstractBase): default=0, help_text="The number of High Dependency Units (HDU) beds" " that a facility has e.g 0") + number_of_inpatient_beds = models.PositiveIntegerField( + default=0, + help_text="The number of General In-patient beds" + " that a facility has e.g 0") # number_of_maternity_beds = models.PositiveIntegerField( default=0, diff --git a/facilities/views/facility_views.py b/facilities/views/facility_views.py index c6c8cab1..d2041de4 100755 --- a/facilities/views/facility_views.py +++ b/facilities/views/facility_views.py @@ -416,6 +416,7 @@ class FacilityListView(QuerysetFilterMixin, generics.ListCreateAPIView): county -- A list of comma separated county pks
constituency -- A list of comma separated constituency pks
owner -- A list of comma separated owner pks
+ number_of_inpatient_beds -- A list of comma separated integers
number_of_beds -- A list of comma separated integers
number_of_cots -- A list of comma separated integers
open_whole_day -- Boolean True/False
From 3f84be233bd49556a66d4b9b427be9b148a68dbe Mon Sep 17 00:00:00 2001 From: atieno Date: Wed, 22 Mar 2023 09:14:38 +0300 Subject: [PATCH 40/41] CHUL Endpoint Fix --- chul/models.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/chul/models.py b/chul/models.py index 5e0ef2d5..68ed7ac3 100755 --- a/chul/models.py +++ b/chul/models.py @@ -226,6 +226,15 @@ def pending_updates(self): return chu.updates except ChuUpdateBuffer.DoesNotExist: return {} + except ChuUpdateBuffer.MultipleObjectsReturned: + + latest_chu = ChuUpdateBuffer.objects.filter( + is_approved=False, + is_rejected=False, + health_unit=self + ).order_by('-updated').first() + return latest_chu.updates + @property def latest_update(self): From 14c999ed2162e0011779672fbdf222e59e393417 Mon Sep 17 00:00:00 2001 From: atieno Date: Wed, 29 Mar 2023 11:04:50 +0300 Subject: [PATCH 41/41] Add CU summary dashboard --- chul/serializers.py | 5 +++++ chul/urls.py | 4 ++++ chul/views.py | 21 +++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/chul/serializers.py b/chul/serializers.py index 3e7f8c14..842c6eee 100755 --- a/chul/serializers.py +++ b/chul/serializers.py @@ -341,3 +341,8 @@ class CHURatingSerializer(AbstractFieldsMixin, serializers.ModelSerializer): class Meta(AbstractFieldsMixin.Meta): model = CHURating +class ChulSummarySerializer(serializers.ModelSerializer): + # count=serializers.IntegerField() + class Meta: + model = None + fields = '__all__' \ No newline at end of file diff --git a/chul/urls.py b/chul/urls.py index a0e4bb18..815e7be1 100755 --- a/chul/urls.py +++ b/chul/urls.py @@ -48,6 +48,10 @@ url(r'^units/(?P[^/]+)/$', views.CommunityHealthUnitDetailView.as_view(), name='community_health_unit_detail'), + url(r'^summary/$', + views.CommunityHealthUnitSummaryView.as_view(), + name='community_health_unit_summary'), + url(r'^chu_ratings/$', views.CHURatingListView.as_view(), name='chu_ratings'), diff --git a/chul/views.py b/chul/views.py index f2ba0573..311454ee 100755 --- a/chul/views.py +++ b/chul/views.py @@ -1,7 +1,11 @@ +from django.http import JsonResponse from django.template import loader, Context from django.utils import timezone from django.views.decorators.cache import never_cache from rest_framework import generics +from django.db.models import Count +from django.db import connection +from django.apps import apps from common.views import AuditableDetailViewMixin, DownloadPDFMixin from common.models import UserConstituency, UserCounty, UserSubCounty from .models import ( @@ -17,6 +21,7 @@ from .serializers import ( CommunityHealthUnitSerializer, + ChulSummarySerializer, CommunityHealthWorkerSerializer, CommunityHealthWorkerContactSerializer, StatusSerializer, @@ -209,6 +214,7 @@ class CommunityHealthUnitContactListView(generics.ListCreateAPIView): ordering_fields = ('health_unit', 'contact', ) + class CommunityHealthUnitContactDetailView( AuditableDetailViewMixin, generics.RetrieveUpdateDestroyAPIView): @@ -248,6 +254,20 @@ class CommunityHealthUnitDetailView( queryset = CommunityHealthUnit.objects.all() serializer_class = CommunityHealthUnitSerializer +class CommunityHealthUnitSummaryView(generics.ListAPIView): + def get_queryset(self): + with connection.cursor() as cursor: + cursor.execute("SELECT chul_status.name, COUNT(chul_communityhealthunit.status_id) As counts FROM chul_communityhealthunit INNER JOIN chul_status ON chul_communityhealthunit.status_id = chul_status.id GROUP BY chul_status.name") + rows = cursor.fetchall() + return rows + + def list(self, request, *args, **kwargs): + queryset = self.get_queryset() + data = [] + for row in queryset: + data.append({"name": row[0], "count": row[1]}) + return JsonResponse(data, safe=False) + class CommunityHealthWorkerListView(generics.ListCreateAPIView): @@ -345,6 +365,7 @@ class ChuUpdateBufferListView( serializer_class = ChuUpdateBufferSerializer filter_class = ChuUpdateBufferFilter ordering_fields = ('health_unit', ) + # print(queryset) class ChuUpdateBufferDetailView(