def handle_domain_specific_delays(msg, domain_object, utcnow): """ Checks whether or not we need to hold off on sending an outbound message due to any restrictions set on the domain, and delays processing of the message if necessary. Returns True if a delay was made, False if not. """ domain_now = ServerTime(utcnow).user_time( domain_object.get_default_timezone()).done() if len(domain_object.restricted_sms_times) > 0: if not time_within_windows(domain_now, domain_object.restricted_sms_times): delay_processing( msg, settings.SMS_QUEUE_DOMAIN_RESTRICTED_RETRY_INTERVAL) return True if msg.chat_user_id is None and len( domain_object.sms_conversation_times) > 0: if time_within_windows(domain_now, domain_object.sms_conversation_times): sms_conversation_length = domain_object.sms_conversation_length conversation_start_timestamp = utcnow - timedelta( minutes=sms_conversation_length) if SMS.inbound_entry_exists(msg.couch_recipient_doc_type, msg.couch_recipient, conversation_start_timestamp, to_timestamp=utcnow): delay_processing(msg, 1) return True return False
def rows(self): data = SMS.by_domain(self.domain, start_date=self.datespan.startdate_utc, end_date=self.datespan.enddate_utc).filter( workflow__iexact=WORKFLOW_DEFAULT).exclude( direction=OUTGOING, processed=False, ).order_by('date') result = [] direction_map = { INCOMING: _("Incoming"), OUTGOING: _("Outgoing"), } reporting_locations_id = self.get_location_filter() contact_cache = {} for message in data: if reporting_locations_id and message.location_id not in reporting_locations_id: continue doc_info = self.get_recipient_info(message, contact_cache) phone_number = message.phone_number timestamp = ServerTime(message.date).user_time( self.timezone).done() result.append([ self._fmt_timestamp(timestamp), self._fmt_contact_link(message, doc_info), _fmt(phone_number), _fmt(direction_map.get(message.direction, "-")), _fmt(message.text) ]) return result
def get_server_date_by_form_id(self, form_id): try: server_date = FormAccessors(self.domain).get_form(form_id).received_on except XFormNotFound: return None else: return ServerTime(server_date).ui_string()
def rows(self): participants = self.get_participants() result = [] for case in participants: pid = case.get_case_property("pid") study_arm = case.get_case_property("study_arm") registration_date = get_date(case, "start_date") first_name = case.get_case_property("first_name") or "" if registration_date is None: continue first_survey_date = self.get_first_tuesday(registration_date) row = [ self._fmt(pid), self._fmt(first_name), self._fmt(study_arm), ] for i in range(8): next_survey_date = first_survey_date + timedelta(days=7 * i) response = self.get_first_survey_response( case, next_survey_date) if response == RESPONSE_NOT_APPLICABLE: row.append(self._fmt("-")) elif response == NO_RESPONSE: row.append(self._fmt(_("No Response"))) else: response_timestamp = ServerTime(response.date).user_time( self.timezone).done() row.append(self._fmt_timestamp(response_timestamp)) result.append(row) return result
def template_context(self): return { 'xforms_session': self.xforms_session, 'contact': get_doc_info_by_id(self.domain, self.xforms_session.connection_id), 'start_time': (ServerTime(self.xforms_session.start_time) .user_time(self.timezone).done().strftime(SERVER_DATETIME_FORMAT)), }
def template_context(self): event = self.messaging_event date = ServerTime(event.date).user_time(self.timezone).done() return { 'messaging_event_date': date.strftime(SERVER_DATETIME_FORMAT), 'messaging_event_type': self.get_source_display(event, display_only=True), }
def rows(self): contact_cache = {} content_cache = {} data = self.get_queryset() if self.request_params.get('sSortDir_0') == 'asc': data = data.order_by('date') else: data = data.order_by('-date') if self.pagination: data = data[self.pagination.start:self.pagination.start + self.pagination.count] for event in data: doc_info = self.get_recipient_info(event.get_recipient_doc_type(), event.recipient_id, contact_cache) timestamp = ServerTime(event.date).user_time(self.timezone).done() status = self.get_status_display(event) yield [ self._fmt_timestamp(timestamp)['html'], self.get_content_display(event, content_cache), self.get_source_display(event, display_only=True), self._fmt_recipient(event, doc_info)['html'], status, self.get_event_detail_link(event), ]
def case_upload_to_user_json(case_upload, request): domain = case_upload.domain tz = get_timezone_for_request(request) return CaseUploadJSON( domain=case_upload.domain, created_display=ServerTime( case_upload.created).user_time(tz).ui_string(), created=json_format_datetime(case_upload.created), upload_id=str(case_upload.upload_id), task_status=case_upload.get_task_status_json(), user_name=get_display_name_for_user_id(domain, case_upload.couch_user_id, default=''), case_type=case_upload.case_type, comment=case_upload.comment, upload_file_name=(case_upload.upload_file_meta.filename if case_upload.upload_file_meta else None), upload_file_length=(case_upload.upload_file_meta.length if case_upload.upload_file_meta else None), upload_file_download_allowed=user_may_view_file_upload( domain, request.couch_user, case_upload), upload_comment_edit_allowed=user_may_update_comment( request.couch_user, case_upload), )
def utc_to_timezone(date, timezone): if not timezone: timezone = pytz.utc if not date: return "---" if isinstance(date, (str, bytes)): raise ValueError("utc_to_timezone no longer accepts strings") return ServerTime(date).user_time(timezone).ui_string()
def submission_or_completion_time(self): time = iso_string_to_datetime( safe_index(self.form, self.report.time_field.split('.'))) if self.report.by_submission_time: user_time = ServerTime(time).user_time(self.report.timezone) else: user_time = PhoneTime(time, self.report.timezone).user_time( self.report.timezone) return user_time.ui_string(USER_DATETIME_FORMAT_WITH_SEC)
def rows(self): data = SMS.by_domain(self.domain, start_date=self.datespan.startdate_utc, end_date=self.datespan.enddate_utc).exclude( direction=OUTGOING, processed=False).order_by('date') if self.show_only_survey_traffic(): data = data.filter(xforms_session_couch_id__isnull=False) result = [] direction_map = { INCOMING: _("Incoming"), OUTGOING: _("Outgoing"), } message_bank_messages = get_message_bank(self.domain, for_comparing=True) FormProcessorInterface(self.domain).casedb_cache(domain=self.domain, strip_history=False, deleted_ok=True) user_cache = UserCache() for message in data: # Add metadata from the message bank if it has not been added already if (message.direction == OUTGOING) and ( not message.fri_message_bank_lookup_completed): add_metadata(message, message_bank_messages) if message.couch_recipient_doc_type == "CommCareCase": recipient = case_cache.get(message.couch_recipient) else: recipient = user_cache.get(message.couch_recipient) if message.chat_user_id: sender = user_cache.get(message.chat_user_id) else: sender = None study_arm = None if message.couch_recipient_doc_type == "CommCareCase": study_arm = case_cache.get( message.couch_recipient).get_case_property("study_arm") timestamp = ServerTime(message.date).user_time( self.timezone).done() result.append([ self._fmt(self._participant_id(recipient)), self._fmt(study_arm or "-"), self._fmt(self._originator(message, recipient, sender)), self._fmt_timestamp(timestamp), self._fmt(message.text), self._fmt(message.fri_id or "-"), self._fmt(direction_map.get(message.direction, "-")), ]) return result
def form_inline_display(form_id, timezone=pytz.utc): if form_id: try: form = XFormInstance.get(form_id) if form: return "%s: %s" % (ServerTime(form.received_on).user_time(timezone).done().date(), form.xmlns) except ResourceNotFound: pass return "%s: %s" % (_("missing form"), form_id) return _("empty form id found")
def rows(self): events = self._get_queryset()[self.pagination.start:self.pagination. end] for event in events: yield [ event.user, ServerTime(event.event_date).user_time( self.timezone).ui_string(), self._event_formatter.display(event), ]
def report_date_to_json(request, domain, date, is_phonetime=True): timezone = get_timezone(request, domain) if date: if is_phonetime: user_time = PhoneTime(date, timezone).user_time(timezone) else: user_time = ServerTime(date).user_time(timezone) user_time.ui_string(SERVER_DATETIME_FORMAT) else: return ''
def test_server_to_user(self): cases = [ ('2015-03-20T12:00:00', pytz.FixedOffset(-4 * 60), '2015-03-20T08:00:00-04:00'), ('2015-03-21T00:30:00', pytz.FixedOffset(-4 * 60), '2015-03-20T20:30:00-04:00'), ] for in_, tz, out in cases: server_dt = dateutil.parser.parse(in_) user_dt = ServerTime(server_dt).user_time(tz).done() self.assertEqual(user_dt.isoformat(), out)
def _format_rule(self, rule): return { 'id': rule.pk, 'name': rule.name, 'case_type': rule.case_type, 'active': rule.active, 'last_run': (ServerTime(rule.last_run) .user_time(self.project_timezone) .done() .strftime(SERVER_DATETIME_FORMAT)) if rule.last_run else '-', 'edit_url': reverse(EditCaseRuleView.urlname, args=[self.domain, rule.pk]), }
def rows(self): def form_data_link(instance_id): return "<a class='ajax_dialog' target='_new' href='%(url)s'>%(text)s</a>" % { "url": absolute_reverse('render_form_data', args=[self.domain, instance_id]), "text": _("View Form") } submissions = [ res['_source'] for res in self.es_results.get('hits', {}).get('hits', []) ] for form in submissions: uid = form["form"]["meta"]["userID"] username = form["form"]["meta"].get("username") try: if username not in ['demo_user', 'admin']: full_name = get_cached_property(CouchUser, uid, 'full_name', expiry=7 * 24 * 60 * 60) name = '"%s"' % full_name if full_name else "" else: name = "" except (ResourceNotFound, IncompatibleDocument): name = "<b>[unregistered]</b>" time = iso_string_to_datetime( safe_index(form, self.time_field.split('.'))) if self.by_submission_time: user_time = ServerTime(time).user_time(self.timezone) else: user_time = PhoneTime(time, self.timezone).user_time(self.timezone) init_cells = [ form_data_link(form["_id"]), (username or _('No data for username')) + (" %s" % name if name else ""), user_time.ui_string(USER_DATETIME_FORMAT_WITH_SEC), xmlns_to_name(self.domain, form.get("xmlns"), app_id=form.get("app_id")), ] def cell(field): return form["form"].get(field) init_cells.extend([cell(field) for field in self.other_fields]) yield init_cells
def get_display_data(data, prop_def, processors=None, timezone=pytz.utc): # when prop_def came from a couchdbkit document, it will be a LazyDict with # a broken pop method. This conversion also has the effect of a shallow # copy, which we want. prop_def = dict(prop_def) default_processors = { 'yesno': yesno, 'doc_info': lambda value: pretty_doc_info(get_doc_info_by_id( data['domain'], value)) } processors = processors or {} processors.update(default_processors) expr_name = _get_expr_name(prop_def) expr = prop_def.pop('expr') name = prop_def.pop('name', None) or _format_slug_string_for_display(expr) format = prop_def.pop('format', None) process = prop_def.pop('process', None) timeago = prop_def.get('timeago', False) has_history = prop_def.pop('has_history', False) val = eval_expr(expr, data) if prop_def.pop('parse_date', None): val = _parse_date_or_datetime(val) # is_utc is deprecated in favor of is_phone_time # but preserving here for backwards compatibility # is_utc = False is just reinterpreted as is_phone_time = True is_phone_time = prop_def.pop('is_phone_time', not prop_def.pop('is_utc', True)) if isinstance(val, datetime.datetime): if not is_phone_time: val = ServerTime(val).user_time(timezone).done() else: val = PhoneTime(val, timezone).user_time(timezone).done() try: val = conditional_escape(processors[process](val)) except KeyError: val = mark_safe(_to_html(val, timeago=timeago)) if format: val = mark_safe(format.format(val)) return { "expr": expr_name, "name": name, "value": val, "has_history": has_history, }
def options(self): timezone = get_timezone_for_user(self.request.couch_user, self.domain) records = UserUploadRecord.objects.filter(domain=self.domain).order_by('-date_created') return [ ( str(record.id), _("Upload by {username} at {time}").format( username=cached_user_id_to_user_display(record.user_id), time=ServerTime(record.date_created).user_time(timezone).ui_string(USER_DATETIME_FORMAT) ) ) for record in records ]
def rendered_report_title(self): new_title = self.name if self.errors_only: new_title = format_html( "Errors & Warnings Log <small>for {}</small>", ", ".join( self.device_log_users) ) if self.device_log_users else "Errors & Warnings Log" elif self.goto_key: log = self.goto_log new_title = format_html( "Last {} Logs <small>before {}</small>", self.limit, ServerTime(log.date).user_time(self.timezone).ui_string()) return new_title
def rendered_report_title(self): new_title = self.name if self.errors_only: new_title = ("Errors & Warnings Log <small>for %s</small>" % (", ".join(self.device_log_users)) if self.device_log_users else "Errors & Warnings Log") elif self.goto_key: log = self.goto_log new_title = "Last %s Logs <small>before %s</small>" % ( self.limit, ServerTime(log.date).user_time( self.timezone).ui_string()) return mark_safe(new_title)
def _format_rule(self, rule): return { 'id': rule.pk, 'name': rule.name, 'case_type': rule.case_type, 'active': rule.active, 'last_run': (ServerTime(rule.last_run) .user_time(self.project_timezone) .done() .strftime(SERVER_DATETIME_FORMAT)) if rule.last_run else '-', 'edit_url': reverse(EditCaseRuleView.urlname, args=[self.domain, rule.pk]), 'action_error': "", # must be provided because knockout template looks for it }
def rows(self): startdate = json_format_datetime(self.datespan.startdate_utc) enddate = json_format_datetime(self.datespan.enddate_utc) data = SMSLog.by_domain_date(self.domain, startdate, enddate) result = [] reporting_locations_id = self.get_location_filter( ) if self.uses_locations else [] # Retrieve message log options message_log_options = getattr(settings, "MESSAGE_LOG_OPTIONS", {}) abbreviated_phone_number_domains = message_log_options.get( "abbreviated_phone_number_domains", []) abbreviate_phone_number = (self.domain in abbreviated_phone_number_domains) contact_cache = {} message_type_filter = self.get_message_type_filter() for message in data: if message.direction == OUTGOING and not message.processed: continue message_types = self._get_message_types(message) if not message_type_filter(message_types): continue if reporting_locations_id and message.location_id not in reporting_locations_id: continue doc_info = self.get_recipient_info( message.couch_recipient_doc_type, message.couch_recipient, contact_cache) phone_number = message.phone_number if abbreviate_phone_number and phone_number is not None: phone_number = phone_number[0:7] if phone_number[ 0:1] == "+" else phone_number[0:6] timestamp = ServerTime(message.date).user_time( self.timezone).done() result.append([ self._fmt_timestamp(timestamp), self._fmt_contact_link(message.couch_recipient, doc_info), self._fmt(phone_number), self._fmt_direction(message.direction), self._fmt(message.text), self._fmt(", ".join(message_types)), ]) return result
def default_datespan(self): # DateSpan.since() will make enddate default to yesterday when it's None enddate = None if self.default_datespan_end_date_to_today: enddate = ServerTime(datetime.utcnow()).user_time( self.timezone).done().date() datespan = DateSpan.since(self.datespan_default_days, enddate=enddate, inclusive=self.inclusive, timezone=self.timezone) datespan.max_days = self.datespan_max_days datespan.is_default = True return datespan
def should_sync(domain, last_sync, utcnow=None): # definitely sync if we haven't synced before if not last_sync or not last_sync.date: return True # utcnow only used in tests to mock other times utcnow = utcnow or datetime.utcnow() try: timezone = domain.get_default_timezone() except pytz.UnknownTimeZoneError: timezone = utc last_sync_utc = last_sync.date # check if user has already synced today (in local timezone). # Indicators only change daily. last_sync_local = ServerTime(last_sync_utc).user_time(timezone).done() current_date_local = ServerTime(utcnow).user_time(timezone).done() if current_date_local.date() != last_sync_local.date(): return True return False
def test_server_to_phone(self): cases = [ ('2015-03-20T12:00:00', pytz.FixedOffset(-4 * 60), '2015-03-20T08:00:00'), ('2015-03-21T00:30:00', pytz.FixedOffset(-4 * 60), '2015-03-20T20:30:00'), ] for in_, tz, out in cases: server_dt = dateutil.parser.parse(in_) phone_dt = ServerTime(server_dt).phone_time(tz).done() if phone_timezones_have_been_processed(): # no change self.assertEqual(phone_dt.isoformat(), in_) else: self.assertEqual(phone_dt.isoformat(), out)
def rows(self): result = [] xforms_session = self.xforms_session for sms in SMS.objects.filter(xforms_session_couch_id=xforms_session.couch_id): timestamp = ServerTime(sms.date).user_time(self.timezone).done() status = self.get_sms_status_display(sms) result.append([ self._fmt_timestamp(timestamp), self._fmt(sms.text), self._fmt(sms.phone_number), self._fmt_direction(sms.direction), self._fmt(sms.backend_api), self._fmt(status), ]) return result
def check_obs_props(obs, props): for k, v in props.items(): if k.endswith("_date"): # datetime check obs_datetime = getattr(obs, k) val_datetime = dateutil.parser.parse(v) if k in ('completed_date', 'created_date'): obs_datetime = ServerTime(obs_datetime).user_time(PACT_TIMEZONE).done() obs_date = obs_datetime.date() val_date = val_datetime.date() self.assertEquals(obs_date, val_date) else: self.assertEquals(getattr(obs, k), v, msg="Error, observation %s\n\t%s didn't match: %s != %s" % ( json.dumps(obs.to_json(), indent=4), k, getattr(obs, k), v))
def rows(self): data = (SMS.by_domain(self.config['domain']).filter( location_id=self.config['location_id']).exclude( processed=False, direction=OUTGOING).order_by('-date')) messages = [] for message in data: recipient = message.recipient timestamp = ServerTime(message.date).user_time( self.config['timezone']).done() messages.append([ _fmt_timestamp(timestamp), recipient.full_name, message.phone_number, _fmt(message.direction), _fmt(message.text), ]) return messages
def __init__(self, domain_object=None): self.domain_object = domain_object if domain_object: self.date = ServerTime(datetime.utcnow()).user_time( domain_object.get_default_timezone()).done().date() else: self.date = datetime.utcnow().date() self.key = 'outbound-daily-count-for-%s-%s' % ( domain_object.name if domain_object else '', self.date.strftime('%Y-%m-%d')) # We need access to the raw redis client because calling incr on # a django_redis RedisCache object raises an error if the key # doesn't exist. self.client = get_redis_client().client.get_client()