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')

PARTNER module-attribute

PARTNER = gettext('partners')

ALL module-attribute

ALL = gettext('all')

APPLICANT_PARTNERS module-attribute

APPLICANT_PARTNERS = f'{APPLICANT} {PARTNER}'

VISIBILITY module-attribute

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

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

    # There are scenarios where users will have activities in which they
    # wouldn't have visibility just using Activity.visibility_for. Thus,
    # the queryset should include activity in which they author
    # (ie. A comment made only to staff from a partner).
    if user.is_applicant:
        return self.exclude(message=messages.get(MESSAGES.NEW_REVIEW)).filter(
            Q(visibility__in=self.model.visibility_for(user)) | Q(user=user)
        )

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

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

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

    # There are scenarios where users will have activities in which they
    # wouldn't have visibility just using Activity.visibility_for. Thus,
    # the queryset should include activity in which they author
    # (ie. A comment made only to staff from a partner).
    if user.is_applicant:
        return self.exclude(message=messages.get(MESSAGES.NEW_REVIEW)).filter(
            Q(visibility__in=self.model.visibility_for(user)) | Q(user=user)
        )

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

newer

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

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))
    )

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

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

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)

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

priviledged property

priviledged

private property

private

Meta

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

visibility_for classmethod

visibility_for(user)

Gets activity visibility for a specified user

Parameters:

  • user –

    User to get visibility for

Returns:

  • List[str] –

    A list of visibility strings

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

    Args:
        user:
            [`User`][hypha.apply.users.models.User] to get visibility for

    Returns:
        A list of visibility strings
    """
    if user.is_apply_staff:
        return [TEAM, APPLICANT, REVIEWER, APPLICANT_PARTNERS, PARTNER, ALL]
    if user.is_reviewer:
        return [REVIEWER, ALL]
    if user.is_finance or user.is_contracting:
        # for project part
        return [TEAM, APPLICANT, REVIEWER, PARTNER, ALL]
    if user.is_applicant:
        return [APPLICANT, ALL, APPLICANT_PARTNERS]
    if user.is_partner:
        return [PARTNER, ALL, APPLICANT_PARTNERS]

    return [ALL]

visibility_choices_for classmethod

visibility_choices_for(user, submission_partner_list=None)

Gets activity visibility choices for the specified user

Uses the given user (and partner query set if provided) to give the specified user activity visibility choices.

Parameters:

  • user –

    The User being given visibility choices

  • submission_has_partner –

    An optional QuerySet of partners (Users)

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

    Uses the given user (and partner query set if provided) to give
    the specified user activity visibility choices.

    Args:
        user:
            The [`User`][hypha.apply.users.models.User] being given
            visibility choices
        submission_has_partner:
            An optional QuerySet of partners
            ([`Users`][hypha.apply.users.models.User])
    Returns:
        A list of tuples in the format of:
        [(<visibility string>, <visibility display string>), ...]
    """
    has_partner = submission_partner_list and len(submission_partner_list) > 0

    if user.is_apply_staff:
        if not has_partner:
            choices = [
                (TEAM, VISIBILITY[TEAM]),
                (APPLICANT, VISIBILITY[APPLICANT]),
                (REVIEWER, VISIBILITY[REVIEWER]),
                (ALL, VISIBILITY[ALL]),
            ]
        else:
            choices = [
                (TEAM, VISIBILITY[TEAM]),
                (APPLICANT, VISIBILITY[APPLICANT]),
                (PARTNER, VISIBILITY[PARTNER]),
                (APPLICANT_PARTNERS, VISIBILITY[APPLICANT_PARTNERS]),
                (REVIEWER, VISIBILITY[REVIEWER]),
                (ALL, VISIBILITY[ALL]),
            ]
        return choices

    if user.is_partner and has_partner and submission_partner_list.contains(user):
        return [
            (APPLICANT_PARTNERS, VISIBILITY[APPLICANT_PARTNERS]),
            (PARTNER, VISIBILITY[PARTNER]),
            (TEAM, VISIBILITY[TEAM]),
        ]

    if user.is_applicant and has_partner:
        return [
            (APPLICANT_PARTNERS, VISIBILITY[PARTNER]),
            (APPLICANT, VISIBILITY[TEAM]),
        ]

    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)}"