diff --git a/src/__pycache__/models.cpython-311.pyc b/src/__pycache__/models.cpython-311.pyc index 0fb0d84..ae4da66 100644 Binary files a/src/__pycache__/models.cpython-311.pyc and b/src/__pycache__/models.cpython-311.pyc differ diff --git a/src/equipment/__pycache__/model.cpython-311.pyc b/src/equipment/__pycache__/model.cpython-311.pyc index 88edd9a..d2e34ce 100644 Binary files a/src/equipment/__pycache__/model.cpython-311.pyc and b/src/equipment/__pycache__/model.cpython-311.pyc differ diff --git a/src/equipment/__pycache__/router.cpython-311.pyc b/src/equipment/__pycache__/router.cpython-311.pyc index 5edb900..945ddd1 100644 Binary files a/src/equipment/__pycache__/router.cpython-311.pyc and b/src/equipment/__pycache__/router.cpython-311.pyc differ diff --git a/src/equipment/__pycache__/schema.cpython-311.pyc b/src/equipment/__pycache__/schema.cpython-311.pyc index ea19e43..99ad407 100644 Binary files a/src/equipment/__pycache__/schema.cpython-311.pyc and b/src/equipment/__pycache__/schema.cpython-311.pyc differ diff --git a/src/equipment/__pycache__/service.cpython-311.pyc b/src/equipment/__pycache__/service.cpython-311.pyc index 571348e..2f0dee4 100644 Binary files a/src/equipment/__pycache__/service.cpython-311.pyc and b/src/equipment/__pycache__/service.cpython-311.pyc differ diff --git a/src/equipment/model.py b/src/equipment/model.py index c097349..7b3559f 100644 --- a/src/equipment/model.py +++ b/src/equipment/model.py @@ -1,17 +1,74 @@ - -from sqlalchemy import Column, Float, Integer, String +from sqlalchemy import Column, Float, Integer, String, ForeignKey +from sqlalchemy.orm import relationship from src.database.core import Base from src.models import DefaultMixin, IdentityMixin - class Equipment(Base, DefaultMixin, IdentityMixin): __tablename__ = "lcc_ms_equipment_data" - - equipment_id = Column(String, nullable=False) + + assetnum = Column(String, nullable=False) acquisition_year = Column(Integer, nullable=False) acquisition_cost = Column(Float, nullable=False) capital_cost_record_time = Column(Integer, nullable=False) design_life = Column(Integer, nullable=False) forecasting_target_year = Column(Integer, nullable=False) - manhours_rate = Column(Float, nullable=False) \ No newline at end of file + manhours_rate = Column(Float, nullable=False) + + +class MasterRecords(Base, DefaultMixin, IdentityMixin): + __tablename__ = "lcc_tr_data" + + equipment = relationship( + "Equipment", + backref="maintenance_records", + lazy="raise", + primaryjoin="and_(MasterRecords.assetnum == foreign(Equipment.assetnum))", + viewonly=True, + ) + + # master_equipment = relationship( + # "MasterEquipment", + # lazy="raise", + # primaryjoin="and_(ScopeEquipment.assetnum == foreign(MasterEquipment.assetnum))", + # uselist=False # Add this if it's a one-to-one relationship + # ) + + assetnum = Column(String, nullable=False) + tahun = Column(String, nullable=False) + seq = Column(String, nullable=False) + is_actual = Column(String, nullable=False) + raw_cm_interval = Column(String, nullable=False) + raw_cm_material_cost = Column(String, nullable=False) + raw_cm_labor_time = Column(String, nullable=False) + raw_cm_labor_human = Column(String, nullable=False) + raw_pm_interval = Column(String, nullable=False) + raw_pm_material_cost = Column(String, nullable=False) + raw_pm_labor_time = Column(String, nullable=False) + raw_pm_labor_human = Column(String, nullable=False) + raw_predictive_labor_time = Column(String, nullable=False) + raw_predictive_labor_human = Column(String, nullable=False) + raw_oh_material_cost = Column(String, nullable=False) + raw_oh_labor_time = Column(String, nullable=False) + raw_oh_labor_human = Column(String, nullable=False) + raw_project_task_material_cost = Column(String, nullable=False) + raw_loss_output_MW = Column(String, nullable=False) + raw_loss_output_price = Column(String, nullable=False) + raw_operational_cost = Column(String, nullable=False) + raw_maintenance_cost = Column(String, nullable=False) + rc_cm_material_cost = Column(String, nullable=False) + rc_cm_labor_cost = Column(String, nullable=False) + rc_pm_material_cost = Column(String, nullable=False) + rc_pm_labor_cost = Column(String, nullable=False) + rc_predictive_labor_cost = Column(String, nullable=False) + rc_oh_material_cost = Column(String, nullable=False) + rc_oh_labor_cost = Column(String, nullable=False) + rc_project_material_cost = Column(String, nullable=False) + rc_lost_cost = Column(String, nullable=False) + rc_operation_cost = Column(String, nullable=False) + rc_maintenance_cost = Column(String, nullable=False) + rc_total_cost = Column(String, nullable=False) + eac_npv = Column(String, nullable=False) + eac_annual_mnt_cost = Column(String, nullable=False) + eac_annual_acq_cost = Column(String, nullable=False) + eac_eac = Column(String, nullable=False) diff --git a/src/equipment/router.py b/src/equipment/router.py index 51e56bc..4344069 100644 --- a/src/equipment/router.py +++ b/src/equipment/router.py @@ -1,7 +1,7 @@ - +from typing import List from fastapi import APIRouter, HTTPException, status -from .model import Equipment +from .model import Equipment, MasterRecords from .schema import EquipmentPagination, EquipmentRead, EquipmentCreate, EquipmentUpdate from .service import get, get_all, create, update, delete @@ -29,20 +29,33 @@ async def get_equipment_tree(): pass -@router.get("/{equipment_id}", response_model=StandardResponse[EquipmentRead]) -async def get_equipment(db_session: DbSession, equipment_id: str): - equipment = await get(db_session=db_session, equipment_id=equipment_id) - if not equipment: +@router.get("/{assetnum}", response_model=StandardResponse[EquipmentRead]) +async def get_equipment(db_session: DbSession, assetnum: str): + equipment_data, chart_data, min_eac_value, min_seq = await get( + db_session=db_session, assetnum=assetnum + ) + # raise Exception(equipment[0]) + if not chart_data: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="A data with this id does not exist.", ) - return StandardResponse(data=equipment, message="Data retrieved successfully") + return StandardResponse( + data=EquipmentRead( + equipment_data=equipment_data, + chart_data=chart_data, + min_eac_value=min_eac_value, + min_seq=min_seq, + ), + message="Data retrieved successfully", + ) @router.post("", response_model=StandardResponse[EquipmentRead]) -async def create_equipment(db_session: DbSession, equipment_in: EquipmentCreate, current_user: CurrentUser): +async def create_equipment( + db_session: DbSession, equipment_in: EquipmentCreate, current_user: CurrentUser +): equipment_in.created_by = current_user.name equipment = await create(db_session=db_session, equipment_in=equipment_in) @@ -50,7 +63,12 @@ async def create_equipment(db_session: DbSession, equipment_in: EquipmentCreate, @router.put("/{equipment_id}", response_model=StandardResponse[EquipmentRead]) -async def update_equipment(db_session: DbSession, equipment_id: str, equipment_in: EquipmentUpdate, current_user: CurrentUser): +async def update_equipment( + db_session: DbSession, + equipment_id: str, + equipment_in: EquipmentUpdate, + current_user: CurrentUser, +): equipment = await get(db_session=db_session, equipment_id=equipment_id) if not equipment: @@ -60,7 +78,12 @@ async def update_equipment(db_session: DbSession, equipment_id: str, equipment_i ) equipment_in.updated_by = current_user.name - return StandardResponse(data=await update(db_session=db_session, equipment=equipment, equipment_in=equipment_in), message="Data updated successfully") + return StandardResponse( + data=await update( + db_session=db_session, equipment=equipment, equipment_in=equipment_in + ), + message="Data updated successfully", + ) @router.delete("/{equipment_id}", response_model=StandardResponse[EquipmentRead]) diff --git a/src/equipment/schema.py b/src/equipment/schema.py index 1785b03..0f6705e 100644 --- a/src/equipment/schema.py +++ b/src/equipment/schema.py @@ -3,10 +3,10 @@ from typing import List, Optional from uuid import UUID from pydantic import Field -from src.models import DefultBase, Pagination +from src.models import DefaultBase, Pagination -class EquipmentBase(DefultBase): +class EquipmentBase(DefaultBase): acquisition_year: Optional[int] = Field(None, nullable=True) acquisition_cost: Optional[float] = Field(None, nullable=True) capital_cost_record_time: Optional[int] = Field(None, nullable=True) @@ -19,6 +19,47 @@ class EquipmentBase(DefultBase): updated_by: Optional[str] = Field(None, nullable=True) +class MasterBase(DefaultBase): + assetnum: Optional[str] = Field(None, nullable=True) + tahun: Optional[float] = Field(None, nullable=True) + seq: Optional[float] = Field(None, nullable=True) + is_actual: Optional[float] = Field(None, nullable=True) + raw_cm_interval: Optional[float] = Field(None, nullable=True) + raw_cm_material_cost: Optional[float] = Field(None, nullable=True) + raw_cm_labor_time: Optional[float] = Field(None, nullable=True) + raw_cm_labor_human: Optional[float] = Field(None, nullable=True) + raw_pm_interval: Optional[float] = Field(None, nullable=True) + raw_pm_material_cost: Optional[float] = Field(None, nullable=True) + raw_pm_labor_time: Optional[float] = Field(None, nullable=True) + raw_pm_labor_human: Optional[float] = Field(None, nullable=True) + raw_predictive_labor_time: Optional[float] = Field(None, nullable=True) + raw_predictive_labor_human: Optional[float] = Field(None, nullable=True) + raw_oh_material_cost: Optional[float] = Field(None, nullable=True) + raw_oh_labor_time: Optional[float] = Field(None, nullable=True) + raw_oh_labor_human: Optional[float] = Field(None, nullable=True) + raw_project_task_material_cost: Optional[float] = Field(None, nullable=True) + raw_loss_output_MW: Optional[float] = Field(None, nullable=True) + raw_loss_output_price: Optional[float] = Field(None, nullable=True) + raw_operational_cost: Optional[float] = Field(None, nullable=True) + raw_maintenance_cost: Optional[float] = Field(None, nullable=True) + rc_cm_material_cost: Optional[float] = Field(None, nullable=True) + rc_cm_labor_cost: Optional[float] = Field(None, nullable=True) + rc_pm_material_cost: Optional[float] = Field(None, nullable=True) + rc_pm_labor_cost: Optional[float] = Field(None, nullable=True) + rc_predictive_labor_cost: Optional[float] = Field(None, nullable=True) + rc_oh_material_cost: Optional[float] = Field(None, nullable=True) + rc_oh_labor_cost: Optional[float] = Field(None, nullable=True) + rc_project_material_cost: Optional[float] = Field(None, nullable=True) + rc_lost_cost: Optional[float] = Field(None, nullable=True) + rc_operation_cost: Optional[float] = Field(None, nullable=True) + rc_maintenance_cost: Optional[float] = Field(None, nullable=True) + rc_total_cost: Optional[float] = Field(None, nullable=True) + eac_npv: Optional[float] = Field(None, nullable=True) + eac_annual_mnt_cost: Optional[float] = Field(None, nullable=True) + eac_annual_acq_cost: Optional[float] = Field(None, nullable=True) + eac_eac: Optional[float] = Field(None, nullable=True) + + class EquipmentCreate(EquipmentBase): pass @@ -27,9 +68,11 @@ class EquipmentUpdate(EquipmentBase): pass -class EquipmentRead(EquipmentBase): - id: UUID - equipment_id: str +class EquipmentRead(DefaultBase): + equipment_data: EquipmentBase + chart_data: List[MasterBase] + min_eac_value: Optional[float] = Field(None, nullable=True) + min_seq: Optional[float] = Field(None, nullable=True) class EquipmentPagination(Pagination): diff --git a/src/equipment/service.py b/src/equipment/service.py index 51e7255..5a18acb 100644 --- a/src/equipment/service.py +++ b/src/equipment/service.py @@ -1,5 +1,6 @@ -from sqlalchemy import Select, Delete -from .model import Equipment +from sqlalchemy import Select, Delete, Float, func +from sqlalchemy.orm import selectinload +from .model import Equipment, MasterRecords from .schema import EquipmentCreate, EquipmentUpdate from typing import Optional @@ -7,11 +8,44 @@ from src.database.core import DbSession from src.auth.service import CurrentUser -async def get(*, db_session: DbSession, equipment_id: str) -> Optional[Equipment]: - """Returns a document based on the given document id.""" - query = Select(Equipment).filter(Equipment.equipment_id == equipment_id) - result = await db_session.execute(query) - return result.scalars().one_or_none() +async def get( + *, db_session: DbSession, assetnum: str +) -> tuple[list[MasterRecords], float | None]: + """Returns master records with equipment data based on asset number.""" + + # First query to get equipment record + equipment_query = Select(Equipment).filter(Equipment.assetnum == assetnum) + equipment_result = await db_session.execute(equipment_query) + equipment_record = equipment_result.scalars().one_or_none() + + # Second query to get master records + master_query = ( + Select(MasterRecords) + .join(MasterRecords.equipment) + .options(selectinload(MasterRecords.equipment)) + .filter(Equipment.assetnum == assetnum) + ) + master_result = await db_session.execute(master_query) + records = master_result.scalars().all() + + # Third query specifically for minimum eac_eac + min_query = ( + Select(func.min(func.cast(MasterRecords.eac_eac, Float)), MasterRecords.seq) + .join(MasterRecords.equipment) + .filter(Equipment.assetnum == assetnum) + .group_by(MasterRecords.seq) + .order_by(func.min(func.cast(MasterRecords.eac_eac, Float))) + .limit(1) + ) + min_result = await db_session.execute(min_query) + min_record = min_result.first() + min_eac_value = ( + float(min_record[0]) if min_record and min_record[0] is not None else None + ) + min_seq = min_record[1] if min_record else None + + return equipment_record, records, min_eac_value, min_seq + # return result.scalars().all() async def get_all(*, db_session: DbSession): diff --git a/src/equipment_master/__pycache__/schema.cpython-311.pyc b/src/equipment_master/__pycache__/schema.cpython-311.pyc index fc41607..bdbe183 100644 Binary files a/src/equipment_master/__pycache__/schema.cpython-311.pyc and b/src/equipment_master/__pycache__/schema.cpython-311.pyc differ diff --git a/src/equipment_master/schema.py b/src/equipment_master/schema.py index 6a040f4..2adce2a 100644 --- a/src/equipment_master/schema.py +++ b/src/equipment_master/schema.py @@ -4,10 +4,10 @@ from typing import ForwardRef, List, Optional from uuid import UUID from pydantic import Field -from src.models import DefultBase, Pagination +from src.models import DefaultBase, Pagination -class EquipmentMasterBase(DefultBase): +class EquipmentMasterBase(DefaultBase): parent_id: Optional[UUID] = Field(None, nullable=True) name: Optional[str] = Field(None, nullable=True) created_at: Optional[datetime] = Field(None, nullable=True) diff --git a/src/masterdata/__pycache__/schema.cpython-311.pyc b/src/masterdata/__pycache__/schema.cpython-311.pyc index fce56be..8dcfce4 100644 Binary files a/src/masterdata/__pycache__/schema.cpython-311.pyc and b/src/masterdata/__pycache__/schema.cpython-311.pyc differ diff --git a/src/masterdata/schema.py b/src/masterdata/schema.py index 1540b59..5f8191b 100644 --- a/src/masterdata/schema.py +++ b/src/masterdata/schema.py @@ -3,11 +3,11 @@ from typing import List, Optional from uuid import UUID from pydantic import Field -from src.models import DefultBase, Pagination +from src.models import DefaultBase, Pagination from src.auth.service import CurrentUser -class MasterdataBase(DefultBase): +class MasterdataBase(DefaultBase): # discount_rate: Optional[float] # inflation_rate: Optional[float] # manhours_rate: Optional[float] diff --git a/src/models.py b/src/models.py index ac00e67..69af726 100644 --- a/src/models.py +++ b/src/models.py @@ -62,7 +62,7 @@ class DefaultMixin(TimeStampMixin, UUIDMixin): # Pydantic Models -class DefultBase(BaseModel): +class DefaultBase(BaseModel): class Config: from_attributes = True validate_assignment = True @@ -76,7 +76,7 @@ class DefultBase(BaseModel): } -class Pagination(DefultBase): +class Pagination(DefaultBase): itemsPerPage: int page: int total: int diff --git a/src/yeardata/__pycache__/schema.cpython-311.pyc b/src/yeardata/__pycache__/schema.cpython-311.pyc index 75503c3..bb00edc 100644 Binary files a/src/yeardata/__pycache__/schema.cpython-311.pyc and b/src/yeardata/__pycache__/schema.cpython-311.pyc differ diff --git a/src/yeardata/schema.py b/src/yeardata/schema.py index 3627ac8..371eae8 100644 --- a/src/yeardata/schema.py +++ b/src/yeardata/schema.py @@ -4,10 +4,10 @@ from typing import List, Optional from uuid import UUID from pydantic import Field -from src.models import DefultBase, Pagination +from src.models import DefaultBase, Pagination -class YeardataBase(DefultBase): +class YeardataBase(DefaultBase): year: Optional[int] = Field(None, nullable=True) rp_per_kwh: Optional[float] = Field(None, nullable=True) created_at: Optional[datetime] = Field(None, nullable=True)