Skip to content

Commit

Permalink
Merge branch 'release-0.2.0' into fix/daniel-load-eer-in-all-cases-1318
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaselhan authored Dec 11, 2024
2 parents 038292e + 38279d5 commit 1e53b5f
Show file tree
Hide file tree
Showing 58 changed files with 1,574 additions and 224 deletions.
8 changes: 4 additions & 4 deletions backend/Dockerfile.openshift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ ENV POETRY_CACHE_DIR=/.cache/pypoetry
RUN poetry install --only main

# Removing gcc
# RUN apt-get purge -y \
# gcc \
# && rm -rf /var/lib/apt/lists/*
RUN apt-get purge -y \
gcc \
&& rm -rf /var/lib/apt/lists/*

# Copying the actual application, wait-for-it script, and prestart script
COPY . /app/
Expand All @@ -45,4 +45,4 @@ RUN chmod +x /app/wait-for-it.sh /app/lcfs/prestart.sh /app/lcfs/start.sh
# Set the APP_ENVIRONMENT variable to 'production'
ENV APP_ENVIRONMENT=prod

CMD ["/app/lcfs/start.sh"]
CMD ["/app/lcfs/start.sh"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Remove notifications email from user_profile
Revision ID: cd8698fe40e6
Revises: 26ab15f8ab18
Create Date: 2024-12-09 22:33:29.554360
"""

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "cd8698fe40e6"
down_revision = "26ab15f8ab18"
branch_labels = None
depends_on = None


def upgrade() -> None:
# Remove notifications_email column from user_profile table
op.drop_column("user_profile", "notifications_email")


def downgrade() -> None:
# Add notifications_email column to user_profile table
op.add_column(
"user_profile",
sa.Column(
"notifications_email",
sa.String(length=255),
nullable=True,
comment="Email address used for notifications",
),
)
3 changes: 0 additions & 3 deletions backend/lcfs/db/models/user/UserProfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ class UserProfile(BaseModel, Auditable):
String(150), unique=True, nullable=False, comment="keycloak Username"
)
email = Column(String(255), nullable=True, comment="Primary email address")
notifications_email = Column(
String(255), nullable=True, comment="Email address used for notifications"
)
title = Column(String(100), nullable=True, comment="Professional Title")
phone = Column(String(50), nullable=True, comment="Primary phone number")
mobile_phone = Column(String(50), nullable=True, comment="Mobile phone number")
Expand Down
4 changes: 2 additions & 2 deletions backend/lcfs/tests/fuel_code/test_fuel_code_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ async def test_approve_fuel_code_not_found():
repo_mock.get_fuel_code.return_value = None

# Act & Assert
with pytest.raises(ServiceException):
with pytest.raises(ValueError, match="Fuel code not found"):
await service.approve_fuel_code(fuel_code_id)
repo_mock.get_fuel_code.assert_called_once_with(fuel_code_id)

Expand All @@ -229,7 +229,7 @@ async def test_approve_fuel_code_invalid_status():
repo_mock.get_fuel_code.return_value = mock_fuel_code

# Act & Assert
with pytest.raises(ServiceException):
with pytest.raises(ValueError, match="Fuel code is not in Draft"):
await service.approve_fuel_code(fuel_code_id)

repo_mock.get_fuel_code.assert_called_once_with(fuel_code_id)
2 changes: 1 addition & 1 deletion backend/lcfs/tests/other_uses/test_other_uses_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ async def test_update_other_use_not_found(other_uses_service):

mock_repo.get_other_use_version_by_user = AsyncMock(return_value=None)

with pytest.raises(ServiceException):
with pytest.raises(ValueError, match="Other use not found"):
await service.update_other_use(other_use_data, UserTypeEnum.SUPPLIER)


Expand Down
14 changes: 6 additions & 8 deletions backend/lcfs/tests/user/test_user_repo.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from unittest.mock import AsyncMock, Mock
from unittest.mock import Mock

import pytest

from lcfs.db.models import UserProfile, UserLoginHistory
from lcfs.web.api.user.repo import UserRepository
from lcfs.tests.user.user_payloads import user_orm_model
from lcfs.web.exception.exceptions import DataNotFoundException


@pytest.fixture
Expand Down Expand Up @@ -50,14 +49,13 @@ async def test_create_login_history(dbsession, user_repo):


@pytest.mark.anyio
async def test_update_notifications_email_success(dbsession, user_repo):
async def test_update_email_success(dbsession, user_repo):
# Arrange: Create a user in the database
user = UserProfile(
keycloak_user_id="user_id_1",
keycloak_email="[email protected]",
keycloak_username="username1",
email="[email protected]",
notifications_email=None,
title="Developer",
phone="1234567890",
mobile_phone="0987654321",
Expand All @@ -70,10 +68,10 @@ async def test_update_notifications_email_success(dbsession, user_repo):
await dbsession.commit()
await dbsession.refresh(user)

# Act: Update the notifications email
updated_user = await user_repo.update_notifications_email(
# Act: Update the email
updated_user = await user_repo.update_email(
user_profile_id=1, email="[email protected]"
)

# Assert: Check if the notifications email was updated
assert updated_user.notifications_email == "[email protected]"
# Assert: Check if the email was updated
assert updated_user.email == "[email protected]"
7 changes: 3 additions & 4 deletions backend/lcfs/tests/user/test_user_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,19 +468,18 @@ async def test_track_logged_in_success(client: AsyncClient, fastapi_app, set_moc


@pytest.mark.anyio
async def test_update_notifications_email_success(
async def test_update_email_success(
client: AsyncClient,
fastapi_app,
set_mock_user,
add_models,
):
set_mock_user(fastapi_app, [RoleEnum.GOVERNMENT])

# Prepare request data
request_data = {"notifications_email": "[email protected]"}
request_data = {"email": "[email protected]"}

# Act: Send POST request to the endpoint
url = fastapi_app.url_path_for("update_notifications_email")
url = fastapi_app.url_path_for("update_email")
response = await client.post(url, json=request_data)

# Assert: Check response status and content
Expand Down
1 change: 0 additions & 1 deletion backend/lcfs/tests/user/user_payloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
keycloak_email="[email protected]",
keycloak_username="username",
email="[email protected]",
notifications_email=None,
title="Developer",
phone="1234567890",
mobile_phone="0987654321",
Expand Down
1 change: 1 addition & 0 deletions backend/lcfs/web/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ def apply_number_filter_conditions(field, filter_value, filter_option):
"greaterThanOrEqual": field >= filter_value,
"lessThan": field < filter_value,
"lessThanOrEqual": field <= filter_value,
"startsWith": cast(field, String).like(f"{filter_value}%"),
}
return number_filter_mapping.get(filter_option)

Expand Down
2 changes: 1 addition & 1 deletion backend/lcfs/web/api/fuel_code/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""User API."""
"""Fuel code API."""

from lcfs.web.api.fuel_code.views import router

Expand Down
22 changes: 8 additions & 14 deletions backend/lcfs/web/api/fuel_code/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,8 @@ async def create_fuel_code(self, fuel_code: FuelCode) -> FuelCode:
"""
self.db.add(fuel_code)
await self.db.flush()
await self.db.refresh(
fuel_code,
[
"fuel_code_status",
"fuel_code_prefix",
"fuel_type",
"feedstock_fuel_transport_modes",
"finished_fuel_transport_modes",
],
)
# Manually load nested relationships
await self.db.refresh(fuel_code.fuel_type, ["provision_1", "provision_2"])
return fuel_code
result = await self.get_fuel_code(fuel_code.fuel_code_id)
return result

@repo_handler
async def get_fuel_code(self, fuel_code_id: int) -> FuelCode:
Expand Down Expand Up @@ -593,9 +582,14 @@ async def validate_fuel_code(self, suffix: str, prefix_id: int) -> str:
result = (await self.db.execute(query)).scalar_one_or_none()
if result:
fuel_code_main_version = suffix.split(".")[0]
return await self.get_next_available_sub_version_fuel_code_by_prefix(
suffix = await self.get_next_available_sub_version_fuel_code_by_prefix(
fuel_code_main_version, prefix_id
)
if int(suffix.split(".")[1]) > 9:
return await self.get_next_available_fuel_code_by_prefix(
result.fuel_code_prefix.prefix
)
return suffix
else:
return suffix

Expand Down
4 changes: 4 additions & 0 deletions backend/lcfs/web/api/fuel_code/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ async def convert_to_model(
transport_mode_id=matching_transport_mode.transport_mode_id,
)
)
else:
raise ValueError(f"Invalid transport mode: {transport_mode}")

for transport_mode in fuel_code_schema.finished_fuel_transport_mode or []:
matching_transport_mode = next(
Expand All @@ -221,6 +223,8 @@ async def convert_to_model(
transport_mode_id=matching_transport_mode.transport_mode_id,
)
)
else:
raise ValueError(f"Invalid transport mode: {transport_mode}")

return fuel_code

Expand Down
3 changes: 2 additions & 1 deletion backend/lcfs/web/api/monitoring/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@


@router.get("/health")
def health_check() -> None:
def health_check() -> str:
"""
Checks the health of a project.
It returns 200 if the project is healthy.
"""
return "healthy"
5 changes: 2 additions & 3 deletions backend/lcfs/web/api/user/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ async def create_login_history(self, user: UserProfile):
self.db.add(login_history)

@repo_handler
async def update_notifications_email(
async def update_email(
self, user_profile_id: int, email: str
) -> UserProfile:
# Fetch the user profile
Expand All @@ -679,8 +679,7 @@ async def update_notifications_email(
result = await self.db.execute(query)
user_profile = result.scalar_one_or_none()

# Update the notifications_email field
user_profile.notifications_email = email
user_profile.email = email

# Flush and refresh without committing
await self.db.flush()
Expand Down
5 changes: 2 additions & 3 deletions backend/lcfs/web/api/user/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class UserBaseSchema(BaseSchema):
keycloak_username: str
keycloak_email: EmailStr
email: Optional[EmailStr] = None
notifications_email: Optional[EmailStr] = None
title: Optional[str] = None
phone: Optional[str] = None
first_name: Optional[str] = None
Expand Down Expand Up @@ -97,5 +96,5 @@ class UserLoginHistoryResponseSchema(BaseSchema):
pagination: PaginationResponseSchema


class UpdateNotificationsEmailSchema(BaseSchema):
notifications_email: EmailStr
class UpdateEmailSchema(BaseSchema):
email: EmailStr
9 changes: 3 additions & 6 deletions backend/lcfs/web/api/user/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,12 @@ async def track_user_login(self, user: UserProfile):
await self.repo.create_login_history(user)

@service_handler
async def update_notifications_email(self, user_id: int, email: str):
async def update_email(self, user_id: int, email: str):
try:
# Update the notifications_email field of the user
return await self.repo.update_notifications_email(user_id, email)
# Return the updated user
return UserBaseSchema.model_validate(user)
return await self.repo.update_email(user_id, email)
except DataNotFoundException as e:
logger.error(f"User not found: {e}")
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
logger.error(f"Error updating notifications email: {e}")
logger.error(f"Error updating email: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
27 changes: 9 additions & 18 deletions backend/lcfs/web/api/user/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
from typing import List

import structlog
from fastapi import (
APIRouter,
Body,
status,
Request,
Response,
Depends,
Query,
HTTPException,
)
from fastapi import APIRouter, Body, status, Request, Response, Depends, Query
from fastapi.responses import StreamingResponse

from lcfs.db import dependencies
Expand All @@ -23,7 +14,7 @@
UserLoginHistoryResponseSchema,
UsersSchema,
UserActivitiesResponseSchema,
UpdateNotificationsEmailSchema,
UpdateEmailSchema,
)
from lcfs.web.api.user.services import UserServices
from lcfs.web.core.decorators import view_handler
Expand Down Expand Up @@ -255,18 +246,18 @@ async def get_all_user_login_history(


@router.post(
"/update-notifications-email",
response_model=UpdateNotificationsEmailSchema,
"/update-email",
response_model=UpdateEmailSchema,
status_code=status.HTTP_200_OK,
)
@view_handler(["*"])
async def update_notifications_email(
async def update_email(
request: Request,
email_data: UpdateNotificationsEmailSchema = Body(...),
email_data: UpdateEmailSchema = Body(...),
service: UserServices = Depends(),
):
user_id = request.user.user_profile_id
email = email_data.notifications_email
email = email_data.email

user = await service.update_notifications_email(user_id, email)
return user
user = await service.update_email(user_id, email)
return UpdateEmailSchema(email=user.email)
Loading

0 comments on commit 1e53b5f

Please sign in to comment.