Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LCFS-1255 Add organization name to FSE identification grid input and view table #1380

Merged
merged 3 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Add Organization name to FSE

Revision ID: 9206124a098b
Revises: aeaa26f5cdd5
Create Date: 2024-12-04 09:59:22.876386

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '9206124a098b'
down_revision = '26ab15f8ab18'
branch_labels = None
depends_on = None


def upgrade():
# Add the column 'organization_name' to 'final_supply_equipment' table
op.add_column("final_supply_equipment", sa.Column("organization_name", sa.String(), nullable=True))


def downgrade():
# Remove the column 'organization_name' from 'final_supply_equipment' table
op.drop_column("final_supply_equipment", "organization_name")
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

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

Expand Down
1 change: 1 addition & 0 deletions backend/lcfs/db/models/compliance/FinalSupplyEquipment.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class FinalSupplyEquipment(BaseModel, Auditable):
Double, nullable=False, comment="The longitude of the equipment location."
)
notes = Column(Text, comment="Any additional notes related to the equipment.")
organization_name = Column(Text, comment="External organization name.")

# relationships
compliance_report = relationship(
Expand Down
5 changes: 1 addition & 4 deletions backend/lcfs/web/api/compliance_report/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ class CompliancePeriodSchema(BaseSchema):
display_order: Optional[int] = None


class ComplianceReportOrganizationSchema(BaseSchema):
organization_id: int
name: str


class SummarySchema(BaseSchema):
summary_id: int
Expand Down Expand Up @@ -118,6 +114,7 @@ class FSEOptionsSchema(BaseSchema):
class FinalSupplyEquipmentSchema(BaseSchema):
final_supply_equipment_id: int
compliance_report_id: int
organization_name: str
supply_from_date: date
supply_to_date: date
registration_nbr: str
Expand Down
39 changes: 35 additions & 4 deletions backend/lcfs/web/api/final_supply_equipment/repo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import structlog
from typing import List, Tuple
from lcfs.db.models.compliance import EndUserType, FinalSupplyEquipment
from lcfs.db.models.compliance import EndUserType, FinalSupplyEquipment, ComplianceReport
from lcfs.db.models.compliance.FinalSupplyEquipmentRegNumber import (
FinalSupplyEquipmentRegNumber,
)
Expand All @@ -27,8 +27,14 @@ def __init__(self, db: AsyncSession = Depends(get_async_db_session)):

@repo_handler
async def get_fse_options(
self,
) -> Tuple[List[EndUseType], List[LevelOfEquipment], List[FuelMeasurementType], List[PortsEnum]]:
self, organization
) -> Tuple[
List[EndUseType],
List[LevelOfEquipment],
List[FuelMeasurementType],
List[PortsEnum],
List[str],
]:
"""
Retrieve all FSE options in a single database transaction
"""
Expand All @@ -37,13 +43,15 @@ async def get_fse_options(
levels_of_equipment = await self.get_levels_of_equipment()
fuel_measurement_types = await self.get_fuel_measurement_types()
intended_user_types = await self.get_intended_user_types()
organization_names = await self.get_organization_names(organization)
ports = list(PortsEnum)
return (
intended_use_types,
levels_of_equipment,
fuel_measurement_types,
intended_user_types,
ports
ports,
organization_names,
)

async def get_intended_use_types(self) -> List[EndUseType]:
Expand Down Expand Up @@ -94,6 +102,29 @@ async def get_intended_user_types(self) -> List[EndUserType]:
.all()
)

async def get_organization_names(self, organization) -> List[str]:
"""
Retrieve unique organization names for Final Supply Equipment records
associated with the given organization_id via ComplianceReport.

Args:
organization_id (int): The ID of the organization.

Returns:
List[str]: A list of unique organization names.
"""
organization_names = (
await self.db.execute(
select(distinct(FinalSupplyEquipment.organization_name))
.join(ComplianceReport, FinalSupplyEquipment.compliance_report_id == ComplianceReport.compliance_report_id)
.filter(ComplianceReport.organization_id == organization.organization_id)
.filter(FinalSupplyEquipment.organization_name.isnot(None))
)
).all()

# Extract strings from the list of tuples
return [name[0] for name in organization_names]

@repo_handler
async def get_intended_user_by_name(self, intended_user: str) -> EndUseType:
"""
Expand Down
2 changes: 2 additions & 0 deletions backend/lcfs/web/api/final_supply_equipment/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ class FSEOptionsSchema(BaseSchema):
levels_of_equipment: List[LevelOfEquipmentSchema]
intended_user_types: List[EndUserTypeSchema]
ports: List[PortsEnum]
organization_names: List[str]


class FinalSupplyEquipmentCreateSchema(BaseSchema):
final_supply_equipment_id: Optional[int] = None
compliance_report_id: Optional[int] = None
organization_name: str
supply_from_date: date
supply_to_date: date
kwh_usage: float
Expand Down
8 changes: 6 additions & 2 deletions backend/lcfs/web/api/final_supply_equipment/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ def __init__(
@service_handler
async def get_fse_options(self):
"""Fetches all FSE options concurrently."""
organization = self.request.user.organization
(
intended_use_types,
levels_of_equipment,
fuel_measurement_types,
intended_user_types,
ports
) = await self.repo.get_fse_options()
ports,
organization_names,
) = await self.repo.get_fse_options(organization)

return {
"intended_use_types": [
Expand All @@ -52,6 +54,7 @@ async def get_fse_options(self):
EndUserTypeSchema.model_validate(u) for u in intended_user_types
],
"ports": [port.value for port in ports],
"organization_names": organization_names,
}

async def convert_to_fse_model(self, fse: FinalSupplyEquipmentCreateSchema):
Expand Down Expand Up @@ -141,6 +144,7 @@ async def update_final_supply_equipment(
if not existing_fse:
raise ValueError("final supply equipment not found")

existing_fse.organization_name = fse_data.organization_name
existing_fse.kwh_usage = fse_data.kwh_usage
existing_fse.serial_nbr = fse_data.serial_nbr
existing_fse.manufacturer = fse_data.manufacturer
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 @@ -27,6 +27,7 @@
"rows": "rows",
"finalSupplyEquipmentColLabels": {
"complianceReportId": "Compliance Report ID",
"organizationName": "Organization",
"supplyFrom": "Supply date range",
"kwhUsage":"kWh usage",
"supplyFromDate": "Dates of supply from",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export const FinalSupplyEquipmentSummary = ({ data }) => {
)
const columns = useMemo(
() => [
{
headerName: t(
'finalSupplyEquipment:finalSupplyEquipmentColLabels.organizationName'
),
field: 'organizationName'
},
{
headerName: t(
'finalSupplyEquipment:finalSupplyEquipmentColLabels.supplyFromDate'
Expand Down
38 changes: 37 additions & 1 deletion frontend/src/views/FinalSupplyEquipments/_schema.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import i18n from '@/i18n'
import { actions, validation } from '@/components/BCDataGrid/columns'
import moment from 'moment'
import { CommonArrayRenderer } from '@/utils/grid/cellRenderers'
import { StandardCellErrors } from '@/utils/grid/errorRenderers'
import { StandardCellWarningAndErrors, StandardCellErrors } from '@/utils/grid/errorRenderers'
import { apiRoutes } from '@/constants/routes'
import { numberFormatter } from '@/utils/formatters.js'

Expand Down Expand Up @@ -41,6 +41,42 @@ export const finalSupplyEquipmentColDefs = (
cellDataType: 'text',
hide: true
},
{
field: 'organizationName',
headerComponent: RequiredHeader,
headerName: i18n.t(
'finalSupplyEquipment:finalSupplyEquipmentColLabels.organizationName'
),
cellEditor: AutocompleteCellEditor,
cellRenderer: (params) =>
params.value ||
(!params.value && <Typography variant="body4">Select</Typography>),
cellEditorParams: {
options: optionsData?.organizationNames?.sort() || [],
multiple: false,
disableCloseOnSelect: false,
freeSolo: true,
openOnFocus: true,
},
cellStyle: (params) =>
StandardCellWarningAndErrors(params, errors),
suppressKeyboardEvent,
minWidth: 260,
editable: true,
valueGetter: (params) => {
return params.data?.organizationName || '';
},
valueSetter: (params) => {
if (params.newValue) {
const isValidOrganizationName = optionsData?.organizationNames.includes(params.newValue);

params.data.organizationName = isValidOrganizationName ? params.newValue : params.newValue;
return true;
}
return false;
},
tooltipValueGetter: (params) => "Select the organization name from the list"
},
{
field: 'supplyFrom',
headerName: i18n.t(
Expand Down