Skip to content

Commit 9a8b1d0

Browse files
authored
Merge pull request #4089 from bcgov/chore/456-compliance-test-helper
456 - Compliance Test Helper
2 parents f21714b + d3f75a0 commit 9a8b1d0

2 files changed

Lines changed: 271 additions & 147 deletions

File tree

bc_obps/compliance/tests/service/test_compliance_obligation_service.py

Lines changed: 45 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -2,68 +2,37 @@
22
from decimal import Decimal
33
from datetime import date
44
from compliance.service.compliance_obligation_service import ComplianceObligationService
5-
import pytest
6-
from compliance.models import ComplianceObligation
5+
from compliance.models import ComplianceObligation, ComplianceReportVersion
76
from compliance.dataclass import ObligationData
8-
from reporting.models import Report
9-
from registration.models import Operation
107
from django.core.exceptions import ValidationError
8+
from compliance.tests.utils.compliance_test_helper import ComplianceTestHelper
9+
import pytest
1110
from model_bakery import baker
1211

1312
pytestmark = pytest.mark.django_db
1413

1514

16-
@pytest.fixture
17-
def report_version():
18-
"""Create a report version with a regulated operation"""
19-
operation = baker.make_recipe(
20-
"registration.tests.utils.operation",
21-
bc_obps_regulated_operation=baker.make_recipe("registration.tests.utils.boro_id"),
22-
status=Operation.Statuses.REGISTERED,
23-
)
24-
25-
# Use a unique year for this fixture to avoid conflicts - use a far future year
26-
reporting_year = baker.make_recipe("reporting.tests.utils.reporting_year", reporting_year=2050)
27-
28-
return baker.make_recipe(
29-
"reporting.tests.utils.report_version", report__operation=operation, report__reporting_year=reporting_year
30-
)
31-
32-
33-
@pytest.fixture
34-
def report_version_unregulated():
35-
"""Create a report version with an unregulated operation (bc_obps_regulated_operation is None)"""
36-
operation = baker.make_recipe(
37-
"registration.tests.utils.operation",
38-
bc_obps_regulated_operation=None,
39-
status=Operation.Statuses.REGISTERED,
40-
)
41-
42-
# Use a different year to avoid conflicts with the other fixture
43-
reporting_year = baker.make_recipe("reporting.tests.utils.reporting_year", reporting_year=2051)
44-
45-
return baker.make_recipe(
46-
"reporting.tests.utils.report_version", report__operation=operation, report__reporting_year=reporting_year
47-
)
48-
49-
5015
class TestComplianceObligationService:
5116
"""Tests for the ComplianceObligationService class"""
5217

53-
def test_get_obligation_id_success(self, report_version):
18+
def test_get_obligation_id_success(self):
5419
"""Test successful generation of obligation ID"""
20+
test_data = ComplianceTestHelper.build_test_data()
5521
# Call the method
56-
obligation_id = ComplianceObligationService._get_obligation_id(report_version)
22+
obligation_id = ComplianceObligationService._get_obligation_id(test_data.report_version)
5723

5824
# Verify results - format should be YY-OOOO-R-V (year-operation-report-version)
5925
assert isinstance(obligation_id, str)
6026
assert len(obligation_id.split('-')) == 4 # Should have 4 parts separated by dashes
6127

62-
def test_get_obligation_id_unregulated_operation(self, report_version_unregulated):
28+
def test_get_obligation_id_unregulated_operation(self):
6329
"""Test ValidationError is raised when operation is not regulated by BC OBPS"""
30+
test_data = ComplianceTestHelper.build_test_data()
31+
test_data.operation.bc_obps_regulated_operation = None
32+
test_data.operation.save()
6433
# Call the method and expect ValidationError
6534
with pytest.raises(ValidationError) as excinfo:
66-
ComplianceObligationService._get_obligation_id(report_version_unregulated)
35+
ComplianceObligationService._get_obligation_id(test_data.report_version)
6736

6837
# Verify error message
6938
error_msg = str(excinfo.value)
@@ -79,39 +48,22 @@ def test_create_compliance_obligation_success(
7948
):
8049
"""Test successful creation of a compliance obligation"""
8150
# Set up mocks
82-
report_compliance_summary = baker.make_recipe(
83-
'reporting.tests.utils.report_compliance_summary', excess_emissions=Decimal('10'), credited_emissions=0
84-
)
85-
compliance_report = baker.make_recipe(
86-
'compliance.tests.utils.compliance_report', report_id=report_compliance_summary.report_version.report_id
87-
)
88-
89-
compliance_report_version = baker.make_recipe(
90-
'compliance.tests.utils.compliance_report_version',
91-
report_compliance_summary_id=report_compliance_summary.id,
92-
compliance_report_id=compliance_report.id,
93-
)
51+
test_data = ComplianceTestHelper.build_test_data()
52+
test_data.report_compliance_summary.excess_emissions = Decimal('100')
53+
test_data.report_compliance_summary.save()
9454
mock_get_rate.return_value = Decimal('50.00')
9555

96-
Report.objects.filter(id=compliance_report.report.id).update(reporting_year=2025)
97-
Operation.objects.filter(id=compliance_report.report.operation_id).update(
98-
bc_obps_regulated_operation=baker.make_recipe('registration.tests.utils.boro_id'),
99-
status=Operation.Statuses.REGISTERED,
100-
)
101-
10256
result = ComplianceObligationService.create_compliance_obligation(
103-
compliance_report_version_id=compliance_report_version.id, emissions_amount=Decimal('100.0')
57+
compliance_report_version_id=test_data.compliance_report_version.id,
58+
emissions_amount=Decimal('100.0'),
10459
)
105-
10660
# Verify results
10761
assert result.fee_amount_dollars == (Decimal('100.0') * Decimal('50.00')).quantize(Decimal('0.01'))
108-
assert result.compliance_report_version_id == compliance_report_version.id
62+
assert result.compliance_report_version_id == test_data.compliance_report_version.id
10963
assert result.penalty_status == ComplianceObligation.PenaltyStatus.NONE
11064
assert result.fee_date == date.today()
111-
mock_get_rate.assert_called_once_with(
112-
compliance_report_version.report_compliance_summary.report_version.report.reporting_year
113-
)
114-
mock_send_email.execute.assert_called_once_with(compliance_report_version.id)
65+
mock_get_rate.assert_called_once_with(test_data.reporting_year)
66+
mock_send_email.execute.assert_called_once_with(test_data.compliance_report_version.id)
11567

11668
@patch('compliance.service.compliance_obligation_service.ComplianceObligation.objects.create')
11769
@patch('compliance.service.compliance_obligation_service.ComplianceChargeRateService.get_rate_for_year')
@@ -122,26 +74,19 @@ def test_create_compliance_obligation_unregulated_operation(
12274
):
12375
"""Test compliance obligation creation fails when operation is not regulated by BC OBPS"""
12476
# Set up mocks
125-
report_compliance_summary = baker.make_recipe(
126-
'reporting.tests.utils.report_compliance_summary', excess_emissions=Decimal('10'), credited_emissions=0
127-
)
128-
compliance_report = baker.make_recipe(
129-
'compliance.tests.utils.compliance_report', report_id=report_compliance_summary.report_version.report_id
130-
)
131-
compliance_report.report.reporting_year.reporting_year = 2024
132-
compliance_report_version = baker.make_recipe(
133-
'compliance.tests.utils.compliance_report_version',
134-
report_compliance_summary_id=report_compliance_summary.id,
135-
compliance_report_id=compliance_report.id,
136-
)
137-
mock_get_rate.return_value = Decimal('50.00')
77+
test_data = ComplianceTestHelper.build_test_data()
78+
test_data.operation.bc_obps_regulated_operation = None
79+
test_data.operation.save()
80+
test_data.report_compliance_summary.excess_emissions = Decimal('100')
81+
test_data.report_compliance_summary.save()
13882

139-
Report.objects.filter(id=compliance_report.report.id).update(reporting_year=2025)
83+
mock_get_rate.return_value = Decimal('50.00')
14084

14185
# Call the method and expect ValidationError
14286
with pytest.raises(ValidationError) as excinfo:
14387
ComplianceObligationService.create_compliance_obligation(
144-
compliance_report_version_id=compliance_report_version.id, emissions_amount=Decimal('100.0')
88+
compliance_report_version_id=test_data.compliance_report_version.id,
89+
emissions_amount=Decimal('100.0'),
14590
)
14691

14792
# Verify error message
@@ -150,9 +95,7 @@ def test_create_compliance_obligation_unregulated_operation(
15095

15196
# Verify ComplianceObligation.objects.create was not called
15297
mock_create.assert_not_called()
153-
mock_get_rate.assert_called_once_with(
154-
compliance_report_version.report_compliance_summary.report_version.report.reporting_year
155-
)
98+
mock_get_rate.assert_called_once_with(test_data.report.reporting_year)
15699

157100
def test_get_obligation_deadline(self):
158101
"""Test get_obligation_deadline returns the correct date"""
@@ -220,79 +163,51 @@ def test_get_obligation_data_by_report_version_success(
220163
mock_calculate_outstanding_balance_tco2e.return_value = Decimal('50.00')
221164

222165
# Create test data
223-
report_compliance_summary = baker.make_recipe(
224-
'reporting.tests.utils.report_compliance_summary', excess_emissions=Decimal('10'), credited_emissions=0
225-
)
226-
compliance_report = baker.make_recipe(
227-
'compliance.tests.utils.compliance_report', report_id=report_compliance_summary.report_version.report_id
228-
)
229-
compliance_report_version = baker.make_recipe(
230-
'compliance.tests.utils.compliance_report_version',
231-
report_compliance_summary_id=report_compliance_summary.id,
232-
compliance_report_id=compliance_report.id,
166+
test_data = ComplianceTestHelper.build_test_data(
167+
crv_status=ComplianceReportVersion.ComplianceStatus.OBLIGATION_NOT_MET
233168
)
234169

235170
# Create elicensing invoice with outstanding balance
236171
elicensing_invoice = baker.make_recipe(
237172
'compliance.tests.utils.elicensing_invoice', invoice_fee_balance=Decimal('2000.00')
238173
)
239174

240-
baker.make_recipe(
241-
'compliance.tests.utils.compliance_obligation',
242-
compliance_report_version=compliance_report_version,
243-
obligation_id="23-0001-1-1",
244-
elicensing_invoice=elicensing_invoice,
245-
)
175+
test_data.compliance_obligation.obligation_id = "23-0001-1-1"
176+
test_data.compliance_obligation.elicensing_invoice = elicensing_invoice
177+
test_data.compliance_obligation.save()
246178

247179
# Set up the refresh mock to return the created invoice
248180
mock_refresh_data.return_value = RefreshWrapperReturn(data_is_fresh=True, invoice=elicensing_invoice)
249181

250182
# Call method
251-
result = ComplianceObligationService.get_obligation_data_by_report_version(compliance_report_version.id)
183+
result = ComplianceObligationService.get_obligation_data_by_report_version(
184+
test_data.compliance_report_version.id
185+
)
252186

253187
# Verify results
254188
assert isinstance(result, ObligationData)
255-
assert (
256-
result.reporting_year
257-
== compliance_report_version.report_compliance_summary.report_version.report.reporting_year.reporting_year
258-
)
189+
assert result.reporting_year == test_data.reporting_year.reporting_year
259190
assert result.equivalent_value == Decimal('2000.00') # This is the outstanding balance in dollars
260191
assert result.obligation_id == "23-0001-1-1"
261192

262193
# Verify refresh was called
263-
mock_refresh_data.assert_called_once_with(compliance_report_version_id=compliance_report_version.id)
194+
mock_refresh_data.assert_called_once_with(compliance_report_version_id=test_data.compliance_report_version.id)
264195

265196
# Verify calculate outstanding balance service was called
266-
mock_calculate_outstanding_balance_tco2e.assert_called_once_with(compliance_report_version)
197+
mock_calculate_outstanding_balance_tco2e.assert_called_once_with(test_data.compliance_report_version)
267198

268199
@patch('compliance.service.compliance_obligation_service.ComplianceChargeRateService.get_rate_for_year')
269200
def test_create_compliance_obligation_calculates_correct_fee(self, mock_get_rate):
270201
"""Test that create_compliance_obligation calculates fee correctly with rounding"""
271202
# Setup
272203
mock_get_rate.return_value = Decimal('45.33') # Odd rate to test rounding
273-
274-
report_compliance_summary = baker.make_recipe(
275-
'reporting.tests.utils.report_compliance_summary', excess_emissions=Decimal('10'), credited_emissions=0
276-
)
277-
compliance_report = baker.make_recipe(
278-
'compliance.tests.utils.compliance_report', report_id=report_compliance_summary.report_version.report_id
279-
)
280-
compliance_report_version = baker.make_recipe(
281-
'compliance.tests.utils.compliance_report_version',
282-
report_compliance_summary_id=report_compliance_summary.id,
283-
compliance_report_id=compliance_report.id,
284-
)
285-
286-
Report.objects.filter(id=compliance_report.report.id).update(reporting_year=2025)
287-
Operation.objects.filter(id=compliance_report.report.operation_id).update(
288-
bc_obps_regulated_operation=baker.make_recipe('registration.tests.utils.boro_id'),
289-
status=Operation.Statuses.REGISTERED,
290-
)
204+
test_data = ComplianceTestHelper.build_test_data()
291205

292206
# Call method with emissions that will require rounding
293207
emissions_amount = Decimal('123.456')
294208
result = ComplianceObligationService.create_compliance_obligation(
295-
compliance_report_version_id=compliance_report_version.id, emissions_amount=emissions_amount
209+
compliance_report_version_id=test_data.compliance_report_version.id,
210+
emissions_amount=emissions_amount,
296211
)
297212

298213
assert result.fee_amount_dollars == Decimal('5596.26')
@@ -302,28 +217,11 @@ def test_create_compliance_obligation_sets_correct_deadline(self, mock_get_rate)
302217
"""Test that create_compliance_obligation sets the correct obligation deadline"""
303218
# Setup
304219
mock_get_rate.return_value = Decimal('40.00')
305-
306-
report_compliance_summary = baker.make_recipe(
307-
'reporting.tests.utils.report_compliance_summary', excess_emissions=Decimal('10'), credited_emissions=0
308-
)
309-
compliance_report = baker.make_recipe(
310-
'compliance.tests.utils.compliance_report', report_id=report_compliance_summary.report_version.report_id
311-
)
312-
compliance_report_version = baker.make_recipe(
313-
'compliance.tests.utils.compliance_report_version',
314-
report_compliance_summary_id=report_compliance_summary.id,
315-
compliance_report_id=compliance_report.id,
316-
)
317-
318-
# Set reporting year to 2023
319-
Report.objects.filter(id=compliance_report.report.id).update(reporting_year=2023)
320-
Operation.objects.filter(id=compliance_report.report.operation_id).update(
321-
bc_obps_regulated_operation=baker.make_recipe('registration.tests.utils.boro_id'),
322-
status=Operation.Statuses.REGISTERED,
323-
)
220+
test_data = ComplianceTestHelper.build_test_data(reporting_year=2023)
324221

325222
result = ComplianceObligationService.create_compliance_obligation(
326-
compliance_report_version_id=compliance_report_version.id, emissions_amount=Decimal('100.0')
223+
compliance_report_version_id=test_data.compliance_report_version.id,
224+
emissions_amount=Decimal('100.0'),
327225
)
328226

329227
# Verify deadline is November 30 of the following year (2024)

0 commit comments

Comments
 (0)