예제 #1
0
파일: util.py 프로젝트: dimagi/commcare-hq
def lookup_case(search_field, search_id, domain, case_type):
    """
    Attempt to find the case in CouchDB by the provided search_field and search_id.

    Returns a tuple with case (if found) and an
    error code (if there was an error in lookup).
    """
    found = False
    case_accessors = CaseAccessors(domain)
    if search_field == 'case_id':
        try:
            case = case_accessors.get_case(search_id)
            if case.domain == domain and case.type == case_type:
                found = True
        except CaseNotFound:
            pass
    elif search_field == EXTERNAL_ID:
        cases_by_type = case_accessors.get_cases_by_external_id(search_id, case_type=case_type)
        if not cases_by_type:
            return (None, LookupErrors.NotFound)
        elif len(cases_by_type) > 1:
            return (None, LookupErrors.MultipleResults)
        else:
            case = cases_by_type[0]
            found = True

    if found:
        return (case, None)
    else:
        return (None, LookupErrors.NotFound)
예제 #2
0
class EnikshayCaseFactory(object):

    domain = None
    patient_detail = None

    def __init__(self,
                 domain,
                 patient_detail,
                 nikshay_codes_to_location,
                 test_phi=None):
        self.domain = domain
        self.patient_detail = patient_detail
        self.case_accessor = CaseAccessors(domain)
        self.nikshay_codes_to_location = nikshay_codes_to_location
        self.test_phi = test_phi

    @property
    def nikshay_id(self):
        return self.patient_detail.PregId

    @property
    @memoized
    def existing_person_case(self):
        """
        Get the existing person case for this nikshay ID, or None if no person case exists
        """
        matching_external_ids = self.case_accessor.get_cases_by_external_id(
            self.nikshay_id, case_type='person')
        if matching_external_ids:
            assert len(matching_external_ids) == 1
            return matching_external_ids[0]
        return None

    @property
    def creating_person_case(self):
        return self.existing_person_case is not None

    @property
    @memoized
    def existing_occurrence_case(self):
        """
        Get the existing occurrence case for this nikshay ID, or None if no occurrence case exists
        """
        if self.existing_person_case:
            try:
                return get_open_occurrence_case_from_person(
                    self.domain, self.existing_person_case.case_id)
            except ENikshayCaseNotFound:
                return None

    @property
    @memoized
    def existing_episode_case(self):
        """
        Get the existing episode case for this nikshay ID, or None if no episode case exists
        """
        if self.existing_occurrence_case:
            try:
                return get_open_episode_case_from_occurrence(
                    self.domain, self.existing_occurrence_case.case_id)
            except ENikshayCaseNotFound:
                return None

    @property
    @memoized
    def existing_drtb_hiv_case(self):
        """
        Get the existing episode case for this nikshay ID, or None if no episode case exists
        """
        if self.existing_episode_case:
            try:
                return get_open_drtb_hiv_case_from_episode(
                    self.domain, self.existing_episode_case.case_id)
            except ENikshayCaseNotFound:
                return None

    def get_case_structures_to_create(self):
        person_structure = self.get_person_case_structure()
        ocurrence_structure = self.get_occurrence_case_structure(
            person_structure)
        episode_structure = self.get_episode_case_structure(
            ocurrence_structure)
        if not self._outcome or self._outcome.hiv_status in [
                'unknown', 'reactive'
        ]:
            drtb_hiv_referral_structure = self.get_drtb_hiv_referral_case_structure(
                episode_structure)
            return [drtb_hiv_referral_structure]
        else:
            return [episode_structure]

    def get_person_case_structure(self):
        kwargs = {
            'attrs': {
                'case_type': PERSON_CASE_TYPE,
                'external_id': self.nikshay_id,
                'update': {
                    'age':
                    self.patient_detail.page,
                    'age_entered':
                    self.patient_detail.page,
                    'current_address':
                    self.patient_detail.paddress,
                    'current_episode_type':
                    'confirmed_tb',
                    'current_patient_type_choice':
                    self.patient_detail.patient_type_choice,
                    'dataset':
                    'real',
                    'dob':
                    date(date.today().year - self.patient_detail.page, 7, 1),
                    'dob_known':
                    'no',
                    'has_open_tests':
                    'no',
                    'hiv_status':
                    self._outcome.hiv_status if self._outcome else 'unknown',
                    'first_name':
                    self.patient_detail.first_name,
                    'last_name':
                    self.patient_detail.last_name,
                    'name':
                    self.patient_detail.pname,
                    'person_id':
                    self.patient_detail.person_id,
                    'phone_number':
                    validate_phone_number(self.patient_detail.pmob),
                    'secondary_contact_name_address':
                    ((self.patient_detail.cname or '') + ', ' +
                     (self.patient_detail.caddress or '')),
                    'secondary_contact_phone_number':
                    validate_phone_number(self.patient_detail.cmob),
                    'sex':
                    self.patient_detail.sex,
                    'migration_created_case':
                    'true',
                },
            },
        }

        if self.phi:
            if self.phi.location_type.code == 'phi':
                kwargs['attrs']['owner_id'] = self.phi.location_id
                kwargs['attrs']['update']['phi'] = self.phi.name
                kwargs['attrs']['update'][
                    'phi_assigned_to'] = self.phi.location_id
                kwargs['attrs']['update']['tu_choice'] = self.tu.location_id
            else:
                kwargs['attrs']['owner_id'] = ARCHIVED_CASE_OWNER_ID
                kwargs['attrs']['update'][
                    'archive_reason'] = 'migration_not_phi_location'
                kwargs['attrs']['update'][
                    'migration_error'] = 'not_phi_location'
                kwargs['attrs']['update'][
                    'migration_error_details'] = self._phi_code
        else:
            kwargs['attrs']['owner_id'] = ARCHIVED_CASE_OWNER_ID
            kwargs['attrs']['update'][
                'archive_reason'] = 'migration_location_not_found'
            kwargs['attrs']['update']['migration_error'] = 'location_not_found'
            kwargs['attrs']['update'][
                'migration_error_details'] = self._phi_code

        if self._outcome:
            if self._outcome.hiv_status:
                kwargs['attrs']['update'][
                    'hiv_status'] = self._outcome.hiv_status
            if self._outcome.is_treatment_ended:
                kwargs['attrs']['owner_id'] = ARCHIVED_CASE_OWNER_ID
                kwargs['attrs']['update']['is_active'] = 'no'
            else:
                kwargs['attrs']['update']['is_active'] = 'yes'
            if self._outcome.treatment_outcome == 'died':
                kwargs['attrs']['close'] = True
        else:
            kwargs['attrs']['update']['is_active'] = 'yes'

        if self.patient_detail.paadharno is not None:
            kwargs['attrs']['update'][
                'aadhaar_number'] = self.patient_detail.paadharno

        if self.existing_person_case is not None:
            kwargs['case_id'] = self.existing_person_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    def get_occurrence_case_structure(self, person_structure):
        """
        This gets the occurrence case structure with a nested person case structure.
        """
        kwargs = {
            'attrs': {
                'case_type': OCCURRENCE_CASE_TYPE,
                'owner_id': '-',
                'update': {
                    'current_episode_type': 'confirmed_tb',
                    'ihv_date': self.patient_detail.ihv_date,
                    'initial_home_visit_status':
                    self.patient_detail.initial_home_visit_status,
                    'name': 'Occurrence #1',
                    'occurrence_episode_count': 1,
                    'occurrence_id': get_human_friendly_id(),
                    'migration_created_case': 'true',
                },
            },
            'indices': [
                CaseIndex(
                    person_structure,
                    identifier='host',
                    relationship=CASE_INDEX_EXTENSION,
                    related_type=PERSON_CASE_TYPE,
                )
            ],
        }

        if self._outcome:
            if self._outcome.is_treatment_ended:
                kwargs['attrs']['close'] = True

        if self.existing_occurrence_case:
            kwargs['case_id'] = self.existing_occurrence_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    def get_episode_case_structure(self, occurrence_structure):
        """
        This gets the episode case structure with a nested occurrence and person case structures
        inside of it.
        """
        kwargs = {
            'attrs': {
                'case_type': EPISODE_CASE_TYPE,
                'date_opened': self.patient_detail.pregdate1,
                'owner_id': '-',
                'update': {
                    'adherence_schedule_date_start':
                    (self.patient_detail.treatment_initiation_date
                     if self.patient_detail.treatment_initiation_date else
                     self.patient_detail.pregdate1),
                    'adherence_schedule_id':
                    'schedule_mwf',
                    'date_of_diagnosis':
                    self.patient_detail.pregdate1,
                    'date_of_mo_signature':
                    (self.patient_detail.date_of_mo_signature
                     if self.patient_detail.date_of_mo_signature else
                     self.patient_detail.pregdate1),
                    'disease_classification':
                    self.patient_detail.disease_classification,
                    'dots_99_enabled':
                    'false',
                    'episode_id':
                    get_human_friendly_id(),
                    'episode_pending_registration':
                    'no',
                    'episode_type':
                    'confirmed_tb',
                    'name':
                    'Episode #1: Confirmed TB (Patient)',
                    'nikshay_id':
                    self.nikshay_id,
                    'occupation':
                    self.patient_detail.occupation,
                    'patient_type_choice':
                    self.patient_detail.patient_type_choice,
                    'transfer_in':
                    'yes' if self.patient_detail.patient_type_choice
                    == 'transfer_in' else '',
                    'treatment_card_completed_date':
                    self.patient_detail.pregdate1,
                    'treatment_initiated':
                    'yes_phi',
                    'treatment_initiation_date':
                    (self.patient_detail.treatment_initiation_date
                     if self.patient_detail.treatment_initiation_date else
                     self.patient_detail.pregdate1),
                    'treatment_supporter_designation':
                    self.patient_detail.treatment_supporter_designation,
                    'treatment_supporter_first_name':
                    self.patient_detail.treatment_supporter_first_name,
                    'treatment_supporter_last_name':
                    self.patient_detail.treatment_supporter_last_name,
                    'treatment_supporter_mobile_number':
                    validate_phone_number(self.patient_detail.dotmob),
                    'migration_created_case':
                    'true',
                },
            },
            'indices': [
                CaseIndex(
                    occurrence_structure,
                    identifier='host',
                    relationship=CASE_INDEX_EXTENSION,
                    related_type=OCCURRENCE_CASE_TYPE,
                )
            ],
        }

        if self.patient_detail.disease_classification == 'extra_pulmonary':
            kwargs['attrs']['update'][
                'site_choice'] = self.patient_detail.site_choice
        if self._outcome:
            if self._outcome.treatment_outcome:
                kwargs['attrs']['update'][
                    'treatment_outcome'] = self._outcome.treatment_outcome
                assert self._outcome.treatment_outcome_date is not None
                kwargs['attrs']['update'][
                    'treatment_outcome_date'] = self._outcome.treatment_outcome_date
            if self._outcome.is_treatment_ended:
                kwargs['attrs']['close'] = True

        if self.existing_episode_case:
            kwargs['case_id'] = self.existing_episode_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    def get_drtb_hiv_referral_case_structure(self, episode_structure):
        kwargs = {
            'attrs': {
                'case_type': DRTB_HIV_REFERRAL_CASE_TYPE,
                'owner_id': self.drtb_hiv.location_id,
                'update': {
                    'name': self.patient_detail.pname,
                }
            },
            'indices': [
                CaseIndex(
                    episode_structure,
                    identifier='host',
                    relationship=CASE_INDEX_EXTENSION,
                    related_type=EPISODE_CASE_TYPE,
                )
            ],
        }
        if self.existing_drtb_hiv_case:
            kwargs['case_id'] = self.existing_drtb_hiv_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True
        return CaseStructure(**kwargs)

    @property
    @memoized
    def _outcome(self):
        zero_or_one_outcomes = list(
            Outcome.objects.filter(PatientId=self.patient_detail))
        if zero_or_one_outcomes:
            return zero_or_one_outcomes[0]
        else:
            return None

    @property
    def tu(self):
        if self.test_phi is not None:
            return MockLocation('FAKETU', 'fake_tu_id',
                                MockLocationType('tu', 'tu'))
        return self.nikshay_codes_to_location.get('-'.join(
            self._phi_code.split('-')[:3]))

    @property
    def phi(self):
        if self.test_phi is not None:
            return MockLocation('FAKEPHI', self.test_phi,
                                MockLocationType('phi', 'phi'))
        return self.nikshay_codes_to_location.get(self._phi_code)

    @property
    def drtb_hiv(self):
        if self.test_phi is not None:
            return MockLocation('FAKEDRTBHIV', 'fake_drtb_hiv_id',
                                MockLocationType('drtb_hiv', 'drtb_hiv'))
        dto = self.nikshay_codes_to_location['-'.join(
            self._phi_code.split('-')[:2])]
        for dto_child in dto.get_children():
            if dto_child.location_type.code == 'drtb-hiv':
                return dto_child

    @property
    def _phi_code(self):
        return '%s-%s-%d-%d' % (
            self.patient_detail.scode,
            self.patient_detail.Dtocode,
            self.patient_detail.Tbunitcode,
            self.patient_detail.PHI,
        )
예제 #3
0
class EnikshayCaseFactory(object):

    domain = None
    patient_detail = None

    def __init__(self, domain, patient_detail, nikshay_codes_to_location):
        self.domain = domain
        self.patient_detail = patient_detail
        self.case_accessor = CaseAccessors(domain)
        self.nikshay_codes_to_location = nikshay_codes_to_location

    @property
    def nikshay_id(self):
        return self.patient_detail.PregId

    @property
    @memoized
    def existing_person_case(self):
        """
        Get the existing person case for this nikshay ID, or None if no person case exists
        """
        matching_external_ids = self.case_accessor.get_cases_by_external_id(self.nikshay_id, case_type='person')
        if matching_external_ids:
            assert len(matching_external_ids) == 1
            return matching_external_ids[0]
        return None

    @property
    def creating_person_case(self):
        return self.existing_person_case is not None

    @property
    @memoized
    def existing_occurrence_case(self):
        """
        Get the existing occurrence case for this nikshay ID, or None if no occurrence case exists
        """
        if self.existing_person_case:
            try:
                return get_open_occurrence_case_from_person(
                    self.domain, self.existing_person_case.case_id
                )
            except ENikshayCaseNotFound:
                return None

    @property
    @memoized
    def existing_episode_case(self):
        """
        Get the existing episode case for this nikshay ID, or None if no episode case exists
        """
        if self.existing_occurrence_case:
            try:
                return get_open_episode_case_from_occurrence(
                    self.domain, self.existing_occurrence_case.case_id
                )
            except ENikshayCaseNotFound:
                return None

    def get_case_structures_to_create(self):
        person_structure = self.get_person_case_structure()
        ocurrence_structure = self.get_occurrence_case_structure(person_structure)
        episode_structure = self.get_episode_case_structure(ocurrence_structure)
        test_structures = [
            self.get_test_case_structure(followup, ocurrence_structure) for followup in self._followups
        ]
        return [episode_structure] + test_structures

    def get_person_case_structure(self):
        kwargs = {
            'attrs': {
                'case_type': PERSON_CASE_TYPE,
                'external_id': self.nikshay_id,
                'update': {
                    'age': self.patient_detail.page,
                    'age_entered': self.patient_detail.page,
                    'contact_phone_number': validate_phone_number(self.patient_detail.pmob),
                    'current_address': self.patient_detail.paddress,
                    'current_address_district_choice': self.district.location_id,
                    'current_address_state_choice': self.state.location_id,
                    'dob': date(date.today().year - self.patient_detail.page, 7, 1),
                    'dob_known': 'no',
                    'first_name': self.patient_detail.first_name,
                    'last_name': self.patient_detail.last_name,
                    'name': self.patient_detail.pname,
                    'nikshay_id': self.nikshay_id,
                    'person_id': 'FROM_NIKSHAY_' + self.nikshay_id,
                    'secondary_contact_name_address': (
                        (self.patient_detail.cname or '')
                        + ', '
                        + (self.patient_detail.caddress or '')
                    ),
                    'secondary_contact_phone_number': validate_phone_number(self.patient_detail.cmob),
                    'sex': self.patient_detail.sex,
                    'tu_choice': self.tu.name,

                    'migration_created_case': 'true',
                },
            },
        }

        if self.phi:
            if self.phi.location_type.code == 'phi':
                kwargs['attrs']['owner_id'] = self.phi.location_id
                kwargs['attrs']['update']['phi'] = self.phi.name
            else:
                kwargs['attrs']['owner_id'] = ARCHIVED_CASE_OWNER_ID
                kwargs['attrs']['update']['archive_reason'] = 'migration_not_phi_location'
                kwargs['attrs']['update']['migration_error'] = 'not_phi_location'
                kwargs['attrs']['update']['migration_error_details'] = self._nikshay_code
        else:
            kwargs['attrs']['owner_id'] = ARCHIVED_CASE_OWNER_ID
            kwargs['attrs']['update']['archive_reason'] = 'migration_location_not_found'
            kwargs['attrs']['update']['migration_error'] = 'location_not_found'
            kwargs['attrs']['update']['migration_error_details'] = self._nikshay_code

        if self.patient_detail.paadharno is not None:
            kwargs['attrs']['update']['aadhaar_number'] = self.patient_detail.paadharno

        if self.existing_person_case is not None:
            kwargs['case_id'] = self.existing_person_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    def get_occurrence_case_structure(self, person_structure):
        """
        This gets the occurrence case structure with a nested person case structure.
        """
        kwargs = {
            'attrs': {
                'case_type': OCCURRENCE_CASE_TYPE,
                'owner_id': '-',
                'update': {
                    'current_episode_type': 'confirmed_tb',
                    'ihv_date': self.patient_detail.ihv_date,
                    'initial_home_visit_status': self.patient_detail.initial_home_visit_status,
                    'name': 'Occurrence #1',
                    'occurrence_episode_count': 1,
                    'occurrence_id': datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3],
                    'migration_created_case': 'true',
                },
            },
            'indices': [CaseIndex(
                person_structure,
                identifier='host',
                relationship=CASE_INDEX_EXTENSION,
                related_type=PERSON_CASE_TYPE,
            )],
        }
        if self._outcome:
            # TODO - store with correct value
            kwargs['attrs']['update']['hiv_status'] = self._outcome.HIVStatus

        if self.existing_occurrence_case:
            kwargs['case_id'] = self.existing_occurrence_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    def get_episode_case_structure(self, occurrence_structure):
        """
        This gets the episode case structure with a nested occurrence and person case structures
        inside of it.
        """
        kwargs = {
            'attrs': {
                'case_type': EPISODE_CASE_TYPE,
                'date_opened': self.patient_detail.pregdate1,
                'owner_id': '-',
                'update': {
                    'date_of_mo_signature': self.patient_detail.date_of_mo_signature,
                    'disease_classification': self.patient_detail.disease_classification,
                    'dots_99_enabled': 'false',
                    'episode_pending_registration': 'no',
                    'episode_type': 'confirmed_tb',
                    'name': 'Episode #1: Confirmed TB (Patient)',
                    'occupation': self.patient_detail.occupation,
                    'patient_type_choice': self.patient_detail.patient_type_choice,
                    'treatment_initiation_date': self.patient_detail.treatment_initiation_date,
                    'treatment_supporter_designation': self.patient_detail.treatment_supporter_designation,
                    'treatment_supporter_first_name': self.patient_detail.treatment_supporter_first_name,
                    'treatment_supporter_last_name': self.patient_detail.treatment_supporter_last_name,
                    'treatment_supporter_mobile_number': validate_phone_number(self.patient_detail.dotmob),

                    'migration_created_case': 'true',
                },
            },
            'indices': [CaseIndex(
                occurrence_structure,
                identifier='host',
                relationship=CASE_INDEX_EXTENSION,
                related_type=OCCURRENCE_CASE_TYPE,
            )],
        }

        if self.existing_episode_case:
            kwargs['case_id'] = self.existing_episode_case.case_id
            kwargs['attrs']['create'] = False
        else:
            kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    def get_test_case_structure(self, followup, occurrence_structure):
        kwargs = {
            'attrs': {
                'create': True,
                'case_type': TEST_CASE_TYPE,
                'owner_id': '-',
                'update': {
                    'date_tested': followup.TestDate,

                    'migration_created_case': 'true',
                    'migration_followup_id': followup.id,
                },
            },
            'indices': [CaseIndex(
                occurrence_structure,
                identifier='host',
                relationship=CASE_INDEX_EXTENSION,
                related_type=occurrence_structure.attrs['case_type'],
            )],
            # this prevents creating duplicate occurrence data on creation of the test cases
            'walk_related': False,
        }

        if self.existing_occurrence_case:
            matching_test_case = next((
                extension_case for extension_case in self.case_accessor.get_cases([
                    index.referenced_id for index in
                    self.existing_occurrence_case.reverse_indices
                ])
                if (
                    extension_case.type == TEST_CASE_TYPE
                    and followup.id == int(extension_case.dynamic_case_properties().get('migration_followup_id', -1))
                )
            ), None)
            if matching_test_case:
                kwargs['case_id'] = matching_test_case.case_id
                kwargs['attrs']['create'] = False
            else:
                kwargs['attrs']['create'] = True

        return CaseStructure(**kwargs)

    @property
    @memoized
    def _outcome(self):
        zero_or_one_outcomes = list(Outcome.objects.filter(PatientId=self.patient_detail))
        if zero_or_one_outcomes:
            return zero_or_one_outcomes[0]
        else:
            return None

    @property
    @memoized
    def _followups(self):
        return Followup.objects.filter(PatientID=self.patient_detail)

    @property
    def state(self):
        return self.nikshay_codes_to_location.get(self.patient_detail.PregId.split('-')[0])

    @property
    def district(self):
        return self.nikshay_codes_to_location.get('-'.join(self.patient_detail.PregId.split('-')[:2]))

    @property
    def tu(self):
        return self.nikshay_codes_to_location.get('-'.join(self.patient_detail.PregId.split('-')[:3]))

    @property
    def phi(self):
        return self.nikshay_codes_to_location.get(self._nikshay_code)

    @property
    def _nikshay_code(self):
        return '-'.join(self.patient_detail.PregId.split('-')[:4])