def save_copy(request, domain, app_id): """ Saves a copy of the app to a new doc. See ApplicationBase.save_copy """ track_built_app_on_hubspot.delay(request.couch_user) comment = request.POST.get('comment') app = get_app(domain, app_id) try: errors = app.validate_app() except ModuleIdMissingException: # For apps (mainly Exchange apps) that lost unique_id attributes on Module app.ensure_module_unique_ids(should_save=True) errors = app.validate_app() if not errors: try: user_id = request.couch_user.get_id timer = datadog_bucket_timer('commcare.app_build.new_release', tags=[], timing_buckets=(1, 10, 30, 60, 120, 240)) with timer: copy = make_app_build(app, comment, user_id) CouchUser.get(user_id).set_has_built_app() except BuildConflictException: return JsonResponse( { 'error': _("There is already a version build in progress. Please wait." ) }, status=400) finally: # To make a RemoteApp always available for building if app.is_remote_app(): app.save(increment_version=True) _track_build_for_app_preview(domain, request.couch_user, app_id, 'User created a build') else: copy = None copy = copy and SavedAppBuild.wrap(copy.to_json()).releases_list_json( get_timezone_for_user(request.couch_user, domain)) lang, langs = get_langs(request, app) return json_response({ "saved_app": copy, "error_html": render_to_string( "app_manager/partials/build_errors.html", { 'app': get_app(domain, app_id), 'build_errors': errors, 'domain': domain, 'langs': langs, }), })
def save_copy(request, domain, app_id): """ Saves a copy of the app to a new doc. See VersionedDoc.save_copy """ track_built_app_on_hubspot_v2.delay(request.couch_user) comment = request.POST.get('comment') app = get_app(domain, app_id) try: errors = app.validate_app() except ModuleIdMissingException: # For apps (mainly Exchange apps) that lost unique_id attributes on Module app.ensure_module_unique_ids(should_save=True) errors = app.validate_app() if not errors: try: user_id = request.couch_user.get_id timer = datadog_bucket_timer('commcare.app_build.new_release', tags=[], timing_buckets=(1, 10, 30, 60, 120, 240)) with timer: copy = app.make_build( comment=comment, user_id=user_id, ) copy.save(increment_version=False) CouchUser.get(user_id).set_has_built_app() finally: # To make a RemoteApp always available for building if app.is_remote_app(): app.save(increment_version=True) _track_build_for_app_preview(domain, request.couch_user, app_id, 'User created a build') else: copy = None copy = copy and SavedAppBuild.wrap(copy.to_json()).releases_list_json( get_timezone_for_user(request.couch_user, domain) ) lang, langs = get_langs(request, app) if copy: # Set if build is supported for Java Phones j2me_enabled_configs = CommCareBuildConfig.j2me_enabled_config_labels() copy['j2me_enabled'] = copy['menu_item_label'] in j2me_enabled_configs return json_response({ "saved_app": copy, "error_html": render_to_string("app_manager/partials/build_errors.html", { 'request': request, 'app': get_app(domain, app_id), 'build_errors': errors, 'domain': domain, 'langs': langs, 'lang': lang }), })
def save_copy(request, domain, app_id): """ Saves a copy of the app to a new doc. See VersionedDoc.save_copy """ track_built_app_on_hubspot.delay(request.couch_user) comment = request.POST.get('comment') app = get_app(domain, app_id) try: errors = app.validate_app() except ModuleIdMissingException: # For apps (mainly Exchange apps) that lost unique_id attributes on Module app.ensure_module_unique_ids(should_save=True) errors = app.validate_app() if not errors: try: user_id = request.couch_user.get_id copy = app.make_build( comment=comment, user_id=user_id, previous_version=app.get_latest_app(released_only=False)) copy.save(increment_version=False) CouchUser.get(user_id).set_has_built_app() finally: # To make a RemoteApp always available for building if app.is_remote_app(): app.save(increment_version=True) _track_build_for_app_preview(domain, request.couch_user, app_id, 'User created a build') else: copy = None copy = copy and SavedAppBuild.wrap(copy.to_json()).to_saved_build_json( get_timezone_for_user(request.couch_user, domain)) lang, langs = get_langs(request, app) if copy: # Set if build is supported for Java Phones j2me_enabled_configs = CommCareBuildConfig.j2me_enabled_config_labels() copy['j2me_enabled'] = copy['menu_item_label'] in j2me_enabled_configs return json_response({ "saved_app": copy, "error_html": render_to_string( "app_manager/partials/build_errors.html", { 'request': request, 'app': get_app(domain, app_id), 'build_errors': errors, 'domain': domain, 'langs': langs, 'lang': lang }), })
def save_copy(request, domain, app_id): """ Saves a copy of the app to a new doc. """ track_built_app_on_hubspot.delay(request.couch_user.get_id) comment = request.POST.get('comment') app = get_app(domain, app_id) try: user_id = request.couch_user.get_id with report_build_time(domain, app._id, 'new_release'): copy = make_app_build(app, comment, user_id) CouchUser.get(user_id).set_has_built_app() except AppValidationError as e: lang, langs = get_langs(request, app) return JsonResponse({ "saved_app": None, "error_html": render_to_string( "app_manager/partials/build_errors.html", { 'app': get_app(domain, app_id), 'build_errors': e.errors, 'domain': domain, 'langs': langs, 'toggles': toggles_enabled_for_request(request), }), }) except BuildConflictException: return JsonResponse( { 'error': _("There is already a version build in progress. Please wait.") }, status=400) except XFormValidationFailed: return JsonResponse({'error': _("Unable to validate forms.")}, status=400) finally: # To make a RemoteApp always available for building if app.is_remote_app(): app.save(increment_version=True) _track_build_for_app_preview(domain, request.couch_user, app_id, 'User created a build') copy_json = copy and SavedAppBuild.wrap(copy.to_json()).releases_list_json( get_timezone_for_user(request.couch_user, domain)) return JsonResponse({ "saved_app": copy_json, "error_html": "", })
def __setstate__(self, state): """ For unpickling a pickled report. """ logging = get_task_logger(__name__) # logging lis likely to happen within celery. self.domain = state.get('domain') self.context = state.get('context', {}) class FakeHttpRequest(object): GET = {} META = {} couch_user = None datespan = None request_data = state.get('request') request = FakeHttpRequest() request.GET = request_data.get('GET', {}) request.META = request_data.get('META', {}) request.datespan = request_data.get('datespan') try: couch_user = CouchUser.get(request_data.get('couch_user')) request.couch_user = couch_user except Exception as e: logging.error("Could not unpickle couch_user from request for report %s. Error: %s" % (self.name, e)) self.request = request self._caching = True self.request_params = state.get('request_params') self._update_initial_context()
def heartbeat(request, domain, app_build_id): """ An endpoint for CommCare mobile to get latest CommCare APK and app version info. (Should serve from cache as it's going to be busy view) 'app_build_id' (that comes from URL) can be id of any version of the app 'app_id' (urlparam) is usually id of an app that is not a copy mobile simply needs it to be resent back in the JSON, and doesn't need any validation on it. This is pulled from @uniqueid from profile.xml """ app_id = request.GET.get('app_id', '') info = {"app_id": app_id} try: # mobile will send brief_app_id info.update(LatestAppInfo(app_id, domain).get_info()) except (Http404, AssertionError): # If it's not a valid 'brief' app id, find it by talking to couch notify_exception(request, 'Received an invalid heartbeat request') app = get_app_cached(domain, app_build_id) brief_app_id = app.master_id info.update(LatestAppInfo(brief_app_id, domain).get_info()) else: if settings.SERVER_ENVIRONMENT not in settings.ICDS_ENVS: # disable on icds for now since couch still not happy couch_user = request.couch_user try: update_user_reporting_data(app_build_id, app_id, couch_user, request) except ResourceConflict: # https://sentry.io/dimagi/commcarehq/issues/521967014/ couch_user = CouchUser.get(couch_user.user_id) update_user_reporting_data(app_build_id, app_id, couch_user, request) return JsonResponse(info)
def handle(self, user, **options): try: self.user = CouchUser.get_by_username(user) if not self.user: self.user = CouchUser.get(user) except ResourceNotFound: print("Could not find user {}".format(user)) return if not isinstance(self.user, CommCareUser): print ("Sorry, the user you specify has to be a mobile worker. " "This changed when delete_cases was refactored to use " "cases_by_owner/view instead of case/by_owner. " "The new view needs an explicit domain, " "and I didn't implement that for WebUsers who can belong " "to multiple domains, but usually do not own cases.") exit(1) self.domain = self.user.domain if should_use_sql_backend(self.domain): raise CommandError('This command only works for couch-based domains.') if not options.get('no_prompt'): msg = "Delete all cases owned by {}? (y/n)\n".format( self.user.username, ) if not input(msg) == 'y': print("cancelling") return self.delete_all() print("Cases successfully deleted, you monster!")
def from_transactions(cls, user_id, product_stock_case, transactions): assert transactions, "can't make a requisition state from an empty transaciton list" def _to_fields(transaction): # TODO support other types if transaction.action_config.action_type == RequisitionActions.REQUEST: return { 'create': True, 'amount_requested': transaction.value, } else: raise ValueError('only requests are currently supported') kwargs = {} for tx in transactions: fields = _to_fields(tx) for field in fields: assert field not in kwargs, 'transaction updates should be disjoint but found %s twice' % field kwargs.update(fields) username = CouchUser.get(user_id).username return cls( domain=product_stock_case.domain, id=uuid.uuid4().hex, # TODO: support non-create case user_id=user_id, username=username, product_stock_case_id=product_stock_case._id, **kwargs )
def __setstate__(self, state): """ For unpickling a pickled report. """ logging = get_task_logger( __name__) # logging lis likely to happen within celery. self.domain = state.get('domain') self.context = state.get('context', {}) class FakeHttpRequest(object): GET = {} META = {} couch_user = None datespan = None request_data = state.get('request') request = FakeHttpRequest() request.GET = request_data.get('GET', {}) request.META = request_data.get('META', {}) request.datespan = request_data.get('datespan') try: couch_user = CouchUser.get(request_data.get('couch_user')) request.couch_user = couch_user except Exception as e: logging.error( "Could not unpickle couch_user from request for report %s. Error: %s" % (self.name, e)) self.request = request self._caching = True self.request_params = state.get('request_params') self._update_initial_context()
def handle(self, *args, **options): if not len(args): print "Usage: ./manage.py delete_cases <user>" return try: self.user = CouchUser.get_by_username(args[0]) if not self.user: self.user = CouchUser.get(args[0]) except ResourceNotFound: print "Could not find user {}".format(args[0]) return if not isinstance(self.user, CommCareUser): print ("Sorry, the user you specify has to be a mobile worker. " "This changed when delete_cases was refactored to use " "cases_by_owner/view instead of case/by_owner. " "The new view needs an explicit domain, " "and I didn't implement that for WebUsers who can belong " "to multiple domains, but usually do not own cases.") exit(1) self.domain = self.user.domain if not options.get('no_prompt'): msg = "Delete all cases owned by {}? (y/n)\n".format( self.user.username, ) if not raw_input(msg) == 'y': print "cancelling" return self.delete_all() print "Cases successfully deleted, you monster!"
def handle(self, user, **options): try: self.user = CouchUser.get_by_username(user) if not self.user: self.user = CouchUser.get(user) except ResourceNotFound: print("Could not find user {}".format(user)) return if not isinstance(self.user, CommCareUser): print("Sorry, the user you specify has to be a mobile worker. " "This changed when delete_cases was refactored to use " "cases_by_owner/view instead of case/by_owner. " "The new view needs an explicit domain, " "and I didn't implement that for WebUsers who can belong " "to multiple domains, but usually do not own cases.") exit(1) self.domain = self.user.domain if should_use_sql_backend(self.domain): raise CommandError( 'This command only works for couch-based domains.') if not options.get('no_prompt'): msg = "Delete all cases owned by {}? (y/n)\n".format( self.user.username, ) if not raw_input(msg) == 'y': print("cancelling") return self.delete_all() print("Cases successfully deleted, you monster!")
def users_for_phone(phone): """ Get users attached to a phone number """ view_results = get_db().view("sms/phones_to_domains", key=phone) user_ids = set([row["id"] for row in view_results]) return [CouchUser.get(id) for id in user_ids]
def handle(self, *args, **options): self.last_submitter = options.get('last_submitter', False) if not len(args): print "Usage: ./manage.py delete_cases <user>" return try: self.user = CouchUser.get_by_username(args[0]) if not self.user: self.user = CouchUser.get(args[0]) except ResourceNotFound: print "Could not find user {}".format(args[0]) return if not options.get('no_prompt'): msg = "Delete all {} cases {} by {}? (y/n)\n".format( self.get_case_count(), "submitted" if self.last_submitter else "owned", self.user.username, ) if not raw_input(msg) == 'y': print "cancelling" return self.delete_all() print "Cases successfully deleted, you monster!"
def update_user_reporting_data(app_build_id, app_id, build_profile_id, couch_user, request): def _safe_int(val): try: return int(val) except: pass app_version = _safe_int(request.GET.get('app_version', '')) device_id = request.GET.get('device_id', '') last_sync_time = request.GET.get('last_sync_time', '') num_unsent_forms = _safe_int(request.GET.get('num_unsent_forms', '')) num_quarantined_forms = _safe_int( request.GET.get('num_quarantined_forms', '')) commcare_version = request.GET.get('cc_version', '') # if mobile cannot determine app version it sends -1 if app_version == -1: app_version = None try: last_sync = adjust_text_to_datetime(last_sync_time) except iso8601.ParseError: try: last_sync = string_to_utc_datetime(last_sync_time) except (ValueError, OverflowError): last_sync = None if settings.USER_REPORTING_METADATA_BATCH_ENABLED: UserReportingMetadataStaging.add_heartbeat( request.domain, couch_user._id, app_id, app_build_id, last_sync, device_id, app_version, num_unsent_forms, num_quarantined_forms, commcare_version, build_profile_id) else: record = UserReportingMetadataStaging( domain=request.domain, user_id=couch_user._id, app_id=app_id, build_id=app_build_id, sync_date=last_sync, device_id=device_id, app_version=app_version, num_unsent_forms=num_unsent_forms, num_quarantined_forms=num_quarantined_forms, commcare_version=commcare_version, build_profile_id=build_profile_id, last_heartbeat=datetime.utcnow(), modified_on=datetime.utcnow()) try: record.process_record(couch_user) except ResourceConflict: # https://sentry.io/dimagi/commcarehq/issues/521967014/ couch_user = CouchUser.get(couch_user.user_id) record.process_record(couch_user)
def get_user_type(user_id): if user_id == SYSTEM_USER_ID: # Every form with user_id == system also has username == system. # But there are some forms where username == system but the user_id is different. # Any chance those should be included? return SYSTEM_USER_TYPE elif user_id == DEMO_USER_ID: return DEMO_USER_TYPE elif user_id == COMMTRACK_USERNAME: return COMMCARE_SUPPLY_USER_TYPE else: try: user = CouchUser.get(user_id) if user.is_web_user(): return WEB_USER_TYPE elif user.is_commcare_user(): return MOBILE_USER_TYPE except: pass return UNKNOWN_USER_TYPE
def get_user_type(user_id): if user_id == SYSTEM_USER_ID: # Every form with user_id == system also has username == system. # But there are some forms where username == system but the user_id is different. # Any chance those should be included? return SYSTEM_USER_TYPE elif user_id == DEMO_USER_ID: return DEMO_USER_TYPE elif user_id == COMMTRACK_USERNAME: return COMMCARE_SUPPLY_USER_TYPE elif user_id: try: user = CouchUser.get(user_id) if user.is_web_user(): return WEB_USER_TYPE elif user.is_commcare_user(): return MOBILE_USER_TYPE except (ResourceNotFound, WrappingAttributeError): pass return UNKNOWN_USER_TYPE
def heartbeat(request, domain, app_build_id): """ An endpoint for CommCare mobile to get latest CommCare APK and app version info. (Should serve from cache as it's going to be busy view) 'app_build_id' (that comes from URL) can be id of any version of the app 'app_id' (urlparam) is usually id of an app that is not a copy mobile simply needs it to be resent back in the JSON, and doesn't need any validation on it. This is pulled from @uniqueid from profile.xml """ app_id = request.GET.get('app_id', '') info = {"app_id": app_id} try: # mobile will send brief_app_id info.update(LatestAppInfo(app_id, domain).get_info()) except (Http404, AssertionError): # If it's not a valid 'brief' app id, find it by talking to couch notify_exception(request, 'Received an invalid heartbeat request') app = get_app_cached(domain, app_build_id) brief_app_id = app.master_id info.update(LatestAppInfo(brief_app_id, domain).get_info()) else: if settings.SERVER_ENVIRONMENT not in settings.ICDS_ENVS: # disable on icds for now since couch still not happy couch_user = request.couch_user try: update_user_reporting_data(app_build_id, app_id, couch_user, request) except ResourceConflict: # https://sentry.io/dimagi/commcarehq/issues/521967014/ couch_user = CouchUser.get(couch_user.user_id) update_user_reporting_data(app_build_id, app_id, couch_user, request) if _should_force_log_submission(request): info['force_logs'] = True return JsonResponse(info)
def handle(self, *args, **options): if not len(args): print "Usage: ./manage.py delete_cases <user>" return try: self.user = CouchUser.get_by_username(args[0]) if not self.user: self.user = CouchUser.get(args[0]) except ResourceNotFound: print "Could not find user {}".format(args[0]) return if not isinstance(self.user, CommCareUser): print( "Sorry, the user you specify has to be a mobile worker. " "This changed when delete_cases was refactored to use " "hqcase/by_owner instead of case/by_owner. " "The new view needs an explicit domain, " "and I didn't implement that for WebUsers who can belong " "to multiple domains, but usually do not own cases.") exit(1) self.domain = self.user.domain if not options.get('no_prompt'): msg = "Delete all {} cases {} by {}? (y/n)\n".format( self.get_case_count(), "owned", self.user.username, ) if not raw_input(msg) == 'y': print "cancelling" return self.delete_all() print "Cases successfully deleted, you monster!"
def _run_reports(reps): for rep in reps: for user_id in rep.user_ids: user = CouchUser.get(user_id) send_report.delay(rep, user.to_json())
def get_user(self, user_id): return CouchUser.get(user_id)
else: target_date = EMPTY_FIELD interaction = { 'url': '', 'name': visit['visit_name'], 'target_date': target_date, 'received_date': EMPTY_FIELD, 'completed_by': EMPTY_FIELD, 'scheduled_date': EMPTY_FIELD } for key, action in enumerate(case['actions']): if visit['xmlns'] == action['xform_xmlns']: interaction['received_date'] = action['date'].strftime( INTERACTION_OUTPUT_DATE_FORMAT) try: user = CouchUser.get(action['user_id']) interaction['completed_by'] = user.raw_username except ResourceNotFound: interaction['completed_by'] = EMPTY_FIELD del case['actions'][key] break if visit['show_button']: interaction['url'] = get_form_url(cm_app_dict, latest_cm_build, visit['module_idx'], visit['xmlns']) if 'scheduled_source' in visit and case.get_case_property( visit['scheduled_source']): interaction['scheduled_date'] = (case.get_case_property( visit['scheduled_source'])).strftime( INTERACTION_OUTPUT_DATE_FORMAT)
def from_transactions(cls, user_id, product_stock_case, transactions): assert transactions, "can't make a requisition state from an empty transaction list" def _to_fields(transaction): ret = { 'requisition_status': RequisitionStatus.by_action_type( transaction.action_config.action_type) } if transaction.action_config.action_type == RequisitionActions.REQUEST: ret.update({ 'create': True, 'owner_id': get_owner_id(product_stock_case) or user_id, 'amount_requested': transaction.value, 'product_id': product_stock_case.product, 'requested_by': user_id, 'requested_on': datetime.utcnow(), }) elif transaction.action_config.action_type == RequisitionActions.APPROVAL: ret.update({ 'amount_approved': transaction.value, 'approved_by': user_id, 'approved_on': datetime.utcnow(), }) elif transaction.action_config.action_type == RequisitionActions.PACK: ret.update({ 'amount_packed': transaction.value, 'packed_by': user_id, 'packed_on': datetime.utcnow(), }) elif transaction.action_config.action_type == RequisitionActions.RECEIPTS: ret.update({ 'amount_received': transaction.value, 'received_by': user_id, 'received_on': datetime.utcnow(), 'close': True, }) else: raise ValueError("the type %s isn't yet supported." % transaction.action_config.action_type) return ret def _get_case_id(transactions): req_case_id = None for tx in transactions: if tx.requisition_case_id: if req_case_id: assert tx.requisition_case_id == req_case_id, 'tried to update multiple cases with one set of transactions' req_case_id = tx.requisition_case_id return req_case_id or uuid.uuid4().hex kwargs = {} for tx in transactions: fields = _to_fields(tx) for field in fields: assert field not in kwargs, 'transaction updates should be disjoint but found %s twice' % field kwargs.update(fields) username = CouchUser.get(user_id).username return cls(domain=product_stock_case.domain, id=_get_case_id(transactions), user_id=user_id, username=username, product_stock_case=product_stock_case, **kwargs)
def from_transactions(cls, user_id, product_stock_case, transactions): assert transactions, "can't make a requisition state from an empty transaction list" def _to_fields(transaction): ret = {'requisition_status': RequisitionStatus.by_action_type(transaction.action_config.action_type)} if transaction.action_config.action_type == RequisitionActions.REQUEST: ret.update({ 'create': True, 'owner_id': get_owner_id(product_stock_case) or user_id, 'amount_requested': transaction.value, 'product_id': product_stock_case.product, 'requested_by': user_id, 'requested_on': datetime.utcnow(), }) elif transaction.action_config.action_type == RequisitionActions.APPROVAL: ret.update({ 'amount_approved': transaction.value, 'approved_by': user_id, 'approved_on': datetime.utcnow(), }) elif transaction.action_config.action_type == RequisitionActions.PACK: ret.update({ 'amount_packed': transaction.value, 'packed_by': user_id, 'packed_on': datetime.utcnow(), }) elif transaction.action_config.action_type == RequisitionActions.RECEIPTS: ret.update({ 'amount_received': transaction.value, 'received_by': user_id, 'received_on': datetime.utcnow(), 'close': True, }) else: raise ValueError("the type %s isn't yet supported." % transaction.action_config.action_type) return ret def _get_case_id(transactions): req_case_id = None for tx in transactions: if tx.requisition_case_id: if req_case_id: assert tx.requisition_case_id == req_case_id, 'tried to update multiple cases with one set of transactions' req_case_id = tx.requisition_case_id return req_case_id or uuid.uuid4().hex kwargs = {} for tx in transactions: fields = _to_fields(tx) for field in fields: assert field not in kwargs, 'transaction updates should be disjoint but found %s twice' % field kwargs.update(fields) username = CouchUser.get(user_id).username return cls( domain=product_stock_case.domain, id=_get_case_id(transactions), user_id=user_id, username=username, product_stock_case=product_stock_case, **kwargs )
def report_context(self): ret = {} try: case = self.get_case() has_error = False except ResourceNotFound: has_error = True case = None if case is None: self.report_template_path = "patient_error.html" if has_error: ret['error_message'] = "Patient not found" else: ret['error_message'] = "No patient selected" return ret def get_form_url(app_dict, app_build_id, module_idx, form, case_id=None): try: module = app_dict['modules'][module_idx] form_idx = [ix for (ix, f) in enumerate(module['forms']) if f['xmlns'] == form][0] except IndexError: form_idx = None return html.escape(get_cloudcare_form_url(domain=self.domain, app_build_id=app_build_id, module_id=module_idx, form_id=form_idx, case_id=case_id) + '/enter/') try: cm_app_dict = get_cloudcare_app(case['domain'], SUCCEED_CM_APPNAME) latest_cm_build = get_app_build(cm_app_dict) pm_app_dict = get_cloudcare_app(case['domain'], SUCCEED_PM_APPNAME) latest_pm_build = get_app_build(pm_app_dict) chw_app_dict = get_cloudcare_app(case['domain'], SUCCEED_CHW_APPNAME) latest_chw_build = get_app_build(pm_app_dict) except ResourceNotFound as ex: self.report_template_path = "patient_error.html" ret['error_message'] = ex.message return ret ret['patient'] = case ret['root_url'] = '?patient_id=%s' % case['_id'] ret['view_mode'] = self.view_mode ret['patient_status_access'] = self.patient_status_access ret['submission_user_access'] = self.submission_user_access if self.view_mode == 'info': self.report_template_path = "patient_info.html" patient_info = PatientInfoDisplay(case) # check user role: user = self.request.couch_user if is_pm_or_pi(user): ret['edit_patient_info_url'] = get_form_url(pm_app_dict, latest_pm_build, PM_APP_PM_MODULE, PM_PM2, case['_id']) elif is_cm(user): ret['edit_patient_info_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_PD_MODULE, PM2, case['_id']) elif is_chw(user): ret['edit_patient_info_url'] = get_form_url(chw_app_dict, latest_chw_build, CHW_APP_PD_MODULE, PM2, case['_id']) if is_pm_or_pi(user): ret['upcoming_appointments_url'] = get_form_url(pm_app_dict, latest_pm_build, PM_APP_PM_MODULE, PM_PM2, case['_id']) elif is_cm(user): ret['upcoming_appointments_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_PD_MODULE, PM2, case['_id']) elif is_chw(user): ret['upcoming_appointments_url'] = get_form_url(chw_app_dict, latest_chw_build, CHW_APP_MA_MODULE, AP2, case['_id']) ret['general_information'] = patient_info.general_information ret['contact_information'] = patient_info.contact_information ret['most_recent_lab_exams'] = patient_info.most_recent_lab_exams ret['allergies'] = patient_info.allergies elif self.view_mode == 'submissions': if self.submission_user_access: tabular_context = super(PatientInfoReport, 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 else: self.report_template_path = "patient_error.html" ret['error_message'] = "Cannot access report(incorrect user role)" return ret elif self.view_mode == 'interactions': self.report_template_path = "patient_interactions.html" ret['problem_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_PD_MODULE, PD1, case['_id']) ret['huddle_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_HUD_MODULE, HUD2, case['_id']) ret['cm_phone_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_CM_MODULE, CM6, case['_id']) ret['chw_phone_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_CHW_MODULE, CHW3, case['_id']) ret['cm_visits_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_APPOINTMENTS_MODULE, AP2, case['_id']) ret['anti_thrombotic_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2AM, case['_id']) ret['blood_pressure_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2BPM, case['_id']) ret['cholesterol_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2CHM, case['_id']) ret['depression_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2DIABM, case['_id']) ret['diabetes_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2DEPM, case['_id']) ret['smoking_cessation_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2SCM, case['_id']) ret['other_meds_url'] = get_form_url(cm_app_dict, latest_cm_build, CM_APP_MEDICATIONS_MODULE, PD2OM, case['_id']) ret['interaction_table'] = [] for visit_key, visit in enumerate(VISIT_SCHEDULE): if case["randomization_date"]: target_date = (case["randomization_date"] + timedelta(days=visit['days'])).strftime(OUTPUT_DATE_FORMAT) else: target_date = EMPTY_FIELD interaction = { 'url': '', 'name': visit['visit_name'], 'target_date': target_date, 'received_date': EMPTY_FIELD, 'completed_by': EMPTY_FIELD, 'scheduled_date': EMPTY_FIELD } for key, action in enumerate(case['actions']): if visit['xmlns'] == action['xform_xmlns']: interaction['received_date'] = action['date'].strftime(INTERACTION_OUTPUT_DATE_FORMAT) try: user = CouchUser.get(action['user_id']) interaction['completed_by'] = user.raw_username except ResourceNotFound: interaction['completed_by'] = EMPTY_FIELD del case['actions'][key] break if visit['show_button']: interaction['url'] = get_form_url(cm_app_dict, latest_cm_build, visit['module_idx'], visit['xmlns'], case['_id']) if 'scheduled_source' in visit and case.get_case_property(visit['scheduled_source']): interaction['scheduled_date'] = format_date(case.get_case_property(visit['scheduled_source']), INTERACTION_OUTPUT_DATE_FORMAT) ret['interaction_table'].append(interaction) medication = [] for med_prop in MEDICATION_DETAILS: medication.append(getattr(case, med_prop, EMPTY_FIELD)) ret['medication_table'] = medication elif self.view_mode == 'plan': self.report_template_path = "patient_plan.html" elif self.view_mode == 'status': if self.patient_status_access: self.report_template_path = "patient_status.html" ret['disenroll_patient_url'] = get_form_url(pm_app_dict, latest_pm_build, PM_APP_PM_MODULE, PM3) ret['change_patient_data_url'] = get_form_url(pm_app_dict, latest_pm_build, PM_APP_PM_MODULE, PM4) else: self.report_template_path = "patient_error.html" ret['error_message'] = "Only PMs can disenrollment participants" return ret else: raise Http404 return ret