Skip to content

Commit

Permalink
Merge pull request #1587 from bcgov/fix/kevin-1545
Browse files Browse the repository at this point in the history
fix: compliance report fuel supply end use logic
  • Loading branch information
kevin-hashimoto authored Jan 6, 2025
2 parents 9e2a069 + 1168a92 commit 23eec01
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ def upgrade() -> None:
(20, 'Compression-ignition engine- Marine, with methane slip reduction kit- Operated within 76 to 100% of load range', TRUE),
(21, 'Compression-ignition engine- Marine, unknown whether kit is installed or average operating load range', TRUE),
(22, 'Unknown engine type', TRUE),
(23, 'Other (i.e. road transportation)', TRUE)
(23, 'Other (i.e. road transportation)', TRUE),
(24, 'Any', TRUE)
ON CONFLICT (end_use_type_id) DO NOTHING;
""")
Expand Down Expand Up @@ -224,13 +225,13 @@ def upgrade() -> None:
eer_id, fuel_category_id, fuel_type_id, end_use_type_id, ratio, effective_status
)
VALUES
(1, 1, 2, NULL, 0.9, TRUE),
(1, 1, 2, 24, 0.9, TRUE),
(2, 1, 3, 1, 3.5, TRUE),
(3, 1, 3, 2, 1.0, TRUE),
(4, 1, 6, 3, 2.4, TRUE),
(5, 1, 6, 2, 0.9, TRUE),
(6, 1, 13, NULL, 0.9, TRUE),
(7, 2, 2, NULL, 0.9, TRUE),
(6, 1, 13, 24, 0.9, TRUE),
(7, 2, 2, 24, 0.9, TRUE),
(8, 2, 3, 4, 3.8, TRUE),
(9, 2, 3, 5, 3.2, TRUE),
(10, 2, 3, 6, 2.5, TRUE),
Expand All @@ -242,9 +243,9 @@ def upgrade() -> None:
(16, 2, 3, 2, 1.0, TRUE),
(17, 2, 6, 3, 1.8, TRUE),
(18, 2, 6, 2, 0.9, TRUE),
(19, 2, 13, NULL, 0.9, TRUE),
(20, 3, 3, NULL, 2.5, TRUE),
(21, 3, 11, NULL, 1.0, TRUE),
(19, 2, 13, 24, 0.9, TRUE),
(20, 3, 3, 24, 2.5, TRUE),
(21, 3, 11, 24, 1.0, TRUE),
(22, 2, 7, 15, 1.0, TRUE),
(23, 2, 7, 16, 1.0, TRUE),
(24, 2, 7, 17, 1.0, TRUE),
Expand All @@ -253,7 +254,20 @@ def upgrade() -> None:
(27, 2, 7, 20, 1.0, TRUE),
(28, 2, 7, 21, 1.0, TRUE),
(29, 2, 7, 22, 0.9, TRUE),
(30, 2, 7, 23, 0.9, TRUE)
(30, 2, 7, 23, 0.9, TRUE),
(31, 2, 1, 24, 1.0, TRUE),
(32, 2, 5, 24, 1.0, TRUE),
(33, 3, 6, 24, 1.0, TRUE),
(34, 1, 14, 24, 1.0, TRUE),
(35, 1, 15, 24, 1.0, TRUE),
(36, 2, 16, 24, 1.0, TRUE),
(37, 1, 17, 24, 1.0, TRUE),
(38, 3, 18, 24, 1.0, TRUE),
(39, 1, 19, 24, 1.0, TRUE),
(40, 2, 19, 24, 1.0, TRUE),
(41, 3, 7, 24, 1.0, TRUE),
(42, 2, 20, 24, 1.0, TRUE),
(43, 1, 4, 24, 1.0, TRUE)
ON CONFLICT (eer_id) DO NOTHING;
""")

Expand Down
4 changes: 3 additions & 1 deletion backend/lcfs/tests/fuel_supply/test_fuel_supplies_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ async def test_check_duplicate(fuel_supply_repo, mock_db_session):
compliance_report_id=1,
fuel_type_id=1,
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=1000,
units="L",
Expand All @@ -82,7 +83,8 @@ async def test_check_duplicate(fuel_supply_repo, mock_db_session):
# Set up the mock chain using regular MagicMock since the chained methods are sync
mock_result_chain = MagicMock()
mock_result_chain.scalars = MagicMock(return_value=mock_result_chain)
mock_result_chain.first = MagicMock(return_value=MagicMock(spec=FuelSupply))
mock_result_chain.first = MagicMock(
return_value=MagicMock(spec=FuelSupply))

# Define an async execute function that returns our mock chain
async def mock_execute(*args, **kwargs):
Expand Down
23 changes: 16 additions & 7 deletions backend/lcfs/tests/fuel_supply/test_fuel_supplies_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ def fuel_supply_service():
@pytest.mark.anyio
async def test_get_fuel_supply_options(fuel_supply_service):
service, mock_repo, mock_fuel_code_repo = fuel_supply_service
mock_repo.get_fuel_supply_table_options = AsyncMock(return_value={"fuel_types": []})
mock_repo.get_fuel_supply_table_options = AsyncMock(
return_value={"fuel_types": []})
compliance_period = "2023"

response = await service.get_fuel_supply_options(compliance_period)

assert isinstance(response, FuelTypeOptionsResponse)
mock_repo.get_fuel_supply_table_options.assert_awaited_once_with(compliance_period)
mock_repo.get_fuel_supply_table_options.assert_awaited_once_with(
compliance_period)


# Asynchronous test for get_fuel_supply_list
Expand All @@ -90,7 +92,8 @@ async def test_get_fuel_supply_list(fuel_supply_service):
response = await service.get_fuel_supply_list(compliance_report_id)

assert isinstance(response, FuelSuppliesSchema)
mock_repo.get_fuel_supply_list.assert_awaited_once_with(compliance_report_id)
mock_repo.get_fuel_supply_list.assert_awaited_once_with(
compliance_report_id)


@pytest.mark.anyio
Expand All @@ -102,6 +105,7 @@ async def test_update_fuel_supply_not_found(fuel_supply_action_service):
compliance_report_id=1,
fuel_type_id=1,
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=2000,
units="L",
Expand Down Expand Up @@ -274,8 +278,10 @@ async def test_create_fuel_supply(fuel_supply_action_service):
"fuelCode": "FUEL123",
"carbonIntensity": 15.0,
},
provisionOfTheAct={"provisionOfTheActId": 1, "name": "Act Provision"},
endUseType={"endUseTypeId": 1, "type": "Transport", "subType": "Personal"},
provisionOfTheAct={"provisionOfTheActId": 1,
"name": "Act Provision"},
endUseType={"endUseTypeId": 1,
"type": "Transport", "subType": "Personal"},
units="L",
compliancePeriod="2024",
)
Expand All @@ -290,7 +296,8 @@ async def test_create_fuel_supply(fuel_supply_action_service):
)
mock_density = MagicMock(spec=EnergyDensity)
mock_density.density = 30.0
mock_fuel_code_repo.get_energy_density = AsyncMock(return_value=mock_density)
mock_fuel_code_repo.get_energy_density = AsyncMock(
return_value=mock_density)

user_type = UserTypeEnum.SUPPLIER

Expand All @@ -315,6 +322,7 @@ async def test_delete_fuel_supply(fuel_supply_action_service):
group_uuid="some-uuid",
fuel_type_id=1,
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=1000,
units="L",
Expand All @@ -338,5 +346,6 @@ async def test_delete_fuel_supply(fuel_supply_action_service):

assert response.success is True
assert response.message == "Marked as deleted."
mock_repo.get_latest_fuel_supply_by_group_uuid.assert_awaited_once_with("some-uuid")
mock_repo.get_latest_fuel_supply_by_group_uuid.assert_awaited_once_with(
"some-uuid")
mock_repo.create_fuel_supply.assert_awaited_once()
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ async def test_check_duplicate(fuel_supply_validation):
compliance_report_id=1,
fuel_type_id=1,
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=2000,
units="L",
Expand All @@ -54,6 +55,7 @@ async def test_validate_other_recognized_type(fuel_supply_validation):
compliance_report_id=1,
fuel_type_id=1, # Some recognized type ID
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=2000,
units="L",
Expand All @@ -76,6 +78,7 @@ async def test_validate_other_unrecognized_type_with_other(fuel_supply_validatio
compliance_report_id=1,
fuel_type_id=99, # Assume 99 is unrecognized "Other" type
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=2000,
units="L",
Expand All @@ -99,6 +102,7 @@ async def test_validate_other_unrecognized_type_missing_other(fuel_supply_valida
compliance_report_id=1,
fuel_type_id=99, # Assume 99 is unrecognized "Other" type
fuel_category_id=1,
end_use_id=24,
provision_of_the_act_id=1,
quantity=2000,
units="L",
Expand Down
6 changes: 5 additions & 1 deletion backend/lcfs/tests/fuel_supply/test_fuel_supplies_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async def test_save_fuel_supply_row_create(
"compliance_report_id": 1,
"fuel_type_id": 1,
"fuel_category_id": 1,
"end_use_id": 24,
"provision_of_the_act_id": 1,
"quantity": 1000,
"units": "L",
Expand Down Expand Up @@ -104,6 +105,7 @@ async def test_save_fuel_supply_row_update(
"fuel_supply_id": 123,
"fuel_type_id": 1,
"fuel_category_id": 1,
"end_use_id": 24,
"provision_of_the_act_id": 1,
"quantity": 1000,
"units": "L",
Expand Down Expand Up @@ -160,6 +162,7 @@ async def test_save_fuel_supply_row_delete(
"fuel_supply_id": 123,
"fuel_type_id": 1,
"fuel_category_id": 1,
"end_use_id": 24,
"provision_of_the_act_id": 1,
"quantity": 1000,
"units": "L",
Expand Down Expand Up @@ -191,7 +194,8 @@ async def test_save_fuel_supply_row_delete(

assert response.status_code == status.HTTP_201_CREATED
data = response.json()
assert data == {"success": True, "message": "Fuel supply row deleted successfully"}
assert data == {"success": True,
"message": "Fuel supply row deleted successfully"}


@pytest.mark.anyio
Expand Down
2 changes: 1 addition & 1 deletion backend/lcfs/web/api/fuel_supply/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class FuelSupplyCreateUpdateSchema(BaseSchema):
version: Optional[int] = None
fuel_type_id: int
fuel_category_id: int
end_use_id: Optional[int] = None
end_use_id: int
provision_of_the_act_id: int
quantity: int
units: str
Expand Down
15 changes: 9 additions & 6 deletions backend/lcfs/web/api/fuel_supply/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ def fuel_type_row_mapper(self, compliance_period, fuel_types, row):
)
eer = EnergyEffectivenessRatioSchema(
eer_id=row_data["eer_id"],
energy_effectiveness_ratio=round(row_data["energy_effectiveness_ratio"], 2),
energy_effectiveness_ratio=round(
row_data["energy_effectiveness_ratio"], 2),
fuel_category=fuel_category,
end_use_type=end_use_type,
)
tci = TargetCarbonIntensitySchema(
target_carbon_intensity_id=row_data["target_carbon_intensity_id"],
target_carbon_intensity=round(row_data["target_carbon_intensity"], 2),
target_carbon_intensity=round(
row_data["target_carbon_intensity"], 2),
reduction_target_percentage=round(
row_data["reduction_target_percentage"], 2
),
Expand All @@ -94,7 +96,8 @@ def fuel_type_row_mapper(self, compliance_period, fuel_types, row):
)
# Find the existing fuel type if it exists
existing_fuel_type = next(
(ft for ft in fuel_types if ft.fuel_type == row_data["fuel_type"]), None
(ft for ft in fuel_types if ft.fuel_type ==
row_data["fuel_type"]), None
)

if existing_fuel_type:
Expand Down Expand Up @@ -135,8 +138,7 @@ def fuel_type_row_mapper(self, compliance_period, fuel_types, row):
(
e
for e in existing_fuel_type.eer_ratios
if e.end_use_type == row_data["end_use_type"]
and e.fuel_category == fuel_category
if e.eer_id == eer.eer_id
),
None,
)
Expand Down Expand Up @@ -258,7 +260,8 @@ async def get_fuel_supplies_paginated(
size=pagination.size,
total=total_count,
total_pages=(
math.ceil(total_count / pagination.size) if total_count > 0 else 0
math.ceil(total_count /
pagination.size) if total_count > 0 else 0
),
),
fuel_supplies=[
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/assets/locales/en/fuelSupply.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"fuelType": "Fuel type",
"fuelTypeOther": "Fuel type other",
"fuelCategoryId": "Fuel category",
"endUse": "End use",
"endUseId": "End use",
"provisionOfTheActId": "Determining carbon intensity",
"fuelCode": "Fuel code",
"quantity": "Quantity supplied",
Expand All @@ -33,4 +33,4 @@
"validateMsg": {
"isRequired": "{{field}} is required"
}
}
}
32 changes: 30 additions & 2 deletions frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const AddEditFuelSupplies = () => {
item.fuelType?.fuelType === 'Other' ? item.fuelTypeOther : null,
provisionOfTheAct: item.provisionOfTheAct?.name,
fuelCode: item.fuelCode?.fuelCode,
endUse: item.endUse?.type || 'Any',
endUse: item.endUse?.type,
id: uuid()
}))
setRowData([...updatedRowData, { id: uuid() }])
Expand Down Expand Up @@ -140,7 +140,7 @@ export const AddEditFuelSupplies = () => {
item.fuelType?.fuelType === 'Other' ? item.fuelTypeOther : null,
provisionOfTheAct: item.provisionOfTheAct?.name,
fuelCode: item.fuelCode?.fuelCode,
endUse: item.endUse?.type || 'Any',
endUse: item.endUse?.type,
id: uuid()
}))
setRowData(updatedRowData)
Expand All @@ -161,11 +161,39 @@ export const AddEditFuelSupplies = () => {
(item) => item.fuelCategory
)

const endUseTypes = selectedFuelType.eerRatios.map(
(item) => item.endUseType
)

// Set to null if multiple options, otherwise use first item
const categoryValue =
fuelCategoryOptions.length === 1 ? fuelCategoryOptions[0] : null
const endUseValue =
endUseTypes.length === 1 ? endUseTypes[0].type : null

params.node.setDataValue('fuelCategory', categoryValue)
params.node.setDataValue('endUseType', endUseValue)
}
}

if (params.column.colId === 'fuelCategory') {
const selectedFuelType = optionsData?.fuelTypes?.find(
(obj) => params.node.data.fuelType === obj.fuelType
)

if (selectedFuelType) {
const endUseTypes = selectedFuelType.eerRatios
.filter(
(item) =>
item.fuelCategory.fuelCategory === params.data.fuelCategory
)
.map((item) => item.endUseType)

// Set to null if multiple options, otherwise use first item
const endUseValue =
endUseTypes.length === 1 ? endUseTypes[0].type : null

params.node.setDataValue('endUseType', endUseValue)
}
}
},
Expand Down
12 changes: 4 additions & 8 deletions frontend/src/views/FuelSupplies/_schema.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export const fuelSupplyColDefs = (optionsData, errors, warnings) => [
{
field: 'endUseType',
headerComponent: RequiredHeader,
headerName: i18n.t('fuelSupply:fuelSupplyColLabels.endUse'),
headerName: i18n.t('fuelSupply:fuelSupplyColLabels.endUseId'),
cellEditorParams: (params) => ({
options: [
...new Set(
Expand All @@ -206,7 +206,7 @@ export const fuelSupplyColDefs = (optionsData, errors, warnings) => [
?.map((item) => item.endUseType?.type)
.sort()
)
].filter((item) => item != null) || ['Any'],
].filter((item) => item != null),
multiple: false,
disableCloseOnSelect: false,
freeSolo: false,
Expand All @@ -219,14 +219,10 @@ export const fuelSupplyColDefs = (optionsData, errors, warnings) => [
cellStyle: (params) =>
StandardCellWarningAndErrors(params, errors, warnings),
suppressKeyboardEvent,
valueGetter: (params) => {
return params.colDef?.cellEditorParams(params).options.length < 1
? 'Any'
: params.data?.endUseType?.type
},
valueGetter: (params) => params.data.endUseType?.type,
editable: (params) => {
const cellParams = params.colDef?.cellEditorParams(params)
return cellParams.options.length > 0
return cellParams.options.length > 1
},
valueSetter: (params) => {
if (params.newValue) {
Expand Down

0 comments on commit 23eec01

Please sign in to comment.