-
Notifications
You must be signed in to change notification settings - Fork 1
/
matching_policy.py
116 lines (85 loc) · 3.65 KB
/
matching_policy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from __future__ import annotations
import typing
from django.db.models import Q, QuerySet
from django.utils.translation import gettext_lazy as _
from apps.sections.models import SectionMembership
if typing.TYPE_CHECKING:
from apps.buddy_system.models import BuddyRequest
class MatchingPolicyProtocol(typing.Protocol):
id: str
title: str
description: str
can_member_match: bool
def limit_requests(self, qs: QuerySet[BuddyRequest], membership: SectionMembership) -> QuerySet[BuddyRequest]:
# TODO: NotImplemented or base implementation?
return qs.filter(self._base_filter(membership=membership)).select_related(
"issuer",
"issuer__profile",
"issuer__profile__faculty",
"issuer__profile__university",
)
def on_created_request(
self,
request: BuddyRequest,
) -> None:
...
@classmethod
def _base_filter(cls, membership: SectionMembership) -> Q:
from apps.buddy_system.models import BuddyRequest
return Q(
responsible_section=membership.section,
state=BuddyRequest.State.CREATED,
match__isnull=True, # to be sure
)
class ManualByEditorMatchingPolicy(MatchingPolicyProtocol):
id = "manual-by-editor"
title = _("Manual by editors")
description = _("Matching is done manually only by editors.")
can_member_match = False
class ManualByMemberMatchingPolicy(MatchingPolicyProtocol):
id = "manual-by-member"
title = _("Manual by members")
description = _("Matching is done manually directly by members.")
can_member_match = True
class ManualWithSameFacultyMatchingPolicy(MatchingPolicyProtocol):
id = "same-faculty"
title = _("Manual by members with restriction to same faculty")
description = _("Matching is done manually by members themselves, but limited to the same faculty.")
can_member_match = True
def limit_requests(self, qs: QuerySet[BuddyRequest], membership: SectionMembership) -> QuerySet[BuddyRequest]:
from apps.accounts.models import UserProfile
member_profile: UserProfile = membership.user.profile_or_none
return qs.filter(self._base_filter(membership=membership)).filter(
issuer_faculty=member_profile.faculty,
)
class LimitedSameFacultyMatchingPolicy(MatchingPolicyProtocol):
id = "same-faculty-limited"
title = _("Restricted to same faculty with limit")
description = _(
"Matching is done manually by members themselves, but limited to same faculty till"
"the rolling limit - limitation is not enabled after reaching the limit."
)
can_member_match = True
# same faculty for N buddies
# after N matches (to rolling_limit), faculty is not limited
class AutoMatchingPolicy(MatchingPolicyProtocol):
...
# by internationals' selected interests
# request will be matched to one from buddies automatically
# (or the 'match' will be proposed to editor to confirm it)
class MatchingPoliciesRegister:
AVAILABLE_POLICIES = [
ManualByEditorMatchingPolicy,
ManualByMemberMatchingPolicy,
ManualWithSameFacultyMatchingPolicy,
# TODO: make it working
# LimitedSameFacultyMatchingPolicy,
# AutoMatchingPolicy
]
DEFAULT_POLICY = ManualByEditorMatchingPolicy
CHOICES = [(p.id, p.title) for p in AVAILABLE_POLICIES]
DESCRIPTION = " <br />".join(f"{p.title}: {p.description}" for p in AVAILABLE_POLICIES)
_ID_TO_POLICY = {p.id: p() for p in AVAILABLE_POLICIES}
@classmethod
def get_policy_by_id(cls, policy_id: str) -> MatchingPolicyProtocol:
return cls._ID_TO_POLICY.get(policy_id)