Skip to content

Commit

Permalink
Add organization field to FSE
Browse files Browse the repository at this point in the history
  • Loading branch information
areyeslo committed Dec 11, 2024
1 parent a46a998 commit 8b438ff
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Add Organization 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 = '8491890dd688'
branch_labels = None
depends_on = None


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


def downgrade():
# Remove the column 'organization' from 'final_supply_equipment' table
op.drop_column("final_supply_equipment", "organization")
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 = Column(Text, comment="External organization.")

# 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: 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()
organizations = await self.get_organizations(organization)
ports = list(PortsEnum)
return (
intended_use_types,
levels_of_equipment,
fuel_measurement_types,
intended_user_types,
ports
ports,
organizations,
)

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_organizations(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))
.join(ComplianceReport, FinalSupplyEquipment.compliance_report_id == ComplianceReport.compliance_report_id)
.filter(ComplianceReport.organization_id == organization.organization_id)
.filter(FinalSupplyEquipment.organization.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]
organizations: List[str]


class FinalSupplyEquipmentCreateSchema(BaseSchema):
final_supply_equipment_id: Optional[int] = None
compliance_report_id: Optional[int] = None
organization: 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,
organizations
) = 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],
"organizations": organizations,
}

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 = fse_data.organization
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",
"organization": "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.organization'
),
field: 'organization'
},
{
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: 'organization',
headerComponent: RequiredHeader,
headerName: i18n.t(
'finalSupplyEquipment:finalSupplyEquipmentColLabels.organization'
),
cellEditor: AutocompleteCellEditor,
cellRenderer: (params) =>
params.value ||
(!params.value && <Typography variant="body4">Select</Typography>),
cellEditorParams: {
options: optionsData?.organizations?.sort() || [],
multiple: false,
disableCloseOnSelect: false,
freeSolo: true,
openOnFocus: true,
},
cellStyle: (params) =>
StandardCellWarningAndErrors(params, errors),
suppressKeyboardEvent,
minWidth: 260,
editable: true,
valueGetter: (params) => {
return params.data?.organization || '';
},
valueSetter: (params) => {
if (params.newValue) {
const isValidOrganization = optionsData?.organizations.includes(params.newValue);

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

0 comments on commit 8b438ff

Please sign in to comment.