def dots_submissions_by_case(case_id, query_date, username=None): """ Actually run query for username submissions todo: do terms for the pact_ids instead of individual term? """ xform_es = ReportXFormES(PACT_DOMAIN) script_fields = { "doc_id": get_report_script_field('_id', is_known=True), "pact_id": get_report_script_field("form.pact_id"), "encounter_date": get_report_script_field('form.encounter_date'), "username": get_report_script_field('form.meta.username', is_known=True), "visit_type": get_report_script_field('form.visit_type'), "visit_kept": get_report_script_field('form.visit_kept'), "contact_type": get_report_script_field('form.contact_type'), "observed_art": get_report_script_field('form.observed_art'), "observed_non_art": get_report_script_field('form.observed_non_art'), "observer_non_art_dose": get_report_script_field('form.observed_non_art_dose'), "observed_art_dose": get_report_script_field('form.observed_art_dose'), "pillbox_check": get_report_script_field('form.pillbox_check.check'), "scheduled": get_report_script_field('form.scheduled'), } term_block = {'form.#type': 'dots_form'} if username is not None: term_block['form.meta.username'] = username query = xform_es.by_case_id_query(PACT_DOMAIN, case_id, terms=term_block, date_field='form.encounter_date.#value', startdate=query_date, enddate=query_date) query['sort'] = {'received_on': 'asc'} query['script_fields'] = script_fields query['size'] = 1 query['from'] = 0 res = xform_es.run_query(query) print(json.dumps(res, indent=2)) return res
def dots_submissions_by_case(case_id, query_date, username=None): """ Actually run query for username submissions todo: do terms for the pact_ids instead of individual term? """ xform_es = ReportXFormES(PACT_DOMAIN) script_fields = { "doc_id": get_report_script_field('_id', is_known=True), "pact_id": get_report_script_field("form.pact_id"), "encounter_date": get_report_script_field('form.encounter_date'), "username": get_report_script_field('form.meta.username', is_known=True), "visit_type": get_report_script_field('form.visit_type'), "visit_kept": get_report_script_field('form.visit_kept'), "contact_type": get_report_script_field('form.contact_type'), "observed_art": get_report_script_field('form.observed_art'), "observed_non_art": get_report_script_field('form.observed_non_art'), "observer_non_art_dose": get_report_script_field('form.observed_non_art_dose'), "observed_art_dose": get_report_script_field('form.observed_art_dose'), "pillbox_check": get_report_script_field('form.pillbox_check.check'), "scheduled": get_report_script_field('form.scheduled'), } term_block = {'form.#type': 'dots_form'} if username is not None: term_block['form.meta.username'] = username query = xform_es.by_case_id_query(PACT_DOMAIN, case_id, terms=term_block, date_field='form.encounter_date.#value', startdate=query_date, enddate=query_date) query['sort'] = {'received_on': 'asc'} query['script_fields'] = script_fields query['size'] = 1 query['from'] = 0 res = xform_es.run_query(query) print simplejson.dumps(res, indent=2) return res
def report_context(self): ret = {} if 'dot_patient' not in self.request.GET or self.request.GET.get( 'dot_patient') == "": self.report_template_path = "pact/dots/dots_report_nopatient.html" return ret submit_id = self.request.GET.get('submit_id', None) ret['dot_case_id'] = self.request.GET['dot_patient'] casedoc = PactPatientCase.get(ret['dot_case_id']) ret['patient_case'] = casedoc start_date_str = self.request.GET.get( 'startdate', json_format_date(datetime.utcnow() - timedelta(days=7))) end_date_str = self.request.GET.get( 'enddate', json_format_date(datetime.utcnow())) start_date = datetime.combine(iso_string_to_date(start_date_str), time()) end_date = datetime.combine(iso_string_to_date(end_date_str), time()) ret['startdate'] = start_date_str ret['enddate'] = end_date_str dcal = DOTCalendarReporter(casedoc, start_date=start_date, end_date=end_date, submit_id=submit_id) ret['dot_calendar'] = dcal unique_visits = dcal.unique_xforms() xform_es = ReportXFormES(PACT_DOMAIN) q = xform_es.base_query(size=len(unique_visits)) lvisits = list(unique_visits) if len(lvisits) > 0: q['filter']['and'].append({"ids": {"values": lvisits}}) #todo double check pactid/caseid matches q['sort'] = {'received_on': 'desc'} res = xform_es.run_query(q) #ugh, not storing all form data by default - need to get? ret['sorted_visits'] = [ DOTSubmission.wrap(x['_source']) for x in [ x for x in res['hits']['hits'] if x['_source']['xmlns'] == XMLNS_DOTS_FORM ] ] return ret
def es_results(self): if not self.patient_id: return None full_query = ReportXFormES.by_case_id_query(self.request.domain, self.patient_id) full_query.update({ "fields": [ "_id", "received_on", "form.meta.timeEnd", "form.meta.timeStart", "form.meta.username", "form.#type", ], "sort": self.get_sorting_block(), "size": self.pagination.count, "from": self.pagination.start }) full_query['script_fields'] = pact_script_fields() res = self.xform_es.run_query(full_query) return res
def handle(self, **options): xform_es = ReportXFormES(PACT_DOMAIN) offset = 0 q = REPORT_XFORM_MISSING_DOTS_QUERY q['size'] = CHUNK_SIZE while True: # q['from'] = offset res = xform_es.run_query(q) print("####### Query block total: %s" % res['hits']['total']) print(res['hits']['hits']) if len(res['hits'].get('hits', [])) == 0: break else: for hit in res['hits']['hits']: doc_id = hit['_id'] if doc_id in self.seen_doc_ids: continue else: self.seen_doc_ids[doc_id] = 1 offset += CHUNK_SIZE
def report_context(self): ret = {} if not self.request.GET.has_key('dot_patient') or self.request.GET.get('dot_patient') == "": self.report_template_path = "pact/dots/dots_report_nopatient.html" return ret submit_id = self.request.GET.get('submit_id', None) ret['dot_case_id'] = self.request.GET['dot_patient'] casedoc = PactPatientCase.get(ret['dot_case_id']) ret['patient_case'] = casedoc start_date_str = self.request.GET.get('startdate', (datetime.utcnow() - timedelta(days=7)).strftime( '%Y-%m-%d')) end_date_str = self.request.GET.get('enddate', datetime.utcnow().strftime("%Y-%m-%d")) start_date = datetime.strptime(start_date_str, "%Y-%m-%d") end_date = datetime.strptime(end_date_str, "%Y-%m-%d") ret['startdate'] = start_date_str ret['enddate'] = end_date_str dcal = DOTCalendarReporter(casedoc, start_date=start_date, end_date=end_date, submit_id=submit_id) ret['dot_calendar'] = dcal unique_visits = dcal.unique_xforms() xform_es = ReportXFormES(PACT_DOMAIN) q = xform_es.base_query(size=len(unique_visits)) lvisits = list(unique_visits) if len(lvisits) > 0: q['filter']['and'].append({"ids": {"values": lvisits}}) #todo double check pactid/caseid matches q['sort'] = {'received_on': 'desc'} res = xform_es.run_query(q) #ugh, not storing all form data by default - need to get? ret['sorted_visits'] = [DOTSubmission.wrap(x['_source']) for x in filter(lambda x: x['_source']['xmlns'] == XMLNS_DOTS_FORM, res['hits']['hits'])] return ret
def handle_noargs(self, **options): xform_es = ReportXFormES(PACT_DOMAIN) offset = 0 q = REPORT_XFORM_MISSING_DOTS_QUERY q['size'] = CHUNK_SIZE while True: # q['from'] = offset res = xform_es.run_query(q) print "####### Query block total: %s" % res['hits']['total'] print res['hits']['hits'] if len(res['hits'].get('hits', [])) == 0: break else: for hit in res['hits']['hits']: doc_id = hit['_id'] if self.seen_doc_ids.has_key(doc_id): continue else: self.seen_doc_ids[doc_id ] =1 offset += CHUNK_SIZE
class PactFormAPI(DomainAPI): xform_es = ReportXFormES(PACT_DOMAIN) @classmethod def allowed_domain(self, domain): return PACT_DOMAIN @classmethod def api_version(cls): return "1" @classmethod def api_name(cls): return "pact_formdata" @method_decorator(httpdigest) @method_decorator(login_or_digest) def get(self, *args, **kwargs): """ Download prior progress note submissions for local access """ db = XFormInstance.get_db() couch_user = CouchUser.from_django_user(self.request.user) username = couch_user.raw_username if hasattr(localsettings, 'debug_pact_user'): username = getattr(localsettings, 'debug_pact_user')(username) offset =0 limit_count=200 total_count = 0 query = { "query": { "filtered": { "filter": { "and": [ {"term": {"domain.exact": "pact"}}, {"term": {"form.#type": "progress_note"}}, {"term": {"form.meta.username": username}} ] }, "query": {"match_all": {}} } }, "sort": {"received_on": "asc"}, "size": limit_count, "fields": ['_id', 'external_blobs'] } query['script_fields'] = {} query['script_fields'].update(pact_script_fields()) query['script_fields'].update(case_script_field()) res = self.xform_es.run_query(query) my_patients_ever_submitted_query = query_per_case_submissions_facet(PACT_DOMAIN, username) patients_res = self.xform_es.run_query(my_patients_ever_submitted_query) #filter by active/discharged? #get all the forms #get all the patients #get all patients to determine which to filter. active_patients = [] for pt in []: #if pt.hp_status == "Discharged": #continue case_id = pt['script_case_id'] active_patients.append(case_id) def return_iterator(): yield "<restoredata>" for result in res['hits']['hits']: data_row = result['fields'] # if data_row['script_case_id'] not in active_patients: # continue try: xml_str = (BlobHelper(data_row, db, CODES.form_xml) .fetch_attachment('form.xml').decode('utf-8') .replace("<?xml version=\'1.0\' ?>", '') .replace("<?xml version='1.0' encoding='UTF-8' ?>", '')) yield xml_str except Exception as ex: logging.error("for downloader: error fetching attachment: %s" % ex) yield "</restoredata>" response = HttpResponse(return_iterator(), content_type='text/xml') return response
class PactPatientInfoReport(PactDrilldownReportMixin, PactElasticTabularReportMixin): slug = "patient" description = "some patient" hide_filters = True filters = [] ajax_pagination = True xform_es = ReportXFormES(PACT_DOMAIN) default_sort = {"received_on": "desc"} name = "Patient Info" @use_timeago def decorator_dispatcher(self, request, *args, **kwargs): return super(PactPatientInfoReport, self).decorator_dispatcher(request, *args, **kwargs) @property def patient_id(self): return self.request.GET.get('patient_id') def get_case(self): if self.patient_id is None: return None return PactPatientCase.get(self.patient_id) @property def report_context(self): from pact import api ret = {} try: patient_doc = self.get_case() has_error = False except Exception as ex: logging.exception( 'problem getting pact patient data for patient {}. {}'.format( self.patient_id, ex)) has_error = True patient_doc = None if patient_doc is None: self.report_template_path = "pact/patient/nopatient.html" if has_error: ret['error_message'] = "Patient not found" else: ret['error_message'] = "No patient selected" return ret view_mode = self.request.GET.get('view', 'info') ret['patient_doc'] = patient_doc ret['pt_root_url'] = patient_doc.get_info_url() ret['view_mode'] = view_mode if view_mode == 'info': self.report_template_path = "pact/patient/pactpatient_info.html" ret['cloudcare_addr_edit_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_ADDRESS) ret['cloudcare_pn_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_PROGRESS_NOTE) ret['cloudcare_dot_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_DOT) ret['cloudcare_bw_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_BLOODWORK) elif view_mode == 'submissions': tabular_context = super(PactPatientInfoReport, self).report_context tabular_context.update(ret) self.report_template_path = "pact/patient/pactpatient_submissions.html" return tabular_context elif view_mode == 'schedule': the_form = ScheduleForm() ret['schedule_form'] = the_form ret['schedule_fields'] = json.dumps(list(the_form.fields.keys())) self.report_template_path = "pact/patient/pactpatient_schedule.html" elif view_mode == 'edit': the_form = PactPatientForm(self.request, patient_doc) ret['patient_form'] = the_form self.report_template_path = "pact/patient/pactpatient_edit.html" elif view_mode == 'providers': self.report_template_path = "pact/patient/pactpatient_providers.html" elif view_mode == 'careplan': ret.update( case_hierarchy_context( patient_doc, lambda case_id: reverse('case_data', args=[PACT_DOMAIN, case_id]), show_view_buttons=False)) self.report_template_path = "pact/patient/pactpatient_careplan.html" else: raise Http404 return ret @property def headers(self): return DataTablesHeader( DataTablesColumn("Show Form", sortable=False, span=1), DataTablesColumn("Received", prop_name="received_on", span=1), DataTablesColumn("Created Date", prop_name="form.meta.timeStart", span=1), DataTablesColumn("Encounter Date", sortable=False, span=1), DataTablesColumn("Form", prop_name="form.#type", span=1), DataTablesColumn("CHW", prop_name="form.meta.username", span=1)) @property def es_results(self): if not self.patient_id: return None full_query = ReportXFormES.by_case_id_query(self.request.domain, self.patient_id) full_query.update({ "fields": [ "_id", "received_on", "form.meta.timeEnd", "form.meta.timeStart", "form.meta.username", "form.#type", ], "sort": self.get_sorting_block(), "size": self.pagination.count, "from": self.pagination.start }) full_query['script_fields'] = pact_script_fields() res = self.xform_es.run_query(full_query) return res @property def rows(self): if self.patient_id: def _format_row(row_field_dict): yield mark_safe( "<a class='ajax_dialog' href='%s'>View</a>" % (reverse('render_form_data', args=[self.domain, row_field_dict['_id']]))) yield self.format_date(row_field_dict["received_on"].replace( '_', ' ')) yield self.format_date( row_field_dict.get("form.meta.timeStart", "")) if row_field_dict["script_encounter_date"] != None: yield row_field_dict["script_encounter_date"] else: yield "---" yield row_field_dict["form.#type"].replace('_', ' ').title() yield row_field_dict.get("form.meta.username", "") res = self.es_results if 'error' in res: pass else: for result in res['hits']['hits']: yield list(_format_row(result['fields']))
class PactPatientInfoReport(PactDrilldownReportMixin, PactElasticTabularReportMixin): slug = "patient" description = "some patient" hide_filters = True filters = [] ajax_pagination = True xform_es = ReportXFormES(PACT_DOMAIN) default_sort = {"received_on": "desc"} name = "Patient Info" @use_timeago def decorator_dispatcher(self, request, *args, **kwargs): return super(PactPatientInfoReport, self).decorator_dispatcher(request, *args, **kwargs) @property def patient_id(self): return self.request.GET.get('patient_id') def get_case(self): if self.patient_id is None: return None return PactPatientCase.get(self.patient_id) @property def report_context(self): from pact import api ret = {} try: patient_doc = self.get_case() has_error = False except Exception, ex: logging.exception( u'problem getting pact patient data for patient {}. {}'.format( self.patient_id, ex)) has_error = True patient_doc = None if patient_doc is None: self.report_template_path = "pact/patient/nopatient.html" if has_error: ret['error_message'] = "Patient not found" else: ret['error_message'] = "No patient selected" return ret view_mode = self.request.GET.get('view', 'info') ret['patient_doc'] = patient_doc ret['pt_root_url'] = patient_doc.get_info_url() ret['view_mode'] = view_mode if view_mode == 'info': self.report_template_path = "pact/patient/pactpatient_info.html" ret['cloudcare_addr_edit_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_ADDRESS) ret['cloudcare_pn_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_PROGRESS_NOTE) ret['cloudcare_dot_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_DOT) ret['cloudcare_bw_url'] = api.get_cloudcare_url( patient_doc._id, api.FORM_BLOODWORK) elif view_mode == 'submissions': tabular_context = super(PactPatientInfoReport, self).report_context tabular_context.update(ret) self.report_template_path = "pact/patient/pactpatient_submissions.html" return tabular_context elif view_mode == 'schedule': the_form = ScheduleForm() ret['schedule_form'] = the_form ret['schedule_fields'] = json.dumps(the_form.fields.keys()) self.report_template_path = "pact/patient/pactpatient_schedule.html" elif view_mode == 'edit': the_form = PactPatientForm(self.request, patient_doc) ret['patient_form'] = the_form self.report_template_path = "pact/patient/pactpatient_edit.html" elif view_mode == 'providers': self.report_template_path = "pact/patient/pactpatient_providers.html" elif view_mode == 'careplan': ret.update({ 'case_hierarchy_options': { "show_view_buttons": False, "get_case_url": lambda case_id: reverse('case_details', args=[PACT_DOMAIN, case_id]) }, 'case': patient_doc, }) self.report_template_path = "pact/patient/pactpatient_careplan.html" else: raise Http404 return ret
class PatientListDashboardReport(PactElasticTabularReportMixin): name = "All Patients" slug = "patients" ajax_pagination = True asynchronous = True default_sort = {"pactid": "asc"} report_template_path = "reports/async/tabular.html" flush_layout = True fields = [ 'pact.reports.patient_list.PactPrimaryHPField', 'pact.reports.patient_list.HPStatusField', 'pact.reports.patient_list.DOTStatus', ] case_es = ReportCaseES(PACT_DOMAIN) xform_es = ReportXFormES(PACT_DOMAIN) def get_pact_cases(self): query = self.case_es.base_query(start=0, size=None) query['fields'] = ['_id', 'name', 'pactid.#value'] results = self.case_es.run_query(query) for res in results['hits']['hits']: yield res['fields'] @property def headers(self): headers = DataTablesHeader( DataTablesColumn("PACT ID", prop_name="pactid.#value"), DataTablesColumn("Name", prop_name="name", sortable=False, span=3), DataTablesColumn("Primary HP", prop_name="hp.#value"), DataTablesColumn("Opened On", prop_name="opened_on"), DataTablesColumn("Last Modified", prop_name="modified_on"), DataTablesColumn("HP Status", prop_name="hp_status.#value"), DataTablesColumn("DOT Status", prop_name='dot_status.#value'), DataTablesColumn("Status", prop_name="closed"), DataTablesColumn("Submissions", sortable=False), ) return headers def case_submits_facet_dict(self, limit): query = query_per_case_submissions_facet(self.request.domain, limit=limit) results = self.xform_es.run_query(query) case_id_count_map = {} for f in results['facets']['case_submissions']['terms']: case_id_count_map[f['term']] = f['count'] return case_id_count_map @property def rows(self): """ Override this method to create a functional tabular report. Returns 2D list of rows. [['row1'],[row2']] """ def _format_row(row_field_dict): yield row_field_dict.get("pactid.#value", '---').replace('_', ' ').title() yield self.pact_case_link(row_field_dict['_id'], row_field_dict.get("name", "---")), yield row_field_dict.get("hp.#value", "---") yield self.format_date(row_field_dict.get("opened_on")) yield self.format_date(row_field_dict.get("modified_on")) yield self.render_hp_status(row_field_dict.get("hp_status.#value")) yield self.pact_dot_link(row_field_dict['_id'], row_field_dict.get("dot_status.#value")) #for closed on, do two checks: if row_field_dict.get('closed', False): #it's closed yield "Closed (%s)" % self.format_date(row_field_dict.get('closed_on')) else: yield "Active" yield facet_dict.get(row_field_dict['_id'], 0) res = self.es_results if res.has_key('error'): pass else: #hack, do a facet query here facet_dict = self.case_submits_facet_dict(SIZE_LIMIT) for result in res['hits']['hits']: yield list(_format_row(result['fields'])) @property def es_results(self): fields = [ "_id", "name", "pactid.#value", "opened_on", "modified_on", "hp_status.#value", "hp.#value", "dot_status.#value", "closed_on", "closed" ] full_query = self.case_es.base_query(terms={'type': PACT_CASE_TYPE}, fields=fields, start=self.pagination.start, size=self.pagination.count) full_query['sort'] = self.get_sorting_block() def status_filtering(slug, field, prefix, any_field, default): if self.request.GET.get(slug, None) is not None: field_status_filter_query = self.request.GET[slug] if field_status_filter_query == "": #silly double default checker here - set default or the any depending on preference field_status_filter_query = default if field_status_filter_query is None: return else: if field_status_filter_query.startswith(prefix): field_status_prefix = field_status_filter_query elif field_status_filter_query == any_field: field_status_prefix = prefix else: field_status_prefix = None full_query['filter']['and'].append({"term": {field: field_status_filter_query.lower()}}) if field_status_prefix is not None: field_filter = {"prefix": {field: field_status_prefix.lower()}} full_query['filter']['and'].append(field_filter) status_filtering(DOTStatus.slug, "dot_status.#value", "DOT", DOTStatus.ANY_DOT, None) status_filtering(HPStatusField.slug, "hp_status.#value", "HP", HPStatusField.ANY_HP, HPStatusField.ANY_HP) #primary_hp filter from the user filter if self.request.GET.get(PactPrimaryHPField.slug, "") != "": primary_hp_term = self.request.GET[PactPrimaryHPField.slug] primary_hp_filter = {"term": {"hp.#value": primary_hp_term}} full_query['filter']['and'].append(primary_hp_filter) return self.case_es.run_query(full_query) def pact_case_link(self, case_id, name): try: return html.mark_safe("<a class='ajax_dialog' href='%s'>%s</a>" % ( html.escape( PactPatientInfoReport.get_url(*[self.domain]) + "?patient_id=%s" % case_id), html.escape(name), )) except NoReverseMatch: return "%s (bad ID format)" % name def render_hp_status(self, status): if status is None or status == '': return '' else: if status.lower() == 'discharged': css = 'label' else: css = 'label label-info' return '<span class="%s">%s</span>' % (css, status) def pact_dot_link(self, case_id, status): if status is None or status == '': return '' try: return html.mark_safe("<span class='label label-info'>%s</span> <a class='ajax_dialog' href='%s'>Report</a>" % ( html.escape(status), html.escape( PactDOTReport.get_url(*[self.domain]) + "?dot_patient=%s" % case_id), )) except NoReverseMatch: return "%s (bad ID format)" % status
class PactCHWProfileReport(PactDrilldownReportMixin, PactElasticTabularReportMixin): slug = "chw_profile" description = "CHW Profile" view_mode = 'info' ajax_pagination = True xform_es = ReportXFormES(PACT_DOMAIN) case_es = ReportCaseES(PACT_DOMAIN) default_sort = {"received_on": "desc"} name = "CHW Profile" hide_filters = True filters = [] def pact_case_link(self, case_id): #stop the madness from pact.reports.patient import PactPatientInfoReport try: return PactPatientInfoReport.get_url( *[self.domain]) + "?patient_id=%s" % case_id except NoReverseMatch: return "#" def pact_dot_link(self, case_id): from pact.reports.dot import PactDOTReport try: return PactDOTReport.get_url( *[self.domain]) + "?dot_patient=%s" % case_id except NoReverseMatch: return "#" def get_assigned_patients(self): """get list of patients and their submissions on who this chw is assigned as primary hp""" fields = [ "_id", "name", "pactid.#value", "hp_status.#value", "dot_status.#value" ] case_query = self.case_es.base_query(terms={ 'type': PACT_CASE_TYPE, 'hp.#value': self.get_user().raw_username }, fields=fields, size=100) case_query['filter']['and'].append( {'not': { 'term': { 'hp_status.#value': 'discharged' } }}) chw_patients_res = self.case_es.run_query(case_query) assigned_patients = [ x['fields'] for x in chw_patients_res['hits']['hits'] ] for x in assigned_patients: x['info_url'] = self.pact_case_link(x['_id']) if x['dot_status.#value'] is not None or x[ 'dot_status.#value'] != "": x['dot_url'] = self.pact_dot_link(x['_id']) return sorted(assigned_patients, key=lambda x: int(x['pactid.#value'])) def get_fields(self): if self.view_mode == 'submissions': yield 'corehq.apps.reports.filters.users.UserTypeFilter' yield 'corehq.apps.reports.filters.dates.DatespanFilter' @memoized def get_user(self): if hasattr(self, 'request') and 'chw_id' in self.request.GET: self._user_doc = CommCareUser.get(self.request.GET['chw_id']) return self._user_doc else: return None @property def report_context(self): user_doc = self.get_user() self.view_mode = self.request.GET.get('view', 'info') self.interval = self.request.GET.get('interval', 7) ret = { 'user_doc': user_doc, 'view_mode': self.view_mode, 'chw_root_url': PactCHWProfileReport.get_url(*[self.request.domain]) + "?chw_id=%s" % self.request.GET['chw_id'] } if self.view_mode == 'info': self.hide_filters = True self.report_template_path = "pact/chw/pact_chw_profile_info.html" ret['assigned_patients'] = self.get_assigned_patients() elif self.view_mode == 'submissions': tabular_context = super(PactCHWProfileReport, self).report_context tabular_context.update(ret) self.report_template_path = "pact/chw/pact_chw_profile_submissions.html" return tabular_context elif self.view_mode == 'schedule': scheduled_context = chw_schedule.chw_calendar_submit_report( self.request, user_doc.raw_username, interval=self.interval) ret.update(scheduled_context) self.report_template_path = "pact/chw/pact_chw_profile_schedule.html" else: raise Http404 return ret #submission stuff @property def headers(self): return DataTablesHeader( DataTablesColumn("Show Form", sortable=False, span=1), DataTablesColumn("Pact ID", sortable=False, span=1), DataTablesColumn("Received", prop_name="received_on", sortable=True, span=1), DataTablesColumn("Encounter Date", sortable=False, span=1), DataTablesColumn("Form", prop_name="form.#type", sortable=True, span=1), ) @property def es_results(self): user = self.get_user() fields = [ "_id", "form.#type", "received_on", "form.meta.timeStart", "form.meta.timeEnd" ] query = self.xform_es.base_query( terms={'form.meta.username': user.raw_username}, fields=fields, start=self.pagination.start, size=self.pagination.count) query['script_fields'] = {} query['script_fields'].update(pact_script_fields()) query['script_fields'].update(case_script_field()) query['sort'] = self.get_sorting_block() return self.xform_es.run_query(query) @property def rows(self): """ Override this method to create a functional tabular report. Returns 2D list of rows. [['row1'],[row2']] """ if self.get_user() is not None: def _format_row(row_field_dict): yield mark_safe( "<a class='ajax_dialog' href='%s'>View</a>" % (reverse('render_form_data', args=[self.domain, row_field_dict['_id']]))) yield row_field_dict['script_pact_id'] yield self.format_date(row_field_dict["received_on"].replace( '_', ' ').title()) yield self.format_date(row_field_dict['script_encounter_date']) yield row_field_dict["form.#type"].replace( '_', ' ').title().strip() res = self.es_results if 'error' in res: pass else: for result in res['hits']['hits']: yield list(_format_row(result['fields']))
class PatientInfoReport(CustomProjectReport, DrilldownReportMixin, ElasticProjectInspectionReport, ProjectReportParametersMixin): slug = "patient" hide_filters = True filters = [] ajax_pagination = True asynchronous = True emailable = False xform_es = ReportXFormES(SUCCEED_DOMAIN) default_sort = {"received_on": "desc"} def __init__(self, request, base_context=None, domain=None, **kwargs): self.view_mode = request.GET.get('view', 'info') super(PatientInfoReport, self).__init__(request, base_context, domain, **kwargs) @property def fields(self): if self.view_mode == 'submissions' and self.submission_user_access: return [ 'custom.succeed.fields.PatientFormNameFilter', 'corehq.apps.reports.standard.cases.filters.CaseSearchFilter' ] else: return [] @property def base_template_filters(self): if self.view_mode == 'submissions' and self.submission_user_access: return 'succeed/report.html' else: return super(PatientInfoReport, self).base_template_filters @property def name(self): if self.view_mode == 'submissions': return "Patient Submissions" if self.view_mode == 'status': return 'Manage Patient Status' return "Patient Info" def get_case(self): if self.request.GET.get('patient_id', None) is None: return None return CommCareCase.get(self.request.GET['patient_id']) @property def submission_user_access(self): user = self.request.couch_user if user and (is_pi(user) or is_cm(user) or is_chw(user)): return True return False @property def patient_status_access(self): user = self.request.couch_user if user and is_pm_or_pi(user): return True return False @property def report_context(self): ret = {} try: case = self.get_case() has_error = False except ResourceNotFound: has_error = True case = None
class PatientSubmissionReport(PatientDetailsReport): slug = "patient_submissions" name = 'Patient Submissions' xform_es = ReportXFormES(SUCCEED_DOMAIN) ajax_pagination = True asynchronous = True default_sort = { "received_on": "desc" } @property def base_template_filters(self): return 'succeed/report.html' @property def fields(self): return ['custom.succeed.fields.PatientFormNameFilter', 'corehq.apps.reports.standard.cases.filters.CaseSearchFilter'] @property def headers(self): return DataTablesHeader( # In order to get dafault_sort working as expected, first column cannot contain a 'prop_name'. DataTablesColumn("", visible=False), DataTablesColumn("Form Name", prop_name='@name'), DataTablesColumn("Submitted By", prop_name='form.meta.username'), DataTablesColumn("Completed", prop_name='received_on')) @property def es_results(self): if not self.request.GET.has_key('patient_id'): return None full_query = { 'query': { "filtered": { "filter": { "and": [ {"term": {"domain.exact": self.request.domain}}, {"term": {"doc_type": "xforminstance"}}, { "nested": { "path": "form.case", "filter": { "or": [ { "term": { "@case_id": "%s" % self.request.GET[ 'patient_id'] } }, { "term": { "case_id": "%s" % self.request.GET['patient_id'] } } ] } } } ] }, "query": {"match_all": {}} } }, "sort": self.get_sorting_block(), "size": self.pagination.count, "from": self.pagination.start } form_name_group = self.request.GET.get('form_name_group', None) form_name_xmnls = self.request.GET.get('form_name_xmlns', None) search_string = SearchFilter.get_value(self.request, self.domain) if search_string: query_block = {"queryString": {"query": "*" + search_string + "*"}} full_query["query"]["filtered"]["query"] = query_block if form_name_group and form_name_xmnls == '': xmlns_terms = [] forms = filter(lambda obj: obj['val'] == form_name_group, SUBMISSION_SELECT_FIELDS)[0] for form in forms['next']: xmlns_terms.append(form['val']) full_query['query']['filtered']['filter']['and'].append({"terms": {"xmlns.exact": xmlns_terms}}) if form_name_xmnls: full_query['query']['filtered']['filter']['and'].append({"term": {"xmlns.exact": form_name_xmnls}}) res = self.xform_es.run_query(full_query) return res @property def rows(self): if self.request.GET.has_key('patient_id'): def _format_row(row_field_dict): return [None, self.submit_history_form_link(row_field_dict["_id"], row_field_dict['_source'].get('es_readable_name', EMPTY_FIELD)), row_field_dict['_source']['form']['meta'].get('username', EMPTY_FIELD), self.form_completion_time(row_field_dict['_source']['form']['meta'].get('timeEnd', EMPTY_FIELD)) ] res = self.es_results if res: if res.has_key('error'): pass else: for result in res['hits']['hits']: yield list(_format_row(result)) def submit_history_form_link(self, form_id, form_name): url = reverse('render_form_data', args=[self.domain, form_id]) return html.mark_safe("<a class='ajax_dialog' href='%s' target='_blank'>%s</a>" % (url, html.escape(form_name))) def form_completion_time(self, date_string): if date_string != EMPTY_FIELD: return format_date(date_string, INTERACTION_OUTPUT_DATE_FORMAT, localize=True) else: return EMPTY_FIELD @property def report_context(self): ret = super(PatientSubmissionReport, self).report_context ret['view_mode'] = 'submissions' tabular_context = super(PatientDetailsReport, self).report_context tabular_context.update(ret) self.report_template_path = "patient_submissions.html" tabular_context['patient_id'] = self.request_params['patient_id'] return tabular_context