class GetAllFormsRepeatsSpec(JsonObject): type = TypeProperty('icds_get_all_forms_repeats') forms_expression = DefaultProperty(required=True) repeat_path = ListProperty(required=True) case_id_path = ListProperty(required=True) repeat_filter = DefaultProperty(required=False) case_id_expression = DefaultProperty(required=False)
class GetLastFormRepeatSpec(JsonObject): type = TypeProperty('icds_get_last_form_repeat') forms_expression = DefaultProperty(required=True) repeat_path = ListProperty(required=True) case_id_path = ListProperty(required=True) repeat_filter = DefaultProperty(required=False) case_id_expression = DefaultProperty(required=False)
class CaseProperty(JsonObject): name = StringProperty() forms = ListProperty(CaseFormMeta) short_details = ListProperty(CaseDetailMeta) long_details = ListProperty(CaseDetailMeta) has_errors = BooleanProperty() description = StringProperty() def get_form(self, form_id): try: form = next(form for form in self.forms if form.form_id == form_id) except StopIteration: form = CaseFormMeta(form_id=form_id) self.forms.append(form) return form def add_load(self, form_id, question): form = self.get_form(form_id) form.load_questions.append(ConditionalFormQuestionResponse( question=question, condition=None )) def add_save(self, form_id, question, condition=None): form = self.get_form(form_id) form.save_questions.append(ConditionalFormQuestionResponse( question=question, condition=(condition if condition and condition.type == 'if' else None) )) def add_detail(self, type_, module_id, header, format): { "short": self.short_details, "long": self.long_details, }[type_].append(CaseDetailMeta(module_id=module_id, header=header, format=format))
class Location(JsonObject): id = IntegerProperty() name = StringProperty() type = StringProperty() parent_id = IntegerProperty() latitude = StringProperty() longitude = StringProperty() code = StringProperty() groups = ListProperty() supervised_by = IntegerProperty() supply_points = ListProperty(item_type=SupplyPoint) is_active = BooleanProperty()
class MigrationConfig(JsonObject): from_db_postfix = StringProperty() to_db_postfix = StringProperty() doc_types = ListProperty(required=True) couch_views = ListProperty() @property def source_db(self): return get_db(self.from_db_postfix) @property def dest_db(self): return get_db(self.to_db_postfix)
class SupplyPoint(JsonObject): id = IntegerProperty() active = BooleanProperty() code = StringProperty() groups = ListProperty() last_reported = StringProperty() name = StringProperty() primary_reporter = IntegerProperty() supervised_by = IntegerProperty() supplied_by = IntegerProperty() type = StringProperty() location_id = IntegerProperty() products = ListProperty() incharges = ListProperty()
class ChoiceListIndicatorSpec(PropertyReferenceIndicatorSpecBase): type = TypeProperty('choice_list') choices = ListProperty(required=True) select_style = StringProperty(choices=['single', 'multiple']) def get_operator(self): return IN_MULTISELECT if self.select_style == 'multiple' else EQUAL
class IteratorExpressionSpec(NoPropertyTypeCoercionMixIn, JsonObject): type = TypeProperty('iterator') expressions = ListProperty(required=True) # an optional filter to test the values on - if they don't match they won't be included in the iteration test = DictProperty() def configure(self, expressions, test): self._expression_fns = expressions if test: self._test = test else: # if not defined then all values should be returned self._test = lambda *args, **kwargs: True def __call__(self, item, context=None): values = [] for expression in self._expression_fns: value = expression(item, context) if self._test(value): values.append(value) return values def __str__(self): expressions_text = ", ".join(str(e) for e in self._expression_fns) return "iterate on [{}] if {}".format(expressions_text, str(self._test))
class GetCaseFormsByDateSpec(JsonObject): type = TypeProperty('ext_get_case_forms_by_date') case_id_expression = DefaultProperty(required=False) xmlns = ListProperty(required=False) start_date = DefaultProperty(required=False) end_date = DefaultProperty(required=False) form_filter = DefaultProperty(required=False)
class PropertyPathGetterSpec(JsonObject): """ This expression returns ``doc["child"]["age"]``: .. code:: json { "type": "property_path", "property_path": ["child", "age"] } An optional ``"datatype"`` attribute may be specified, which will attempt to cast the property to the given data type. The options are "date", "datetime", "string", "integer", and "decimal". If no datatype is specified, "string" will be used. """ type = TypeProperty('property_path') property_path = ListProperty(str, required=True) datatype = DataTypeProperty(required=False) def __call__(self, item, context=None): transform = transform_from_datatype(self.datatype) return transform(safe_recursive_lookup(item, self.property_path)) def __str__(self): value = "/".join(self.property_path) if self.datatype: "({datatype}){value}".format(datatype=self.datatype, value=value) return value
class CaseTypeMeta(JsonObject): name = StringProperty(required=True) relationships = DictProperty() # relationship name -> case type properties = ListProperty(CaseProperty) # property -> CaseProperty opened_by = DictProperty(ConditionList) # form_ids -> [FormActionCondition, ...] closed_by = DictProperty(ConditionList) # form_ids -> [FormActionCondition, ...] error = StringProperty() has_errors = BooleanProperty() def get_property(self, name, allow_parent=False): if not allow_parent: assert '/' not in name, "Add parent properties to the correct case type" try: prop = next(prop for prop in self.properties if prop.name == name) except StopIteration: prop = CaseProperty(name=name) self.properties.append(prop) return prop def add_opener(self, form_id, condition): openers = self.opened_by.get(form_id, ConditionList()) if condition.type == 'if': # only add optional conditions openers.conditions.append(condition) self.opened_by[form_id] = openers def add_closer(self, form_id, condition): closers = self.closed_by.get(form_id, ConditionList()) if condition.type == 'if': # only add optional conditions closers.conditions.append(condition) self.closed_by[form_id] = closers
class PillowResetConfig(JsonObject): seq = StringProperty(required=True) pillow_names = ListProperty(required=True) @property def pillows(self): return [get_pillow_by_name(name) for name in self.pillow_names]
class GetCaseHistoryByDateSpec(JsonObject): type = TypeProperty('icds_get_case_history_by_date') case_id_expression = DefaultProperty(required=False) start_date = DefaultProperty(required=False) end_date = DefaultProperty(required=False) filter = DefaultProperty(required=False) xmlns = ListProperty(required=False)
class PropertyPathGetterSpec(JsonObject): type = TypeProperty('property_path') property_path = ListProperty(six.text_type, required=True) datatype = DataTypeProperty(required=False) def __call__(self, item, context=None): transform = transform_from_datatype(self.datatype) return transform(safe_recursive_lookup(item, self.property_path))
class GetLastCasePropertyUpdateSpec(JsonObject): type = TypeProperty('icds_get_last_case_property_update') case_property = StringProperty(required=True) case_id_expression = DefaultProperty(required=False) start_date = DefaultProperty(required=False) end_date = DefaultProperty(required=False) filter = DefaultProperty(required=False) xmlns = ListProperty(required=False)
class SumWhenTemplateSpec(JsonObject): type = StringProperty(required=True) expression = StringProperty(required=True) binds = ListProperty() then = IntegerProperty() def bind_count(self): return len(re.sub(r'[^?]', '', self.expression))
class FormsExpressionSpec(JsonObject): type = TypeProperty('get_case_forms') case_id_expression = DefaultProperty(required=True) xmlns = ListProperty(required=False) 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 [] assert context.root_doc['domain'] return self._get_forms(case_id, context) def _get_forms(self, case_id, context): domain = context.root_doc['domain'] cache_key = (self.__class__.__name__, case_id, tuple(self.xmlns)) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) xforms = self._get_case_forms(case_id, context) if self.xmlns: xforms = [f for f in xforms if f.xmlns in self.xmlns] xforms = [ self._get_form_json(f, context) for f in xforms if f.domain == domain ] context.set_cache_value(cache_key, xforms) return xforms @ucr_context_cache(vary_on=('case_id', )) def _get_case_forms(self, case_id, context): domain = context.root_doc['domain'] return FormProcessorInterface(domain).get_case_forms(case_id) def _get_form_json(self, form, context): cache_key = (XFORM_CACHE_KEY_PREFIX, form.get_id) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) form_json = form.to_json() context.set_cache_value(cache_key, form_json) return form_json def __str__(self): xmlns_text = ", ".join(self.xmlns) if xmlns_text: form_text = "({})".format(xmlns_text) else: form_text = "all" return "get {} forms for {}".format(form_text, str(self._case_id_expression))
class LedgerBalancesIndicatorSpec(IndicatorSpecBase): type = TypeProperty('ledger_balances') product_codes = ListProperty(required=True) ledger_section = StringProperty(required=True) case_id_expression = DictProperty(required=True) def get_case_id_expression(self): from corehq.apps.userreports.expressions.factory import ExpressionFactory return ExpressionFactory.from_spec(self.case_id_expression)
class Location(JsonObject): id = IntegerProperty() name = StringProperty() type = StringProperty() parent_id = IntegerProperty() latitude = StringProperty() longitude = StringProperty() code = StringProperty() groups = ListProperty() historical_groups = DictProperty()
class IteratorExpressionSpec(NoPropertyTypeCoercionMixIn, JsonObject): """ .. code:: json { "type": "iterator", "expressions": [ { "type": "property_name", "property_name": "p1" }, { "type": "property_name", "property_name": "p2" }, { "type": "property_name", "property_name": "p3" }, ], "test": {} } This will emit ``[doc.p1, doc.p2, doc.p3]``. You can add a ``test`` attribute to filter rows from what is emitted - if you don't specify this then the iterator will include one row per expression it contains regardless of what is passed in. This can be used/combined with the ``base_item_expression`` to emit multiple rows per document. """ type = TypeProperty('iterator') expressions = ListProperty(required=True) # an optional filter to test the values on - if they don't match they won't be included in the iteration test = DictProperty() def configure(self, expressions, test): self._expression_fns = expressions if test: self._test = test else: # if not defined then all values should be returned self._test = lambda *args, **kwargs: True def __call__(self, item, context=None): values = [] for expression in self._expression_fns: value = expression(item, context) if self._test(value): values.append(value) return values def __str__(self): expressions_text = ", ".join(str(e) for e in self._expression_fns) return "iterate on [{}] if {}".format(expressions_text, str(self._test))
class PropertyReferenceIndicatorSpecBase(IndicatorSpecBase): """ Extension of an indicator spec that references a property - either via a property_name or property_path. """ property_name = StringProperty() property_path = ListProperty() @property def getter(self): return getter_from_property_reference(self)
class SMSUser(JsonObject): id = IntegerProperty() name = StringProperty() role = StringProperty() is_active = StringProperty() supply_point = DecimalProperty() email = StringProperty() phone_numbers = ListProperty() backend = StringProperty() date_updated = StringProperty() language = StringProperty()
class FormsExpressionSpec(JsonObject): type = TypeProperty('get_case_forms') case_id_expression = DefaultProperty(required=True) xmlns = ListProperty(required=False) 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 [] assert context.root_doc['domain'] return self._get_forms(case_id, context) def _get_forms(self, case_id, context): domain = context.root_doc['domain'] cache_key = (self.__class__.__name__, case_id, tuple(self.xmlns)) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) xforms = self._get_case_forms(case_id, context) if self.xmlns: xforms = [f for f in xforms if f.xmlns in self.xmlns] xforms = [ self._get_form_json(f, context) for f in xforms if f.domain == domain ] context.set_cache_value(cache_key, xforms) return xforms def _get_case_forms(self, case_id, context): cache_key = (self.__class__.__name__, 'helper', case_id) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) domain = context.root_doc['domain'] xforms = FormProcessorInterface(domain).get_case_forms(case_id) context.set_cache_value(cache_key, xforms) return xforms def _get_form_json(self, form, context): cache_key = (XFORM_CACHE_KEY_PREFIX, form.get_id) if context.get_cache_value(cache_key) is not None: return context.get_cache_value(cache_key) form_json = form.to_json() context.set_cache_value(cache_key, form_json) return form_json
class SumWhenTemplateColumn(SumWhenColumn): type = TypeProperty("sum_when_template") whens = ListProperty(DictProperty) # List of SumWhenTemplateSpec dicts def get_whens(self): from corehq.apps.userreports.reports.factory import SumWhenTemplateFactory whens = [] for spec in self.whens: template = SumWhenTemplateFactory.make_template(spec) whens.append([template.expression] + template.binds + [template.then]) return whens
class ChoiceListIndicatorSpec(PropertyReferenceIndicatorSpecBase): type = TypeProperty('choice_list') choices = ListProperty() select_style = StringProperty(choices=['single', 'multiple']) def get_operator(self): return in_multiselect if self.select_style == 'multiple' else equal def readable_output(self, context): readable_output = super(ChoiceListIndicatorSpec, self).readable_output(context) return "{} for choices:\n{}".format(readable_output, add_tabbed_text(str(self.choices)))
class LedgerBalancesIndicatorSpec(IndicatorSpecBase): type = TypeProperty('ledger_balances') product_codes = ListProperty(required=True) ledger_section = StringProperty(required=True) case_id_expression = DictProperty(required=True) def get_case_id_expression(self, context=None): from corehq.apps.userreports.expressions.factory import ExpressionFactory return ExpressionFactory.from_spec(self.case_id_expression, context) def readable_output(self, context): return "Ledgers from {}".format(str(self.get_case_id_expression(context)))
class SMSUser(JsonObject): id = IntegerProperty() name = StringProperty() role = StringProperty() is_active = StringProperty() supply_point = ObjectProperty(item_type=SupplyPoint) email = StringProperty() phone_numbers = ListProperty() backend = StringProperty() family_name = StringProperty() to = StringProperty() language = StringProperty()
class FormQuestionResponse(FormQuestion): response = DefaultProperty() children = ListProperty(lambda: FormQuestionResponse, exclude_if_none=True) def get_formatted_response(self): timezone = get_timezone_for_request() if self.type == 'DateTime' and timezone \ and isinstance(self.response, datetime.datetime): return (PhoneTime(self.response, timezone).user_time(timezone) .ui_string()) else: return self.response
class PropertyPathGetterSpec(JsonObject): type = TypeProperty('property_path') property_path = ListProperty(unicode, required=True) datatype = DataTypeProperty(required=False) @property def expression(self): transform = transform_from_datatype(self.datatype) getter = NestedDictGetter(self.property_path) return TransformedGetter(getter, transform) def __call__(self, item, context=None): return self.expression(item, context)
class PropertyReferenceIndicatorSpecBase(IndicatorSpecBase): """ Extension of an indicator spec that references a property - either via a property_name or property_path. """ property_name = StringProperty() property_path = ListProperty() @property def getter(self): return getter_from_property_reference(self) def readable_output(self, context): return self.property_name or "/".join(self.property_path)