feature/reliability_stat
Cizz22 1 year ago
parent fea0b6d5bd
commit 96707a7fa7

@ -14,6 +14,8 @@ from src.calculation_time_constrains.router import router as calculation_time_co
from src.overhaul_history.router import router as overhaul_history_router
from src.scope_equipment_activity.router import router as scope_equipment_activity_router
from src.overhaul_schedule.router import router as ovehaul_schedule_router
from src.scope_equipment_part.router import router as scope_equipment_part_router
from src.calculation_target_reliability.router import router as calculation_target_reliability
class ErrorMessage(BaseModel):
@ -61,7 +63,11 @@ authenticated_api_router.include_router(
)
authenticated_api_router.include_router(
scope_equipment_activity_router, prefix="/equipment-activities", tags=["overhaul_activities"]
scope_equipment_activity_router, prefix="/equipment-activities", tags=["scope_equipment_activities"]
)
authenticated_api_router.include_router(
scope_equipment_part_router, prefix="/equipment-parts", tags=["scope_equipment_parts"]
)
authenticated_api_router.include_router(
@ -73,9 +79,12 @@ calculation_router = APIRouter(prefix="/calculation", tags=["calculations"])
# Time constrains
calculation_router.include_router(
calculation_time_constrains_router, prefix="/time-constraint", tags=["time_constraint"])
calculation_time_constrains_router, prefix="/time-constraint", tags=["calculation", "time_constraint"])
# Target reliability
calculation_router.include_router(
calculation_target_reliability, prefix="/target-reliability", tags=["calculation", "target_reliability"]
)
# Budget Constrain

@ -0,0 +1,21 @@
from typing import Dict, List, Optional
from fastapi import APIRouter, HTTPException, status
from fastapi.params import Query
from .service import get_all_target_reliability
from src.models import StandardResponse
from src.database.core import DbSession
router = APIRouter()
@router.get("", response_model=StandardResponse[List[Dict]])
async def get_target_reliability(db_session: DbSession, scope_name: Optional[str] = Query(None), eaf_threshold: float = Query(100)):
"""Get all scope pagination."""
results = await get_all_target_reliability(db_session=db_session, scope_name=scope_name, eaf_threshold=eaf_threshold)
return StandardResponse(
data=results,
message="Data retrieved successfully",
)

@ -0,0 +1,71 @@
from datetime import datetime
from typing import Any, Dict, List, Optional
from uuid import UUID
from pydantic import Field, BaseModel
from src.models import DefultBase, Pagination
class OverhaulBase(BaseModel):
pass
class OverhaulCriticalParts(OverhaulBase):
criticalParts: List[str] = Field(..., description="List of critical parts")
class OverhaulSchedules(OverhaulBase):
schedules: List[Dict[str, Any]
] = Field(..., description="List of schedules")
class OverhaulSystemComponents(OverhaulBase):
systemComponents: Dict[str,
Any] = Field(..., description="List of system components")
class OverhaulRead(OverhaulBase):
overview: Dict[str, Any]
criticalParts: List[str]
schedules: List[Dict[str, Any]]
systemComponents: Dict[str, Any]
# {
# "overview": {
# "totalEquipment": 30,
# "nextSchedule": {
# "date": "2025-01-12",
# "Overhaul": "B",
# "equipmentCount": 30
# }
# },
# "criticalParts": [
# "Boiler feed pump",
# "Boiler reheater system",
# "Drum Level (Right) Root Valve A",
# "BCP A Discharge Valve",
# "BFPT A EXH Press HI Root VLV"
# ],
# "schedules": [
# {
# "date": "2025-01-12",
# "Overhaul": "B",
# "status": "upcoming"
# }
# // ... other scheduled overhauls
# ],
# "systemComponents": {
# "boiler": {
# "status": "operational",
# "lastOverhaul": "2024-06-15"
# },
# "turbine": {
# "hpt": { "status": "operational" },
# "ipt": { "status": "operational" },
# "lpt": { "status": "operational" }
# }
# // ... other major components
# }
# }

@ -0,0 +1,63 @@
from sqlalchemy import Select, Delete
from typing import Optional
from src.database.core import DbSession
from src.auth.service import CurrentUser
from src.overhaul_schedule.service import get_all as get_all_schedules
from src.scope.model import Scope
from src.scope_equipment.model import ScopeEquipment
from src.scope_equipment.service import get_by_scope_name
async def get_all_target_reliability(*, db_session: DbSession, scope_name: str, eaf_threshold: float = 100.0):
"""Get all overhaul overview with EAF values that sum to 100%."""
equipments = await get_by_scope_name(db_session=db_session, scope_name=scope_name)
# If no equipments found, return empty list
if not equipments:
return []
import random
n = len(equipments)
base_value = 100 / n # Even distribution as base
# Generate EAF values with ±30% variation from base
eaf_values = [
base_value + random.uniform(-0.3 * base_value, 0.3 * base_value)
for _ in range(n)
]
# Normalize to ensure sum is 100
total = sum(eaf_values)
eaf_values = [(v * 100 / total) for v in eaf_values]
# Create result array of dictionaries
result = [
{
'id': equipment.id,
'assetnum': equipment.assetnum,
'location_tag': equipment.master_equipment.location_tag,
'name' : equipment.master_equipment.name,
'eaf': round(eaf, 4) # Add EAF value
}
for equipment, eaf in zip(equipments, eaf_values)
]
result.sort(key=lambda x: x['eaf'], reverse=True)
# Filter equipment up to threshold
cumulative_eaf = 0
filtered_result = []
for equipment in result:
cumulative_eaf += equipment['eaf']
filtered_result.append(equipment)
if cumulative_eaf >= eaf_threshold:
break
return filtered_result

@ -46,7 +46,19 @@ class ScopeEquipment(Base, DefaultMixin):
class MasterEquipment(Base, DefaultMixin):
__tablename__ = "ms_equipment_master"
parent_id = Column(UUID(as_uuid=True), nullable=True)
assetnum = Column(String, nullable=True)
system_tag = Column(String, nullable=True)
location_tag = Column(String, nullable=True)
name = Column(String, nullable=True)
equipment_tree_id = Column(UUID(as_uuid=True), ForeignKey(
"ms_equipment_tree.id"), nullable=True)
equipment_tree = relationship(
"MasterEquipmentTree", backref="master_equipments")
class MasterEquipmentTree(Base, DefaultMixin):
__tablename__ = "ms_equipment_tree"
level_no = Column(Integer)

@ -4,7 +4,7 @@ from fastapi import HTTPException, status
from sqlalchemy import Select, Delete, desc, func, not_, or_
from sqlalchemy.dialects.postgresql import insert
from src.workorder.model import MasterWorkOrder
from .model import ScopeEquipment, MasterEquipment
from .model import MasterEquipmentTree, ScopeEquipment, MasterEquipment
from src.scope.service import get_by_scope_name as get_scope_by_name_service
from .schema import ScopeEquipmentCreate, ScopeEquipmentUpdate
from typing import Optional, Union
@ -130,7 +130,7 @@ async def get_by_scope_name(*, db_session: DbSession, scope_name: Union[str, lis
"""Returns a document based on the given document id."""
scope = await get_scope_by_name_service(db_session=db_session, scope_name=scope_name)
query = Select(ScopeEquipment)
query = Select(ScopeEquipment).options(selectinload(ScopeEquipment.master_equipment))
if scope:
query = query.filter(ScopeEquipment.current_scope_id == scope.id)
@ -169,3 +169,10 @@ async def get_all_master_equipment(*, db_session: DbSession, exclude: Optional[s
results = await search_filter_sort_paginate(model=query, **common)
return results
async def get_equipment_level_by_no(*, db_session: DbSession, level: int):
query = Select(MasterEquipmentTree).filter(
MasterEquipmentTree.level_no == level)
result = await db_session.scalar(query)
return result

@ -0,0 +1,19 @@
from sqlalchemy import UUID, Column, Float, Integer, String, ForeignKey
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
from sqlalchemy.orm import relationship
from src.workorder.model import MasterWorkOrder
from sqlalchemy.ext.hybrid import hybrid_property
class ScopeEquipmentPart(Base, DefaultMixin):
__tablename__ = "oh_tr_scope_equipment_part"
assetnum = Column(String, nullable=False)
stock = Column(Integer, nullable=False, default=0)
master_equipments = relationship(
"MasterEquipment", lazy="raise", primaryjoin="and_(ScopeEquipmentPart.assetnum == foreign(MasterEquipment.assetnum))", uselist=False)

@ -0,0 +1,25 @@
from fastapi import APIRouter, HTTPException, Query, status
from .service import get_all
from .schema import ScopeEquipmentActivityCreate, ScopeEquipmentActivityPagination, ScopeEquipmentActivityRead, ScopeEquipmentActivityUpdate
from src.models import StandardResponse
from src.database.service import CommonParameters, search_filter_sort_paginate, DbSession
router = APIRouter()
@router.get("/{assetnum}", response_model=StandardResponse[ScopeEquipmentActivityPagination])
async def get_scope_equipment_activities(common: CommonParameters, assetnum):
"""Get all scope activity pagination."""
# return
data = await get_all(common=common, assetnum=assetnum)
raise Exception(data)
return StandardResponse(
data=data,
message="Data retrieved successfully",
)

@ -0,0 +1,69 @@
from datetime import datetime
from typing import Any, Dict, List, Optional
from uuid import UUID
from pydantic import Field, BaseModel
from src.models import DefultBase, Pagination
class ScopeEquipmentActivityBase(DefultBase):
assetnum: str = Field(..., description="Assetnum is required")
class ScopeEquipmentActivityCreate(ScopeEquipmentActivityBase):
name: str
cost: Optional[float] = Field(0)
class ScopeEquipmentActivityUpdate(ScopeEquipmentActivityBase):
name: Optional[str] = Field(None)
cost: Optional[str] = Field(0)
class ScopeEquipmentActivityRead(ScopeEquipmentActivityBase):
name: str
cost: float
class ScopeEquipmentActivityPagination(Pagination):
items: List[ScopeEquipmentActivityRead] = []
# {
# "overview": {
# "totalEquipment": 30,
# "nextSchedule": {
# "date": "2025-01-12",
# "Overhaul": "B",
# "equipmentCount": 30
# }
# },
# "criticalParts": [
# "Boiler feed pump",
# "Boiler reheater system",
# "Drum Level (Right) Root Valve A",
# "BCP A Discharge Valve",
# "BFPT A EXH Press HI Root VLV"
# ],
# "schedules": [
# {
# "date": "2025-01-12",
# "Overhaul": "B",
# "status": "upcoming"
# }
# // ... other scheduled overhauls
# ],
# "systemComponents": {
# "boiler": {
# "status": "operational",
# "lastOverhaul": "2024-06-15"
# },
# "turbine": {
# "hpt": { "status": "operational" },
# "ipt": { "status": "operational" },
# "lpt": { "status": "operational" }
# }
# // ... other major components
# }
# }

@ -0,0 +1,83 @@
from sqlalchemy import Select, Delete, and_
from sqlalchemy.orm import selectinload
from typing import Optional
from src.scope_equipment.model import MasterEquipment, MasterEquipmentTree
from src.scope_equipment.service import get_equipment_level_by_no
from .model import ScopeEquipmentPart
from .schema import ScopeEquipmentActivityCreate, ScopeEquipmentActivityUpdate
from src.database.core import DbSession
from src.database.service import CommonParameters, search_filter_sort_paginate
from src.auth.service import CurrentUser
# async def get(*, db_session: DbSession, scope_equipment_activity_id: str) -> Optional[ScopeEquipmentActivity]:
# """Returns a document based on the given document id."""
# result = await db_session.get(ScopeEquipmentActivity, scope_equipment_activity_id)
# return result
async def get_all(common: CommonParameters, assetnum: Optional[str]):
if not assetnum:
raise ValueError("assetnum parameter is required")
db_session: DbSession = common.get("db_session")
# First get the parent equipment
equipment_stmt = Select(MasterEquipment).where(
MasterEquipment.assetnum == assetnum)
equipment: MasterEquipment = await db_session.scalar(equipment_stmt)
if not equipment:
raise ValueError(f"No equipment found with assetnum: {assetnum}")
# Build query for parts
stmt = (
Select(ScopeEquipmentPart)
.join(ScopeEquipmentPart.master_equipments)
.join(MasterEquipment.equipment_tree)
.where(
and_(
MasterEquipment.parent_id == equipment.id,
MasterEquipmentTree.level_no == 4
)
).options(selectinload(ScopeEquipmentPart.master_equipments))
)
results = await search_filter_sort_paginate(model=stmt, **common)
return results
# async def create(*, db_session: DbSession, scope_equipment_activty_in: ScopeEquipmentActivityCreate):
# activity = ScopeEquipmentActivity(
# **scope_equipment_activty_in.model_dump())
# db_session.add(activity)
# await db_session.commit()
# return activity
# async def update(*, db_session: DbSession, activity: ScopeEquipmentActivity, scope_equipment_activty_in: ScopeEquipmentActivityUpdate):
# """Updates a document."""
# data = scope_equipment_activty_in.model_dump()
# update_data = scope_equipment_activty_in.model_dump(exclude_defaults=True)
# for field in data:
# if field in update_data:
# setattr(activity, field, update_data[field])
# await db_session.commit()
# return activity
# async def delete(*, db_session: DbSession, scope_equipment_activity_id: str):
# """Deletes a document."""
# activity = await db_session.get(ScopeEquipmentActivity, scope_equipment_activity_id)
# await db_session.delete(activity)
# await db_session.commit()
Loading…
Cancel
Save