class Fields(JsonObject): """ Fields model for issue""" status = ObjectProperty(Status) components = ListProperty(Component, default=None) labels = ListProperty(StringProperty, default=None) summary = StringProperty(default='') assignee = ObjectProperty(User) closed_sprints = ListProperty(Sprint, default=None, name='closedSprints') reporter = ObjectProperty(User) issue_type = ObjectProperty(IssueType) parent_ = DefaultProperty(default=None, name='parent') subtasks_ = DefaultProperty(default=None, name='subtasks') @property def parent(self): """ Getter for parent issue """ if self.parent_: return Issue(self.parent_) return None @property def subtasks(self): """ Getter for subtasks """ if self.subtasks_: return list(map(Issue, self.subtasks_)) return None
class AncestorLocationExpression(JsonObject): """ For a given location id and location type, this expression returns the ancestor of the location that is the given type. If no such location exists, return None. e.g. (boston.location_id, "state") => massachusetts.to_json() """ type = TypeProperty("ancestor_location") location_id = DefaultProperty(required=True) location_type = DefaultProperty(required=True) def configure(self, location_id_expression, location_type_expression): self._location_id_expression = location_id_expression self._location_type_expression = location_type_expression def __call__(self, item, context=None): location_id = self._location_id_expression(item, context) location_type = self._location_type_expression(item, context) return self._get_ancestor(location_id, location_type, context) @staticmethod @ucr_context_cache(vary_on=( 'location_id', 'location_type', )) def _get_ancestor(location_id, location_type, context): try: location = _get_location(location_id, context) ancestor = location.get_ancestors(include_self=False).get( location_type__name=location_type) return ancestor.to_json() except (AttributeError, SQLLocation.DoesNotExist): # location is None, or location does not have an ancestor of that type return None
class AncestorLocationExpression(JsonObject): """ For a given location id and location type, this expression returns the ancestor of the location that is the given type. If no such location exists, return None. e.g. (boston.location_id, "state") => massachusetts.to_json() """ type = TypeProperty("ancestor_location") location_id = DefaultProperty(required=True) location_type = DefaultProperty(required=True) def configure(self, location_id_expression, location_type_expression): self._location_id_expression = location_id_expression self._location_type_expression = location_type_expression def __call__(self, item, context=None): location_id = self._location_id_expression(item, context) location_type = self._location_type_expression(item, context) cache_key = (self.__class__.__name__, location_id, location_type) if context.get_cache_value(cache_key, False) is not False: return context.get_cache_value(cache_key) ancestor_json = self._get_ancestor(location_id, location_type) context.set_cache_value(cache_key, ancestor_json) return ancestor_json def _get_ancestor(self, location_id, location_type): try: location = SQLLocation.objects.get(location_id=location_id) ancestor = location.get_ancestors(include_self=False).get( location_type__name=location_type) return ancestor.to_json() except (AttributeError, SQLLocation.DoesNotExist): # location is None, or location does not have an ancestor of that type return None
class AncestorLocationExpression(JsonObject): """ For a given location id and location type, this expression returns the ancestor of the location that is the given type. If no such location exists, return None. e.g. (boston.location_id, "state") => massachusetts.to_json() """ type = TypeProperty("ancestor_location") location_id = DefaultProperty(required=True) location_type = DefaultProperty(required=True) def configure(self, location_id_expression, location_type_expression): self._location_id_expression = location_id_expression self._location_type_expression = location_type_expression def __call__(self, item, context=None): location_id = self._location_id_expression(item, context) location_type = self._location_type_expression(item, context) return self._get_ancestors_by_type(location_id, context).get(location_type) @staticmethod @ucr_context_cache(vary_on=('location_id', )) def _get_ancestors_by_type(location_id, context): location = _get_location(location_id, context) if not location: return {} ancestors = (location.get_ancestors( include_self=False).prefetch_related('location_type', 'parent')) return { ancestor.location_type.name: ancestor.to_json(include_lineage=False) for ancestor in ancestors }
class ChangeMeta(jsonobject.JsonObject): """ Metadata about a change. If available, this will be set on Change.metadata. This is only used in kafka-based pillows. """ _allow_dynamic_properties = False document_id = DefaultProperty(required=True) # Only relevant for Couch documents document_rev = jsonobject.StringProperty() # 'couch' or 'sql' data_source_type = jsonobject.StringProperty(required=True) # couch database name or one of data sources listed in corehq.apps.change_feed.data_sources data_source_name = jsonobject.StringProperty(required=True) # doc_type property of doc or else the topic name document_type = DefaultProperty() document_subtype = jsonobject.StringProperty() domain = jsonobject.StringProperty() is_deletion = jsonobject.BooleanProperty() publish_timestamp = jsonobject.DateTimeProperty(default=datetime.utcnow) # track of retry attempts attempts = jsonobject.IntegerProperty(default=0)
class FirstCaseFormWithXmlns(JsonObject): type = TypeProperty('first_case_form_with_xmlns') xmlns = DefaultProperty(required=True) case_id_expression = DefaultProperty(required=True) reverse = BooleanProperty(default=False) def configure(self, case_id_expression): self._case_id_expression = case_id_expression def __call__(self, item, context=None): assert isinstance(self.xmlns, (six.string_types, list)) case_id = self._case_id_expression(item, context) if not case_id: return None assert context.root_doc['domain'] return self._get_forms(case_id, context) def _get_forms(self, case_id, context): domain = context.root_doc['domain'] xmlns = [self.xmlns] if isinstance(self.xmlns, six.string_types) else self.xmlns xforms = _get_case_forms(domain, case_id, context) xforms = sorted( [form for form in xforms if form.xmlns in xmlns and form.domain == domain], key=lambda x: x.received_on ) if not xforms: form = None else: index = -1 if self.reverse else 0 form = xforms[index].to_json() return form
class CountCaseFormsWithXmlns(JsonObject): type = TypeProperty('count_case_forms_with_xmlns') xmlns = DefaultProperty(required=True) case_id_expression = DefaultProperty(required=True) def configure(self, case_id_expression): self._case_id_expression = case_id_expression def __call__(self, item, context=None): assert isinstance(self.xmlns, (six.string_types, list)) case_id = self._case_id_expression(item, context) if not case_id: return None assert context.root_doc['domain'] return self._count_forms(case_id, context) def _count_forms(self, case_id, context): domain = context.root_doc['domain'] xmlns = [self.xmlns] if isinstance(self.xmlns, six.string_types) else self.xmlns cache_key = (self.__class__.__name__, case_id, hashlib.md5(','.join(xmlns)).hexdigest()) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) xforms = FormProcessorInterface(domain).get_case_forms(case_id) count = len([form for form in xforms if form.xmlns in xmlns and form.domain == domain]) context.set_cache_value(cache_key, count) return count
class CountCaseFormsWithXmlns(JsonObject): type = TypeProperty('count_case_forms_with_xmlns') xmlns = DefaultProperty(required=True) case_id_expression = DefaultProperty(required=True) def configure(self, case_id_expression): self._case_id_expression = case_id_expression def __call__(self, item, context=None): assert isinstance(self.xmlns, (six.string_types, list)) case_id = self._case_id_expression(item, context) if not case_id: return None assert context.root_doc['domain'] return self._count_forms(case_id, context) def _count_forms(self, case_id, context): domain = context.root_doc['domain'] xmlns = [self.xmlns] if isinstance(self.xmlns, six.string_types) else self.xmlns xforms = _get_case_forms(domain, case_id, context) count = len([ form for form in xforms if form.xmlns in xmlns and form.domain == domain ]) return count
class ChangeMeta(jsonobject.JsonObject): """ Metadata about a change. If available, this will be set on Change.metadata. This is only used in kafka-based pillows. """ document_id = DefaultProperty(required=True) data_source_type = jsonobject.StringProperty(required=True) data_source_name = jsonobject.StringProperty(required=True) document_type = DefaultProperty() document_subtype = jsonobject.StringProperty() domain = jsonobject.StringProperty() is_deletion = jsonobject.BooleanProperty() _allow_dynamic_properties = False
class CountCaseFormsWithXmlns(JsonObject): type = TypeProperty('count_case_forms_with_xmlns') xmlns = StringProperty(required=True) case_id_expression = DefaultProperty(required=True) def configure(self, case_id_expression): self._case_id_expression = case_id_expression def __call__(self, item, context=None): case_id = self._case_id_expression(item, context) if not case_id: return None assert context.root_doc['domain'] return self._count_forms(case_id, context) def _count_forms(self, case_id, context): domain = context.root_doc['domain'] cache_key = (self.__class__.__name__, case_id, self.xmlns) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) xforms = FormProcessorInterface(domain).get_case_forms(case_id) count = len([ form for form in xforms if form.xmlns == self.xmlns and form.domain == domain ]) context.set_cache_value(cache_key, count) return count
class ExpressionIndicatorSpec(IndicatorSpecBase): type = TypeProperty('expression') datatype = DataTypeProperty(required=True) is_nullable = BooleanProperty(default=True) is_primary_key = BooleanProperty(default=False) create_index = BooleanProperty(default=False) expression = DefaultProperty(required=True) transform = DictProperty(required=False) def parsed_expression(self, context): from corehq.apps.userreports.expressions.factory import ExpressionFactory expression = ExpressionFactory.from_spec(self.expression, context) datatype_transform = transform_for_datatype(self.datatype) if self.transform: generic_transform = TransformFactory.get_transform( self.transform).get_transform_function() inner_getter = TransformedGetter(expression, generic_transform) else: inner_getter = expression return TransformedGetter(inner_getter, datatype_transform) def readable_output(self, context): from corehq.apps.userreports.expressions.factory import ExpressionFactory expression_object = ExpressionFactory.from_spec( self.expression, context) return str(expression_object)
class ChangeMeta(jsonobject.JsonObject): """ Metadata about a change. If available, this will be set on Change.metadata. This is only used in kafka-based pillows. """ document_id = DefaultProperty(required=True) document_rev = jsonobject.StringProperty() # Only relevant for Couch documents data_source_type = jsonobject.StringProperty(required=True) data_source_name = jsonobject.StringProperty(required=True) document_type = DefaultProperty() document_subtype = jsonobject.StringProperty() domain = jsonobject.StringProperty() is_deletion = jsonobject.BooleanProperty() publish_timestamp = jsonobject.DateTimeProperty(default=datetime.utcnow) _allow_dynamic_properties = False
class MostRecentEpisodeCaseFromPerson(JsonObject): """ An expression that returns the the most recent Referral Case from Person which pass the filters: -> referral_status != 'rejected' and 'referral_closed_reason' != 'duplicate_referral_reconciliation' """ type = TypeProperty('enikshay_most_recent_episode_from_person') person_id_expression = DefaultProperty(required=True) def configure(self, person_id_expression): self._person_id_expression = person_id_expression def __call__(self, item, context=None): person_id = self._person_id_expression(item, context) return self._get_most_recent_episode_case_json(person_id, context) @staticmethod @ucr_context_cache(vary_on=('person_id', )) def _get_most_recent_episode_case_json(person_id, context): domain = context.root_doc['domain'] if not person_id: return None try: episode = get_most_recent_episode_case_from_person( domain, person_id) except ENikshayCaseNotFound: episode = None if episode: return episode.to_json()
class ReferralExpressionBase(JsonObject): person_id_expression = DefaultProperty(required=True) def configure(self, person_id_expression): self._person_id_expression = person_id_expression def __call__(self, item, context=None): person_id = self._person_id_expression(item, context) domain = context.root_doc['domain'] if not person_id: return None referral = self._get_referral(context, domain, person_id) if referral: return self._handle_referral_case(referral) trail = self._get_trail(context, domain, person_id) if trail: return self._handle_trail_case(context, trail, domain) return None @staticmethod def _get_referral(context, domain, person_id): cache_key = (ReferralExpressionBase.__name__, "_get_referral", person_id) if context.get_cache_value(cache_key, False) is not False: return context.get_cache_value(cache_key) referral = get_open_referral_case_from_person(domain, person_id) if referral and (referral.dynamic_case_properties().get("referral_status") == "rejected"): referral = None context.set_cache_value(cache_key, referral) return referral @staticmethod def _get_referral_by_id(context, domain, referral_id): cache_key = (ReferralExpressionBase.__name__, "_get_referral_by_id", referral_id) if context.get_cache_value(cache_key, False) is not False: return context.get_cache_value(cache_key) referral = CaseAccessors(domain).get_case(referral_id) context.set_cache_value(cache_key, referral) return referral @staticmethod def _get_trail(context, domain, person_id): cache_key = (ReferralExpressionBase.__name__, "_get_trail", person_id) if context.get_cache_value(cache_key, False) is not False: return context.get_cache_value(cache_key) trail = get_latest_trail_case_from_person(domain, person_id) context.set_cache_value(cache_key, trail) return trail def _handle_referral_case(self, referral): raise NotImplementedError def _handle_trail_case(self, context, trail, domain): raise NotImplementedError
class FirstCaseFormWithXmlns(JsonObject): type = TypeProperty('first_case_form_with_xmlns') xmlns = DefaultProperty(required=True) case_id_expression = DefaultProperty(required=True) reverse = BooleanProperty(default=False) def configure(self, case_id_expression): self._case_id_expression = case_id_expression def __call__(self, item, context=None): assert isinstance(self.xmlns, (six.string_types, list)) case_id = self._case_id_expression(item, context) if not case_id: return None assert context.root_doc['domain'] return self._get_forms(case_id, context) def _get_forms(self, case_id, context): domain = context.root_doc['domain'] xmlns = [self.xmlns] if isinstance(self.xmlns, six.string_types) else self.xmlns cache_key = (self.__class__.__name__, case_id, hashlib.md5(','.join(xmlns)).hexdigest(), self.reverse) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) xforms = FormProcessorInterface(domain).get_case_forms(case_id) xforms = sorted([ form for form in xforms if form.xmlns in xmlns and form.domain == domain ], key=lambda x: x.received_on) if not xforms: form = None else: index = -1 if self.reverse else 0 form = xforms[index].to_json() context.set_cache_value(cache_key, form) return form
class KeyPopulationsExpression(JsonObject): type = TypeProperty('enikshay_key_populations') key_populations_expression = DefaultProperty(required=True) def configure(self, key_populations_expression): self._key_populations_expression = key_populations_expression def __call__(self, item, context=None): key_populations_value = self._key_populations_expression(item, context) if not key_populations_value: return '' return ', '.join(key_populations_value.split(' '))
class MonthExpression(JsonObject): type = TypeProperty('month_expression') month_expression = DefaultProperty(required=True) def configure(self, month_expression): self._month_expression = month_expression def __call__(self, item, context=None): try: date = force_to_datetime(self._month_expression(item, context)) except ValueError: return '' if not date: return '' return str(date.month)
class ReferralExpressionBase(JsonObject): person_id_expression = DefaultProperty(required=True) def configure(self, person_id_expression): self._person_id_expression = person_id_expression def __call__(self, item, context=None): person_id = self._person_id_expression(item, context) domain = context.root_doc['domain'] if not person_id: return None referral = self._get_referral(context, domain, person_id) if referral: return self._handle_referral_case(referral) trail = self._get_trail(context, domain, person_id) if trail: return self._handle_trail_case(context, trail, domain) return None @staticmethod @ucr_context_cache(vary_on=('person_id', )) def _get_referral(context, domain, person_id): referral = get_open_referral_case_from_person(domain, person_id) if referral and ( referral.dynamic_case_properties().get("referral_status") == "rejected"): referral = None return referral @staticmethod @ucr_context_cache(vary_on=('referral_id', )) def _get_referral_by_id(context, domain, referral_id): return CaseAccessors(domain).get_case(referral_id) @staticmethod @ucr_context_cache(vary_on=('person_id', )) def _get_trail(context, domain, person_id): return get_latest_trail_case_from_person(domain, person_id) def _handle_referral_case(self, referral): raise NotImplementedError def _handle_trail_case(self, context, trail, domain): raise NotImplementedError
class EpisodeFromPersonExpression(JsonObject): type = TypeProperty('enikshay_episode_from_person') person_id_expression = DefaultProperty(required=True) def configure(self, person_id_expression): self._person_id_expression = person_id_expression def __call__(self, item, context=None): person_id = self._person_id_expression(item, context) domain = context.root_doc['domain'] if not person_id: return None try: episode = get_open_episode_case_from_person(domain, person_id) except ENikshayCaseNotFound: return None if episode: return episode.to_json() return None
class AncestorLocationExpression(JsonObject): """ This is used to return a json object representing the ancestor of the given type of the given location. For instance, if we had locations configured with a hierarchy like ``country -> state -> county -> city``, we could pass the location id of Cambridge and a location type of state to this expression to get the Massachusetts location. .. code:: json { "type": "ancestor_location", "location_id": { "type": "property_name", "name": "owner_id" }, "location_type": { "type": "constant", "constant": "state" } } If no such location exists, returns null. Optionally you can specifiy ``location_property`` to return a single property of the location. .. code:: json { "type": "ancestor_location", "location_id": { "type": "property_name", "name": "owner_id" }, "location_type": { "type": "constant", "constant": "state" }, "location_property": "site_code" } """ type = TypeProperty("ancestor_location") location_id = DefaultProperty(required=True) location_type = DefaultProperty(required=True) location_property = StringProperty(required=False) def configure(self, location_id_expression, location_type_expression): self._location_id_expression = location_id_expression self._location_type_expression = location_type_expression def __call__(self, item, context=None): location_id = self._location_id_expression(item, context) location_type = self._location_type_expression(item, context) location = self._get_ancestors_by_type(location_id, context).get(location_type) if not location: return None if self.location_property: return location.get(self.location_property) return location @staticmethod @ucr_context_cache(vary_on=('location_id', )) def _get_ancestors_by_type(location_id, context): location = _get_location(location_id, context) if not location: return {} ancestors = (location.get_ancestors( include_self=False).prefetch_related('location_type', 'parent')) return { ancestor.location_type.name: ancestor.to_json(include_lineage=False) for ancestor in ancestors }
class AppPart(jsonobject.JsonObject): id = jsonobject.IntegerProperty() names = DefaultProperty( ) # this is almost always a dict, but for user registration it's a string