Skip to content

Commit

Permalink
Merge branch 'release-0.2.0' into LCFS-1426-UploadFileAttachements-Co…
Browse files Browse the repository at this point in the history
…mplianceReports
  • Loading branch information
areyeslo authored Dec 18, 2024
2 parents 32ba64f + 37360a9 commit 1683355
Show file tree
Hide file tree
Showing 28 changed files with 471 additions and 150 deletions.
6 changes: 1 addition & 5 deletions backend/lcfs/tests/compliance_report/test_summary_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,8 +810,7 @@ async def test_calculate_fuel_quantities_renewable(
):
# Create a mock repository
mock_repo.aggregate_fuel_supplies.return_value = {"gasoline": 200.0}
mock_repo.aggregate_other_uses.return_value = {"diesel": 75.0}
mock_repo.aggregate_allocation_agreements.return_value = {"jet-fuel": 25.0}
mock_repo.aggregate_other_uses.return_value = {"diesel": 75.0, "jet-fuel": 25.0}

# Define test inputs
compliance_report_id = 2
Expand All @@ -830,7 +829,4 @@ async def test_calculate_fuel_quantities_renewable(
mock_repo.aggregate_other_uses.assert_awaited_once_with(
compliance_report_id, fossil_derived
)
mock_repo.aggregate_allocation_agreements.assert_awaited_once_with(
compliance_report_id
)
assert result == {"gasoline": 200.0, "diesel": 75.0, "jet-fuel": 25.0}
90 changes: 84 additions & 6 deletions backend/lcfs/tests/fuel_supply/test_fuel_supplies_validation.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
from unittest.mock import MagicMock, AsyncMock

import pytest
from fastapi import Request
from fastapi.exceptions import RequestValidationError

from lcfs.web.api.fuel_supply.repo import FuelSupplyRepository
from lcfs.web.api.fuel_code.repo import FuelCodeRepository
from lcfs.web.api.fuel_supply.schema import FuelSupplyCreateUpdateSchema
from lcfs.web.api.fuel_supply.validation import FuelSupplyValidation


@pytest.fixture
def fuel_supply_validation():
# Mock repositories
mock_fs_repo = MagicMock(spec=FuelSupplyRepository)
request = MagicMock(spec=Request)
mock_fc_repo = MagicMock(spec=FuelCodeRepository)

# Create the validation instance with mocked repositories
validation = FuelSupplyValidation(
request=request, fs_repo=mock_fs_repo
fs_repo=mock_fs_repo,
fc_repo=mock_fc_repo,
)
return validation, mock_fs_repo
return validation, mock_fs_repo, mock_fc_repo


@pytest.mark.anyio
async def test_check_duplicate(fuel_supply_validation):
validation, mock_fs_repo = fuel_supply_validation
validation, mock_fs_repo, _ = fuel_supply_validation
fuel_supply_data = FuelSupplyCreateUpdateSchema(
compliance_report_id=1,
fuel_type_id=1,
Expand All @@ -29,9 +33,83 @@ async def test_check_duplicate(fuel_supply_validation):
quantity=2000,
units="L",
)

mock_fs_repo.check_duplicate = AsyncMock(return_value=True)

result = await validation.check_duplicate(fuel_supply_data)

assert result is True
mock_fs_repo.check_duplicate.assert_awaited_once_with(fuel_supply_data)


@pytest.mark.anyio
async def test_validate_other_recognized_type(fuel_supply_validation):
validation, _, mock_fc_repo = fuel_supply_validation
# Mock a recognized fuel type (unrecognized = False)
mock_fc_repo.get_fuel_type_by_id = AsyncMock(
return_value=MagicMock(unrecognized=False)
)

fuel_supply_data = FuelSupplyCreateUpdateSchema(
compliance_report_id=1,
fuel_type_id=1, # Some recognized type ID
fuel_category_id=1,
provision_of_the_act_id=1,
quantity=2000,
units="L",
)

# Should not raise any error as fuel_type_other is not needed for recognized type
await validation.validate_other(fuel_supply_data)


@pytest.mark.anyio
async def test_validate_other_unrecognized_type_with_other(fuel_supply_validation):
validation, _, mock_fc_repo = fuel_supply_validation
# Mock an unrecognized fuel type
mock_fc_repo.get_fuel_type_by_id = AsyncMock(
return_value=MagicMock(unrecognized=True)
)

# Provide fuel_type_other since it's unrecognized
fuel_supply_data = FuelSupplyCreateUpdateSchema(
compliance_report_id=1,
fuel_type_id=99, # Assume 99 is unrecognized "Other" type
fuel_category_id=1,
provision_of_the_act_id=1,
quantity=2000,
units="L",
fuel_type_other="Some other fuel",
)

# Should not raise an error since fuel_type_other is provided
await validation.validate_other(fuel_supply_data)


@pytest.mark.anyio
async def test_validate_other_unrecognized_type_missing_other(fuel_supply_validation):
validation, _, mock_fc_repo = fuel_supply_validation
# Mock an unrecognized fuel type
mock_fc_repo.get_fuel_type_by_id = AsyncMock(
return_value=MagicMock(unrecognized=True)
)

# Missing fuel_type_other
fuel_supply_data = FuelSupplyCreateUpdateSchema(
compliance_report_id=1,
fuel_type_id=99, # Assume 99 is unrecognized "Other" type
fuel_category_id=1,
provision_of_the_act_id=1,
quantity=2000,
units="L",
)

# Should raise RequestValidationError since fuel_type_other is required
with pytest.raises(RequestValidationError) as exc:
await validation.validate_other(fuel_supply_data)

# Assert that the error message is as expected
errors = exc.value.errors()
assert len(errors) == 1
assert errors[0]["loc"] == ("fuelTypeOther",)
assert "required when using Other" in errors[0]["msg"]
8 changes: 8 additions & 0 deletions backend/lcfs/tests/internal_comment/test_internal_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from httpx import AsyncClient
from datetime import datetime

from lcfs.db.models import UserProfile
from lcfs.db.models.transfer.Transfer import Transfer, TransferRecommendationEnum
from lcfs.db.models.initiative_agreement.InitiativeAgreement import InitiativeAgreement
from lcfs.db.models.admin_adjustment.AdminAdjustment import AdminAdjustment
Expand Down Expand Up @@ -334,6 +335,13 @@ async def test_get_internal_comments_multiple_comments(
)
await add_models([transfer])

user = UserProfile(
keycloak_username="IDIRUSER",
first_name="Test",
last_name="User",
)
await add_models([user])

comments = []
for i in range(3):
internal_comment = InternalComment(
Expand Down
2 changes: 1 addition & 1 deletion backend/lcfs/tests/user/test_user_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ async def test_get_user_activities_as_manage_users_same_org(
add_models,
):
# Mock the current user as a user with MANAGE_USERS
set_mock_user(fastapi_app, [RoleEnum.MANAGE_USERS])
set_mock_user(fastapi_app, [RoleEnum.ADMINISTRATOR, RoleEnum.MANAGE_USERS])

# Assuming target user with user_profile_id=3 exists and is in organization_id=1
target_user_id = 1
Expand Down
6 changes: 3 additions & 3 deletions backend/lcfs/web/api/final_supply_equipment/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ async def get_fse_list(self, report_id: int) -> List[FinalSupplyEquipment]:
joinedload(FinalSupplyEquipment.level_of_equipment),
)
.where(FinalSupplyEquipment.compliance_report_id == report_id)
.order_by(FinalSupplyEquipment.final_supply_equipment_id)
.order_by(FinalSupplyEquipment.create_date.asc())
)
return result.unique().scalars().all()

Expand Down Expand Up @@ -232,7 +232,7 @@ async def get_fse_paginated(
result = await self.db.execute(
query.offset(offset)
.limit(limit)
.order_by(FinalSupplyEquipment.create_date.desc())
.order_by(FinalSupplyEquipment.create_date.asc())
)
final_supply_equipments = result.unique().scalars().all()
return final_supply_equipments, total_count
Expand Down Expand Up @@ -356,7 +356,7 @@ async def increment_seq_by_org_and_postal_code(
sequence_number = 1

return sequence_number

@repo_handler
async def check_uniques_of_fse_row(self, row: FinalSupplyEquipmentCreateSchema) -> bool:
"""
Expand Down
23 changes: 20 additions & 3 deletions backend/lcfs/web/api/fuel_supply/validation.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
from fastapi import Depends, Request
from fastapi import Depends
from fastapi.exceptions import RequestValidationError

from lcfs.web.api.fuel_code.repo import FuelCodeRepository
from lcfs.web.api.fuel_supply.repo import FuelSupplyRepository
from lcfs.web.api.fuel_supply.schema import FuelSupplyCreateUpdateSchema


class FuelSupplyValidation:
def __init__(
self,
request: Request = None,
fs_repo: FuelSupplyRepository = Depends(FuelSupplyRepository),
fc_repo: FuelCodeRepository = Depends(FuelCodeRepository),
):
self.fs_repo = fs_repo
self.request = request
self.fc_repo = fc_repo

async def check_duplicate(self, fuel_supply: FuelSupplyCreateUpdateSchema):
return await self.fs_repo.check_duplicate(fuel_supply)

async def validate_other(self, fuel_supply: FuelSupplyCreateUpdateSchema):
fuel_type = await self.fc_repo.get_fuel_type_by_id(fuel_supply.fuel_type_id)

if fuel_type.unrecognized:
if not fuel_supply.fuel_type_other:
raise RequestValidationError(
[
{
"loc": ("fuelTypeOther",),
"msg": "required when using Other",
"type": "value_error",
}
]
)
1 change: 1 addition & 0 deletions backend/lcfs/web/api/fuel_supply/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ async def save_fuel_supply_row(
return await action_service.delete_fuel_supply(request_data, current_user_type)
else:
duplicate_id = await fs_validate.check_duplicate(request_data)
await fs_validate.validate_other(request_data)
if duplicate_id is not None:
duplicate_response = format_duplicate_error(duplicate_id)
return duplicate_response
Expand Down
5 changes: 4 additions & 1 deletion backend/lcfs/web/api/internal_comment/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ async def get_internal_comments(
List[InternalCommentResponseSchema]: A list of internal comments as data transfer objects.
"""
comments = await self.repo.get_internal_comments(entity_type, entity_id)
return [InternalCommentResponseSchema.from_orm(comment) for comment in comments]
return [
InternalCommentResponseSchema.model_validate(comment)
for comment in comments
]

@service_handler
async def get_internal_comment_by_id(
Expand Down
7 changes: 0 additions & 7 deletions backend/lcfs/web/api/notification/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@ class NotificationUserProfileSchema(BaseSchema):
organization_id: Optional[int] = None
is_government: bool = False

@model_validator(mode="before")
def update_government_profile(cls, data):
if data.is_government:
data.first_name = "Government of B.C."
data.last_name = ""
return data

@computed_field
@property
def full_name(self) -> str:
Expand Down
3 changes: 3 additions & 0 deletions backend/lcfs/web/core/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import os

from fastapi import HTTPException, Request
from fastapi.exceptions import RequestValidationError

from lcfs.services.clamav.client import VirusScanException
from lcfs.web.exception.exceptions import (
Expand Down Expand Up @@ -191,6 +192,8 @@ async def wrapper(request: Request, *args, **kwargs):
status_code=422,
detail="Viruses detected in file, please upload another",
)
except RequestValidationError as e:
raise e
except Exception as e:
context = extract_context()
log_unhandled_exception(logger, e, context, "view", func=func)
Expand Down
39 changes: 39 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"material-ui-popup-state": "^5.0.10",
"moment": "^2.30.1",
"mui-daterange-picker-plus": "^1.0.4",
"notistack": "^3.0.1",
"papaparse": "^5.4.1",
"pretty-bytes": "^6.1.1",
"quill": "^2.0.2",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/assets/locales/en/finalSupplyEquipment.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"fseTitle": "Final supply equipment (FSE)",
"addFSErowsTitle": "Add new final supply equipment(s) (FSE)",
"fseSubtitle": "Report dates of supply for your FSE. If your billing location is different from your equipment location provided below use the Notes field. Use the Notes field if you use any Other options.",
"reportingResponsibilityInfo": "If you are reporting on behalf of an FSE for which you hold allocated reporting responsibility, please list the utility account holder's organization name associated with the specific station, rather than your own organization's name.",
"newFinalSupplyEquipmentBtn": "New final supply equipment",
"noFinalSupplyEquipmentsFound": "No final supply equipments found",
"finalSupplyEquipmentDownloadBtn": "Download as Excel",
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/assets/locales/en/fuelExport.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
"fuelExportColLabels": {
"complianceReportId": "Compliance Report ID",
"fuelExportId": "Fuel export ID",
"fuelTypeId": "Fuel type",
"fuelType": "Fuel type",
"exportDate": "Export date",
"fuelTypeOther": "Fuel type other",
"fuelCategoryId": "Fuel catgory",
"fuelCategory": "Fuel catgory",
"endUse": "End use",
"provisionOfTheActId": "Determining carbon intensity",
"fuelCode": "Fuel code",
Expand Down
Loading

0 comments on commit 1683355

Please sign in to comment.