def add_form_to_patient(line): change = Change(line) # check the global max seq in this process to avoid repeating ourselves. if change.seq < max_seq: return log_and_abort(logging.DEBUG, "ignoring item %s because it's seq is old") update_max_seq(change) form_id = change.id # don't bother with deleted or old documents if change.deleted or not change.is_current(db): return formdoc = CXFormInstance.get(form_id) pat_id = get_patient_id_from_form(formdoc) if pat_id is not None and get_classification(formdoc.namespace) == "clinic": try: # this is so we don't get conflicting updates. # resolve conflicts and bump version numbers before adding forms pat_data = get_db().get(pat_id, conflicts=True) if "_conflicts" in pat_data: return log_and_abort(logging.INFO, "ignoring patient %s because there are still conflicts that need to be resolved" % pat_id) else: pat = CPatient.wrap(pat_data) if pat.requires_upgrade(): return log_and_abort(logging.INFO, "ignoring patient %s, form %s because it is not yet upgraded to the latest version" % (pat_id, form_id)) found_ids = [enc.xform_id for enc in pat.encounters] if form_id in found_ids and not formdoc.requires_upgrade(): return log_and_abort(logging.DEBUG, "Already found appropriate version of form %s in patient %s, no need to do anything" % (form_id, pat_id)) else: print "Form %s not found in patient %s or was old. Rebuilding the patient now" % (form_id, pat_id) reprocess(pat_id) except ResourceNotFound, e: return log_and_abort(logging.WARNING, "tried to check form %s in patient %s but patient has been deleted. Ignoring" % (form_id, pat_id))
def post_xform_to_couch(instance): """ Post an xform to couchdb, based on the settings.XFORMS_POST_URL. Returns the newly created document from couchdb, or raises an exception if anything goes wrong """ def _has_errors(response, errors): return errors or "error" in response # check settings for authentication credentials try: response, errors = post_from_settings(instance) if not _has_errors(response, errors): doc_id = response try: xform = CXFormInstance.get(doc_id) # fire signals feedback = xform_saved.send_robust(sender="post", form=xform) for func, errors in feedback: if errors: logging.error("Problem sending post-save signal %s for xform %s" % (func, doc_id)) xform.release_lock() return xform except Exception, e: logging.exception("Problem accessing form %s after post" % doc_id) raise else:
def single_patient(request, patient_id): patient = loader.get_patient(patient_id) xforms = CXFormInstance.view("patient/xforms", key=patient.get_id, include_docs=True) encounter_types = get_encounters(patient) options = TouchscreenOptions.default() # TODO: are we upset about how this breaks MVC? options.nextbutton.show = False options.backbutton = ButtonOptions(text="BACK", link=reverse("patient_select")) encounters = sorted(patient.encounters, key=lambda encounter: encounter.visit_date, reverse=True) # TODO: figure out a way to do this more centrally # Inject cases into encounters so we can show them linked in the view for encounter in patient.encounters: if encounter.get_xform(): encounter.dynamic_data["classification"] = get_classification(encounter.get_xform().namespace) encounter.dynamic_data["cases"] = [] for case in patient.cases: if case.encounter_id == encounter.get_id: encounter.dynamic_data["cases"].append(case) return render_to_response(request, "patient/single_patient_touchscreen.html", {"patient": patient, "encounters": encounters, "xforms": xforms, "encounter_types": encounter_types, "options": options })
def add_sha1_to_line(line): try: xform_id = line["id"] xform = CXFormInstance.get(xform_id) add_sha1(None, xform) except Exception: logging.exception("problem with sha1 callback")
def pi_details(request): year = int(request.GET["year"]) month = int(request.GET["month"]) clinic = request.GET["clinic"] report_slug = request.GET["report"] col_slug = request.GET["col"] results = get_db().view(const.get_view_name(report_slug), reduce=False, key=[year, month -1, clinic, col_slug], include_docs=True) forms = [] for row in results: num, denom = row["value"] # only count forms for now, and make sure they have a patient id # and contributed to the report denominator if row["doc"]["doc_type"] == "CXFormInstance" and denom > 0: form = CXFormInstance.wrap(row["doc"]) try: form.patient_id = form.xpath("case/patient_id") form.bhoma_patient_id = CPatient.get(form.patient_id).formatted_id except ResourceNotFound: form.patient = form.patient_id = form.bhoma_patient_id = None form.num = num form.denom = denom form.good = num == denom forms.append(form) elif row["doc"]["doc_type"] == "PregnancyReportRecord" and denom > 0: # for the pregnancy PI force the aggregated pregnancy docs # to look like forms preg = PregnancyReportRecord.wrap(row["doc"]) try: preg.bhoma_patient_id = CPatient.get(preg.patient_id).formatted_id except ResourceNotFound: form.patient = form.patient_id = form.bhoma_patient_id = None preg.num = num preg.denom = denom preg.good = num == denom preg.encounter_date = preg.first_visit_date forms.append(preg) title = "PI Details - %s: %s (%s, %s)" % (const.get_name(report_slug), const.get_display_name(report_slug, col_slug), datetime(year, month, 1).strftime("%B %Y"), clinic_display_name(clinic)) return render_to_response(request, "reports/pi_details.html", {"report": {"name": title}, "forms": forms})
def delete_all_xforms(): for form in CXFormInstance.view(const.VIEW_XFORMS_BY_XMLNS, include_docs=True).all(): form.delete()
def get_bhoma_case_id_from_pregnancy(pregnancy): """ Generate a unique (but deterministic) bhoma case id from pregnancy data. """ return "preg%s" % CXFormInstance.get(pregnancy.anchor_form_id).sha1