Skip to content

Commit 841c9fa

Browse files
authored
Merge pull request #3677 from bcgov/release-v1.2.2
Release v1.2.2
2 parents a01667b + 17abacd commit 841c9fa

File tree

81 files changed

+7512
-566
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+7512
-566
lines changed

backend/lcfs/db/seeders/staging/test_compliance_report_summary_seeder.py

Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -329,39 +329,59 @@ async def seed_test_compliance_report_summaries(session):
329329
"total_non_compliance_penalty_payable": 0.0,
330330
},
331331
# New LCFS1-10 summaries (lightweight values matching status)
332-
# 101 Draft 2024 (unlocked)
332+
# 101 Draft 2024 (unlocked) - retains fuel (line 6) and defers obligation (line 8)
333333
{
334334
"summary_id": 101,
335335
"compliance_report_id": 101,
336336
"is_locked": False,
337-
"line_1_fossil_derived_base_fuel_gasoline": 100.0,
338-
"line_2_eligible_renewable_fuel_supplied_gasoline": 20.0,
339-
"line_3_total_tracked_fuel_supplied_gasoline": 120.0,
340-
"line_4_eligible_renewable_fuel_required_gasoline": 5.0,
341-
"line_5_net_notionally_transferred_gasoline": 20.0,
342-
"line_6_renewable_fuel_retained_gasoline": 0.0,
337+
"line_1_fossil_derived_base_fuel_gasoline": 50000000.0,
338+
"line_1_fossil_derived_base_fuel_diesel": 25000000.0,
339+
"line_2_eligible_renewable_fuel_supplied_gasoline": 10000000.0,
340+
"line_2_eligible_renewable_fuel_supplied_diesel": 5000000.0,
341+
"line_3_total_tracked_fuel_supplied_gasoline": 60000000.0,
342+
"line_3_total_tracked_fuel_supplied_diesel": 30000000.0,
343+
"line_4_eligible_renewable_fuel_required_gasoline": 2500000.0,
344+
"line_4_eligible_renewable_fuel_required_diesel": 1250000.0,
345+
"line_5_net_notionally_transferred_gasoline": 1000000.0,
346+
"line_5_net_notionally_transferred_diesel": 0.0,
347+
"line_6_renewable_fuel_retained_gasoline": 250000.0,
348+
"line_6_renewable_fuel_retained_diesel": 125000.0,
343349
"line_7_previously_retained_gasoline": 0.0,
344-
"line_8_obligation_deferred_gasoline": 0.0,
350+
"line_7_previously_retained_diesel": 0.0,
351+
"line_8_obligation_deferred_gasoline": 150000.0,
352+
"line_8_obligation_deferred_diesel": 75000.0,
345353
"line_9_obligation_added_gasoline": 0.0,
346-
"line_10_net_renewable_fuel_supplied_gasoline": 40.0,
347-
"line_20_surplus_deficit_units": 40.0,
354+
"line_9_obligation_added_diesel": 0.0,
355+
"line_10_net_renewable_fuel_supplied_gasoline": 10600000.0,
356+
"line_10_net_renewable_fuel_supplied_diesel": 4800000.0,
357+
"line_20_surplus_deficit_units": 15400000.0,
348358
},
349-
# 102 Submitted 2024 (reserved)
359+
# 102 Submitted 2024 (reserved) - adds previously deferred obligation (line 9)
350360
{
351361
"summary_id": 102,
352362
"compliance_report_id": 102,
353363
"is_locked": False,
354-
"line_1_fossil_derived_base_fuel_gasoline": 80.0,
355-
"line_2_eligible_renewable_fuel_supplied_gasoline": 16.0,
356-
"line_3_total_tracked_fuel_supplied_gasoline": 96.0,
357-
"line_4_eligible_renewable_fuel_required_gasoline": 4.0,
358-
"line_5_net_notionally_transferred_gasoline": -15.0,
364+
"line_1_fossil_derived_base_fuel_gasoline": 40000000.0,
365+
"line_1_fossil_derived_base_fuel_diesel": 20000000.0,
366+
"line_2_eligible_renewable_fuel_supplied_gasoline": 8000000.0,
367+
"line_2_eligible_renewable_fuel_supplied_diesel": 4000000.0,
368+
"line_3_total_tracked_fuel_supplied_gasoline": 48000000.0,
369+
"line_3_total_tracked_fuel_supplied_diesel": 24000000.0,
370+
"line_4_eligible_renewable_fuel_required_gasoline": 2000000.0,
371+
"line_4_eligible_renewable_fuel_required_diesel": 1000000.0,
372+
"line_5_net_notionally_transferred_gasoline": -750000.0,
373+
"line_5_net_notionally_transferred_diesel": 0.0,
359374
"line_6_renewable_fuel_retained_gasoline": 0.0,
375+
"line_6_renewable_fuel_retained_diesel": 0.0,
360376
"line_7_previously_retained_gasoline": 0.0,
377+
"line_7_previously_retained_diesel": 0.0,
361378
"line_8_obligation_deferred_gasoline": 0.0,
362-
"line_9_obligation_added_gasoline": 0.0,
363-
"line_10_net_renewable_fuel_supplied_gasoline": 1.0,
364-
"line_20_surplus_deficit_units": 1.0,
379+
"line_8_obligation_deferred_diesel": 0.0,
380+
"line_9_obligation_added_gasoline": 150000.0,
381+
"line_9_obligation_added_diesel": 75000.0,
382+
"line_10_net_renewable_fuel_supplied_gasoline": 7100000.0,
383+
"line_10_net_renewable_fuel_supplied_diesel": 3925000.0,
384+
"line_20_surplus_deficit_units": 11025000.0,
365385
},
366386
# 103 Recommended 2024 (locked)
367387
# CR 103 locked recommended: fuel 12 + notional 10, retention 2, deferral 1 => line10/20 = 21
@@ -372,41 +392,61 @@ async def seed_test_compliance_report_summaries(session):
372392
# 105 Analyst Adjustment 2025 (locked)
373393
# CR 105 locked analyst adj: fuel 10 + notional 8, retention 1, deferral 0.5 => line10/20 = 17.5
374394
{"summary_id": 105, "compliance_report_id": 105, "is_locked": True, "line_1_fossil_derived_base_fuel_gasoline": 40.0, "line_2_eligible_renewable_fuel_supplied_gasoline": 10.0, "line_3_total_tracked_fuel_supplied_gasoline": 50.0, "line_4_eligible_renewable_fuel_required_gasoline": 2.0, "line_5_net_notionally_transferred_gasoline": 8.0, "line_6_renewable_fuel_retained_gasoline": 1.0, "line_7_previously_retained_gasoline": 0.0, "line_8_obligation_deferred_gasoline": 0.5, "line_9_obligation_added_gasoline": 0.0, "line_10_net_renewable_fuel_supplied_gasoline": 17.5, "line_20_surplus_deficit_units": 17.5},
375-
# 106 Supplier Supplemental 2025 (draft)
395+
# 106 Supplier Supplemental 2025 (draft) - uses previous retention (line 7)
376396
{
377397
"summary_id": 106,
378398
"compliance_report_id": 106,
379399
"is_locked": False,
380-
"line_1_fossil_derived_base_fuel_gasoline": 90.0,
381-
"line_2_eligible_renewable_fuel_supplied_gasoline": 18.0,
382-
"line_3_total_tracked_fuel_supplied_gasoline": 108.0,
383-
"line_4_eligible_renewable_fuel_required_gasoline": 4.5,
384-
"line_5_net_notionally_transferred_gasoline": -18.0,
400+
"line_1_fossil_derived_base_fuel_gasoline": 45000000.0,
401+
"line_2_eligible_renewable_fuel_supplied_gasoline": 9000000.0,
402+
"line_3_total_tracked_fuel_supplied_gasoline": 54000000.0,
403+
"line_4_eligible_renewable_fuel_required_gasoline": 2250000.0,
404+
"line_5_net_notionally_transferred_gasoline": -900000.0,
385405
"line_6_renewable_fuel_retained_gasoline": 0.0,
386-
"line_7_previously_retained_gasoline": 15.0,
406+
"line_7_previously_retained_gasoline": 750000.0,
387407
"line_8_obligation_deferred_gasoline": 0.0,
388-
"line_9_obligation_added_gasoline": 5.0,
389-
"line_10_net_renewable_fuel_supplied_gasoline": 10.0,
390-
"line_20_surplus_deficit_units": 10.0,
408+
"line_9_obligation_added_gasoline": 0.0,
409+
"line_10_net_renewable_fuel_supplied_gasoline": 8850000.0,
410+
"line_20_surplus_deficit_units": 8850000.0,
391411
},
392-
# 107 Gov Supplemental 2025 (draft)
412+
# 107 Gov Supplemental 2025 (draft) - uses previous retention (line 7) and retains more (line 6)
393413
{
394414
"summary_id": 107,
395415
"compliance_report_id": 107,
396416
"is_locked": False,
397-
"line_1_fossil_derived_base_fuel_gasoline": 40.0,
398-
"line_2_eligible_renewable_fuel_supplied_gasoline": 8.0,
399-
"line_3_total_tracked_fuel_supplied_gasoline": 48.0,
400-
"line_4_eligible_renewable_fuel_required_gasoline": 2.0,
401-
"line_5_net_notionally_transferred_gasoline": 7.0,
402-
"line_6_renewable_fuel_retained_gasoline": 0.0,
403-
"line_7_previously_retained_gasoline": 0.0,
417+
"line_1_fossil_derived_base_fuel_gasoline": 20000000.0,
418+
"line_1_fossil_derived_base_fuel_diesel": 15000000.0,
419+
"line_1_fossil_derived_base_fuel_jet_fuel": 10000000.0,
420+
"line_2_eligible_renewable_fuel_supplied_gasoline": 4000000.0,
421+
"line_2_eligible_renewable_fuel_supplied_diesel": 3000000.0,
422+
"line_2_eligible_renewable_fuel_supplied_jet_fuel": 2000000.0,
423+
"line_3_total_tracked_fuel_supplied_gasoline": 24000000.0,
424+
"line_3_total_tracked_fuel_supplied_diesel": 18000000.0,
425+
"line_3_total_tracked_fuel_supplied_jet_fuel": 12000000.0,
426+
"line_4_eligible_renewable_fuel_required_gasoline": 1000000.0,
427+
"line_4_eligible_renewable_fuel_required_diesel": 750000.0,
428+
"line_4_eligible_renewable_fuel_required_jet_fuel": 0.0,
429+
"line_5_net_notionally_transferred_gasoline": 350000.0,
430+
"line_5_net_notionally_transferred_diesel": 0.0,
431+
"line_5_net_notionally_transferred_jet_fuel": 0.0,
432+
"line_6_renewable_fuel_retained_gasoline": 100000.0,
433+
"line_6_renewable_fuel_retained_diesel": 50000.0,
434+
"line_6_renewable_fuel_retained_jet_fuel": 25000.0,
435+
"line_7_previously_retained_gasoline": 200000.0,
436+
"line_7_previously_retained_diesel": 100000.0,
437+
"line_7_previously_retained_jet_fuel": 0.0,
404438
"line_8_obligation_deferred_gasoline": 0.0,
439+
"line_8_obligation_deferred_diesel": 0.0,
440+
"line_8_obligation_deferred_jet_fuel": 0.0,
405441
"line_9_obligation_added_gasoline": 0.0,
406-
"line_10_net_renewable_fuel_supplied_gasoline": 15.0,
407-
"line_20_surplus_deficit_units": 15.0,
442+
"line_9_obligation_added_diesel": 0.0,
443+
"line_9_obligation_added_jet_fuel": 0.0,
444+
"line_10_net_renewable_fuel_supplied_gasoline": 4450000.0,
445+
"line_10_net_renewable_fuel_supplied_diesel": 3050000.0,
446+
"line_10_net_renewable_fuel_supplied_jet_fuel": 1975000.0,
447+
"line_20_surplus_deficit_units": 9475000.0,
408448
},
409-
# 108 Early issuance quarterly draft 2025
449+
# 108 Early issuance quarterly draft 2025 - defers obligation (line 8)
410450
{
411451
"summary_id": 108,
412452
"compliance_report_id": 108,
@@ -415,17 +455,27 @@ async def seed_test_compliance_report_summaries(session):
415455
"early_issuance_credits_q2": 20,
416456
"early_issuance_credits_q3": 0,
417457
"early_issuance_credits_q4": 0,
418-
"line_1_fossil_derived_base_fuel_gasoline": 30.0,
419-
"line_2_eligible_renewable_fuel_supplied_gasoline": 6.0,
420-
"line_3_total_tracked_fuel_supplied_gasoline": 36.0,
421-
"line_4_eligible_renewable_fuel_required_gasoline": 1.5,
422-
"line_5_net_notionally_transferred_gasoline": -5.0,
458+
"line_1_fossil_derived_base_fuel_gasoline": 15000000.0,
459+
"line_1_fossil_derived_base_fuel_diesel": 12500000.0,
460+
"line_2_eligible_renewable_fuel_supplied_gasoline": 3000000.0,
461+
"line_2_eligible_renewable_fuel_supplied_diesel": 2500000.0,
462+
"line_3_total_tracked_fuel_supplied_gasoline": 18000000.0,
463+
"line_3_total_tracked_fuel_supplied_diesel": 15000000.0,
464+
"line_4_eligible_renewable_fuel_required_gasoline": 750000.0,
465+
"line_4_eligible_renewable_fuel_required_diesel": 625000.0,
466+
"line_5_net_notionally_transferred_gasoline": -250000.0,
467+
"line_5_net_notionally_transferred_diesel": 0.0,
423468
"line_6_renewable_fuel_retained_gasoline": 0.0,
469+
"line_6_renewable_fuel_retained_diesel": 0.0,
424470
"line_7_previously_retained_gasoline": 0.0,
425-
"line_8_obligation_deferred_gasoline": 0.0,
471+
"line_7_previously_retained_diesel": 0.0,
472+
"line_8_obligation_deferred_gasoline": 100000.0,
473+
"line_8_obligation_deferred_diesel": 50000.0,
426474
"line_9_obligation_added_gasoline": 0.0,
427-
"line_10_net_renewable_fuel_supplied_gasoline": 1.0,
428-
"line_20_surplus_deficit_units": 1.0,
475+
"line_9_obligation_added_diesel": 0.0,
476+
"line_10_net_renewable_fuel_supplied_gasoline": 2650000.0,
477+
"line_10_net_renewable_fuel_supplied_diesel": 2450000.0,
478+
"line_20_surplus_deficit_units": 5100000.0,
429479
},
430480
# 109 Assessed 2023 baseline
431481
# CR 109 locked assessed baseline: fuel 13 + notional 14 => line10/20 27

backend/lcfs/tests/charging_equipment/test_charging_equipment_repo.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
from unittest.mock import AsyncMock, MagicMock, patch
33
from sqlalchemy.exc import DatabaseError
44

5+
from lcfs.db.base import ActionTypeEnum
56
from lcfs.db.models.compliance.ChargingEquipment import ChargingEquipment
67
from lcfs.db.models.compliance.ChargingEquipmentStatus import ChargingEquipmentStatus
8+
from lcfs.db.models.compliance.ChargingSite import ChargingSite
79
from lcfs.db.models.compliance.ComplianceReportChargingEquipment import (
810
ComplianceReportChargingEquipment,
911
)
@@ -602,3 +604,143 @@ async def test_auto_submit_draft_updated_fse_for_report_missing_status(repo, moc
602604
assert mock_db.execute.call_count == 1
603605
# flush should not be called since no updates were made
604606
mock_db.flush.assert_not_called()
607+
608+
609+
class TestChargingEquipmentRepositoryDeletedFiltering:
610+
"""Test class for verifying deleted equipment and sites are filtered out"""
611+
612+
@pytest.mark.anyio
613+
async def test_get_charging_equipment_list_excludes_deleted_equipment(
614+
self, valid_charging_equipment
615+
):
616+
"""Test that get_charging_equipment_list excludes equipment with action_type=DELETE"""
617+
mock_db = AsyncMock()
618+
mock_db.add = MagicMock()
619+
mock_db.flush = AsyncMock()
620+
mock_db.refresh = AsyncMock()
621+
622+
repo = ChargingEquipmentRepository(mock_db)
623+
624+
# Setup pagination
625+
pagination = PaginationRequestSchema(page=1, size=10, sort_orders=[])
626+
627+
# Mock the count and items query results
628+
mock_count_result = MagicMock()
629+
mock_count_result.scalar.return_value = 1
630+
631+
mock_items_result = MagicMock()
632+
mock_items_result.scalars.return_value.all.return_value = [valid_charging_equipment]
633+
634+
mock_db.execute.side_effect = [mock_count_result, mock_items_result]
635+
636+
# Call the repository method
637+
items, total_count = await repo.get_charging_equipment_list(1, pagination)
638+
639+
# Verify results
640+
assert len(items) == 1
641+
assert total_count == 1
642+
assert mock_db.execute.call_count == 2
643+
644+
@pytest.mark.anyio
645+
async def test_get_charging_equipment_list_excludes_equipment_from_deleted_sites(
646+
self, valid_charging_equipment
647+
):
648+
"""Test that get_charging_equipment_list excludes equipment from deleted charging sites"""
649+
mock_db = AsyncMock()
650+
mock_db.add = MagicMock()
651+
mock_db.flush = AsyncMock()
652+
mock_db.refresh = AsyncMock()
653+
654+
repo = ChargingEquipmentRepository(mock_db)
655+
656+
# Setup pagination
657+
pagination = PaginationRequestSchema(page=1, size=10, sort_orders=[])
658+
659+
# Mock the count and items query results - no results since site is deleted
660+
mock_count_result = MagicMock()
661+
mock_count_result.scalar.return_value = 0
662+
663+
mock_items_result = MagicMock()
664+
mock_items_result.scalars.return_value.all.return_value = []
665+
666+
mock_db.execute.side_effect = [mock_count_result, mock_items_result]
667+
668+
# Call the repository method
669+
items, total_count = await repo.get_charging_equipment_list(1, pagination)
670+
671+
# Verify that no equipment is returned (site was deleted)
672+
assert len(items) == 0
673+
assert total_count == 0
674+
675+
@pytest.mark.anyio
676+
async def test_get_all_equipment_by_organization_id_excludes_deleted(
677+
self, valid_charging_equipment
678+
):
679+
"""Test that get_all_equipment_by_organization_id excludes deleted equipment"""
680+
mock_db = AsyncMock()
681+
mock_db.add = MagicMock()
682+
mock_db.flush = AsyncMock()
683+
mock_db.refresh = AsyncMock()
684+
685+
repo = ChargingEquipmentRepository(mock_db)
686+
687+
# Mock the query result
688+
mock_result = MagicMock()
689+
mock_result.scalars.return_value.all.return_value = [valid_charging_equipment]
690+
mock_db.execute.return_value = mock_result
691+
692+
# Call the repository method
693+
result = await repo.get_all_equipment_by_organization_id(1)
694+
695+
# Verify results
696+
assert len(result) == 1
697+
mock_db.execute.assert_called_once()
698+
699+
@pytest.mark.anyio
700+
async def test_get_charging_sites_by_organization_excludes_deleted(self):
701+
"""Test that get_charging_sites_by_organization excludes deleted sites"""
702+
mock_db = AsyncMock()
703+
mock_db.add = MagicMock()
704+
mock_db.flush = AsyncMock()
705+
mock_db.refresh = AsyncMock()
706+
707+
repo = ChargingEquipmentRepository(mock_db)
708+
709+
# Create mock site
710+
mock_site = MagicMock(spec=ChargingSite)
711+
mock_site.action_type = ActionTypeEnum.CREATE
712+
mock_sites = [mock_site]
713+
714+
# Mock the query result
715+
mock_result = MagicMock()
716+
mock_result.scalars.return_value.all.return_value = mock_sites
717+
mock_db.execute.return_value = mock_result
718+
719+
# Call the repository method
720+
result = await repo.get_charging_sites_by_organization(1)
721+
722+
# Verify results
723+
assert len(result) == 1
724+
mock_db.execute.assert_called_once()
725+
726+
@pytest.mark.anyio
727+
async def test_get_charging_sites_by_organization_returns_empty_when_all_deleted(self):
728+
"""Test that get_charging_sites_by_organization returns empty list when all sites are deleted"""
729+
mock_db = AsyncMock()
730+
mock_db.add = MagicMock()
731+
mock_db.flush = AsyncMock()
732+
mock_db.refresh = AsyncMock()
733+
734+
repo = ChargingEquipmentRepository(mock_db)
735+
736+
# Mock the query result - empty because all sites are deleted
737+
mock_result = MagicMock()
738+
mock_result.scalars.return_value.all.return_value = []
739+
mock_db.execute.return_value = mock_result
740+
741+
# Call the repository method
742+
result = await repo.get_charging_sites_by_organization(1)
743+
744+
# Verify results
745+
assert len(result) == 0
746+
mock_db.execute.assert_called_once()

0 commit comments

Comments
 (0)