Skip to content

Commit 1d2db99

Browse files
authored
Refactor "Reports" into its own app (#4468)
- The app is named "project_reports," and currently, the table names are hardcoded. - It is currently located under "hypha.apply.projects.reports," but in the future, I plan to move the entire "projects" app/module as "hypha.projects." - The database tables will stay unchanged; the migration state will show that the models have been relocated to a different app. - All URLs will stay the same. This is the initial step among other refactors/fixes for the reporting module. Additionally, once this is approved, I will proceed to refactor the invoicing module.
1 parent f63d29f commit 1d2db99

36 files changed

Lines changed: 1081 additions & 217 deletions

hypha/apply/funds/files.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class PrivateStreamFieldFile(StreamFieldFile):
2222

2323
def get_entity_id(self):
2424
from hypha.apply.funds.models import ApplicationRevision
25-
from hypha.apply.projects.models import ReportVersion
25+
from hypha.apply.projects.reports.models import ReportVersion
2626

2727
entity_id = self.instance.pk
2828

@@ -34,7 +34,7 @@ def get_entity_id(self):
3434
return entity_id
3535

3636
def generate_filename(self):
37-
from hypha.apply.projects.models import ReportVersion
37+
from hypha.apply.projects.reports.models import ReportVersion
3838

3939
path_start = "submission"
4040
if isinstance(self.instance, ReportVersion):
@@ -48,7 +48,7 @@ def generate_filename(self):
4848

4949
@property
5050
def url(self):
51-
from hypha.apply.projects.models import ReportVersion
51+
from hypha.apply.projects.reports.models import ReportVersion
5252

5353
view_name = "apply:submissions:serve_private_media"
5454
kwargs = {

hypha/apply/projects/filters.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
PROJECT_STATUS_CHOICES,
1818
Project,
1919
)
20-
from .models.report import Report
2120

2221
User = get_user_model()
2322

@@ -78,51 +77,3 @@ def filter_reporting(self, queryset, name, value):
7877
Q(outstanding_reports__lt=1) | Q(outstanding_reports__isnull=True),
7978
status__in=(INVOICING_AND_REPORTING, CLOSING),
8079
)
81-
82-
83-
class DateRangeInputWidget(filters.widgets.SuffixedMultiWidget):
84-
template_name = "application_projects/filters/widgets/date_range_input_widget.html"
85-
suffixes = ["after", "before"]
86-
87-
def __init__(self, attrs=None):
88-
widgets = (forms.DateInput, forms.DateInput)
89-
super().__init__(widgets, attrs)
90-
91-
def decompress(self, value):
92-
if value:
93-
return [value.start, value.stop]
94-
return [None, None]
95-
96-
97-
class ReportingFilter(filters.FilterSet):
98-
current_report_status = MultipleChoiceFilter(
99-
label=_("Status"),
100-
choices=[
101-
("Not started", "Not started"),
102-
("In progress", "In progress"),
103-
("Submitted", "Submitted"),
104-
],
105-
)
106-
107-
108-
class ReportListFilter(filters.FilterSet):
109-
reporting_period = filters.DateFromToRangeFilter(
110-
label=_("Reporting Period"),
111-
method="filter_reporting_period",
112-
widget=DateRangeInputWidget,
113-
)
114-
submitted = filters.DateFromToRangeFilter(widget=DateRangeInputWidget)
115-
116-
class Meta:
117-
model = Report
118-
fields = ["submitted"]
119-
120-
def filter_reporting_period(self, queryset, name, value):
121-
after, before = value.start, value.stop
122-
q = {}
123-
if after:
124-
q["start__gte"] = after
125-
if before:
126-
q["end_date__lte"] = before
127-
128-
return queryset.filter(**q)

hypha/apply/projects/forms/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
UploadContractForm,
2525
UploadDocumentForm,
2626
)
27-
from .report import ReportEditForm, ReportFrequencyForm
2827

2928
__all__ = [
3029
"UpdateProjectTitleForm",
@@ -46,8 +45,6 @@
4645
"StaffUploadContractForm",
4746
"UploadDocumentForm",
4847
"UpdateProjectLeadForm",
49-
"ReportEditForm",
50-
"ReportFrequencyForm",
5148
"CreateInvoiceForm",
5249
"ChangeInvoiceStatusForm",
5350
"EditInvoiceForm",

hypha/apply/projects/migrations/0025_add_report_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class Migration(migrations.Migration):
8787
"document",
8888
models.FileField(
8989
storage=django.core.files.storage.FileSystemStorage(),
90-
upload_to=hypha.apply.projects.models.report.report_path,
90+
upload_to=hypha.apply.projects.reports.models.report_path,
9191
),
9292
),
9393
],
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Generated by Django 4.2.20 on 2025-03-26 07:02
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("application_projects", "0098_move_project_comments_to_application"),
9+
(
10+
"project_reports",
11+
"0001_initial",
12+
),
13+
]
14+
15+
state_operations = [
16+
migrations.RemoveField(
17+
model_name="reportconfig",
18+
name="project",
19+
),
20+
migrations.RemoveField(
21+
model_name="reportprivatefiles",
22+
name="report",
23+
),
24+
migrations.RemoveField(
25+
model_name="reportversion",
26+
name="author",
27+
),
28+
migrations.RemoveField(
29+
model_name="reportversion",
30+
name="report",
31+
),
32+
migrations.DeleteModel(
33+
name="Report",
34+
),
35+
migrations.DeleteModel(
36+
name="ReportConfig",
37+
),
38+
migrations.DeleteModel(
39+
name="ReportPrivateFiles",
40+
),
41+
migrations.DeleteModel(
42+
name="ReportVersion",
43+
),
44+
]
45+
46+
operations = [
47+
migrations.SeparateDatabaseAndState(state_operations=state_operations)
48+
]

hypha/apply/projects/models/__init__.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
ProjectSettings,
1414
ProjectSOWForm,
1515
)
16-
from .report import Report, ReportConfig, ReportPrivateFiles, ReportVersion
1716

1817
__all__ = [
1918
"Project",
@@ -28,10 +27,6 @@
2827
"ContractPacketFile",
2928
"DocumentCategory",
3029
"ContractDocumentCategory",
31-
"Report",
32-
"ReportVersion",
33-
"ReportPrivateFiles",
34-
"ReportConfig",
3530
"Invoice",
3631
"SupportingDocument",
3732
]

hypha/apply/projects/models/project.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def with_last_payment(self):
147147
)
148148

149149
def with_outstanding_reports(self):
150-
Report = apps.get_model("application_projects", "Report")
150+
Report = apps.get_model("project_reports", "Report")
151151
return self.annotate(
152152
outstanding_reports=Subquery(
153153
Report.objects.filter(
@@ -193,7 +193,7 @@ def for_table(self):
193193

194194
def for_reporting_table(self):
195195
today = timezone.now().date()
196-
Report = apps.get_model("application_projects", "Report")
196+
Report = apps.get_model("project_reports", "Report")
197197
return self.invoicing_and_reporting().annotate(
198198
current_report_submitted_date=Subquery(
199199
Report.objects.filter(
File renamed without changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ReportsConfig(AppConfig):
5+
name = "hypha.apply.projects.reports"
6+
label = "project_reports"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import django_filters as filters
2+
from django import forms
3+
from django.utils.translation import gettext_lazy as _
4+
5+
from hypha.apply.funds.tables import (
6+
MultipleChoiceFilter,
7+
)
8+
9+
from .models import Report
10+
11+
12+
class DateRangeInputWidget(filters.widgets.SuffixedMultiWidget):
13+
template_name = "application_projects/filters/widgets/date_range_input_widget.html"
14+
suffixes = ["after", "before"]
15+
16+
def __init__(self, attrs=None):
17+
widgets = (forms.DateInput, forms.DateInput)
18+
super().__init__(widgets, attrs)
19+
20+
def decompress(self, value):
21+
if value:
22+
return [value.start, value.stop]
23+
return [None, None]
24+
25+
26+
class ReportingFilter(filters.FilterSet):
27+
current_report_status = MultipleChoiceFilter(
28+
label=_("Status"),
29+
choices=[
30+
("Not started", "Not started"),
31+
("In progress", "In progress"),
32+
("Submitted", "Submitted"),
33+
],
34+
)
35+
36+
37+
class ReportListFilter(filters.FilterSet):
38+
reporting_period = filters.DateFromToRangeFilter(
39+
label=_("Reporting Period"),
40+
method="filter_reporting_period",
41+
widget=DateRangeInputWidget,
42+
)
43+
submitted = filters.DateFromToRangeFilter(widget=DateRangeInputWidget)
44+
45+
class Meta:
46+
model = Report
47+
fields = ["submitted"]
48+
49+
def filter_reporting_period(self, queryset, name, value):
50+
after, before = value.start, value.stop
51+
q = {}
52+
if after:
53+
q["start__gte"] = after
54+
if before:
55+
q["end_date__lte"] = before
56+
57+
return queryset.filter(**q)

0 commit comments

Comments
 (0)