def post(self, request, *args, **kwargs): try: new_openmrs_importers = json.loads( request.POST['openmrs_importers']) current_openmrs_importers = get_openmrs_importers_by_domain( request.domain) i = -1 for i, openmrs_importer in enumerate(current_openmrs_importers): if i < len(new_openmrs_importers): self._update_importer(openmrs_importer, new_openmrs_importers[i]) else: # Delete removed OpenMRS Importers openmrs_importer.delete() if i + 1 < len(new_openmrs_importers): # Insert new OpenMRS Importers for j in range(i + 1, len(new_openmrs_importers)): openmrs_importer = OpenmrsImporter(domain=request.domain) self._update_importer(openmrs_importer, new_openmrs_importers[j]) get_openmrs_importers_by_domain.clear(request.domain) return json_response({ 'message': _('OpenMRS Importers saved'), 'error': None }) except Exception as err: return json_response({ 'message': None, 'error': str(err) }, status_code=500)
def page_context(self): # TODO: Look up locations for location_id field. openmrs_importers = [] for importer in get_openmrs_importers_by_domain(self.request.domain): dict_ = dict(importer) dict_['password'] = PASSWORD_PLACEHOLDER dict_['report_params'] = json.dumps(dict_['report_params'], cls=DjangoJSONEncoder, indent=2) dict_['column_map'] = json.dumps( [ { k: v for k, v in dict(m).items() if not ( # Drop '"doc_type": ColumnMapping' from each column mapping. k == 'doc_type' or # Drop "data_type" if it's not specified (k == 'data_type' and v is None)) } for m in dict_['column_map'] ], indent=2) openmrs_importers.append(dict_) return { 'openmrs_importers': openmrs_importers, 'form': OpenmrsImporterForm( ), # Use an unbound form to render openmrs_importer_template.html }
def save(self, domain_name): try: importers = get_openmrs_importers_by_domain(domain_name) importer = importers[0] if importers else None # TODO: Support multiple if importer is None: importer = OpenmrsImporter(domain=domain_name) importer.server_url = self.cleaned_data['server_url'] importer.username = self.cleaned_data['username'] if self.cleaned_data['password']: # Don't save it if it hasn't been changed. importer.password = b64_aes_encrypt(self.cleaned_data['password']) importer.location_id = self.cleaned_data['location_id'] importer.import_frequency = self.cleaned_data['import_frequency'] importer.log_level = self.cleaned_data['log_level'] importer.report_uuid = self.cleaned_data['report_uuid'] importer.report_params = self.cleaned_data['report_params'] importer.case_type = self.cleaned_data['case_type'] importer.owner_id = self.cleaned_data['owner_id'] importer.location_type_name = self.cleaned_data['location_type_name'] importer.external_id_column = self.cleaned_data['external_id_column'] importer.name_columns = self.cleaned_data['name_columns'] importer.column_map = list(map(ColumnMapping.wrap, self.cleaned_data['column_map'])) importer.save() return True except Exception as err: logging.error('Unable to save OpenMRS Importer: %s' % err) return False
def openmrs_importer_form(self): importers = get_openmrs_importers_by_domain(self.request.domain) if importers: initial = dict(importers[0]) # TODO: Support multiple initial['column_map'] = [ {k: v for k, v in dict(m).items() if k != 'doc_type'} # Just for the pretty for m in initial['column_map'] ] else: initial = {} if self.request.method == 'POST': return OpenmrsImporterForm(self.request.POST, initial=initial) return OpenmrsImporterForm(initial=initial)
def post(self, request, *args, **kwargs): try: new_openmrs_importers = json.loads(request.POST['openmrs_importers']) current_openmrs_importers = get_openmrs_importers_by_domain(request.domain) i = -1 for i, openmrs_importer in enumerate(current_openmrs_importers): if i < len(new_openmrs_importers): self._update_importer(openmrs_importer, new_openmrs_importers[i]) else: # Delete removed OpenMRS Importers openmrs_importer.delete() if i + 1 < len(new_openmrs_importers): # Insert new OpenMRS Importers for j in range(i + 1, len(new_openmrs_importers)): openmrs_importer = OpenmrsImporter(domain=request.domain) self._update_importer(openmrs_importer, new_openmrs_importers[j]) get_openmrs_importers_by_domain.clear(request.domain) return json_response({'message': _('OpenMRS Importers saved'), 'error': None}) except Exception as err: return json_response({'message': None, 'error': str(err)}, status_code=500)
def page_context(self): # TODO: Look up locations for location_id field. openmrs_importers = [] for importer in get_openmrs_importers_by_domain(self.request.domain): dict_ = dict(importer) dict_['password'] = PASSWORD_PLACEHOLDER dict_['report_params'] = json.dumps(dict_['report_params'], indent=2) dict_['column_map'] = json.dumps([ {k: v for k, v in dict(m).items() if not ( # Drop '"doc_type": ColumnMapping' from each column mapping. k == 'doc_type' or # Drop "data_type" if it's not specified (k == 'data_type' and v is None) )} for m in dict_['column_map'] ], indent=2) openmrs_importers.append(dict_) return { 'openmrs_importers': openmrs_importers, 'form': OpenmrsImporterForm(), # Use an unbound form to render openmrs_importer_template.html }
def import_patients_to_domain(domain_name, force=False): """ Iterates OpenmrsImporters of a domain, and imports patients Who owns the imported cases? If `importer.owner_id` is set, then the server will be queried once. All patients, regardless of their location, will be assigned to the mobile worker whose ID is `importer.owner_id`. If `importer.location_type_name` is set, then check whether the OpenmrsImporter's location is set with `importer.location_id`. If `importer.location_id` is given, then the server will be queried for each location among its descendants whose type is `importer.location_type_name`. The request's query parameters will include that descendant location's OpenMRS UUID. Imported cases will be owned by the first mobile worker in that location. If `importer.location_id` is given, then the server will be queried for each location in the project space whose type is `importer.location_type_name`. As when `importer.location_id` is specified, the request's query parameters will include that location's OpenMRS UUID, and imported cases will be owned by the first mobile worker in that location. ..NOTE:: As you can see from the description above, if `importer.owner_id` is set then `importer.location_id` is not used. :param domain_name: The name of the domain :param force: Import regardless of the configured import frequency / today's date """ for importer in get_openmrs_importers_by_domain(domain_name): if importer.should_import_today() or force: import_patients_with_importer.delay(importer.to_json())
def import_patients_to_domain(domain_name, force=False): """ Iterates OpenmrsImporters of a domain, and imports patients Who owns the imported cases? If `importer.owner_id` is set, then the server will be queried once. All patients, regardless of their location, will be assigned to the mobile worker whose ID is `importer.owner_id`. If `importer.location_type_name` is set, then check whether the OpenmrsImporter's location is set with `importer.location_id`. If `importer.location_id` is given, then the server will be queried for each location among its descendants whose type is `importer.location_type_name`. The request's query parameters will include that descendant location's OpenMRS UUID. Imported cases will be owned by the first mobile worker in that location. If `importer.location_id` is given, then the server will be queried for each location in the project space whose type is `importer.location_type_name`. As when `importer.location_id` is specified, the request's query parameters will include that location's OpenMRS UUID, and imported cases will be owned by the first mobile worker in that location. ..NOTE:: As you can see from the description above, if `importer.owner_id` is set then `importer.location_id` is not used. :param domain_name: The name of the domain :param force: Import regardless of the configured import frequency / today's date """ today = datetime.today() for importer in get_openmrs_importers_by_domain(domain_name): if not force and importer.import_frequency == IMPORT_FREQUENCY_WEEKLY and today.weekday( ) != 1: continue # Import on Tuesdays if not force and importer.import_frequency == IMPORT_FREQUENCY_MONTHLY and today.day != 1: continue # Import on the first of the month # TODO: ^^^ Make those configurable password = b64_aes_decrypt(importer.password) requests = Requests(domain_name, importer.server_url, importer.username, password) if importer.location_type_name: try: location_type = LocationType.objects.get( domain=domain_name, name=importer.location_type_name) except LocationType.DoesNotExist: logger.error( 'No organization level named "{location_type}" found in project space "{domain}".' .format(location_type=importer.location_type_name, domain=domain_name)) continue if importer.location_id: location = SQLLocation.objects.filter(domain=domain_name).get( importer.location_id) locations = location.get_descendants.filter( location_type=location_type) else: locations = SQLLocation.objects.filter( domain=domain_name, location_type=location_type) for location in locations: # Assign cases to the first user in the location, not to the location itself owner = get_one_commcare_user_at_location( domain_name, location.location_id) if not owner: logger.error( 'Project space "{domain}" at location "{location}" has no user to own cases imported from ' 'OpenMRS Importer "{importer}"'.format( domain=domain_name, location=location.name, importer=importer)) continue import_patients_of_owner(requests, importer, domain_name, owner, location) elif importer.owner_id: try: owner = CommCareUser.get(importer.owner_id) except ResourceNotFound: logger.error( 'Project space "{domain}" has no user to own cases imported from OpenMRS Importer ' '"{importer}"'.format(domain=domain_name, importer=importer)) continue import_patients_of_owner(requests, importer, domain_name, owner) else: logger.error( 'Error importing patients for project space "{domain}" from OpenMRS Importer "{importer}": Unable ' 'to determine the owner of imported cases without either owner_id or location_type_name' .format(domain=domain_name, importer=importer)) continue
def import_patients_to_domain(domain_name, force=False): """ Iterates OpenmrsImporters of a domain, and imports patients Who owns the imported cases? If `importer.owner_id` is set, then the server will be queried once. All patients, regardless of their location, will be assigned to the mobile worker whose ID is `importer.owner_id`. If `importer.location_type_name` is set, then check whether the OpenmrsImporter's location is set with `importer.location_id`. If `importer.location_id` is given, then the server will be queried for each location among its descendants whose type is `importer.location_type_name`. The request's query parameters will include that descendant location's OpenMRS UUID. Imported cases will be owned by the first mobile worker in that location. If `importer.location_id` is given, then the server will be queried for each location in the project space whose type is `importer.location_type_name`. As when `importer.location_id` is specified, the request's query parameters will include that location's OpenMRS UUID, and imported cases will be owned by the first mobile worker in that location. ..NOTE:: As you can see from the description above, if `importer.owner_id` is set then `importer.location_id` is not used. :param domain_name: The name of the domain :param force: Import regardless of the configured import frequency / today's date """ today = datetime.today() for importer in get_openmrs_importers_by_domain(domain_name): if not force and importer.import_frequency == IMPORT_FREQUENCY_WEEKLY and today.weekday() != 1: continue # Import on Tuesdays if not force and importer.import_frequency == IMPORT_FREQUENCY_MONTHLY and today.day != 1: continue # Import on the first of the month # TODO: ^^^ Make those configurable password = b64_aes_decrypt(importer.password) requests = Requests(domain_name, importer.server_url, importer.username, password) if importer.location_type_name: try: location_type = LocationType.objects.get(domain=domain_name, name=importer.location_type_name) except LocationType.DoesNotExist: logger.error( 'No organization level named "{location_type}" found in project space "{domain}".'.format( location_type=importer.location_type_name, domain=domain_name) ) continue if importer.location_id: location = SQLLocation.objects.filter(domain=domain_name).get(importer.location_id) locations = location.get_descendants.filter(location_type=location_type) else: locations = SQLLocation.objects.filter(domain=domain_name, location_type=location_type) for location in locations: # Assign cases to the first user in the location, not to the location itself owner = get_one_commcare_user_at_location(domain_name, location.location_id) if not owner: logger.error( 'Project space "{domain}" at location "{location}" has no user to own cases imported from ' 'OpenMRS Importer "{importer}"'.format( domain=domain_name, location=location.name, importer=importer) ) continue import_patients_of_owner(requests, importer, domain_name, owner, location) elif importer.owner_id: try: owner = CommCareUser.get(importer.owner_id) except ResourceNotFound: logger.error( 'Project space "{domain}" has no user to own cases imported from OpenMRS Importer ' '"{importer}"'.format( domain=domain_name, importer=importer) ) continue import_patients_of_owner(requests, importer, domain_name, owner) else: logger.error( 'Error importing patients for project space "{domain}" from OpenMRS Importer "{importer}": Unable ' 'to determine the owner of imported cases without either owner_id or location_type_name'.format( domain=domain_name, importer=importer) ) continue