Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
class TaskStatus(jsonobject.StrictJsonObject):
    # takes on values of soil.progress.STATES
    state = jsonobject.IntegerProperty()
    progress = jsonobject.ObjectProperty(lambda: TaskStatusProgress)
    result = jsonobject.ObjectProperty(lambda: TaskStatusResult)

    def is_finished(self):
        return self.state not in (STATES.not_started, STATES.started)
Ejemplo n.º 3
0
class CaseUploadJSON(jsonobject.StrictJsonObject):
    domain = jsonobject.StringProperty(required=True)
    # In user display format, e.g. Dec 08, 2016 19:19 EST
    created = jsonobject.StringProperty(required=True)
    upload_id = jsonobject.StringProperty(required=True)
    task_status = jsonobject.ObjectProperty(lambda: TaskStatus)
    user_name = jsonobject.StringProperty(required=True)
    case_type = jsonobject.StringProperty(required=True)
    comment = jsonobject.StringProperty()

    upload_file_name = jsonobject.StringProperty()
    upload_file_length = jsonobject.IntegerProperty()
    upload_file_download_allowed = jsonobject.BooleanProperty(required=True)
    upload_comment_edit_allowed = jsonobject.BooleanProperty(required=True)
Ejemplo n.º 4
0
class PaymentUpdate(jsonobject.JsonObject):
    id = jsonobject.StringProperty(required=True)
    status = jsonobject.StringProperty(required=True,
                                       choices=[SUCCESS, FAILURE])
    amount = jsonobject.IntegerProperty(required=False)
    paymentDate = FlexibleDateTimeProperty(required=True)
    comments = jsonobject.StringProperty(required=False)
    failureDescription = jsonobject.StringProperty(required=False)
    paymentMode = jsonobject.StringProperty(required=False)
    checkNumber = jsonobject.StringProperty(required=False)
    bankName = jsonobject.StringProperty(required=False)

    @property
    def case_id(self):
        return self.id
Ejemplo n.º 5
0
class MonthlyPerformanceSummary(jsonobject.JsonObject):
    month = jsonobject.DateProperty()
    domain = jsonobject.StringProperty()
    performance_threshold = jsonobject.IntegerProperty()
    active = jsonobject.IntegerProperty()
    performing = jsonobject.IntegerProperty()

    def __init__(self,
                 domain,
                 month,
                 selected_users,
                 active_not_deleted_users,
                 performance_threshold,
                 previous_summary=None,
                 delta_high_performers=0,
                 delta_low_performers=0):
        self._previous_summary = previous_summary
        self._next_summary = None
        self._is_final = None

        base_queryset = MALTRow.objects.filter(
            domain_name=domain,
            month=month,
            user_type__in=['CommCareUser', 'CommCareUser-Deleted'],
            user_id__in=active_not_deleted_users,
        )
        if selected_users:
            base_queryset = base_queryset.filter(user_id__in=selected_users, )

        self._user_stat_from_malt = (base_queryset.values(
            'user_id',
            'username').annotate(total_num_forms=Sum('num_of_forms')))

        num_performing_users = (self._user_stat_from_malt.filter(
            total_num_forms__gte=performance_threshold).count())

        num_active_users = self._user_stat_from_malt.count()
        num_low_performing_user = num_active_users - num_performing_users

        if self._previous_summary:
            delta_high_performers = num_performing_users - self._previous_summary.number_of_performing_users
            delta_low_performers = num_low_performing_user - self._previous_summary.number_of_low_performing_users

        super(MonthlyPerformanceSummary, self).__init__(
            month=month,
            domain=domain,
            performance_threshold=performance_threshold,
            active=num_active_users,
            total_users_by_month=0,
            percent_active=0,
            performing=num_performing_users,
            delta_high_performers=delta_high_performers,
            delta_low_performers=delta_low_performers,
        )

    def set_next_month_summary(self, next_month_summary):
        self._next_summary = next_month_summary

    def set_percent_active(self):
        self.total_users_by_month = self.inactive + self.number_of_active_users
        if self.total_users_by_month:
            self.percent_active = float(self.number_of_active_users) / float(
                self.total_users_by_month)
        else:
            self.percent_active = 0

    @property
    def number_of_performing_users(self):
        return self.performing

    @property
    def number_of_low_performing_users(self):
        return self.active - self.performing

    @property
    def number_of_active_users(self):
        return self.active

    @property
    @memoized
    def inactive(self):
        dropouts = self.get_dropouts()
        return len(dropouts) if dropouts else 0

    @property
    def previous_month(self):
        prev_year, prev_month = add_months(self.month.year, self.month.month,
                                           -1)
        return datetime.datetime(prev_year, prev_month, 1)

    @property
    def delta_high_performing(self):
        if self._previous_summary:
            return self.number_of_performing_users - self._previous_summary.number_of_performing_users
        else:
            return self.number_of_performing_users

    @property
    def delta_high_performing_pct(self):
        if (self.delta_high_performing and self._previous_summary
                and self._previous_summary.number_of_performing_users):
            return float(self.delta_high_performing / float(
                self._previous_summary.number_of_performing_users)) * 100.

    @property
    def delta_low_performing(self):
        if self._previous_summary:
            return self.number_of_low_performing_users - self._previous_summary.number_of_low_performing_users
        else:
            return self.number_of_low_performing_users

    @property
    def delta_low_performing_pct(self):
        if self.delta_low_performing and self._previous_summary \
                and self._previous_summary.number_of_low_performing_users:
            return float(self.delta_low_performing / float(
                self._previous_summary.number_of_low_performing_users)) * 100.

    @property
    def delta_active(self):
        return self.active - self._previous_summary.active if self._previous_summary else self.active

    @property
    def delta_active_pct(self):
        if self.delta_active and self._previous_summary and self._previous_summary.active:
            return float(self.delta_active /
                         float(self._previous_summary.active)) * 100.

    @property
    def delta_inactive(self):
        return self.inactive - self._previous_summary.inactive if self._previous_summary else self.inactive

    @property
    def delta_inactive_pct(self):
        if self.delta_inactive and self._previous_summary:
            if self._previous_summary.inactive == 0:
                return self.delta_inactive * 100.
            return float(self.delta_inactive /
                         float(self._previous_summary.inactive)) * 100.

    def _get_all_user_stubs(self):
        return {
            row['user_id']: UserActivityStub(
                user_id=row['user_id'],
                username=raw_username(row['username']),
                num_forms_submitted=row['total_num_forms'],
                is_performing=row['total_num_forms'] >=
                self.performance_threshold,
                previous_stub=None,
                next_stub=None,
            )
            for row in self._user_stat_from_malt
        }

    def finalize(self):
        """
        Before a summary is "finalized" certain fields can't be accessed.
        """
        self._is_final = True

    @memoized
    def _get_all_user_stubs_with_extra_data(self):
        if not self._is_final:
            # intentionally fail-hard with developer-facing error
            raise Exception(
                "User stubs accessed before finalized. "
                "Please call finalize() before calling this method.")
        if self._previous_summary:
            previous_stubs = self._previous_summary._get_all_user_stubs()
            next_stubs = self._next_summary._get_all_user_stubs(
            ) if self._next_summary else {}
            user_stubs = self._get_all_user_stubs()
            ret = []
            for user_stub in user_stubs.values():
                ret.append(
                    UserActivityStub(
                        user_id=user_stub.user_id,
                        username=user_stub.username,
                        num_forms_submitted=user_stub.num_forms_submitted,
                        is_performing=user_stub.is_performing,
                        previous_stub=previous_stubs.get(user_stub.user_id),
                        next_stub=next_stubs.get(user_stub.user_id),
                    ))
            for missing_user_id in set(previous_stubs.keys()) - set(
                    user_stubs.keys()):
                previous_stub = previous_stubs[missing_user_id]
                ret.append(
                    UserActivityStub(
                        user_id=previous_stub.user_id,
                        username=previous_stub.username,
                        num_forms_submitted=0,
                        is_performing=False,
                        previous_stub=previous_stub,
                        next_stub=next_stubs.get(missing_user_id),
                    ))
            return ret

    def get_unhealthy_users(self):
        """
        Get a list of unhealthy users - defined as those who were "performing" last month
        but are not this month (though are still active).
        """
        if self._previous_summary:
            unhealthy_users = filter(
                lambda stub: stub.is_active and not stub.is_performing,
                self._get_all_user_stubs_with_extra_data())
            return sorted(unhealthy_users, key=lambda stub: stub.delta_forms)

    def get_dropouts(self):
        """
        Get a list of dropout users - defined as those who were active last month
        but are not active this month
        """
        if self._previous_summary:
            dropouts = filter(lambda stub: not stub.is_active,
                              self._get_all_user_stubs_with_extra_data())
            return sorted(dropouts, key=lambda stub: stub.delta_forms)

    def get_newly_performing(self):
        """
        Get a list of "newly performing" users - defined as those who are "performing" this month
        after not performing last month.
        """
        if self._previous_summary:
            dropouts = filter(lambda stub: stub.is_newly_performing,
                              self._get_all_user_stubs_with_extra_data())
            return sorted(dropouts, key=lambda stub: -stub.delta_forms)
Ejemplo n.º 6
0
class AppPart(jsonobject.JsonObject):
    id = jsonobject.IntegerProperty()
    names = DefaultProperty(
    )  # this is almost always a dict, but for user registration it's a string
Ejemplo n.º 7
0
class TaskStatusResult(jsonobject.StrictJsonObject):
    match_count = jsonobject.IntegerProperty()
    created_count = jsonobject.IntegerProperty()
    too_many_matches = jsonobject.IntegerProperty()
    num_chunks = jsonobject.IntegerProperty()
    errors = jsonobject.ListProperty(lambda: TaskStatusResultError)
Ejemplo n.º 8
0
class TaskStatusProgress(jsonobject.StrictJsonObject):
    percent = jsonobject.IntegerProperty()