Skip to content

Commit 637b866

Browse files
committed
Merge branch 'enhancement/lower-ram-usage-submissions' into test
2 parents 4bc1965 + 4a6e571 commit 637b866

22 files changed

Lines changed: 147 additions & 138 deletions

File tree

hypha/apply/activity/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class Meta:
236236
def get_absolute_url(self):
237237
# coverup for both submission and project as source.
238238
submission_id = (
239-
self.source.submission.id
239+
self.source.submission_id
240240
if hasattr(self.source, "submission")
241241
else self.source.id
242242
)

hypha/apply/dashboard/services.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
from django.db.models import Count
1+
from django.db.models import Count, Exists, OuterRef
22

33
from hypha.apply.projects.models import PAFApprovals
44

55

66
def get_paf_for_review(user, is_paf_approval_sequential):
7-
"""Return a list of paf approvals ready for user's review"""
7+
"""Return a queryset of paf approvals ready for user's review"""
8+
user_groups = list(user.groups.all())
89

910
paf_approvals = PAFApprovals.objects.annotate(
1011
roles_count=Count("paf_reviewer_role__user_roles")
1112
).filter(
12-
roles_count=user.groups.count(),
13+
roles_count=len(user_groups),
1314
approved=False,
1415
)
1516

16-
for role in user.groups.all():
17+
for role in user_groups:
1718
paf_approvals = paf_approvals.filter(paf_reviewer_role__user_roles__id=role.id)
1819

1920
if is_paf_approval_sequential:
20-
all_matched_paf_approvals = list(paf_approvals)
21-
for matched_paf_approval in all_matched_paf_approvals:
22-
if matched_paf_approval.project.paf_approvals.filter(
23-
paf_reviewer_role__sort_order__lt=matched_paf_approval.paf_reviewer_role.sort_order,
24-
approved=False,
25-
).exists():
26-
paf_approvals = paf_approvals.exclude(id=matched_paf_approval.id)
21+
blocking_step = PAFApprovals.objects.filter(
22+
project=OuterRef("project"),
23+
approved=False,
24+
paf_reviewer_role__sort_order__lt=OuterRef("paf_reviewer_role__sort_order"),
25+
)
26+
paf_approvals = paf_approvals.exclude(Exists(blocking_step))
2727

2828
return paf_approvals

hypha/apply/dashboard/templates/dashboard/contracting_dashboard.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ <h2 class="section-header" id="paf-for-review">
4141
</section>
4242

4343

44-
{% if projects_in_contracting.count %}
44+
{% if PROJECTS_ENABLED and projects_in_contracting.count %}
4545
{% include "dashboard/includes/projects_in_contracting.html" with projects_in_contracting=projects_in_contracting %}
4646
{% endif %}
4747
</div>

hypha/apply/dashboard/templates/dashboard/finance_dashboard.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ <h2 class="section-header">{% trans 'Invoices' %} </h2>
9292
<section id="paf_for_review">
9393
<h2 class="section-header">{% trans "PAFs for review" %}</h2>
9494
<div class="overflow-x-auto border rounded-box">
95-
{% if not paf_for_review.count %}
95+
{% if PROJECTS_ENABLED and paf_for_review.count %}
9696
{% render_table paf_for_review.table %}
9797
{% else %}
9898
<p class="p-4 text-sm text-fg-muted">

hypha/apply/dashboard/views.py

Lines changed: 64 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,32 @@ def my_flagged(self, submissions):
7171
)
7272

7373

74-
class AdminDashboardView(MyFlaggedMixin, TemplateView):
74+
class PAFReviewMixin:
75+
paf_reviewer_role = None # set to a user attribute e.g. "is_apply_staff"
76+
77+
def paf_for_review(self):
78+
if not getattr(self.request.user, self.paf_reviewer_role, False):
79+
return {"count": None, "table": None}
80+
project_settings = ProjectSettings.for_request(self.request)
81+
paf_approvals = list(
82+
get_paf_for_review(
83+
user=self.request.user,
84+
is_paf_approval_sequential=project_settings.paf_approval_sequential,
85+
).select_related("project__submission__page", "paf_reviewer_role", "user")
86+
)
87+
paf_table = PAFForReviewDashboardTable(
88+
paf_approvals, prefix="paf-review-", order_by="-date_requested"
89+
)
90+
RequestConfig(self.request, paginate=False).configure(paf_table)
91+
return {
92+
"count": len(paf_approvals),
93+
"table": paf_table,
94+
}
95+
96+
97+
class AdminDashboardView(PAFReviewMixin, MyFlaggedMixin, TemplateView):
7598
template_name = "dashboard/staff_dashboard.html"
99+
paf_reviewer_role = "is_apply_staff"
76100

77101
def get_context_data(self, **kwargs):
78102
context = super().get_context_data(**kwargs)
@@ -97,25 +121,6 @@ def get_context_data(self, **kwargs):
97121

98122
return context
99123

100-
def paf_for_review(self):
101-
if not self.request.user.is_apply_staff:
102-
return {"count": None, "table": None}
103-
project_settings = ProjectSettings.for_request(self.request)
104-
105-
paf_approvals = get_paf_for_review(
106-
user=self.request.user,
107-
is_paf_approval_sequential=project_settings.paf_approval_sequential,
108-
)
109-
paf_table = PAFForReviewDashboardTable(
110-
paf_approvals, prefix="paf-review-", order_by="-date_requested"
111-
)
112-
RequestConfig(self.request, paginate=False).configure(paf_table)
113-
114-
return {
115-
"count": paf_approvals.count(),
116-
"table": paf_table,
117-
}
118-
119124
def my_tasks(self):
120125
tasks = render_task_templates_for_user(self.request, self.request.user)
121126
return {
@@ -137,12 +142,16 @@ def awaiting_reviews(self, submissions):
137142
}
138143

139144
def active_invoices(self):
140-
invoices = Invoice.objects.filter(
141-
project__lead=self.request.user,
142-
).in_progress()
145+
invoices = list(
146+
Invoice.objects.filter(
147+
project__lead=self.request.user,
148+
)
149+
.in_progress()
150+
.select_related("project")
151+
)
143152

144153
return {
145-
"count": invoices.count(),
154+
"count": len(invoices),
146155
"table": InvoiceDashboardTable(invoices),
147156
}
148157

@@ -154,12 +163,13 @@ def projects(self):
154163
)
155164

156165
limit = 10
166+
projects_count = projects.count()
157167

158168
return {
159-
"count": projects.count(),
169+
"count": projects_count,
160170
"filterset": filterset,
161171
"table": ProjectsDashboardTable(data=projects[:limit], prefix="project-"),
162-
"display_more": projects.count() > limit,
172+
"display_more": projects_count > limit,
163173
"url": reverse("apply:projects:all"),
164174
}
165175

@@ -178,8 +188,9 @@ def rounds(self):
178188
}
179189

180190

181-
class FinanceDashboardView(MyFlaggedMixin, TemplateView):
191+
class FinanceDashboardView(PAFReviewMixin, MyFlaggedMixin, TemplateView):
182192
template_name = "dashboard/finance_dashboard.html"
193+
paf_reviewer_role = "is_finance"
183194

184195
def get_context_data(self, **kwargs):
185196
context = super().get_context_data(**kwargs)
@@ -196,25 +207,6 @@ def get_context_data(self, **kwargs):
196207

197208
return context
198209

199-
def paf_for_review(self):
200-
if not self.request.user.is_finance:
201-
return {"count": None, "table": None}
202-
project_settings = ProjectSettings.for_request(self.request)
203-
204-
paf_approvals = get_paf_for_review(
205-
user=self.request.user,
206-
is_paf_approval_sequential=project_settings.paf_approval_sequential,
207-
)
208-
paf_table = PAFForReviewDashboardTable(
209-
paf_approvals, prefix="paf-review-", order_by="-date_requested"
210-
)
211-
RequestConfig(self.request, paginate=False).configure(paf_table)
212-
213-
return {
214-
"count": paf_approvals.count(),
215-
"table": paf_table,
216-
}
217-
218210
def my_tasks(self):
219211
tasks = render_task_templates_for_user(self.request, self.request.user)
220212
return {
@@ -223,22 +215,20 @@ def my_tasks(self):
223215
}
224216

225217
def active_invoices(self):
226-
invoices = Invoice.objects.for_finance_1()
227-
218+
invoices = list(Invoice.objects.for_finance_1().select_related("project"))
228219
return {
229-
"count": invoices.count(),
220+
"count": len(invoices),
230221
"table": InvoiceDashboardTable(invoices),
231222
}
232223

233224
def invoices_for_approval(self):
234-
invoices = Invoice.objects.approved_by_staff()
235-
236-
return {"count": invoices.count(), "table": InvoiceDashboardTable(invoices)}
225+
invoices = list(Invoice.objects.approved_by_staff().select_related("project"))
226+
return {"count": len(invoices), "table": InvoiceDashboardTable(invoices)}
237227

238228
def invoices_to_convert(self):
239-
invoices = Invoice.objects.waiting_to_convert()
229+
invoices = list(Invoice.objects.waiting_to_convert().select_related("project"))
240230
return {
241-
"count": invoices.count(),
231+
"count": len(invoices),
242232
"table": InvoiceDashboardTable(invoices),
243233
}
244234

@@ -302,8 +292,9 @@ def awaiting_reviews(self, submissions):
302292
}
303293

304294

305-
class ContractingDashboardView(MyFlaggedMixin, TemplateView):
295+
class ContractingDashboardView(PAFReviewMixin, MyFlaggedMixin, TemplateView):
306296
template_name = "dashboard/contracting_dashboard.html"
297+
paf_reviewer_role = "is_contracting"
307298

308299
def get_context_data(self, **kwargs):
309300
context = super().get_context_data(**kwargs)
@@ -317,25 +308,6 @@ def get_context_data(self, **kwargs):
317308

318309
return context
319310

320-
def paf_for_review(self):
321-
if not self.request.user.is_contracting:
322-
return {"count": None, "table": None}
323-
project_settings = ProjectSettings.for_request(self.request)
324-
325-
paf_approvals = get_paf_for_review(
326-
user=self.request.user,
327-
is_paf_approval_sequential=project_settings.paf_approval_sequential,
328-
)
329-
paf_table = PAFForReviewDashboardTable(
330-
paf_approvals, prefix="paf-review-", order_by="-date_requested"
331-
)
332-
RequestConfig(self.request, paginate=False).configure(paf_table)
333-
334-
return {
335-
"count": paf_approvals.count(),
336-
"table": paf_table,
337-
}
338-
339311
def my_tasks(self):
340312
tasks = render_task_templates_for_user(self.request, self.request.user)
341313
return {
@@ -357,22 +329,22 @@ def projects_in_contracting(self):
357329
},
358330
}
359331
projects_in_contracting = Project.objects.in_contracting()
360-
waiting_for_contract = projects_in_contracting.filter(
361-
contracts__isnull=True
362-
).for_table()
363-
waiting_for_contract_approval = projects_in_contracting.filter(
364-
contracts__isnull=False
365-
).for_table()
332+
waiting_for_contract = list(
333+
projects_in_contracting.filter(contracts__isnull=True).for_table()
334+
)
335+
waiting_for_contract_approval = list(
336+
projects_in_contracting.filter(contracts__isnull=False).for_table()
337+
)
366338
return {
367-
"count": projects_in_contracting.count(),
339+
"count": len(waiting_for_contract) + len(waiting_for_contract_approval),
368340
"waiting_for_contract": {
369-
"count": waiting_for_contract.count(),
341+
"count": len(waiting_for_contract),
370342
"table": ProjectsDashboardTable(
371343
data=waiting_for_contract, prefix="project-waiting-contract-"
372344
),
373345
},
374346
"waiting_for_contract_approval": {
375-
"count": waiting_for_contract_approval.count(),
347+
"count": len(waiting_for_contract_approval),
376348
"table": ProjectsDashboardTable(
377349
data=waiting_for_contract_approval,
378350
prefix="project-waiting-approval-",
@@ -389,13 +361,13 @@ def get_context_data(self, **kwargs):
389361
submissions = ApplicationSubmission.objects.all().for_table(self.request.user)
390362

391363
# Submissions in community review phase
392-
my_community_review, my_community_review = self.my_community_review(
364+
my_community_review_qs, my_community_review_table = self.my_community_review(
393365
self.request.user, submissions
394366
)
395367
context.update(
396368
{
397-
"my_community_review": my_community_review,
398-
"my_community_review_count": my_community_review.count(),
369+
"my_community_review": my_community_review_table,
370+
"my_community_review_count": my_community_review_qs.count(),
399371
"my_reviewed": get_preview_context(
400372
submissions.reviewed_by(self.request.user).order_by("-submit_time")
401373
),
@@ -444,26 +416,26 @@ def my_tasks(self):
444416
}
445417

446418
def active_invoices(self):
447-
active_invoices = (
419+
active_invoices = list(
448420
Invoice.objects.filter(project__user=self.request.user)
449421
.exclude(status__in=[PAID, DECLINED])
450422
.order_by("-requested_at")
451423
)
452-
return {"count": active_invoices.count(), "data": active_invoices}
424+
return {"count": len(active_invoices), "data": active_invoices}
453425

454426
def historical_project_data(self):
455-
historical_projects = (
427+
historical_projects = list(
456428
Project.objects.filter(user=self.request.user).complete().for_table()
457429
)
458430
return {
459-
"count": historical_projects.count(),
431+
"count": len(historical_projects),
460432
"table": ProjectsDashboardTable(
461433
data=historical_projects, prefix="past-project-"
462434
),
463435
}
464436

465437
def historical_submission_data(self):
466-
historical_submissions = (
438+
historical_submissions = list(
467439
ApplicationSubmission.objects.filter(
468440
user=self.request.user,
469441
)
@@ -472,8 +444,7 @@ def historical_submission_data(self):
472444
.for_table(self.request.user)
473445
)
474446
return {
475-
"count": historical_submissions.count(),
476-
"submissions": historical_submissions,
447+
"count": len(historical_submissions),
477448
"table": SubmissionsTable(data=historical_submissions),
478449
}
479450

hypha/apply/determinations/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def clean_outcome(self):
135135
def get_absolute_url(self):
136136
return reverse(
137137
"apply:submissions:determinations:detail",
138-
args=(self.submission.id, self.id),
138+
args=(self.submission_id, self.id),
139139
)
140140

141141
@property

hypha/apply/determinations/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def form_valid(self, form):
197197
submissions = self.get_submissions()
198198
response = super().form_valid(form)
199199
determinations = {
200-
determination.submission.id: determination
200+
determination.submission_id: determination
201201
for determination in form.instances
202202
}
203203
sources = submissions.filter(id__in=list(determinations))

hypha/apply/funds/files.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ def get_entity_id(self):
3030
if isinstance(self.instance, ApplicationRevision) or isinstance(
3131
self.instance, Project
3232
):
33-
entity_id = self.instance.submission.pk
33+
entity_id = self.instance.submission_id
3434
elif isinstance(self.instance, Report) or isinstance(self.instance, ProjectSOW):
35-
entity_id = self.instance.project.submission.pk
35+
entity_id = self.instance.project.submission_id
3636
elif isinstance(self.instance, ReportVersion):
3737
# Reports are project documents.
38-
entity_id = self.instance.report.project.submission.pk
38+
entity_id = self.instance.report.project.submission_id
3939
return entity_id
4040

4141
def generate_filename(self):

0 commit comments

Comments
 (0)