fix overhaul equipments

feature/reliability_stat
Cizz22 1 year ago
parent 9204d75de3
commit 93158c0055

@ -7,17 +7,23 @@ from pydantic import BaseModel
from src.auth.service import JWTBearer
from src.scope.router import router as scope_router
from src.scope_equipment.router import router as scope_equipment_router
from src.overhaul.router import router as overhaul_router
from src.calculation_time_constrains.router import router as calculation_time_constrains_router
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
from src.calculation_budget_constrains.router import router as calculation_budget_constraint
# from src.overhaul_scope.router import router as scope_router
# from src.scope_equipment.router import router as scope_equipment_router
# from src.overhaul.router import router as overhaul_router
# from src.calculation_time_constrains.router import router as calculation_time_constrains_router
# from src.overhaul_history.router import router as overhaul_history_router
# from src.overhaul_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
# from src.calculation_budget_constrains.router import router as calculation_budget_constraint
# from src.master_activity.router import router as activity_router
from src.overhaul.router import router as overhaul_router
from src.scope_equipment.router import router as scope_equipment_router
from src.overhaul_scope.router import router as scope_router
from src.overhaul_activity.router import router as overhaul_activity_router
class ErrorMessage(BaseModel):
msg: str
@ -51,49 +57,57 @@ authenticated_api_router.include_router(
overhaul_router, prefix="/overhauls", tags=["overhaul"])
# Scope data
# # Overhaul session data
authenticated_api_router.include_router(
scope_router, prefix="/scopes", tags=["scope"])
scope_router, prefix="/overhaul-session", tags=["overhaul-session"])
authenticated_api_router.include_router(
scope_equipment_router, prefix="/scope-equipments", tags=["scope_equipment"]
)
authenticated_api_router.include_router(
overhaul_history_router, prefix="/overhaul-history", tags=["overhaul_history"]
overhaul_activity_router, prefix="/overhaul-activity", tags=["activity"]
)
authenticated_api_router.include_router(
scope_equipment_activity_router, prefix="/equipment-activities", tags=["scope_equipment_activities"]
)
# authenticated_api_router.include_router(
# overhaul_history_router, prefix="/overhaul-history", tags=["overhaul_history"]
# )
authenticated_api_router.include_router(
scope_equipment_part_router, prefix="/equipment-parts", tags=["scope_equipment_parts"]
)
# authenticated_api_router.include_router(
# scope_equipment_activity_router, prefix="/equipment-activities", tags=["scope_equipment_activities"]
# )
authenticated_api_router.include_router(
ovehaul_schedule_router, prefix="/overhaul-schedules", tags=["overhaul_schedules"]
)
# authenticated_api_router.include_router(
# activity_router, prefix="/activities", tags=["activities"]
# )
# calculation
calculation_router = APIRouter(prefix="/calculation", tags=["calculations"])
# authenticated_api_router.include_router(
# scope_equipment_part_router, prefix="/equipment-parts", tags=["scope_equipment_parts"]
# )
# Time constrains
calculation_router.include_router(
calculation_time_constrains_router, prefix="/time-constraint", tags=["calculation", "time_constraint"])
# authenticated_api_router.include_router(
# ovehaul_schedule_router, prefix="/overhaul-schedules", tags=["overhaul_schedules"]
# )
# Target reliability
calculation_router.include_router(
calculation_target_reliability, prefix="/target-reliability", tags=["calculation", "target_reliability"]
)
# # calculation
# calculation_router = APIRouter(prefix="/calculation", tags=["calculations"])
# Budget Constrain
calculation_router.include_router(
calculation_budget_constraint, prefix="/budget-constraint", tags=["calculation", "budget_constraint"]
)
# # Time constrains
# calculation_router.include_router(
# calculation_time_constrains_router, prefix="/time-constraint", tags=["calculation", "time_constraint"])
authenticated_api_router.include_router(
calculation_router
)
# # Target reliability
# calculation_router.include_router(
# calculation_target_reliability, prefix="/target-reliability", tags=["calculation", "target_reliability"]
# )
# # Budget Constrain
# calculation_router.include_router(
# calculation_budget_constraint, prefix="/budget-constraint", tags=["calculation", "budget_constraint"]
# )
# authenticated_api_router.include_router(
# calculation_router
# )
api_router.include_router(authenticated_api_router)

@ -1,12 +1,12 @@
import random
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
@ -25,7 +25,7 @@ async def get_all_budget_constrains(*, db_session: DbSession, scope_name: str, c
'assetnum': equipment.assetnum,
'location_tag': equipment.master_equipment.location_tag,
'name': equipment.master_equipment.name,
'total_cost': equipment.total_cost
'total_cost': 1000000 + random.randint(10000, 5000000)
}
for equipment in equipments
]
@ -38,9 +38,10 @@ async def get_all_budget_constrains(*, db_session: DbSession, scope_name: str, c
for equipment in result:
cumulative_cost += equipment['total_cost']
filtered_result.append(equipment)
if cumulative_cost >= cost_threshold:
break
filtered_result.append(equipment)
return filtered_result

@ -6,7 +6,6 @@ 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

@ -5,9 +5,8 @@ from sqlalchemy import Select, func, select
from sqlalchemy.orm import joinedload
from src.workorder.model import MasterWorkOrder
from src.scope_equipment.model import ScopeEquipment
from src.scope.model import Scope
from src.database.core import DbSession
from src.scope.service import get_all
from src.overhaul_scope.service import get_all
from .schema import CalculationTimeConstrainsParametersRead, CalculationTimeConstrainsParametersRetrive, CalculationTimeConstrainsParametersCreate
from .service import get_calculation_by_reference_and_parameter, get_calculation_result, get_overhaul_cost_by_time_chart, get_corrective_cost_time_chart, create_param_and_data, get_calculation_data_by_id, create_calculation_result_service, get_avg_cost_by_asset
from src.scope_equipment.service import get_by_assetnum

@ -9,7 +9,7 @@ from src.workorder.model import MasterWorkOrder
from .schema import CalculationTimeConstrainsParametersCreate, CalculationTimeConstrainsRead
from .model import CalculationParam, OverhaulReferenceType, CalculationData, CalculationResult
from fastapi import HTTPException, status
from src.scope.service import get_by_scope_name, get
from src.overhaul_scope.service import get_by_scope_name, get
from src.scope_equipment.service import get_by_assetnum

@ -27,6 +27,7 @@ def common_parameters(
sort_by: List[str] = Query([], alias="sortBy[]"),
descending: List[bool] = Query([], alias="descending[]"),
exclude: List[str] = Query([], alias="exclude[]"),
all: int = Query(0)
# role: QueryStr = Depends(get_current_role),
):
return {
@ -38,13 +39,14 @@ def common_parameters(
"sort_by": sort_by,
"descending": descending,
"current_user": current_user,
"all": bool(all)
# "role": role,
}
CommonParameters = Annotated[
dict[str, int | str | DbSession | QueryStr |
Json | List[str] | List[bool]],
Json | List[str] | List[bool]] | bool,
Depends(common_parameters),
]
@ -90,10 +92,11 @@ async def search_filter_sort_paginate(
descending: List[bool] = None,
current_user: str = None,
exclude: List[str] = None,
all: bool = False
):
"""Common functionality for searching, filtering, sorting, and pagination."""
# try:
## Check if model is Select
# Check if model is Select
if not isinstance(model, Select):
query = Select(model)
else:
@ -104,33 +107,31 @@ async def search_filter_sort_paginate(
query = search(query_str=query_str, query=query,
model=model, sort=sort)
# Get total count
count_query = Select(func.count()).select_from(query.subquery())
total = await db_session.scalar(count_query)
if all:
result = await db_session.execute(query)
items = result.scalars().all()
return {
"items": items,
"itemsPerPage": total,
"page": 1,
"total": total,
"totalPages": 1,
}
query = (
query
.offset((page - 1) * items_per_page)
.limit(items_per_page)
)
result = await db_session.execute(query)
items = result.scalars().all()
# try:
# query, pagination = apply_pagination(
# query=query, page_number=page, page_size=items_per_page)
# except ProgrammingError as e:
# log.debug(e)
# return {
# "items": [],
# "itemsPerPage": items_per_page,
# "page": page,
# "total": 0,
# }
return {
"items": items,
"itemsPerPage": items_per_page,

@ -0,0 +1,28 @@
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 MasterActivity(Base, DefaultMixin):
__tablename__ = "oh_ms_activity"
name = Column(String, nullable=False)
details = relationship(
"MasterActivityDetail",
lazy="raise",
primaryjoin="and_(MasterActivity.id == foreign(MasterActivityDetail.activity_id))",
)
class MasterActivityDetail(Base, DefaultMixin):
__tablename__ = "oh_ms_activity_detail"
name = Column(String, nullable=False)
activity_id = Column(UUID(as_uuid=True))

@ -0,0 +1,71 @@
from fastapi import APIRouter, HTTPException, Query, status
from .service import get_all, create, get, update, delete
from .schema import ActivityMaster, ActivityMasterCreate, ActivityMasterPagination
from src.models import StandardResponse
from src.database.service import CommonParameters, search_filter_sort_paginate, DbSession
router = APIRouter()
@router.get("", response_model=StandardResponse[ActivityMasterPagination])
async def get_activities(common: CommonParameters):
"""Get all scope activity pagination."""
# return
data = await get_all(common=common)
return StandardResponse(
data=data,
message="Data retrieved successfully",
)
@router.post("", response_model=StandardResponse[ActivityMasterCreate])
async def create_activity(db_session: DbSession, activity_in: ActivityMasterCreate):
activity = await create(db_session=db_session, activty_in=activity_in)
return StandardResponse(data=activity, message="Data created successfully")
@router.get("/{scope_equipment_activity_id}", response_model=StandardResponse[ActivityMaster])
async def get_activity(db_session: DbSession, activity_id: str):
activity = await get(db_session=db_session, activity_id=activity_id)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=activity, message="Data retrieved successfully")
@router.put("/{scope_equipment_activity_id}", response_model=StandardResponse[ActivityMaster])
async def update_scope(db_session: DbSession, activity_in: ActivityMasterCreate, activity_id):
activity = await get(db_session=db_session, activity_id=activity_id)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=await update(db_session=db_session, activity=activity, activity_in=activity_in), message="Data updated successfully")
@router.delete("/{scope_equipment_activity_id}", response_model=StandardResponse[ActivityMaster])
async def delete_scope(db_session: DbSession, activity_id: str):
activity = await get(db_session=db_session, activity_id=activity_id)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=[{"msg": "A data with this id does not exist."}],
)
await delete(db_session=db_session, activity_id=activity_id)
return StandardResponse(message="Data deleted successfully", data=activity)

@ -7,28 +7,25 @@ from pydantic import Field, BaseModel
from src.models import DefultBase, Pagination
class ScopeEquipmentActivityBase(DefultBase):
assetnum: str = Field(..., description="Assetnum is required")
class ActivityMaster(DefultBase):
name: str
class ScopeEquipmentActivityCreate(ScopeEquipmentActivityBase):
class ActivityMasterDetail(DefultBase):
name: str
cost: Optional[float] = Field(0)
class ScopeEquipmentActivityUpdate(ScopeEquipmentActivityBase):
name: Optional[str] = Field(None)
cost: Optional[float] = Field(0)
class ActivityMasterCreate(ActivityMaster):
pass
class ScopeEquipmentActivityRead(ScopeEquipmentActivityBase):
class ActivityMasterRead(ActivityMaster):
id: UUID
name: str
cost: float
details: List[ActivityMasterDetail] = []
class ScopeEquipmentActivityPagination(Pagination):
items: List[ScopeEquipmentActivityRead] = []
class ActivityMasterPagination(Pagination):
items: List[ActivityMasterRead] = []
# {

@ -0,0 +1,57 @@
from sqlalchemy import Select, Delete
from sqlalchemy.orm import joinedload, selectinload
from typing import Optional
from .model import MasterActivity, MasterActivityDetail
from .schema import ActivityMaster, ActivityMasterCreate
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, activity_id: str) -> Optional[ActivityMaster]:
"""Returns a document based on the given document id."""
result = await db_session.get(MasterActivity, activity_id)
return result
async def get_all(common: CommonParameters):
query = Select(MasterActivity).options(
selectinload(MasterActivity.details))
results = await search_filter_sort_paginate(model=query, **common)
return results
async def create(*, db_session: DbSession, activty_in: ActivityMasterCreate):
activity = MasterActivity(
**activty_in.model_dump())
db_session.add(activity)
await db_session.commit()
return activity
async def update(*, db_session: DbSession, activity: MasterActivity, activity_in: ActivityMasterCreate):
"""Updates a document."""
data = activity_in.model_dump()
update_data = activity_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, activity_id: str):
"""Deletes a document."""
activity = await db_session.get(MasterActivity, activity_id)
await db_session.delete(activity)
await db_session.commit()

@ -1,7 +1,9 @@
from typing import List
from fastapi import APIRouter, HTTPException, status
from src.overhaul.service import get_overhaul_critical_parts, get_overhaul_overview, get_overhaul_schedules, get_overhaul_system_components
from src.overhaul_scope.schema import ScopeRead
from .schema import OverhaulRead, OverhaulSchedules, OverhaulCriticalParts, OverhaulSystemComponents
@ -29,12 +31,12 @@ async def get_overhaul(db_session: DbSession):
)
@router.get("/schedules", response_model=StandardResponse[OverhaulSchedules])
@router.get("/schedules", response_model=StandardResponse[List[ScopeRead]])
async def get_schedules():
"""Get all overhaul schedules."""
schedules = get_overhaul_schedules()
return StandardResponse(
data=OverhaulSchedules(schedules=schedules),
data=schedules,
message="Data retrieved successfully",
)

@ -5,7 +5,7 @@ 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.overhaul_scope.service import get_all as get_all_session
def get_overhaul_overview():
@ -35,7 +35,7 @@ def get_overhaul_critical_parts():
async def get_overhaul_schedules(*, db_session: DbSession):
"""Get all overhaul schedules."""
schedules = await get_all_schedules(db_session=db_session)
schedules = await get_all_session(db_session=db_session)
return schedules

@ -0,0 +1,31 @@
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 OverhaulActivity(Base, DefaultMixin):
__tablename__ = "oh_tr_overhaul_activity"
assetnum = Column(String, nullable=True)
overhaul_scope_id = Column(UUID(as_uuid=True), ForeignKey(
"oh_ms_overhaul_scope.id"), nullable=False)
material_cost = Column(Float, nullable=False, default=0)
service_cost = Column(Float, nullable=False, default=0)
status = Column(String, nullable=False, default="pending")
equipment = relationship(
"MasterEquipment",
lazy="raise",
primaryjoin="and_(OverhaulActivity.assetnum == foreign(MasterEquipment.assetnum))",
uselist=False # Add this if it's a one-to-one relationship
)
overhaul_scope = relationship(
"OverhaulScope",
lazy="raise",
)

@ -0,0 +1,73 @@
from typing import Optional
from uuid import UUID
from fastapi import APIRouter, HTTPException, Query, status
from .service import get_all, create, get, update, delete
from .schema import OverhaulActivityCreate, OverhaulActivityPagination, OverhaulActivityRead, OverhaulActivityUpdate
from src.models import StandardResponse
from src.database.service import CommonParameters, search_filter_sort_paginate, DbSession
router = APIRouter()
@router.get("/{overhaul_session}", response_model=StandardResponse[OverhaulActivityPagination])
async def get_scope_equipments(common: CommonParameters, overhaul_session: str, assetnum: Optional[str] = Query(None), scope_name: Optional[str] = Query(None)):
"""Get all scope activity pagination."""
# return
data = await get_all(common=common, assetnum=assetnum, scope_name=scope_name, overhaul_session_id=overhaul_session)
return StandardResponse(
data=data,
message="Data retrieved successfully",
)
@ router.post("/{overhaul_session}", response_model=StandardResponse[OverhaulActivityRead])
async def create_overhaul_equipment(db_session: DbSession, overhaul_activty_in: OverhaulActivityCreate, overhaul_session: str):
activity = await create(db_session=db_session, overhaul_activty_in=overhaul_activty_in, overhaul_session_id=overhaul_session)
return StandardResponse(data=activity, message="Data created successfully")
@ router.get("/{overhaul_session}/{assetnum}", response_model=StandardResponse[OverhaulActivityRead])
async def get_overhaul_equipment(db_session: DbSession, assetnum: str, overhaul_session):
equipment = await get(db_session=db_session, assetnum=assetnum, overhaul_session_id=overhaul_session)
if not equipment:
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")
@ router.put("/{overhaul_session}/{assetnum}", response_model=StandardResponse[OverhaulActivityRead])
async def update_scope(db_session: DbSession, scope_equipment_activity_in: OverhaulActivityUpdate, assetnum: str):
activity = await get(db_session=db_session, assetnum=assetnum)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=await update(db_session=db_session, activity=activity, scope_equipment_activity_in=scope_equipment_activity_in), message="Data updated successfully")
@ router.delete("/{overhaul_session}/{assetnum}", response_model=StandardResponse[OverhaulActivityRead])
async def delete_scope(db_session: DbSession, assetnum: str):
activity = await get(db_session=db_session, assetnum=assetnum)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=[{"msg": "A data with this id does not exist."}],
)
await delete(db_session=db_session, assetnum=assetnum)
return StandardResponse(message="Data deleted successfully", data=activity)

@ -0,0 +1,35 @@
from datetime import datetime
from typing import Any, Dict, List, Optional
from uuid import UUID
from pydantic import Field, BaseModel
from src.master_activity.schema import ActivityMaster
from src.models import DefultBase, Pagination
from src.scope_equipment.schema import MasterEquipmentRead
class OverhaulActivityBase(DefultBase):
assetnum: str = Field(..., description="Assetnum is required")
class OverhaulActivityCreate(OverhaulActivityBase):
material_cost: Optional[float] = Field(0)
service_cost: Optional[float] = Field(0)
class OverhaulActivityUpdate(OverhaulActivityBase):
material_cost: Optional[float] = Field(0)
service_cost: Optional[float] = Field(0)
class OverhaulActivityRead(OverhaulActivityBase):
id: UUID
material_cost: Optional[float] = Field(0)
service_cost: Optional[float] = Field(0)
status: str
equipment: MasterEquipmentRead
class OverhaulActivityPagination(Pagination):
items: List[OverhaulActivityRead] = []

@ -0,0 +1,101 @@
from uuid import UUID
from sqlalchemy import Select, Delete
from sqlalchemy.orm import joinedload
from typing import List, Optional
from src.scope_equipment.model import ScopeEquipment
from .model import OverhaulActivity
from .schema import OverhaulActivityCreate, OverhaulActivityUpdate, OverhaulActivityRead
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, assetnum: str, overhaul_session_id: Optional[UUID] = None) -> Optional[OverhaulActivityRead]:
"""Returns a document based on the given document id."""
query = Select(OverhaulActivity).where(
OverhaulActivity.assetnum == assetnum).options(joinedload(OverhaulActivity.equipment))
if overhaul_session_id:
query = query.filter(
OverhaulActivity.overhaul_scope_id == overhaul_session_id)
result = await db_session.execute(query)
return result.scalar()
async def get_all(*, common: CommonParameters, overhaul_session_id: UUID, assetnum: Optional[str] = None, scope_name: Optional[str] = None):
query = Select(OverhaulActivity).where(
OverhaulActivity.overhaul_scope_id == overhaul_session_id).options(joinedload(OverhaulActivity.equipment))
if assetnum:
query = query.filter(OverhaulActivity.assetnum == assetnum).options(
joinedload(OverhaulActivity.overhaul_scope))
if scope_name:
query = query.filter(OverhaulActivity.assetnum == assetnum).options(
joinedload(OverhaulActivity.overhaul_scope))
results = await search_filter_sort_paginate(model=query, **common)
return results
async def create(*, db_session: DbSession, overhaul_activty_in: OverhaulActivityCreate, overhaul_session_id: UUID):
# Check if the combination of assetnum and activity_id already exists
existing_equipment_query = (
Select(OverhaulActivity)
.where(
OverhaulActivity.assetnum == overhaul_activty_in.assetnum,
OverhaulActivity.overhaul_scope_id == overhaul_session_id
)
)
result = await db_session.execute(existing_equipment_query)
existing_activity = result.scalar_one_or_none()
# If the combination exists, raise an exception or return the existing activity
if existing_activity:
raise ValueError("This assetnum already exist.")
activity = OverhaulActivity(
**overhaul_activty_in.model_dump(),
overhaul_scope_id=overhaul_session_id)
db_session.add(activity)
await db_session.commit()
# Refresh and load relationships using joinedload
query = (
Select(OverhaulActivity)
.options(joinedload(OverhaulActivity.equipment))
.where(OverhaulActivity.id == activity.id)
)
result = await db_session.execute(query)
activity_with_relationship = result.scalar_one()
return activity_with_relationship
async def update(*, db_session: DbSession, activity: OverhaulActivity, overhaul_activity_in: OverhaulActivityUpdate):
"""Updates a document."""
data = overhaul_activity_in.model_dump()
update_data = overhaul_activity_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, overhaul_activity_id: str):
"""Deletes a document."""
activity = await db_session.get(OverhaulActivity, overhaul_activity_id)
await db_session.delete(activity)
await db_session.commit()

@ -1,9 +0,0 @@
from src.enums import OptimumOHEnum
class OverhaulStatus(OptimumOHEnum):
PLANNED = "PLANNED"
IN_PROGRESS = "IN_PROGRESS"
COMPLETED = "COMPLETED"
DELAYED = "DELAYED"
CANCELLED = "CANCELLED"
ON_HOLD = "ON_HOLD"

@ -1,35 +0,0 @@
from sqlalchemy import UUID, Column, DateTime, Float, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from src.database.core import Base
from src.models import DefaultMixin
from .enums import OverhaulStatus
class OverhaulHistory(Base, DefaultMixin):
__tablename__ = "oh_tr_overhaul_history"
scope_id = Column(UUID(as_uuid=True), ForeignKey(
"oh_scope.id"), nullable=True)
schedule_start_date = Column(DateTime(timezone=True))
schedule_end_date = Column(DateTime(timezone=True))
total_cost = Column(Float, nullable=False, default=0)
status = Column(String, nullable=False, default=OverhaulStatus.PLANNED)
maximo_id = Column(String, nullable=True,
comment="Id From MAXIMO regarding overhaul schedule")
equipments = relationship("OverhaulHistoryEquip",
back_populates="overhaul_history",
cascade="all, delete-orphan")
class OverhaulHistoryEquip(Base, DefaultMixin):
__tablename__ = "oh_tr_overhaul_history_equip"
assetnum = Column(String(10), nullable=False)
overhaul_history_id = Column(
UUID(as_uuid=True), ForeignKey("oh_tr_overhaul_history.id"), nullable=False)
# Relationship to OverhaulHistory
overhaul_history = relationship("OverhaulHistory",
back_populates="equipments")

@ -1,52 +0,0 @@
from fastapi import APIRouter, HTTPException, status
from src.maximo.service import MaximoService
from .model import OverhaulHistory
from .schema import OverhaulHistoryCreate, OverhaulHistoryRead, OverhaulHistoryUpdate, OverhaulHistoryPagination
from .service import get, get_all, start_overhaul
from src.database.service import CommonParameters, search_filter_sort_paginate
from src.database.core import DbSession
from src.auth.service import CurrentUser
from src.models import StandardResponse
router = APIRouter()
@router.get("", response_model=StandardResponse[OverhaulHistoryPagination])
async def get_histories(common: CommonParameters):
"""Get all scope pagination."""
# return
return StandardResponse(
data=await search_filter_sort_paginate(model=OverhaulHistory, **common),
message="Data retrieved successfully",
)
@router.get("/{overhaul_history_id}", response_model=StandardResponse[OverhaulHistoryRead])
async def get_history(db_session: DbSession, overhaul_history_id: str):
overhaul_history = await get(db_session=db_session, overhaul_history_id=overhaul_history_id)
if not overhaul_history:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=overhaul_history, message="Data retrieved successfully")
@router.post("", response_model=StandardResponse[OverhaulHistoryRead])
async def create_history(db_session: DbSession, scope_in: OverhaulHistoryCreate):
try:
maximo_service = MaximoService()
maximo_data = await maximo_service.get_recent_overhaul()
overhaul = await start_overhaul(db_session=db_session, maximo_data=maximo_data)
except HTTPException as he:
raise he
return StandardResponse(data=overhaul, message="Data created successfully")

@ -1,33 +0,0 @@
from datetime import datetime
from typing import List, Optional
from uuid import UUID
from pydantic import Field
from src.models import DefultBase, Pagination
from src.scope.schema import ScopeRead
class OverhaulHistoryBase(DefultBase):
pass
class OverhaulHistoryCreate(OverhaulHistoryBase):
pass
class OverhaulHistoryUpdate(OverhaulHistoryBase):
pass
class OverhaulHistoryRead(OverhaulHistoryBase):
id: UUID
scope_id: UUID
schedule_start_date: datetime
schedule_end_date: Optional[datetime]
total_cost: Optional[float] = Field(0)
maximo_id: Optional[str]
class OverhaulHistoryPagination(Pagination):
items: List[OverhaulHistoryRead] = []

@ -1,81 +0,0 @@
from fastapi import HTTPException
from sqlalchemy import Select, Delete, and_
from src.maximo.service import MaximoDataMapper
from src.overhaul_history.enums import OverhaulStatus
from src.overhaul_history.utils import determine_overhaul_status
from .model import OverhaulHistory, OverhaulHistoryEquip
from .schema import OverhaulHistoryRead, OverhaulHistoryCreate
from typing import Optional
from src.database.core import DbSession
from src.auth.service import CurrentUser
from src.scope.service import get_by_scope_name
from src.scope_equipment.service import get_by_scope_name as scope_equipment_by_scope_name
async def get(*, db_session: DbSession, overhaul_history_id: str) -> Optional[OverhaulHistory]:
"""Returns a document based on the given document id."""
result = await db_session.get(OverhaulHistory, overhaul_history_id)
return result.scalars().one_or_none()
async def get_all(*, db_session: DbSession):
"""Returns all documents."""
query = Select(OverhaulHistory)
result = await db_session.execute(query)
return result.scalars().all()
async def start_overhaul(*, db_session: DbSession, maximo_data: dict):
mapper = MaximoDataMapper(maximo_data)
maximo_id = mapper.get_maximo_id()
# Check for existing overhaul
existing_overhaul = Select(OverhaulHistory).filter(
and_(
OverhaulHistory.maximo_id == maximo_id,
OverhaulHistory.status == OverhaulStatus.IN_PROGRESS
)
)
res = await db_session.execute(existing_overhaul)
if res.first():
raise HTTPException(
status_code=409,
detail=f"Overhaul with MAXIMO ID {maximo_id} already started"
)
status, status_reason = await determine_overhaul_status(maximo_data)
scope = await get_by_scope_name(db_session=db_session, scope_name=mapper.get_scope_name())
overhaul = OverhaulHistory(
scope_id=scope.id,
schedule_start_date=mapper.get_start_date(),
schedule_end_date=mapper.get_end_date(),
total_cost=mapper.get_total_cost(),
maximo_id=maximo_id,
status=status
)
# Get equipment list asynchronously
scope_equipment = await scope_equipment_by_scope_name(
db_session=db_session,
scope_name="A"
)
# Create equipment instances
equipments = [OverhaulHistoryEquip(assetnum=eq.assetnum)
for eq in scope_equipment]
# Assign equipment to overhaul
overhaul.equipments = equipments
# Get All Equipment
db_session.add(overhaul)
await db_session.commit()
await db_session.refresh(overhaul)
return overhaul

@ -1,20 +0,0 @@
from typing import Any, Dict, Optional
from .enums import OverhaulStatus
from src.maximo.service import MaximoDataMapper
async def determine_overhaul_status(maximo_data: Dict[Any, Any]) -> tuple[str, Optional[str]]:
"""Map MAXIMO status to our status enum"""
mapper = MaximoDataMapper(maximo_data)
maximo_status = mapper.get_status()
# TODO: Update these mappings based on actual MAXIMO status values
status_mapping = {
'COMP': OverhaulStatus.COMPLETED,
'INPRG': OverhaulStatus.IN_PROGRESS,
'PLAN': OverhaulStatus.PLANNED,
'HOLD': OverhaulStatus.ON_HOLD,
# Add other status mappings based on actual MAXIMO statuses
}
return status_mapping.get(maximo_status, OverhaulStatus.PLANNED), None

@ -1,16 +0,0 @@
from sqlalchemy import UUID, Column, DateTime, Float, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from src.database.core import Base
from src.models import DefaultMixin
class OverhaulSchedule(Base, DefaultMixin):
__tablename__ = "oh_tr_overhaul_schedule"
scope_id = Column(UUID(as_uuid=True), ForeignKey(
"oh_scope.id"), nullable=True)
start_date = Column(DateTime(timezone=True))
end_date = Column(DateTime(timezone=True))
scope = relationship("Scope", backref="overhaul_schedules", lazy="raise")

@ -1,37 +0,0 @@
from typing import List
from fastapi import APIRouter, HTTPException, status
from src.maximo.service import MaximoService
from .schema import OverhaulScheduleCreate, OverhaulScheduleRead
from .service import get, get_all, create
from src.database.service import CommonParameters, search_filter_sort_paginate
from src.database.core import DbSession
from src.auth.service import CurrentUser
from src.models import StandardResponse
router = APIRouter()
@router.get("", response_model=StandardResponse[List[OverhaulScheduleRead]])
async def get_schedules(db_session: DbSession):
"""Get all scope pagination."""
schedules = await get_all(db_session=db_session)
# return
return StandardResponse(
data=schedules,
message="Data retrieved successfully",
)
@router.post("", response_model=StandardResponse[OverhaulScheduleRead])
async def create_schedule(db_session: DbSession, overhaul_schedule_in: OverhaulScheduleCreate):
schedule = await create(db_session=db_session, overhaul_schedule_in=overhaul_schedule_in)
# raise Exception(schedule.scope)
return StandardResponse(data=schedule, message="Data created successfully")

@ -1,33 +0,0 @@
from datetime import datetime
from typing import List, Optional, Union
from uuid import UUID
from pydantic import Field
from src.models import DefultBase, Pagination
from src.scope.schema import ScopeRead
class OverhaulScheduleBase(DefultBase):
pass
class OverhaulScheduleCreate(OverhaulScheduleBase):
scope_id: Union[UUID, str]
start_date: datetime
end_date: Optional[datetime] = Field(None)
class OverhaulScheduleUpdate(OverhaulScheduleBase):
pass
class OverhaulScheduleRead(OverhaulScheduleBase):
id: UUID
scope: Optional[ScopeRead] = Field(None)
start_date: datetime
end_date: Optional[datetime]
class OverhaulSchedulePagination(Pagination):
items: List[OverhaulScheduleRead] = []

@ -1,68 +0,0 @@
from fastapi import HTTPException
from sqlalchemy import Select, Delete, and_
from sqlalchemy.orm import selectinload
from .model import OverhaulSchedule
from .schema import OverhaulScheduleCreate, OverhaulScheduleUpdate
from typing import Optional
from src.database.core import DbSession
from src.scope.service import get_by_scope_name
async def get(*, db_session: DbSession, overhaul_history_id: str) -> Optional[OverhaulSchedule]:
"""Returns a document based on the given document id."""
result = await db_session.get(OverhaulSchedule, overhaul_history_id)
return result.scalars().one_or_none()
async def get_all(*, db_session: DbSession):
"""Returns all documents."""
query = Select(OverhaulSchedule).options(
selectinload(OverhaulSchedule.scope))
result = await db_session.execute(query)
return result.scalars().all()
async def create(*, db_session: DbSession, overhaul_schedule_in: OverhaulScheduleCreate):
"""Creates a new document."""
scope = await get_by_scope_name(db_session=db_session, scope_name=overhaul_schedule_in.scope_id)
if not scope:
raise HTTPException(
status_code=404,
detail="Not Found"
)
overhaul_schedule_in.scope_id = scope.id
overhaul_schedule = OverhaulSchedule(**overhaul_schedule_in.model_dump())
db_session.add(overhaul_schedule)
await db_session.commit()
results = Select(OverhaulSchedule).options(selectinload(OverhaulSchedule.scope)).filter(OverhaulSchedule.id == overhaul_schedule.id)
return await db_session.scalar(results)
async def update(*, db_session: DbSession, overhaul_schedule: OverhaulSchedule, overhaul_schedule_in: OverhaulScheduleUpdate):
"""Updates a document."""
data = overhaul_schedule_in.model_dump()
update_data = overhaul_schedule_in.model_dump(exclude_defaults=True)
for field in data:
if field in update_data:
setattr(overhaul_schedule, field, update_data[field])
await db_session.commit()
return overhaul_schedule
async def delete(*, db_session: DbSession, overhaul_schedule_id: str):
"""Deletes a document."""
query = Delete(OverhaulSchedule).where(
overhaul_schedule_id == overhaul_schedule_id)
await db_session.execute(query)
await db_session.commit()

@ -0,0 +1,17 @@
from sqlalchemy import Column, DateTime, Float, Integer, String
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
class OverhaulScope(Base, DefaultMixin):
__tablename__ = "oh_ms_overhaul_scope"
type = Column(String, nullable=True)
start_date = Column(DateTime(timezone=True))
end_date = Column(DateTime(timezone=True))
duration_oh = Column(Integer, nullable=True)
crew_number = Column(Integer, nullable=True, default=1)
status = Column(String, nullable=False, default="upcoming")

@ -1,7 +1,8 @@
from typing import Optional
from fastapi import APIRouter, HTTPException, status
from .model import Scope
from .model import OverhaulScope
from .schema import ScopeCreate, ScopeRead, ScopeUpdate, ScopePagination
from .service import get, get_all, create, update, delete
@ -14,18 +15,20 @@ router = APIRouter()
@router.get("", response_model=StandardResponse[ScopePagination])
async def get_scopes(common: CommonParameters):
async def get_scopes(common: CommonParameters, scope_name: Optional[str] = None):
"""Get all scope pagination."""
# return
results = await get_all(common=common, scope_name=scope_name)
return StandardResponse(
data=await search_filter_sort_paginate(model=Scope, **common),
data=results,
message="Data retrieved successfully",
)
@router.get("/{scope_id}", response_model=StandardResponse[ScopeRead])
async def get_scope(db_session: DbSession, scope_id: str):
scope = await get(db_session=db_session, scope_id=scope_id)
@router.get("/{overhaul_session_id}", response_model=StandardResponse[ScopeRead])
async def get_scope(db_session: DbSession, overhaul_session_id: str):
scope = await get(db_session=db_session, overhaul_session_id=overhaul_session_id)
if not scope:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,

@ -8,13 +8,15 @@ from src.models import DefultBase, Pagination
class ScopeBase(DefultBase):
scope_name: Optional[str] = Field(None, title="Scope Name")
duration_oh: Optional[int] = Field(None, title="Duration OH")
crew: Optional[int] = Field(None, title="Crew")
crew_number: Optional[int] = Field(1, title="Crew")
status: Optional[str] = Field("Upcoming")
type: str
class ScopeCreate(ScopeBase):
pass
start_date: datetime
end_date: Optional[datetime] = Field(None)
class ScopeUpdate(ScopeBase):
@ -23,6 +25,8 @@ class ScopeUpdate(ScopeBase):
class ScopeRead(ScopeBase):
id: UUID
start_date: datetime
end_date: Optional[datetime]
class ScopePagination(Pagination):

@ -0,0 +1,93 @@
from sqlalchemy import Select, Delete
from src.database.service import search_filter_sort_paginate
from src.overhaul_activity.model import OverhaulActivity
from src.scope_equipment.service import get_by_scope_name
from .model import OverhaulScope
from .schema import ScopeCreate, ScopeUpdate
from typing import Optional
from src.database.core import DbSession
from src.auth.service import CurrentUser
async def get(*, db_session: DbSession, overhaul_session_id: str) -> Optional[OverhaulScope]:
"""Returns a document based on the given document id."""
query = Select(OverhaulScope).filter(
OverhaulScope.id == overhaul_session_id)
result = await db_session.execute(query)
return result.scalars().one_or_none()
async def get_all(*, common, scope_name: Optional[str] = None):
"""Returns all documents."""
query = Select(OverhaulScope)
if scope_name:
query = query.filter(OverhaulScope.type == scope_name)
results = await search_filter_sort_paginate(model=query, **common)
return results
async def create(*, db_session: DbSession, scope_in: ScopeCreate):
"""Creates a new document."""
overhaul_session = OverhaulScope(**scope_in.model_dump())
db_session.add(overhaul_session)
# Need to flush to get the id
await db_session.flush()
scope_name = scope_in.type
# Fix the function call - parameters were in wrong order
equipments = await get_by_scope_name(
db_session=db_session,
scope_name=scope_name
)
scope_equipments = [
OverhaulActivity(
assetnum=equipment.assetnum,
overhaul_scope_id=overhaul_session.id,
material_cost=100000,
service_cost=100000,
)
for equipment in equipments
]
if scope_equipments: # Only add if there are items
db_session.add_all(scope_equipments)
await db_session.commit()
return overhaul_session
async def update(*, db_session: DbSession, scope: OverhaulScope, scope_in: ScopeUpdate):
"""Updates a document."""
data = scope_in.model_dump()
update_data = scope_in.model_dump(exclude_defaults=True)
for field in data:
if field in update_data:
setattr(scope, field, update_data[field])
await db_session.commit()
return scope
async def delete(*, db_session: DbSession, scope_id: str):
"""Deletes a document."""
query = Delete(OverhaulScope).where(OverhaulScope.id == scope_id)
await db_session.execute(query)
await db_session.commit()
# async def get_by_scope_name(*, db_session: DbSession, scope_name: str) -> Optional[OverhaulScope]:
# """Returns a document based on the given document id."""
# query = Select(OverhaulScope).filter(OverhaulScope.tyoe == scope_name)
# result = await db_session.execute(query)
# return result.scalars().one_or_none()

@ -1,12 +0,0 @@
from sqlalchemy import Column, Float, Integer, String
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
class Scope(Base, DefaultMixin):
__tablename__ = "oh_scope"
scope_name = Column(String, nullable=True)
duration_oh = Column(Integer, nullable=True)
crew = Column(Integer, nullable=True)

@ -1,60 +0,0 @@
from sqlalchemy import Select, Delete
from .model import Scope
from .schema import ScopeCreate, ScopeUpdate
from typing import Optional
from src.database.core import DbSession
from src.auth.service import CurrentUser
async def get(*, db_session: DbSession, scope_id: str) -> Optional[Scope]:
"""Returns a document based on the given document id."""
query = Select(Scope).filter(Scope.id == scope_id)
result = await db_session.execute(query)
return result.scalars().one_or_none()
async def get_all(*, db_session: DbSession):
"""Returns all documents."""
query = Select(Scope)
result = await db_session.execute(query)
return result.scalars().all()
async def create(*, db_session: DbSession, scope_in: ScopeCreate):
"""Creates a new document."""
scope = Scope(**scope_in.model_dump())
db_session.add(scope)
await db_session.commit()
return scope
async def update(*, db_session: DbSession, scope: Scope, scope_in: ScopeUpdate):
"""Updates a document."""
data = scope_in.model_dump()
update_data = scope_in.model_dump(exclude_defaults=True)
for field in data:
if field in update_data:
setattr(scope, field, update_data[field])
await db_session.commit()
return scope
async def delete(*, db_session: DbSession, scope_id: str):
"""Deletes a document."""
query = Delete(Scope).where(Scope.id == scope_id)
await db_session.execute(query)
await db_session.commit()
async def get_by_scope_name(*, db_session: DbSession, scope_name: str) -> Optional[Scope]:
"""Returns a document based on the given document id."""
query = Select(Scope).filter(Scope.scope_name == scope_name)
result = await db_session.execute(query)
return result.scalars().one_or_none()

@ -0,0 +1,8 @@
from src.enums import OptimumOHEnum
class ScopeEquipmentType(OptimumOHEnum):
TEMP = "Temporary"
PERM = "Permanent"

@ -1,5 +1,5 @@
from sqlalchemy import UUID, Column, Float, Integer, String, ForeignKey
from sqlalchemy import UUID, Column, Date, Float, Integer, String, ForeignKey
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
from sqlalchemy.orm import relationship
@ -8,26 +8,13 @@ from sqlalchemy.ext.hybrid import hybrid_property
class ScopeEquipment(Base, DefaultMixin):
__tablename__ = "oh_scope_equip"
__tablename__ = "oh_ms_scope_equipment"
assetnum = Column(String, nullable=True)
scope_id = Column(UUID(as_uuid=True), ForeignKey(
'oh_scope.id'), nullable=True)
current_scope_id = Column(UUID(as_uuid=True), ForeignKey(
'oh_scope.id'), nullable=False)
parent_scope = relationship(
"Scope",
foreign_keys=[scope_id],
backref="equipments",
lazy="raise"
)
current_scope = relationship(
"Scope",
foreign_keys=[current_scope_id],
backref="overhaul_equipments",
lazy="raise"
)
scope_overhaul = Column(String, nullable=False)
type = Column(String, nullable=False, default="Permanent")
removal_date = Column(Date, nullable=True)
assigned_date = Column(Date, nullable=True)
master_equipment = relationship(
"MasterEquipment",
@ -35,12 +22,6 @@ class ScopeEquipment(Base, DefaultMixin):
primaryjoin="and_(ScopeEquipment.assetnum == foreign(MasterEquipment.assetnum))",
uselist=False # Add this if it's a one-to-one relationship
)
work_orders = relationship("MasterWorkOrder", lazy="selectin",
primaryjoin="and_(ScopeEquipment.assetnum == foreign(MasterWorkOrder.assetnum))")
@ hybrid_property
def total_cost(self):
return sum(wo.total_cost_max for wo in self.work_orders if wo.total_cost_max)
class MasterEquipment(Base, DefaultMixin):

@ -5,7 +5,7 @@ from fastapi.params import Query
from .model import ScopeEquipment
from .schema import ScopeEquipmentCreate, ScopeEquipmentPagination, ScopeEquipmentRead, ScopeEquipmentUpdate, MasterEquipmentPagination
from .service import get, get_all, create, update, delete, get_by_scope_name, get_exculed_scope_name, get_all_master_equipment
from .service import get_all, create, update, delete, get_all_master_equipment, get_by_assetnum
from src.database.service import CommonParameters, search_filter_sort_paginate
from src.database.core import DbSession
@ -16,10 +16,10 @@ router = APIRouter()
@router.get("", response_model=StandardResponse[ScopeEquipmentPagination])
async def get_scope_equipments(common: CommonParameters, scope_name: str = Query(None), exclude: bool = Query(False)):
async def get_scope_equipments(common: CommonParameters, scope_name: str = Query(None)):
"""Get all scope pagination."""
# return
data = await get_all(db_session=common["db_session"], common=common, scope_name=scope_name, exclude=exclude)
data = await get_all(common=common, scope_name=scope_name)
return StandardResponse(
data=data,
@ -27,33 +27,13 @@ async def get_scope_equipments(common: CommonParameters, scope_name: str = Query
)
@router.get("/scope/{scope_name}", response_model=StandardResponse[List[ScopeEquipmentRead]])
async def get_scope_name(db_session: DbSession, scope_name: str, exclude: bool = Query(False)):
if exclude:
return StandardResponse(data=await get_exculed_scope_name(db_session=db_session, scope_name=scope_name), message="Data retrieved successfully")
return StandardResponse(data=await get_by_scope_name(db_session=db_session, scope_name=scope_name), message="Data retrieved successfully")
@router.get("/available/{scope_name}", response_model=StandardResponse[MasterEquipmentPagination])
async def get_master_equipment(db_session: DbSession, common: CommonParameters, scope_name: str):
results = await get_all_master_equipment(db_session=db_session, common=common, exclude=scope_name)
async def get_master_equipment(common: CommonParameters, scope_name: str):
results = await get_all_master_equipment(common=common, scope_name=scope_name)
return StandardResponse(data=results, message="Data retrieved successfully")
@router.get("/{scope_equipment_id}", response_model=StandardResponse[ScopeEquipmentRead])
async def get_scope_equipment(db_session: DbSession, scope_equipment_id: str):
scope = await get(db_session=db_session, scope_equipment_id=scope_equipment_id)
if not scope:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=scope, message="Data retrieved successfully")
@router.post("", response_model=StandardResponse[List[str]])
async def create_scope_equipment(db_session: DbSession, scope_equipment_in: ScopeEquipmentCreate):
scope = await create(db_session=db_session, scope_equipment_in=scope_equipment_in)
@ -61,9 +41,9 @@ async def create_scope_equipment(db_session: DbSession, scope_equipment_in: Scop
return StandardResponse(data=scope, message="Data created successfully")
@router.put("/{scope_equipment_id}", response_model=StandardResponse[ScopeEquipmentRead])
async def update_scope_equipment(db_session: DbSession, scope_equipment_id: str, scope__equipment_in: ScopeEquipmentUpdate):
scope_equipment = await get(db_session=db_session, scope_equipment_id=scope_equipment_id)
@router.put("/{assetnum}", response_model=StandardResponse[ScopeEquipmentRead])
async def update_scope_equipment(db_session: DbSession, assetnum: str, scope__equipment_in: ScopeEquipmentUpdate):
scope_equipment = await get_by_assetnum(db_session=db_session, assetnum=assetnum)
if not scope_equipment:
raise HTTPException(
@ -74,9 +54,9 @@ async def update_scope_equipment(db_session: DbSession, scope_equipment_id: str,
return StandardResponse(data=await update(db_session=db_session, scope_equipment=scope_equipment, scope__equipment_in=scope__equipment_in), message="Data updated successfully")
@router.delete("/{scope_equipment_id}", response_model=StandardResponse[None])
async def delete_scope_equipment(db_session: DbSession, scope_equipment_id: str):
scope_equipment = await get(db_session=db_session, scope_equipment_id=scope_equipment_id)
@router.delete("/{assetnum}", response_model=StandardResponse[None])
async def delete_scope_equipment(db_session: DbSession, assetnum: str):
scope_equipment = await get_by_assetnum(db_session=db_session, assetnum=assetnum)
if not scope_equipment:
raise HTTPException(
@ -84,6 +64,6 @@ async def delete_scope_equipment(db_session: DbSession, scope_equipment_id: str)
detail=[{"msg": "A data with this id does not exist."}],
)
await delete(db_session=db_session, scope_equipment_id=scope_equipment_id)
await delete(db_session=db_session, assetnum=assetnum)
return StandardResponse(message="Data deleted successfully", data=None)

@ -5,7 +5,8 @@ from uuid import UUID
from pydantic import Field, computed_field, field_validator, validator
from src.models import DefultBase, Pagination
from src.scope.schema import ScopeRead
from src.overhaul_scope.schema import ScopeRead
from .enum import ScopeEquipmentType
class MasterEquipmentBase(DefultBase):
@ -14,12 +15,14 @@ class MasterEquipmentBase(DefultBase):
class ScopeEquipmentBase(DefultBase):
scope_id: Optional[UUID] = Field(None, title="Scope ID")
scope_overhaul: Optional[str] = Field(None, title="Scope ID")
class ScopeEquipmentCreate(DefultBase):
assetnums: List[str]
scope_name: str
removal_date: Optional[datetime] = Field(None)
type: Optional[str] = Field(ScopeEquipmentType.PERM)
class ScopeEquipmentUpdate(ScopeEquipmentBase):
@ -29,10 +32,8 @@ class ScopeEquipmentUpdate(ScopeEquipmentBase):
class ScopeEquipmentRead(ScopeEquipmentBase):
id: UUID
assetnum: str
parent_scope: ScopeRead
current_scope: ScopeRead
assigned_date: datetime
master_equipment: MasterEquipmentBase
total_cost: float
class ScopeEquipmentPagination(Pagination):

@ -1,11 +1,13 @@
from datetime import datetime, timedelta
from fastapi import HTTPException, status
from sqlalchemy import Select, Delete, desc, func, not_, or_
from sqlalchemy import Select, Delete, and_, desc, func, not_, or_
from sqlalchemy.dialects.postgresql import insert
from src.overhaul_scope.model import OverhaulScope
from src.scope_equipment.enum import ScopeEquipmentType
from src.workorder.model import MasterWorkOrder
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
from sqlalchemy.orm import selectinload
@ -15,14 +17,6 @@ from src.database.core import DbSession
from src.auth.service import CurrentUser
async def get(*, db_session: DbSession, scope_equipment_id: str) -> Optional[ScopeEquipment]:
"""Returns a document based on the given document id."""
query = Select(ScopeEquipment).filter(
ScopeEquipment.id == scope_equipment_id)
result = await db_session.execute(query)
return result.scalars().one_or_none()
async def get_by_assetnum(*, db_session: DbSession, assetnum: str):
query = Select(ScopeEquipment).filter(ScopeEquipment.assetnum == assetnum).options(
selectinload(ScopeEquipment.master_equipment))
@ -31,17 +25,15 @@ async def get_by_assetnum(*, db_session: DbSession, assetnum: str):
return result.unique().scalars().one_or_none()
async def get_all(*, db_session: DbSession, common, scope_name: str = None, exclude: bool = False):
async def get_all(*, common, scope_name: str = None):
"""Returns all documents."""
query = Select(ScopeEquipment).options(selectinload(
ScopeEquipment.parent_scope), selectinload(ScopeEquipment.current_scope), selectinload(ScopeEquipment.master_equipment))
query = Select(ScopeEquipment).options(
selectinload(ScopeEquipment.master_equipment))
query = query.order_by(desc(ScopeEquipment.created_at))
if scope_name:
scope = await get_scope_by_name_service(db_session=db_session, scope_name=scope_name)
query = query.filter(ScopeEquipment.current_scope_id == scope.id) if not exclude else query.filter(
ScopeEquipment.current_scope_id != scope.id)
query = query.where(ScopeEquipment.scope_overhaul == scope_name)
results = await search_filter_sort_paginate(model=query, **common)
return results
@ -51,28 +43,36 @@ async def create(*, db_session: DbSession, scope_equipment_in: ScopeEquipmentCre
"""Creates a new document."""
# scope_equipment = ScopeEquipment(**scope_equipment_in.model_dump())
assetnums = scope_equipment_in.assetnums
scope = await get_scope_by_name_service(
db_session=db_session, scope_name=scope_equipment_in.scope_name)
results = []
removal_date = scope_equipment_in.removal_date
if not scope:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A scope with this name does not exist.",
)
if scope_equipment_in.type == ScopeEquipmentType.TEMP:
# Search for the next or ongoing overhaul session for the given scope
stmt = Select(OverhaulScope.end_date).where(
OverhaulScope.type == scope_equipment_in.scope_name,
(OverhaulScope.start_date <= datetime.now()) & (
OverhaulScope.end_date >= datetime.now()) # Ongoing
| (OverhaulScope.start_date > datetime.now()) # Upcoming
).order_by(OverhaulScope.start_date.asc()).limit(1)
results = []
result = await db_session.execute(stmt)
removal_date = result.scalar_one_or_none()
# If no overhaul found, set a default removal date or handle the error
if removal_date is None:
# Handle if no overhaul session is found, set default or raise an error
removal_date = datetime.now() + timedelta(days=30) # Example: 30 days from now
for assetnum in assetnums:
stmt = insert(ScopeEquipment).values(
assetnum=assetnum,
current_scope_id=scope.id
scope_overhaul=scope_equipment_in.scope_name,
type=scope_equipment_in.type,
removal_date=removal_date
)
stmt = stmt.on_conflict_do_update(
index_elements=["assetnum"],
set_={
"current_scope_id": scope.id
}
stmt = stmt.on_conflict_do_nothing(
index_elements=["assetnum", "scope_overhaul"]
)
await db_session.execute(stmt)
@ -97,75 +97,72 @@ async def update(*, db_session: DbSession, scope_equipment: ScopeEquipment, scop
return scope_equipment
async def delete(*, db_session: DbSession, scope_equipment_id: str):
async def delete(*, db_session: DbSession, assetnum: str):
"""Deletes a document."""
# query = Delete(ScopeEquipment).where(
# ScopeEquipment.id == scope_equipment_id)
# await db_session.execute(query)
# await db_session.commit()
query = Select(ScopeEquipment).filter(
ScopeEquipment.id == scope_equipment_id)
scope_equipment = await db_session.execute(query)
scope_equipment: ScopeEquipment = scope_equipment.scalars().one_or_none()
query = Delete(ScopeEquipment).where(
ScopeEquipment.assetnum == assetnum)
await db_session.execute(query)
await db_session.commit()
if not scope_equipment:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
# query = Select(ScopeEquipment).filter(
# ScopeEquipment.id == scope_equipment_id)
if not scope_equipment.scope_id:
await db_session.delete(scope_equipment)
else:
if scope_equipment.current_scope_id == scope_equipment.scope_id:
await db_session.delete(scope_equipment)
else:
scope_equipment.current_scope_id = scope_equipment.scope_id
await db_session.commit()
# scope_equipment = await db_session.execute(query)
# scope_equipment: ScopeEquipment = scope_equipment.scalars().one_or_none()
# if not scope_equipment:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail="A data with this id does not exist.",
# )
# if not scope_equipment.scope_id:
# await db_session.delete(scope_equipment)
# else:
# if scope_equipment.current_scope_id == scope_equipment.scope_id:
# await db_session.delete(scope_equipment)
# else:
# scope_equipment.current_scope_id = scope_equipment.scope_id
# await db_session.commit()
async def get_by_scope_name(*, db_session: DbSession, scope_name: Union[str, list]) -> Optional[ScopeEquipment]:
async def get_by_scope_name(*, db_session: DbSession, scope_name: Optional[str]) -> Optional[ScopeEquipment]:
"""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).options(selectinload(ScopeEquipment.master_equipment))
query = Select(ScopeEquipment).options(
selectinload(ScopeEquipment.master_equipment))
if scope:
query = query.filter(ScopeEquipment.current_scope_id == scope.id)
if scope_name:
query = query.filter(ScopeEquipment.scope_overhaul == scope_name)
result = await db_session.execute(query)
return result.scalars().all()
async def get_exculed_scope_name(*, db_session: DbSession, scope_name: Union[str, list]) -> Optional[ScopeEquipment]:
scope = await get_scope_by_name_service(db_session=db_session, scope_name=scope_name)
query = Select(ScopeEquipment)
# async def get_exculed_scope_name(*, db_session: DbSession, scope_name: Union[str, list]) -> Optional[ScopeEquipment]:
# scope = await get_scope_by_name_service(db_session=db_session, scope_name=scope_name)
if scope:
query = query.filter(ScopeEquipment.current_scope_id != scope.id)
# query = Select(ScopeEquipment)
else:
query = query.filter(ScopeEquipment.current_scope_id != None)
# if scope:
# query = query.filter(ScopeEquipment.current_scope_id != scope.id)
result = await db_session.execute(query)
return result.scalars().all()
# else:
# query = query.filter(ScopeEquipment.current_scope_id != None)
# result = await db_session.execute(query)
# return result.scalars().all()
async def get_all_master_equipment(*, db_session: DbSession, exclude: Optional[str] = None, common: CommonParameters):
scope = await get_scope_by_name_service(db_session=db_session, scope_name=exclude)
query = Select(MasterEquipment).filter(MasterEquipment.assetnum != None)
async def get_all_master_equipment(*, common: CommonParameters, scope_name):
equipments_scope = [equip.assetnum for equip in await get_by_scope_name(
db_session=common.get("db_session"), scope_name=scope_name)]
query = query.outerjoin(
ScopeEquipment, MasterEquipment.assetnum == ScopeEquipment.assetnum)
query = Select(MasterEquipment).filter(
MasterEquipment.assetnum.is_not(None))
if scope:
query = query.filter(
not_(ScopeEquipment.current_scope_id == scope.id)
)
# Only add not_in filter if there are items in equipments_scope
if equipments_scope:
query = query.filter(MasterEquipment.assetnum.not_in(equipments_scope))
results = await search_filter_sort_paginate(model=query, **common)
return results

@ -1,18 +0,0 @@
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 ScopeEquipmentActivity(Base, DefaultMixin):
__tablename__ = "oh_tr_overhaul_activity"
assetnum = Column(String, nullable=True)
name = Column(String, nullable=False)
cost = Column(Float, nullable=False, default=0)
scope_equipments = relationship(
"ScopeEquipment", lazy="raise", primaryjoin="and_(ScopeEquipmentActivity.assetnum == foreign(ScopeEquipment.assetnum))", uselist=False)

@ -1,71 +0,0 @@
from fastapi import APIRouter, HTTPException, Query, status
from .service import get_all, create, get, update, delete
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("", response_model=StandardResponse[ScopeEquipmentActivityPagination])
async def get_scope_equipment_activities(common: CommonParameters, assetnum: str = Query(None)):
"""Get all scope activity pagination."""
# return
data = await get_all(common=common, assetnum=assetnum)
return StandardResponse(
data=data,
message="Data retrieved successfully",
)
@router.post("", response_model=StandardResponse[ScopeEquipmentActivityRead])
async def create_activity(db_session: DbSession, scope_equipment_activity_in: ScopeEquipmentActivityCreate):
activity = await create(db_session=db_session, scope_equipment_activty_in=scope_equipment_activity_in)
return StandardResponse(data=activity, message="Data created successfully")
@router.get("/{scope_equipment_activity_id}", response_model=StandardResponse[ScopeEquipmentActivityRead])
async def get_activity(db_session: DbSession, scope_equipment_activity_id: str):
activity = await get(db_session=db_session, scope_equipment_activity_id=scope_equipment_activity_id)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=activity, message="Data retrieved successfully")
@router.put("/{scope_equipment_activity_id}", response_model=StandardResponse[ScopeEquipmentActivityRead])
async def update_scope(db_session: DbSession, scope_equipment_activity_in: ScopeEquipmentActivityUpdate, scope_equipment_activity_id):
activity = await get(db_session=db_session, scope_equipment_activity_id=scope_equipment_activity_id)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
return StandardResponse(data=await update(db_session=db_session, activity=activity, scope_equipment_activity_in=scope_equipment_activity_in), message="Data updated successfully")
@router.delete("/{scope_equipment_activity_id}", response_model=StandardResponse[ScopeEquipmentActivityRead])
async def delete_scope(db_session: DbSession, scope_equipment_activity_id: str):
activity = await get(db_session=db_session, scope_equipment_activity_id=scope_equipment_activity_id)
if not activity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=[{"msg": "A data with this id does not exist."}],
)
await delete(db_session=db_session, scope_equipment_activity_id=scope_equipment_activity_id)
return StandardResponse(message="Data deleted successfully", data=activity)

@ -1,58 +0,0 @@
from sqlalchemy import Select, Delete
from typing import Optional
from .model import ScopeEquipmentActivity
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]):
query = Select(ScopeEquipmentActivity)
if assetnum:
query = query.filter(ScopeEquipmentActivity.assetnum == assetnum)
results = await search_filter_sort_paginate(model=query, **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_activity_in: ScopeEquipmentActivityUpdate):
"""Updates a document."""
data = scope_equipment_activity_in.model_dump()
update_data = scope_equipment_activity_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