def save(self, domain): try: settings = Dhis2Settings.for_domain(domain.name) if settings is None: # Create settings settings = Dhis2Settings() settings.domain = domain.name settings.dhis2 = { 'enabled': self.cleaned_data['enabled'], 'host': self.cleaned_data['host'], 'username': self.cleaned_data['username'], 'password': self.cleaned_data['password'], 'top_org_unit_name': self.cleaned_data['top_org_unit_name'], } settings.save() else: # Update settings settings.dhis2.update({ 'enabled': self.cleaned_data['enabled'], 'host': self.cleaned_data['host'], 'username': self.cleaned_data['username'], 'top_org_unit_name': self.cleaned_data['top_org_unit_name'], }) # Only update the password if it has been set if self.cleaned_data['password']: settings.dhis2['password'] = self.cleaned_data['password'] settings.save() return True except Exception as err: # TODO: What Exception? logger.error('Unable to save DHIS2 API settings: %s' % err) return False
def fetch_org_units(): """ Synchronize DHIS2 Organization Units with local data. This data is used to fulfill the first requirement of `DHIS2 Integration`_: Allow mobile users in CommCareHQ to be associated with a particular DHIS2 Organisation Unit, so that when they create cases their new cases can be associated with that area or facility. .. _DHIS2 Integration: https://www.dropbox.com/s/8djk1vh797t6cmt/WV Sri Lanka Detailed Requirements.docx """ for settings in Dhis2Settings.all_enabled(): logger.info('DHIS2: Fetching org units for domain "%s" with "%s"', settings.domain, settings.dhis2['host']) dhis2_api = Dhis2Api(settings.dhis2['host'], settings.dhis2['username'], settings.dhis2['password'], settings.dhis2['top_org_unit_name']) Dhis2OrgUnit.objects = FixtureManager(Dhis2OrgUnit, settings.domain, ORG_UNIT_FIXTURES) our_org_units = {ou.id: ou for ou in Dhis2OrgUnit.objects.all()} their_org_units = {} # Add new org units for ou in dhis2_api.gen_org_units(): their_org_units[ou['id']] = ou if ou['id'] not in our_org_units: logger.info('DHIS2: Adding org unit "%s"', ou['name']) org_unit = Dhis2OrgUnit(id=ou['id'], name=ou['name'], parent_id=dhis2_api.get_org_unit_parent_id(ou['id'])) org_unit.save() # Delete former org units for id_, ou in our_org_units.iteritems(): if id_ not in their_org_units: logger.info('DHIS2: Deleting org unit "%s"', ou.name) ou.delete()
def get_payload(self, repeat_record, form): if not Dhis2Settings.is_enabled_for_domain(form['domain']): return from casexml.apps.case.models import CommCareCase # avoid circular import settings = Dhis2Settings.for_domain(form['domain']) dhis2_api = Dhis2Api(settings.dhis2.host, settings.dhis2.username, settings.dhis2.password, settings.dhis2.top_org_unit_name) if form['xmlns'] == 'http://openrosa.org/formdesigner/b6a45e8c03a6167acefcdb225ee671cbeb332a40': # This is a growth monitoring form. It needs to be converted into # a paediatric nutrition assessment event. nutrition_id = dhis2_api.get_program_id('Paediatric Nutrition Assessment') event = dhis2_api.form_to_event(nutrition_id, form, NUTRITION_ASSESSMENT_EVENT_FIELDS) # If the form is not to be forwarded, the event will be None return json.dumps(event, default=json_serializer) if event else None elif form['xmlns'] == 'http://openrosa.org/formdesigner/39F09AD4-B770-491E-9255-C97B34BDD7FC': # This is a risk assessment form. It needs to be converted into a # risk assessment event. risk_id = dhis2_api.get_program_id('Underlying Risk Assessment') # Check whether the case needs to be enrolled in the Risk Assessment Program cases = CommCareCase.get_by_xform_id(form.get_id) if len(cases) != 1: # TODO: Fail permanently return None case = cases[0] if not case.get('external_id'): # This case has not yet been pushed to DHIS2. # TODO: Try again later return None # TODO: Test one-line alternative below with risk assessment forms # Either ... if not dhis2_api.enrolled_in(case['external_id'], 'Underlying Risk Assessment'): today = date.today().strftime('%Y-%m-%d') program_data = {dhis2_attr: case[cchq_attr] for cchq_attr, dhis2_attr in RISK_ASSESSMENT_PROGRAM_FIELDS.iteritems()} dhis2_api.enroll_in_id(case['external_id'], risk_id, today, program_data) event = dhis2_api.form_to_event(risk_id, form, RISK_ASSESSMENT_EVENT_FIELDS) # ... or just ... # event = dhis2_api.form_to_event(risk_id, form, RISK_ASSESSMENT_EVENT_FIELDS, case['external_id']) # ...? return json.dumps(event, default=json_serializer) if event else None else: # This is not a form we care about return None
def fetch_cases(): """ Import new child cases from DHIS2 for nutrition tracking """ for settings in Dhis2Settings.all_enabled(): logger.info('DHIS2: Fetching cases for domain "%s" from "%s"', settings.domain, settings.dhis2['host']) children = get_children_only_theirs(settings) pull_child_entities(settings, children)
def get_payload(self, repeat_record, form): from casexml.apps.case.xform import cases_referenced_by_xform logger.debug('DHIS2: Form domain "%s" XMLNS "%s"', form['domain'], form['xmlns']) if form['xmlns'] not in (REGISTER_CHILD_XMLNS, GROWTH_MONITORING_XMLNS, RISK_ASSESSMENT_XMLNS): # This is not a form we care about raise IgnoreDocument settings = Dhis2Settings.for_domain(form['domain']) dhis2_api = Dhis2Api(settings.dhis2['host'], settings.dhis2['username'], settings.dhis2['password'], settings.dhis2['top_org_unit_name']) cases = cases_referenced_by_xform(form) case = next(c for c in cases if c.type == CASE_TYPE) event = None if form['xmlns'] == REGISTER_CHILD_XMLNS: # Create a DHIS2 tracked entity instance from the form's case and # enroll in the nutrition assessment programme. logger.debug('DHIS2: Processing Register Child form') push_case(case, dhis2_api) # We just need to enroll. No event to create raise IgnoreDocument elif form['xmlns'] == GROWTH_MONITORING_XMLNS: logger.debug('DHIS2: Processing Growth Monitoring form') if not getattr(case, 'external_id', None): logger.info('Register Child form must be processed before Growth Monitoring form') return # Try again later self._update_instance(dhis2_api, case) # Create a paediatric nutrition assessment event. program_id = dhis2_api.get_program_id('Paediatric Nutrition Assessment') program_stage_id = dhis2_api.get_program_stage_id('Nutrition Assessment') event = dhis2_api.form_to_event(program_id, form, NUTRITION_ASSESSMENT_EVENT_FIELDS, program_stage_id, case['external_id']) elif form['xmlns'] == RISK_ASSESSMENT_XMLNS: logger.debug('DHIS2: Processing Risk Assessment form') if not getattr(case, 'external_id', None): logger.info('Register Child form must be processed before Risk Assessment form') return # Try again later self._update_instance(dhis2_api, case) # Check whether the case needs to be enrolled in the Risk Assessment Program program_id = dhis2_api.get_program_id('Underlying Risk Assessment') if not dhis2_api.enrolled_in(case['external_id'], 'Underlying Risk Assessment'): today = json_format_date(date.today()) program_data = {dhis2_attr: case[cchq_attr] for cchq_attr, dhis2_attr in RISK_ASSESSMENT_PROGRAM_FIELDS.iteritems()} dhis2_api.enroll_in_id(case['external_id'], program_id, today, program_data) # Create a risk assessment event. program_stage_id = dhis2_api.get_program_stage_id('Underlying Risk Assessment') event = dhis2_api.form_to_event(program_id, form, RISK_ASSESSMENT_EVENT_FIELDS, program_stage_id, case['external_id']) return json.dumps(event, default=json_serializer)
def sync_cases(): """ Create new child cases in CommCare for nutrition tracking, and associate CommCare child cases with DHIS2 child entities and enroll them in the Pediatric Nutrition Assessment and Underlying Risk Assessment programs. """ for domain in Domain.get_all(): settings = Dhis2Settings.for_domain(domain.name) if settings is None or not settings.is_enabled(): continue children = get_children_only_theirs(settings) pull_child_entities(settings, children) children = gen_children_only_ours(domain.name) push_child_entities(settings, children)
def get_payload(self, repeat_record, form): from casexml.apps.case.xform import cases_referenced_by_xform logger.debug('DHIS2: Form domain "%s" XMLNS "%s"', form['domain'], form['xmlns']) if form['xmlns'] not in (REGISTER_CHILD_XMLNS, GROWTH_MONITORING_XMLNS, RISK_ASSESSMENT_XMLNS): # This is not a form we care about raise IgnoreDocument settings = Dhis2Settings.for_domain(form['domain']) dhis2_api = Dhis2Api(settings.dhis2['host'], settings.dhis2['username'], settings.dhis2['password'], settings.dhis2['top_org_unit_name']) cases = cases_referenced_by_xform(form) case = next(c for c in cases if c.type == CASE_TYPE) event = None if form['xmlns'] == REGISTER_CHILD_XMLNS: # Create a DHIS2 tracked entity instance from the form's case and # enroll in the nutrition assessment programme. logger.debug('DHIS2: Processing Register Child form') push_case(case, dhis2_api) # We just need to enroll. No event to create raise IgnoreDocument elif form['xmlns'] == GROWTH_MONITORING_XMLNS: logger.debug('DHIS2: Processing Growth Monitoring form') if not getattr(case, 'external_id', None): logger.info( 'Register Child form must be processed before Growth Monitoring form' ) return # Try again later self._update_instance(dhis2_api, case) # Create a paediatric nutrition assessment event. program_id = dhis2_api.get_program_id( 'Paediatric Nutrition Assessment') program_stage_id = dhis2_api.get_program_stage_id( 'Nutrition Assessment') event = dhis2_api.form_to_event(program_id, form, NUTRITION_ASSESSMENT_EVENT_FIELDS, program_stage_id, case['external_id'])
def fetch_org_units(): """ Synchronize DHIS2 Organization Units with local data. This data is used to fulfill the first requirement of `DHIS2 Integration`_: Allow mobile users in CommCareHQ to be associated with a particular DHIS2 Organisation Unit, so that when they create cases their new cases can be associated with that area or facility. .. _DHIS2 Integration: https://www.dropbox.com/s/8djk1vh797t6cmt/WV Sri Lanka Detailed Requirements.docx """ for settings in Dhis2Settings.all_enabled(): logger.info('DHIS2: Fetching org units for domain "%s" with "%s"', settings.domain, settings.dhis2['host']) dhis2_api = Dhis2Api(settings.dhis2['host'], settings.dhis2['username'], settings.dhis2['password'], settings.dhis2['top_org_unit_name']) Dhis2OrgUnit.objects = FixtureManager(Dhis2OrgUnit, settings.domain, ORG_UNIT_FIXTURES) our_org_units = {ou.id: ou for ou in Dhis2OrgUnit.objects.all()} their_org_units = {} # Add new org units for ou in dhis2_api.gen_org_units(): their_org_units[ou['id']] = ou if ou['id'] not in our_org_units: logger.info('DHIS2: Adding org unit "%s"', ou['name']) org_unit = Dhis2OrgUnit( id=ou['id'], name=ou['name'], parent_id=dhis2_api.get_org_unit_parent_id(ou['id'])) org_unit.save() # Delete former org units for id_, ou in our_org_units.iteritems(): if id_ not in their_org_units: logger.info('DHIS2: Deleting org unit "%s"', ou.name) ou.delete()
def sync_org_units(): """ Synchronize DHIS2 Organization Units with local data. This data is used to fulfill the first requirement of `DHIS2 Integration`_: Allow mobile users in CommCareHQ to be associated with a particular DHIS2 Organisation Unit, so that when they create cases their new cases can be associated with that area or facility. .. _DHIS2 Integration: https://www.dropbox.com/s/8djk1vh797t6cmt/WV Sri Lanka Detailed Requirements.docx """ # Loop through all enabled domains for domain in Domain.get_all(): settings = Dhis2Settings.for_domain(domain.name) if settings is None or not settings.is_enabled(): continue dhis2_api = Dhis2Api(settings.dhis2.host, settings.dhis2.username, settings.dhis2.password, settings.dhis2.top_org_unit_name) # Is it a bad idea to read all org units into dictionaries and sync them ... their_org_units = {ou['id']: ou for ou in dhis2_api.gen_org_units_with_parents()} # ... or should we rather just drop all ours and import all theirs every time? org_unit_objects = FixtureManager(Dhis2OrgUnit, domain, ORG_UNIT_FIXTURES) our_org_units = {ou.id: ou for ou in org_unit_objects.all()} # Add new org units for id_, ou in their_org_units.iteritems(): if id_ not in our_org_units: org_unit = Dhis2OrgUnit(id=id_, name=ou['name'], parent_id=ou['parent_id']) org_unit.save() # Delete former org units for id_, ou in our_org_units.iteritems(): if id_ not in their_org_units: ou.delete()
def enabled_for_domain(domain): return Dhis2Settings.is_enabled_for_domain(domain)