-
Notifications
You must be signed in to change notification settings - Fork 618
/
Copy pathuse_cases.py
208 lines (171 loc) · 6.7 KB
/
use_cases.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
"""
This module holds Use Cases (UCs) implementations. These are indirections to trigger business rules
and avoid the sponsors core logic and state management to be spread across views codes.
"""
from abc import ABC, abstractmethod
from sponsors import notifications
from sponsors.models import Sponsorship, Contract, SponsorContact, SponsorEmailNotificationTemplate
from sponsors.pdf import render_contract_to_pdf_file, render_contract_to_docx_file
class BaseUseCaseWithNotifications(ABC):
"""
Abstract base class to be used to implement use cases.
It holds a list of notifications to be dispatched by the UC if needed
"""
notifications = []
@classmethod
def build(cls):
"""
Factory method to explicity handle complex logic and/or dependency injection
"""
return cls(cls.notifications)
@abstractmethod
def execute(self, *args, **kwargs):
"""
Abstract method to implement specific UC business rules
"""
pass
def __init__(self, notifications):
self.notifications = notifications
def notify(self, **kwargs):
for notification in self.notifications:
notification.notify(**kwargs)
class CreateSponsorshipApplicationUseCase(BaseUseCaseWithNotifications):
"""
Use case called to create a new sponsorships application for submitted by a user
"""
notifications = [
notifications.AppliedSponsorshipNotificationToPSF(),
notifications.AppliedSponsorshipNotificationToSponsors(),
]
def execute(self, user, sponsor, benefits, package=None, request=None):
sponsorship = Sponsorship.new(sponsor, benefits, package, submited_by=user)
self.notify(sponsorship=sponsorship, request=request)
return sponsorship
class RejectSponsorshipApplicationUseCase(BaseUseCaseWithNotifications):
"""
Use case to enable PSF staff to reject an application
"""
notifications = [
notifications.RejectedSponsorshipNotificationToPSF(),
notifications.RejectedSponsorshipNotificationToSponsors(),
]
def execute(self, sponsorship, request=None):
sponsorship.reject()
sponsorship.save()
self.notify(request=request, sponsorship=sponsorship)
return sponsorship
class ApproveSponsorshipApplicationUseCase(BaseUseCaseWithNotifications):
"""
Use case to enable PSF staff to approve an application
"""
notifications = [
notifications.SponsorshipApprovalLogger(),
]
def execute(self, sponsorship, start_date, end_date, **kwargs):
sponsorship.approve(start_date, end_date)
package = kwargs.get("package")
fee = kwargs.get("sponsorship_fee")
if package:
sponsorship.package = package
sponsorship.level_name = package.name
if fee:
sponsorship.sponsorship_fee = fee
sponsorship.save()
contract = Contract.new(sponsorship)
self.notify(
request=kwargs.get("request"),
sponsorship=sponsorship,
contract=contract,
)
return sponsorship
class SendContractUseCase(BaseUseCaseWithNotifications):
"""
Use case to enable PSF staff to generate the contract .docx
file and sent it over email
"""
notifications = [
notifications.ContractNotificationToPSF(),
# TODO: sponsor's notification will be enabled again once
# the generate contract file gets approved by PSF Board.
# After that, the line bellow can be uncommented to enable
# the desired behavior.
#notifications.ContractNotificationToSponsors(),
notifications.SentContractLogger(),
]
def execute(self, contract, **kwargs):
pdf_file = render_contract_to_pdf_file(contract)
docx_file = render_contract_to_docx_file(contract)
contract.set_final_version(pdf_file, docx_file)
self.notify(
request=kwargs.get("request"),
contract=contract,
)
class ExecuteExistingContractUseCase(BaseUseCaseWithNotifications):
"""
Use case to PSF Staff to finalize a sponsorship by "executing" a contract.
This UC was created to enable to enable to upload existing contracts documents
that weren't generated by the sponsors app.
It's probable that this UC will become a legacy one once all the new
contracts and sponsorships were created via the Django application
"""
notifications = [
notifications.ExecutedExistingContractLogger(),
]
force_execute = True
def execute(self, contract, contract_file, **kwargs):
contract.signed_document = contract_file
contract.execute(force=self.force_execute)
self.notify(
request=kwargs.get("request"),
contract=contract,
)
class ExecuteContractUseCase(ExecuteExistingContractUseCase):
"""
Use case to PSF Staff to execute a contract created by the sponsors app.
Execute a contract requires the admin user to upload the signed contract
and this will flag the contract as Executed and the corresponding Sponsorship
as Finalized.
"""
notifications = [
notifications.ExecutedContractLogger(),
]
force_execute = False
class NullifyContractUseCase(BaseUseCaseWithNotifications):
"""
Use case to enable PSF staff to nullify non-executed contracts
"""
notifications = [
notifications.NullifiedContractLogger(),
]
def execute(self, contract, **kwargs):
contract.nullify()
self.notify(
request=kwargs.get("request"),
contract=contract,
)
class SendSponsorshipNotificationUseCase(BaseUseCaseWithNotifications):
"""
Use case to enable PSF staff to send DB stored email notifications
to a list of selected sponsorships.
"""
notifications = [
notifications.SendSponsorNotificationLogger(),
]
def execute(self, notification: SponsorEmailNotificationTemplate, sponsorships, contact_types, **kwargs):
msg_kwargs = {
"to_primary": SponsorContact.PRIMARY_CONTACT in contact_types,
"to_administrative": SponsorContact.ADMINISTRATIVE_CONTACT in contact_types,
"to_accounting": SponsorContact.ACCOUTING_CONTACT in contact_types,
"to_manager": SponsorContact.MANAGER_CONTACT in contact_types,
}
for sponsorship in sponsorships:
email = notification.get_email_message(sponsorship, **msg_kwargs)
if not email:
continue
email.send()
self.notify(
notification=notification,
sponsorship=sponsorship,
contact_types=contact_types,
request=kwargs.get("request"),
)