Skip to content

Commit 2bb7088

Browse files
committed
chore: add vitests
chore: cleanup chore: cleanup chore: cleanup chore: cleanup chore: cleanup
1 parent 44e47c9 commit 2bb7088

8 files changed

Lines changed: 474 additions & 77 deletions

File tree

bc_obps/registration/tests/endpoints/_operations/test_reportable.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from registration.models import Operation
33
from registration.tests.utils.helpers import CommonTestSetup, TestUtils
44
from registration.utils import custom_reverse_lazy
5+
from model_bakery.baker import make_recipe
56

67

78
class TestOperationsPreviousReportableEndpoint(CommonTestSetup):
@@ -10,27 +11,40 @@ def test_list_previous_reportable_operations(
1011
self,
1112
mock_list_previous_reportable_operations,
1213
):
13-
# Arrange: Mock service data
14+
approved_user_operator = make_recipe(
15+
"registration.tests.utils.approved_user_operator",
16+
user=self.user,
17+
)
18+
19+
operation = make_recipe(
20+
"registration.tests.utils.operation",
21+
operator=approved_user_operator.operator,
22+
)
23+
1424
mock_list_previous_reportable_operations.return_value = [
1525
{
16-
"operation_id": "123",
17-
"operation_name": "Test Operation",
26+
"operation_id": operation.id,
27+
"operation_name": operation.name,
1828
"reporting_year": 2023,
1929
"registration_purposes": [
2030
Operation.Purposes.REPORTING_OPERATION,
2131
],
2232
}
2333
]
2434

25-
# Act: Authorize user and perform GET request
2635
response = TestUtils.mock_get_with_auth_role(
2736
self,
2837
"industry_user",
2938
custom_reverse_lazy("list_previous_reportable_operations"),
3039
)
3140

32-
# Assert: Verify the response status
3341
assert response.status_code == 200
42+
assert len(response.json()) == 1
43+
assert response.json()[0].get("operation_name") == operation.name
44+
assert response.json()[0].get("operation_id") == str(operation.id)
45+
assert response.json()[0].get("reporting_year") == 2023
46+
assert response.json()[0].get("registration_purposes") == [
47+
Operation.Purposes.REPORTING_OPERATION,
48+
]
3449

35-
# Assert: Verify the service was called
3650
mock_list_previous_reportable_operations.assert_called_once()

bc_obps/service/operation_service.py

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,17 @@
5454
from reporting.models.reporting_year import ReportingYear
5555
from service.reporting_year_service import ReportingYearService
5656
from django.conf import settings
57-
from service.operation_designated_operator_timeline_service import OperationDesignatedOperatorTimelineService
57+
from service.operation_designated_operator_timeline_service import (
58+
OperationDesignatedOperatorTimelinePlus,
59+
OperationDesignatedOperatorTimelineService,
60+
)
5861
from reporting.models.report import Report
5962

6063

6164
class OperationService:
6265

6366
OPERATION_DEFAULT_START_DATE = datetime(2024, 1, 1, tzinfo=ZoneInfo("America/Vancouver"))
67+
MIN_REPORTING_YEAR = 2024
6468

6569
@classmethod
6670
def get_if_authorized(
@@ -755,6 +759,7 @@ def handle_change_of_registration_purpose(
755759

756760
return payload
757761

762+
# list previous reportable operations methods:
758763
@staticmethod
759764
def get_valid_operation_regulated_products(operation: Operation, reporting_year: int) -> QuerySet[RegulatedProduct]:
760765
"""
@@ -772,19 +777,31 @@ def _is_reportable_operation_year(
772777
) -> bool:
773778
return operation_year not in added_operation_years and operation_year not in existing_reports
774779

780+
@classmethod
781+
def _is_designated_to_user_operator(
782+
cls,
783+
designated_operator_timeline: OperationDesignatedOperatorTimelinePlus | None,
784+
user_operator: UserOperator,
785+
) -> bool:
786+
return (
787+
designated_operator_timeline is not None
788+
and designated_operator_timeline.operator.id == user_operator.operator_id
789+
)
790+
775791
@classmethod
776792
def _get_previous_reporting_years(cls) -> QuerySet[ReportingYear]:
777793
"""
778794
Returns reporting years that are eligible for the Start Past Report workflow
779795
780-
Only reporting years prior to the current reporting year are returned
796+
Only reporting years from MIN_REPORTING_YEAR up to (but not including) the current
797+
reporting year are returned.
781798
"""
782-
783799
current_reporting_year = ReportingYearService.get_current_reporting_year()
784800

785-
return ReportingYear.objects.filter(reporting_year__lt=current_reporting_year.reporting_year).order_by(
786-
"-reporting_year"
787-
)
801+
return ReportingYear.objects.filter(
802+
reporting_year__gte=cls.MIN_REPORTING_YEAR,
803+
reporting_year__lt=current_reporting_year.reporting_year,
804+
).order_by("-reporting_year")
788805

789806
@staticmethod
790807
def _get_registration_purposes_for_operation_type(
@@ -812,6 +829,29 @@ def _get_registration_purposes_for_operation_type(
812829

813830
raise ValueError(f"Unsupported operation type: {operation_type}")
814831

832+
@classmethod
833+
def _add_reportable_operation(
834+
cls,
835+
reportable_operations: list[dict],
836+
added_operation_years: set[tuple[UUID, int]],
837+
operation: Operation,
838+
reporting_year: ReportingYear,
839+
is_current_registered_fallback: bool,
840+
) -> None:
841+
"""
842+
Adds a reportable operation/reporting year combination to the result set
843+
and tracks it to prevent duplicates.
844+
"""
845+
operation_year = (operation.id, reporting_year.reporting_year)
846+
847+
reportable_operations.append(
848+
{
849+
**cls._build_reportable_operation_row(operation, reporting_year),
850+
"is_current_registered_fallback": is_current_registered_fallback,
851+
}
852+
)
853+
added_operation_years.add(operation_year)
854+
815855
@classmethod
816856
def _build_reportable_operation_row(
817857
cls,
@@ -897,6 +937,7 @@ def list_previous_reportable_operations(
897937
reporting_year.reporting_year,
898938
)
899939

940+
# Skip combinations that have already have a report
900941
if not cls._is_reportable_operation_year(
901942
operation_year,
902943
added_operation_years,
@@ -906,46 +947,41 @@ def list_previous_reportable_operations(
906947

907948
designated_operator_timeline = designations_lookup.get(operation_year)
908949

909-
if (
910-
designated_operator_timeline
911-
and designated_operator_timeline.operator.id == user_operator.operator_id
950+
# Include operations designated to the user's operator for the reporting year
951+
if cls._is_designated_to_user_operator(
952+
designated_operator_timeline,
953+
user_operator,
912954
):
913-
reportable_operations.append(
914-
{
915-
**cls._build_reportable_operation_row(
916-
timeline.operation,
917-
reporting_year,
918-
),
919-
"is_current_registered_fallback": False,
920-
}
955+
cls._add_reportable_operation(
956+
reportable_operations,
957+
added_operation_years,
958+
timeline.operation,
959+
reporting_year,
960+
False,
921961
)
922962

923-
added_operation_years.add(operation_year)
924-
925963
for operation in current_registered_operations:
926964
for reporting_year in reporting_years:
927965
operation_year = (
928966
operation.id,
929967
reporting_year.reporting_year,
930968
)
931969

970+
# Skip combinations that have already have a report
932971
if not cls._is_reportable_operation_year(
933972
operation_year,
934973
added_operation_years,
935974
existing_reports,
936975
):
937976
continue
938977

939-
reportable_operations.append(
940-
{
941-
**cls._build_reportable_operation_row(
942-
operation,
943-
reporting_year,
944-
),
945-
"is_current_registered_fallback": True,
946-
}
978+
# Fall back to the current registered operator when no historical designation applies
979+
cls._add_reportable_operation(
980+
reportable_operations,
981+
added_operation_years,
982+
operation,
983+
reporting_year,
984+
True,
947985
)
948986

949-
added_operation_years.add(operation_year)
950-
951987
return reportable_operations

bc_obps/service/report_service.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@ def create_report_for_reporting_year(
114114
# allow report creation only if the authenticated user's operator was
115115
# the designated operator for the selected reporting year
116116
if designated_operator_timeline.operator.id != user_operator.operator_id:
117-
raise UserError("You are not authorized to create a report for this operation and reporting year.")
117+
raise UserError(
118+
f"This operation was owned by another operation in {reporting_year}, "
119+
"you do not need to report on this operation. "
120+
"If you believe this is incorrect, please contact ghgregulator@gov.bc.ca."
121+
)
118122

119123
operator = designated_operator_timeline.operator
120124
use_transferred_operation_handling = designated_operator_timeline.has_been_transferred
@@ -124,7 +128,11 @@ def create_report_for_reporting_year(
124128
# no historical designation exists for the selected reporting year
125129
# allow creation only if the operation is currently registered to the authenticated user's operator
126130
if operation.operator_id != user_operator.operator_id:
127-
raise UserError("You are not authorized to create a report for this operation and reporting year.")
131+
raise UserError(
132+
f"This operation was owned by another operation in {reporting_year}, "
133+
"you do not need to report on this operation. "
134+
"If you believe this is incorrect, please contact ghgregulator@gov.bc.ca."
135+
)
128136

129137
if operation.status != Operation.Statuses.REGISTERED:
130138
raise UserError(
@@ -148,7 +156,9 @@ def create_report_for_reporting_year(
148156
]
149157

150158
if requires_boro_id and operation.bc_obps_regulated_operation_id is None:
151-
raise UserError("Regulated operations must have a BORO ID before a report can be created.")
159+
raise UserError(
160+
"This operation does not have a BORO ID, please wait for a BORO ID to be issued before starting this report."
161+
)
152162

153163
report = Report.objects.create(
154164
operation=operation,

0 commit comments

Comments
 (0)