Exemplo n.º 1
0
def get_open_cases_to_send(clinic_id, zone, last_sync):
    """
    Given a list of patients, get the open/updated cases since the last sync
    operation.  This returns tuples phone_case objects, and flags that say 
    whether or not they should be created
    """ 
    to_return = []
    case_ids = []
    # find all relevant cases for the CHW and send them to the phone, unless
    # they have already been sent and haven't changed.
    potential_case_list = PatientCase.view_with_patient("case/open_for_chw_for_phone", key=[clinic_id, zone])
    last_sync_date = datetime.min if not last_sync else last_sync.date 
    for case in potential_case_list:
        # keep a running list of case ids sent down because the phone doesn't
        # deal well with duplicates.  There shouldn't be duplicates, but they
        # can come up with bugs, so arbitrarily only send down the first case
        # if there are any duplicates
        if case.get_id not in case_ids:
            phone_case = PhoneCase.from_bhoma_case(case)
            if phone_case is None:
                # we don't expect to get into this scenario, but it can happen 
                # don't fail hard with null reference below
                continue
            previously_synced = case_previously_synced(phone_case.case_id, last_sync)
            if phone_case and phone_case.is_started() and not phone_case.is_over():
                # this is an active case, so send it unless it's a duplicate
                # or was already synced
                if phone_case.case_id in case_ids:
                    logging.warning("Found a duplicate case for %s. Will not be sent to phone." % phone_case.case_id)
                elif previously_synced and phone_case.date_modified < last_sync_date:
                    logging.debug("Case %s already sent to phone and no changes. Won't be sent again" % phone_case.case_id)
                else:
                    case_ids.append(phone_case.case_id)
                    to_return.append((phone_case, not previously_synced))
    return to_return
Exemplo n.º 2
0
Arquivo: case.py Projeto: dimagi/bhoma
def get_healthy_pregnancy_case(pregnancy, encounter):
    # Any pregnancy case that is created that hasn't been closed by a delivery 
    # gets a followup.  The followups become active at week 42 and expires in
    # week 46 of the pregnancy
    # The CHW should track the delivery and give an outcome to the pregnancy.
    
    lmp = pregnancy.lmp
    # TODO: is this check/logic necessary?
    if lmp:
        send_to_phone = True
        reason = "pregnancy_expecting_outcome"
    else:
        send_to_phone = False
        reason = "unknown_lmp"
    
    ltfu_date = lmp + timedelta(days=46*7) if lmp else None
    bhoma_case = PatientCase(_id=get_bhoma_case_id_from_pregnancy(pregnancy), 
                             opened_on=datetime.combine(encounter.visit_date, time()),
                             modified_on=datetime.utcnow(),
                             type=const.CASE_TYPE_PREGNANCY,
                             encounter_id=encounter.get_id,
                             patient_id=get_patient_id_from_form(encounter.get_xform()),
                             ltfu_date=ltfu_date,
                             outcome=pregnancy.outcome,
                             closed=pregnancy.closed,
                             closed_on=pregnancy.closed_on,
                             send_to_phone=send_to_phone,
                             send_to_phone_reason=reason)
    bhoma_case.status = "pending outcome"
    
    if send_to_phone and not bhoma_case.closed:
        cccase = get_first_commcare_case(encounter, bhoma_case=bhoma_case, 
                                     case_id=get_commcare_case_id_from_block(encounter,bhoma_case))
        cccase.followup_type = const.PHONE_FOLLOWUP_TYPE_PREGNANCY
    
        # starts and becomes active the same day, 42 weeks from LMP
        bhoma_case.lmp = lmp
        cccase.start_date = lmp + timedelta(days= 7 * 42)
        cccase.missed_appointment_date = cccase.start_date
        cccase.activation_date = cccase.start_date
        cccase.due_date = cccase.activation_date + timedelta(days=DAYS_AFTER_PREGNANCY_ACTIVE_DUE)
        bhoma_case.commcare_cases = [cccase]
    return bhoma_case
Exemplo n.º 3
0
def duplicate_details(request, case_id):
    case_details = PatientCase.view("case/all_and_patient", key=case_id)
    return render_to_response('case/details.html',
                              {"case_id": case_id, 
                               "cases" : case_details},
                               context_instance=RequestContext(request))
Exemplo n.º 4
0
def get_delivery_case(patient, encounter, delivery):
    # All deliveries get two follow ups.

    if delivery.date:
        send_to_phone = True
        reason = "delivery_needing_followup"
    else:
        send_to_phone = False
        reason = "unknown_delivery_date"

    # todo proper ltfu date
    ltfu_date = delivery.date + timedelta(days=7*42)
    bhoma_case = PatientCase(
        _id=get_bhoma_case_id_from_delivery(delivery),
        opened_on=datetime.combine(encounter.visit_date, time()),
        modified_on=datetime.utcnow(),
        type=const.CASE_TYPE_DELIVERY,
        encounter_id=encounter.get_id,
        patient_id=patient._id,
        ltfu_date=ltfu_date,
        status="pending outcome",
        outcome=delivery.outcome,
        closed=delivery.closed,
        closed_on=delivery.closed_on,
        send_to_phone=send_to_phone,
        send_to_phone_reason=reason,
    )

    if send_to_phone and not bhoma_case.closed:
        # we'll generate two commcare cases immedieately
        ccfu1 = get_first_commcare_case(
            encounter,
            bhoma_case=bhoma_case,
            case_id=get_commcare_case_id_from_delivery(delivery, 1)
        )
        ccfu1.followup_type = const.PHONE_FOLLOWUP_TYPE_DELIVERY

        # starts after 4 days, active after 6 days
        ccfu1.start_date = delivery.date + timedelta(days=1)
        ccfu1.orig_visit_date = delivery.date
        ccfu1.missed_appointment_date = None # TODO: do we need to change this so the phone can use it?
        ccfu1.activation_date = delivery.date + timedelta(days=2)
        ccfu1.due_date = ccfu1.activation_date + timedelta(days=14)
        ccfu1.ltfu_date = ccfu1.activation_date + timedelta(days=24)
        ccfu1.visit_number = '1'

        ccfu2 = get_first_commcare_case(
            encounter,
            bhoma_case=bhoma_case,
            case_id=get_commcare_case_id_from_delivery(delivery, 2)
        )
        ccfu2.followup_type = const.PHONE_FOLLOWUP_TYPE_DELIVERY

        # starts after 23 days, active after 28 days, due in 5, ltfu after 42
        ccfu2.start_date = delivery.date + timedelta(days=23)
        ccfu2.orig_visit_date = delivery.date
        ccfu2.missed_appointment_date = None # TODO: do we need to change this so the phone can use it?
        ccfu2.activation_date = delivery.date + timedelta(days=28)
        ccfu2.due_date = ccfu2.activation_date + timedelta(days=5)
        ccfu2.ltfu_date = ccfu2.activation_date + timedelta(days=42)
        ccfu2.visit_number = '2'


        bhoma_case.commcare_cases = [ccfu1, ccfu2]
    return bhoma_case
Exemplo n.º 5
0
def process_followup(patient, new_encounter):
    form = new_encounter.get_xform()
    assert form.namespace == config.CHW_FOLLOWUP_NAMESPACE
    caseblocks = extract_case_blocks(form)
    for caseblock in caseblocks:
        case_id = caseblock[const.CASE_TAG_ID]
        # find bhoma case 
        try:
            results = get_db().view("case/bhoma_case_lookup", key=case_id, reduce=False).one()
        except MultipleResultsFound:
            logging.error("Found duplicate cases in a patient: patient_id: %s, case_id: %s" % (patient.get_id, case_id))
            results = None
        if results:
            raw_data = results["value"]
            bhoma_case = PatientCase.wrap(raw_data)
            for case in bhoma_case.commcare_cases:
                if case.case_id == case_id:
                    # apply generic commcare update to the case
                    case.update_from_block(caseblock, new_encounter.visit_date)
                    
                    # apply custom updates to bhoma case
                    bhoma_case_close_value = case.all_properties().get(const.CASE_TAG_BHOMA_CLOSE, None)
                    bhoma_case_outcome_value = case.all_properties().get(const.CASE_TAG_BHOMA_OUTCOME, "")
                            
                    if bhoma_case_close_value and int(bhoma_case_close_value):
                        # bhoma case should be closed
                        if bhoma_case.closed:
                            logging.warn("Tried to close case %s from phone but it was already closed! Ignoring." % bhoma_case.get_id) 
                        else:
                            bhoma_case.closed = True
                            bhoma_case.outcome = bhoma_case_outcome_value
                            bhoma_case.closed_on = datetime.combine(new_encounter.visit_date, time())
                    else:
                        # we didn't close the bhoma case, check if we need to 
                        # create any new commcare cases

                        # referred back: create an appointment
                        if bhoma_case_outcome_value == const.Outcome.REFERRED_BACK_TO_CLINIC:
                            appt_date_string = form.xpath("met/followup/refer_when")
                            if appt_date_string:
                                new_case = new_commcare_case(case_id=get_commcare_case_id_from_block(new_encounter, bhoma_case),
                                                             name=get_commcare_case_name(new_encounter, bhoma_case), 
                                                             type=bhoma_case.type, 
                                                             opened_on=datetime.combine(new_encounter.visit_date, time()), 
                                                             modified_on=datetime.utcnow(),
                                                             user_id=get_user_id(new_encounter), 
                                                             encounter_id=new_encounter.get_id, 
                                                             bhoma_case_id=bhoma_case.get_id)
                                new_case.followup_type = const.PHONE_FOLLOWUP_TYPE_MISSED_APPT
                                appt_date = string_to_datetime(appt_date_string).date()
                                add_missed_appt_dates(new_case, appt_date)
                                bhoma_case.status = const.Status.RETURN_TO_CLINIC
                                bhoma_case.commcare_cases.append(new_case)
                        elif bhoma_case_outcome_value == const.Outcome.ACTUALLY_WENT_TO_CLINIC:
                            bhoma_case.status = const.STATUS_WENT_BACK_TO_CLINIC
                        elif bhoma_case_outcome_value == const.Outcome.PENDING_PATIENT_MEETING:
                            bhoma_case.status = const.STATUS_PENDING_CHW_MEETING

            if is_delivery(bhoma_case):
                custom_process_delivery_case(bhoma_case, new_encounter)

            patient.update_cases([bhoma_case])
        else:
            logging.error(("No case in patient %s with id %s found.  "
                           "If you are not debugging then this is a weird error.") % (patient.get_id, case_id))
Exemplo n.º 6
0
def cases_for_patient(patient_id):
    """
    Get the list of open cases for a particular patient
    """
    return PatientCase.view_with_patient("case/open_for_patient", key=patient_id).all()
Exemplo n.º 7
0
def cases_for_chw(chw):
    """
    From chw clinic zone, get the list of open cases
    """
    key = [chw.current_clinic_id, chw.current_clinic_zone]
    return PatientCase.view_with_patient("case/open_for_chw", key=key).all()