Skip to content

Models

hypha.apply.activity.models

COMMENT module-attribute

COMMENT = 'comment'

ACTION module-attribute

ACTION = 'action'

ACTIVITY_TYPES module-attribute

ACTIVITY_TYPES = {COMMENT: gettext('Comment'), ACTION: gettext('Action')}

APPLICANT module-attribute

APPLICANT = gettext('applicant')

TEAM module-attribute

TEAM = gettext('team')

REVIEWER module-attribute

REVIEWER = gettext('reviewers')

ALL module-attribute

ALL = gettext('all')

VISIBILITY module-attribute

VISIBILITY = {APPLICANT: gettext('Applicants'), TEAM: gettext('Staff only'), REVIEWER: gettext('Reviewers'), ALL: gettext('All')}

BaseActivityQuerySet

Bases: QuerySet

visible_to

visible_to(user)

Get a QuerySet of all items that are visible to the given user.

Parameters:

  • user –

    User to filter visibility of

Returns:

  • QuerySet –

    A QuerySet containing all items visible to the specified user

Source code in hypha/apply/activity/models.py
def visible_to(self, user) -> models.QuerySet:
    """Get a QuerySet of all items that are visible to the given user.

    Args:
        user:
            [`User`][hypha.apply.users.models.User] to filter visibility of

    Returns:
        A QuerySet containing all items visible to the specified user
    """

    # To hide reviews from the applicant's activity feed
    # Todo: It is just for historic data and not be needed for new data after this.
    from .messaging import ActivityAdapter

    messages = ActivityAdapter.messages

    user_qs = Q(user=user)

    if user.is_applicant:
        # Handle the edge case where a reviewer is also an
        # applicant. Ensures that any applications/projects the user
        # authored will have comment visibility of applicant while others
        # will get the appropriate role.
        if user.is_reviewer:
            ApplicationSubmission = apps.get_model("funds", "ApplicationSubmission")
            Project = apps.get_model("application_projects", "Project")

            app_content_type = ContentType.objects.get_for_model(
                ApplicationSubmission
            )
            proj_content_type = ContentType.objects.get_for_model(Project)

            authored_apps = ApplicationSubmission.objects.filter(user_qs).values(
                "id"
            )
            authored_projs = Project.objects.filter(user_qs).values("id")

            proj_app_qs = (
                Q(source_content_type=app_content_type)
                & Q(source_object_id__in=authored_apps)
            ) | (
                Q(source_content_type=proj_content_type)
                & Q(source_object_id__in=authored_projs)
            )

            # Activities the user is the author of the source submission
            applicant_activity = self.filter(
                proj_app_qs
                & Q(
                    Q(visibility__in=self.model.visibility_for(user, True))
                    | user_qs
                )
            )
            # All other activities
            other_activity = self.exclude(
                Q(message=messages.get(MESSAGES.NEW_REVIEW)) | proj_app_qs
            ).filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)
            return applicant_activity | other_activity
        else:
            return self.exclude(message=messages.get(MESSAGES.NEW_REVIEW)).filter(
                Q(visibility__in=self.model.visibility_for(user)) | user_qs
            )

    return self.filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)

newer

newer(activity)
Source code in hypha/apply/activity/models.py
def newer(self, activity):
    return self.filter(timestamp__gt=activity.timestamp)

ActivityQuerySet

Bases: BaseActivityQuerySet

comments

comments()
Source code in hypha/apply/activity/models.py
def comments(self):
    return self.filter(type=COMMENT)

actions

actions()
Source code in hypha/apply/activity/models.py
def actions(self):
    return self.filter(type=ACTION)

latest

latest()
Source code in hypha/apply/activity/models.py
def latest(self):
    return self.filter(
        timestamp__gte=(timezone.now() - timezone.timedelta(days=30))
    )

visible_to

visible_to(user)

Get a QuerySet of all items that are visible to the given user.

Parameters:

  • user –

    User to filter visibility of

Returns:

  • QuerySet –

    A QuerySet containing all items visible to the specified user

Source code in hypha/apply/activity/models.py
def visible_to(self, user) -> models.QuerySet:
    """Get a QuerySet of all items that are visible to the given user.

    Args:
        user:
            [`User`][hypha.apply.users.models.User] to filter visibility of

    Returns:
        A QuerySet containing all items visible to the specified user
    """

    # To hide reviews from the applicant's activity feed
    # Todo: It is just for historic data and not be needed for new data after this.
    from .messaging import ActivityAdapter

    messages = ActivityAdapter.messages

    user_qs = Q(user=user)

    if user.is_applicant:
        # Handle the edge case where a reviewer is also an
        # applicant. Ensures that any applications/projects the user
        # authored will have comment visibility of applicant while others
        # will get the appropriate role.
        if user.is_reviewer:
            ApplicationSubmission = apps.get_model("funds", "ApplicationSubmission")
            Project = apps.get_model("application_projects", "Project")

            app_content_type = ContentType.objects.get_for_model(
                ApplicationSubmission
            )
            proj_content_type = ContentType.objects.get_for_model(Project)

            authored_apps = ApplicationSubmission.objects.filter(user_qs).values(
                "id"
            )
            authored_projs = Project.objects.filter(user_qs).values("id")

            proj_app_qs = (
                Q(source_content_type=app_content_type)
                & Q(source_object_id__in=authored_apps)
            ) | (
                Q(source_content_type=proj_content_type)
                & Q(source_object_id__in=authored_projs)
            )

            # Activities the user is the author of the source submission
            applicant_activity = self.filter(
                proj_app_qs
                & Q(
                    Q(visibility__in=self.model.visibility_for(user, True))
                    | user_qs
                )
            )
            # All other activities
            other_activity = self.exclude(
                Q(message=messages.get(MESSAGES.NEW_REVIEW)) | proj_app_qs
            ).filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)
            return applicant_activity | other_activity
        else:
            return self.exclude(message=messages.get(MESSAGES.NEW_REVIEW)).filter(
                Q(visibility__in=self.model.visibility_for(user)) | user_qs
            )

    return self.filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)

newer

newer(activity)
Source code in hypha/apply/activity/models.py
def newer(self, activity):
    return self.filter(timestamp__gt=activity.timestamp)

ActivityBaseManager

Bases: Manager

create

create(**kwargs)
Source code in hypha/apply/activity/models.py
def create(self, **kwargs):
    kwargs.update(type=self.type)
    return super().create(**kwargs)

get_queryset

get_queryset()
Source code in hypha/apply/activity/models.py
def get_queryset(self):
    return (
        super()
        .get_queryset()
        .filter(
            type=self.type,
            current=True,
        )
    )

CommentQueryset

Bases: BaseActivityQuerySet

visible_to

visible_to(user)

Get a QuerySet of all items that are visible to the given user.

Parameters:

  • user –

    User to filter visibility of

Returns:

  • QuerySet –

    A QuerySet containing all items visible to the specified user

Source code in hypha/apply/activity/models.py
def visible_to(self, user) -> models.QuerySet:
    """Get a QuerySet of all items that are visible to the given user.

    Args:
        user:
            [`User`][hypha.apply.users.models.User] to filter visibility of

    Returns:
        A QuerySet containing all items visible to the specified user
    """

    # To hide reviews from the applicant's activity feed
    # Todo: It is just for historic data and not be needed for new data after this.
    from .messaging import ActivityAdapter

    messages = ActivityAdapter.messages

    user_qs = Q(user=user)

    if user.is_applicant:
        # Handle the edge case where a reviewer is also an
        # applicant. Ensures that any applications/projects the user
        # authored will have comment visibility of applicant while others
        # will get the appropriate role.
        if user.is_reviewer:
            ApplicationSubmission = apps.get_model("funds", "ApplicationSubmission")
            Project = apps.get_model("application_projects", "Project")

            app_content_type = ContentType.objects.get_for_model(
                ApplicationSubmission
            )
            proj_content_type = ContentType.objects.get_for_model(Project)

            authored_apps = ApplicationSubmission.objects.filter(user_qs).values(
                "id"
            )
            authored_projs = Project.objects.filter(user_qs).values("id")

            proj_app_qs = (
                Q(source_content_type=app_content_type)
                & Q(source_object_id__in=authored_apps)
            ) | (
                Q(source_content_type=proj_content_type)
                & Q(source_object_id__in=authored_projs)
            )

            # Activities the user is the author of the source submission
            applicant_activity = self.filter(
                proj_app_qs
                & Q(
                    Q(visibility__in=self.model.visibility_for(user, True))
                    | user_qs
                )
            )
            # All other activities
            other_activity = self.exclude(
                Q(message=messages.get(MESSAGES.NEW_REVIEW)) | proj_app_qs
            ).filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)
            return applicant_activity | other_activity
        else:
            return self.exclude(message=messages.get(MESSAGES.NEW_REVIEW)).filter(
                Q(visibility__in=self.model.visibility_for(user)) | user_qs
            )

    return self.filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)

newer

newer(activity)
Source code in hypha/apply/activity/models.py
def newer(self, activity):
    return self.filter(timestamp__gt=activity.timestamp)

CommentManger

Bases: ActivityBaseManager

type class-attribute instance-attribute

type = COMMENT

create

create(**kwargs)
Source code in hypha/apply/activity/models.py
def create(self, **kwargs):
    kwargs.update(type=self.type)
    return super().create(**kwargs)

get_queryset

get_queryset()
Source code in hypha/apply/activity/models.py
def get_queryset(self):
    return (
        super()
        .get_queryset()
        .filter(
            type=self.type,
            current=True,
        )
    )

ActionQueryset

Bases: BaseActivityQuerySet

visible_to

visible_to(user)

Get a QuerySet of all items that are visible to the given user.

Parameters:

  • user –

    User to filter visibility of

Returns:

  • QuerySet –

    A QuerySet containing all items visible to the specified user

Source code in hypha/apply/activity/models.py
def visible_to(self, user) -> models.QuerySet:
    """Get a QuerySet of all items that are visible to the given user.

    Args:
        user:
            [`User`][hypha.apply.users.models.User] to filter visibility of

    Returns:
        A QuerySet containing all items visible to the specified user
    """

    # To hide reviews from the applicant's activity feed
    # Todo: It is just for historic data and not be needed for new data after this.
    from .messaging import ActivityAdapter

    messages = ActivityAdapter.messages

    user_qs = Q(user=user)

    if user.is_applicant:
        # Handle the edge case where a reviewer is also an
        # applicant. Ensures that any applications/projects the user
        # authored will have comment visibility of applicant while others
        # will get the appropriate role.
        if user.is_reviewer:
            ApplicationSubmission = apps.get_model("funds", "ApplicationSubmission")
            Project = apps.get_model("application_projects", "Project")

            app_content_type = ContentType.objects.get_for_model(
                ApplicationSubmission
            )
            proj_content_type = ContentType.objects.get_for_model(Project)

            authored_apps = ApplicationSubmission.objects.filter(user_qs).values(
                "id"
            )
            authored_projs = Project.objects.filter(user_qs).values("id")

            proj_app_qs = (
                Q(source_content_type=app_content_type)
                & Q(source_object_id__in=authored_apps)
            ) | (
                Q(source_content_type=proj_content_type)
                & Q(source_object_id__in=authored_projs)
            )

            # Activities the user is the author of the source submission
            applicant_activity = self.filter(
                proj_app_qs
                & Q(
                    Q(visibility__in=self.model.visibility_for(user, True))
                    | user_qs
                )
            )
            # All other activities
            other_activity = self.exclude(
                Q(message=messages.get(MESSAGES.NEW_REVIEW)) | proj_app_qs
            ).filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)
            return applicant_activity | other_activity
        else:
            return self.exclude(message=messages.get(MESSAGES.NEW_REVIEW)).filter(
                Q(visibility__in=self.model.visibility_for(user)) | user_qs
            )

    return self.filter(Q(visibility__in=self.model.visibility_for(user)) | user_qs)

newer

newer(activity)
Source code in hypha/apply/activity/models.py
def newer(self, activity):
    return self.filter(timestamp__gt=activity.timestamp)

ActionManager

Bases: ActivityBaseManager

type class-attribute instance-attribute

type = ACTION

create

create(**kwargs)
Source code in hypha/apply/activity/models.py
def create(self, **kwargs):
    kwargs.update(type=self.type)
    return super().create(**kwargs)

get_queryset

get_queryset()
Source code in hypha/apply/activity/models.py
def get_queryset(self):
    return (
        super()
        .get_queryset()
        .filter(
            type=self.type,
            current=True,
        )
    )

ActivityAttachment

Bases: Model

wagtail_reference_index_ignore class-attribute instance-attribute

wagtail_reference_index_ignore = True

uuid class-attribute instance-attribute

uuid = UUIDField(unique=True, default=uuid4, editable=False)

activity class-attribute instance-attribute

activity = ForeignKey('Activity', on_delete=CASCADE, related_name='attachments')

file class-attribute instance-attribute

file = FileField(upload_to=get_attachment_upload_path, storage=PrivateStorage())

filename property

filename

get_absolute_url

get_absolute_url()
Source code in hypha/apply/activity/models.py
def get_absolute_url(self):
    return reverse("activity:attachment", kwargs={"file_pk": str(self.uuid)})

Activity

Bases: Model

timestamp class-attribute instance-attribute

timestamp = DateTimeField()

type class-attribute instance-attribute

type = CharField(choices=items(), max_length=30)

user class-attribute instance-attribute

user = ForeignKey(AUTH_USER_MODEL, on_delete=PROTECT)

source_content_type class-attribute instance-attribute

source_content_type = ForeignKey(ContentType, blank=True, null=True, on_delete=CASCADE, related_name='activity_source')

source_object_id class-attribute instance-attribute

source_object_id = PositiveIntegerField(blank=True, null=True, db_index=True)

source class-attribute instance-attribute

source = GenericForeignKey('source_content_type', 'source_object_id')

message class-attribute instance-attribute

message = TextField()

visibility class-attribute instance-attribute

visibility = CharField(choices=list(items()), default=APPLICANT, max_length=30)

edited class-attribute instance-attribute

edited = DateTimeField(default=None, null=True)

deleted class-attribute instance-attribute

deleted = DateTimeField(default=None, null=True)

current class-attribute instance-attribute

current = BooleanField(default=True)

previous class-attribute instance-attribute

previous = ForeignKey('self', on_delete=CASCADE, null=True)

related_content_type class-attribute instance-attribute

related_content_type = ForeignKey(ContentType, blank=True, null=True, on_delete=CASCADE, related_name='activity_related')

related_object_id class-attribute instance-attribute

related_object_id = PositiveIntegerField(blank=True, null=True)

related_object class-attribute instance-attribute

related_object = GenericForeignKey('related_content_type', 'related_object_id')

objects class-attribute instance-attribute

objects = from_queryset(ActivityQuerySet)()

comments class-attribute instance-attribute

comments = from_queryset(CommentQueryset)()

actions class-attribute instance-attribute

actions = from_queryset(ActionQueryset)()

wagtail_reference_index_ignore class-attribute instance-attribute

wagtail_reference_index_ignore = True

privileged property

privileged

private property

private

Meta

ordering class-attribute instance-attribute
ordering = ['-timestamp']
base_manager_name class-attribute instance-attribute
base_manager_name = 'objects'

get_absolute_url

get_absolute_url()
Source code in hypha/apply/activity/models.py
def get_absolute_url(self):
    # coverup for both submission and project as source.
    submission_id = (
        self.source.submission.id
        if hasattr(self.source, "submission")
        else self.source.id
    )
    return f"{reverse('funds:submissions:comments', args=[submission_id])}#communications--{self.id}"

visibility_for classmethod

visibility_for(user, is_submission_author=False)

Gets activity visibility for a specified user

Takes an optional boolean that is used to determine the visibility of an application comment.

Parameters:

  • user –

    User to get visibility for

  • is_submission_author (Optional[bool], default: False ) –

    boolean used when the user is the applicant of the source activity

Returns:

  • List[str] –

    A list of visibility strings

Source code in hypha/apply/activity/models.py
@classmethod
def visibility_for(
    cls, user, is_submission_author: Optional[bool] = False
) -> List[str]:
    """Gets activity visibility for a specified user

    Takes an optional boolean that is used to determine the visibility of
    an application comment.

    Args:
        user:
            [`User`][hypha.apply.users.models.User] to get visibility for
        is_submission_author:
            boolean used when the `user` is the applicant of the source activity

    Returns:
        A list of visibility strings
    """
    if user.is_apply_staff or user.is_finance or user.is_contracting:
        return [TEAM, APPLICANT, REVIEWER, ALL]
    if user.is_reviewer and not is_submission_author:
        return [REVIEWER, ALL]
    if user.is_applicant:
        return [APPLICANT, ALL]

    return [ALL]

visibility_choices_for classmethod

visibility_choices_for(user)

Gets activity visibility choices for the specified user

Parameters:

  • user –

    The User being given visibility choices

Returns:

  • List[Tuple[str, str]] –

    A list of tuples in the format of:

  • List[Tuple[str, str]] –

    [(, ), ...]

Source code in hypha/apply/activity/models.py
@classmethod
def visibility_choices_for(cls, user) -> List[Tuple[str, str]]:
    """Gets activity visibility choices for the specified user

    Args:
        user: The [`User`][hypha.apply.users.models.User] being given visibility choices

    Returns:
        A list of tuples in the format of:
        [(<visibility string>, <visibility display string>), ...]
    """

    if user.is_apply_staff:
        return [
            (TEAM, VISIBILITY[TEAM]),
            (APPLICANT, VISIBILITY[APPLICANT]),
            (REVIEWER, VISIBILITY[REVIEWER]),
            (ALL, VISIBILITY[ALL]),
        ]

    if user.is_applicant:
        return [(APPLICANT, VISIBILITY[APPLICANT])]

    if user.is_reviewer:
        return [(REVIEWER, VISIBILITY[REVIEWER])]

    if user.is_finance or user.is_contracting:
        return [(TEAM, VISIBILITY[TEAM]), (APPLICANT, VISIBILITY[APPLICANT])]

    return [(ALL, VISIBILITY[ALL])]

Event

Bases: Model

Model to track when messages are triggered

wagtail_reference_index_ignore class-attribute instance-attribute

wagtail_reference_index_ignore = True

when class-attribute instance-attribute

when = DateTimeField(auto_now_add=True)

type class-attribute instance-attribute

type = CharField(gettext('verb'), choices=choices, max_length=50)

by class-attribute instance-attribute

by = ForeignKey(AUTH_USER_MODEL, on_delete=PROTECT, null=True)

content_type class-attribute instance-attribute

content_type = ForeignKey(ContentType, blank=True, null=True, on_delete=CASCADE)

object_id class-attribute instance-attribute

object_id = PositiveIntegerField(blank=True, null=True)

source class-attribute instance-attribute

source = GenericForeignKey('content_type', 'object_id')

MessagesQueryset

Bases: QuerySet

update_status

update_status(status)
Source code in hypha/apply/activity/models.py
def update_status(self, status):
    if status:
        return self.update(
            status=Case(
                When(status="", then=Value(status)),
                default=Concat("status", Value("<br />" + status)),
                output_field=models.TextField(),
            ),
        )

Message

Bases: Model

Model to track content of messages sent from an event

type class-attribute instance-attribute

type = CharField(max_length=15)

content class-attribute instance-attribute

content = TextField()

recipient class-attribute instance-attribute

recipient = CharField(max_length=250)

event class-attribute instance-attribute

event = ForeignKey(Event, on_delete=CASCADE)

status class-attribute instance-attribute

status = TextField()

external_id class-attribute instance-attribute

external_id = CharField(max_length=75, null=True, blank=True)

sent_in_email_digest class-attribute instance-attribute

sent_in_email_digest = BooleanField(default=False)

objects class-attribute instance-attribute

objects = as_manager()

update_status

update_status(status)
Source code in hypha/apply/activity/models.py
def update_status(self, status):
    if status:
        self.status = Case(
            When(status="", then=Value(status)),
            default=Concat("status", Value("<br />" + status)),
            output_field=models.TextField(),
        )
        self.save()

get_attachment_upload_path

get_attachment_upload_path(instance, filename)
Source code in hypha/apply/activity/models.py
def get_attachment_upload_path(instance, filename):
    return f"activity/attachments/{instance.id}/{get_valid_filename(filename)}"