add requests

feature/reliability_stat
Cizz22 6 months ago
parent 3421ce4dff
commit e6e87b0d9d

@ -9,17 +9,21 @@ from src.calculation_budget_constrains.router import \
router as calculation_budget_constraint router as calculation_budget_constraint
from src.calculation_target_reliability.router import \ from src.calculation_target_reliability.router import \
router as calculation_target_reliability router as calculation_target_reliability
from src.calculation_time_constrains.router import \ # from src.calculation_time_constrains.router import \
router as calculation_time_constrains_router # router as calculation_time_constrains_router
from src.job.router import router as job_router # from src.job.router import router as job_router
from src.overhaul.router import router as overhaul_router from src.overhaul.router import router as overhaul_router
from src.standard_scope.router import router as standard_scope_router
from src.overhaul_activity.router import router as overhaul_activity_router from src.overhaul_activity.router import router as overhaul_activity_router
from src.overhaul_job.router import router as job_overhaul_router from src.workscope_group.router import router as workscope_group_router
from src.overhaul_scope.router import router as scope_router from src.equipment_workscope_group.router import router as equipment_workscope_group_router
from src.scope_equipment.router import router as scope_equipment_router # from src.overhaul_job.router import router as job_overhaul_router
from src.scope_equipment_job.router import router as scope_equipment_job_router # from src.overhaul_scope.router import router as scope_router
from src.overhaul_schedule.router import router as overhaul_schedule_router # from src.scope_equipment.router import router as scope_equipment_router
from src.overhaul_gantt.router import router as gantt_router # from src.scope_equipment_job.router import router as scope_equipment_job_router
# from src.overhaul_schedule.router import router as overhaul_schedule_router
# from src.overhaul_gantt.router import router as gantt_router
# from src.overhaul_scope.router import router as scope_router # from src.overhaul_scope.router import router as scope_router
@ -67,15 +71,15 @@ authenticated_api_router.include_router(
overhaul_router, prefix="/overhauls", tags=["overhaul"] overhaul_router, prefix="/overhauls", tags=["overhaul"]
) )
authenticated_api_router.include_router(job_router, prefix="/jobs", tags=["job"]) # authenticated_api_router.include_router(job_router, prefix="/jobs", tags=["job"])
# # Overhaul session data # # # Overhaul session data
authenticated_api_router.include_router( # authenticated_api_router.include_router(
scope_router, prefix="/overhaul-session", tags=["overhaul-session"] # scope_router, prefix="/overhaul-session", tags=["overhaul-session"]
) # )
authenticated_api_router.include_router( authenticated_api_router.include_router(
scope_equipment_router, prefix="/scope-equipments", tags=["scope_equipment"] standard_scope_router, prefix="/scope-equipments", tags=["scope_equipment"]
) )
authenticated_api_router.include_router( authenticated_api_router.include_router(
@ -83,24 +87,33 @@ authenticated_api_router.include_router(
) )
authenticated_api_router.include_router( authenticated_api_router.include_router(
scope_equipment_job_router, workscope_group_router, prefix="/workscopes", tags=["workscope_groups"]
prefix="/scope-equipment-jobs",
tags=["scope_equipment", "job"],
) )
authenticated_api_router.include_router( authenticated_api_router.include_router(
overhaul_schedule_router, equipment_workscope_group_router,
prefix="/overhaul-schedules", prefix="/equipment-workscopes",
tags=["overhaul_schedule"], tags=["equipment_workscope_groups"],
) )
# authenticated_api_router.include_router(
# scope_equipment_job_router,
# prefix="/scope-equipment-jobs",
# tags=["scope_equipment", "job"],
# )
authenticated_api_router.include_router( # authenticated_api_router.include_router(
job_overhaul_router, prefix="/overhaul-jobs", tags=["job", "overhaul"] # overhaul_schedule_router,
) # prefix="/overhaul-schedules",
# tags=["overhaul_schedule"],
# )
authenticated_api_router.include_router( # authenticated_api_router.include_router(
gantt_router, prefix="/overhaul-gantt", tags=["gantt"] # job_overhaul_router, prefix="/overhaul-jobs", tags=["job", "overhaul"]
) # )
# authenticated_api_router.include_router(
# gantt_router, prefix="/overhaul-gantt", tags=["gantt"]
# )
# authenticated_api_router.include_router( # authenticated_api_router.include_router(
# overhaul_history_router, prefix="/overhaul-history", tags=["overhaul_history"] # overhaul_history_router, prefix="/overhaul-history", tags=["overhaul_history"]
@ -125,12 +138,12 @@ authenticated_api_router.include_router(
# calculation # calculation
calculation_router = APIRouter(prefix="/calculation", tags=["calculations"]) calculation_router = APIRouter(prefix="/calculation", tags=["calculations"])
# Time constrains # # Time constrains
calculation_router.include_router( # calculation_router.include_router(
calculation_time_constrains_router, # calculation_time_constrains_router,
prefix="/time-constraint", # prefix="/time-constraint",
tags=["calculation", "time_constraint"], # tags=["calculation", "time_constraint"],
) # )
# Target reliability # Target reliability
calculation_router.include_router( calculation_router.include_router(

@ -5,8 +5,8 @@ from sqlalchemy import Delete, Select
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.database.core import DbSession from src.database.core import DbSession
from src.scope_equipment.model import ScopeEquipment # from src.scope_equipment.model import ScopeEquipment
from src.scope_equipment.service import get_by_scope_name # from src.scope_equipment.service import get_by_scope_name
from src.overhaul_activity.service import get_all_by_session_id from src.overhaul_activity.service import get_all_by_session_id
# async def get_all_budget_constrains( # async def get_all_budget_constrains(

@ -4,9 +4,9 @@ from sqlalchemy import Delete, Select
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.database.core import DbSession from src.database.core import DbSession
from src.scope_equipment.model import ScopeEquipment # from src.scope_equipment.model import ScopeEquipment
from src.scope_equipment.service import get_by_scope_name # from src.scope_equipment.service import get_by_scope_name
from src.scope_equipment_job.service import get_equipment_level_by_no # from src.scope_equipment_job.service import get_equipment_level_by_no
from datetime import datetime, timedelta from datetime import datetime, timedelta
import random import random
from typing import List from typing import List

@ -10,7 +10,7 @@ from sqlalchemy import and_, case, func, select, update
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from src.database.core import DbSession from src.database.core import DbSession
from src.overhaul_activity.service import get_all_by_session_id from src.overhaul_activity.service import get_all as get_all_by_session_id
from src.overhaul_scope.service import get as get_scope, get_prev_oh from src.overhaul_scope.service import get as get_scope, get_prev_oh
from src.utils import get_latest_numOfFail from src.utils import get_latest_numOfFail
from src.workorder.model import MasterWorkOrder from src.workorder.model import MasterWorkOrder
@ -264,9 +264,9 @@ class SparePartsService:
return projected_stock return projected_stock
async def reduce_stock(self, db_session, assetnum: str): async def reduce_stock(self, db_session, location_tag: str):
requirements_query = select(ScopeEquipmentPart).where( requirements_query = select(ScopeEquipmentPart).where(
ScopeEquipmentPart.assetnum == assetnum ScopeEquipmentPart.location_tag == location_tag
) )
requirements = await db_session.execute(requirements_query) requirements = await db_session.execute(requirements_query)
@ -293,7 +293,7 @@ class SparePartsService:
all_available = True all_available = True
requirements_query = select(ScopeEquipmentPart).where( requirements_query = select(ScopeEquipmentPart).where(
ScopeEquipmentPart.assetnum == equipment.assetnum ScopeEquipmentPart.location_tag == equipment.location_tag
) )
requirements = await db_session.execute(requirements_query) requirements = await db_session.execute(requirements_query)
@ -504,7 +504,7 @@ class OverhaulCalculator:
) )
#reduce sparepart stock #reduce sparepart stock
await self.spare_parts_service.reduce_stock(db_session, equipment.assetnum) await self.spare_parts_service.reduce_stock(db_session, equipment.location_tag)
# Aggregate costs # Aggregate costs
corrective_costs = [r["corrective_cost"] for r in all_results] corrective_costs = [r["corrective_cost"] for r in all_results]
@ -1035,7 +1035,7 @@ async def get_calculation_result(db_session: DbSession, calculation_id: str):
for eq in scope_calculation.equipment_results: for eq in scope_calculation.equipment_results:
if eq.procurement_details[i]: if eq.procurement_details[i]:
result["procurement_details"][eq.assetnum] = { result["procurement_details"][eq.location_tag] = {
"is_included": eq.is_included, "is_included": eq.is_included,
"details": eq.procurement_details[i], "details": eq.procurement_details[i],
} }
@ -1280,14 +1280,14 @@ async def create_calculation_result_service(
total = [] total = []
predicted_num_failures = await get_number_of_failures( predicted_num_failures = await get_number_of_failures(
location_tag=eq.equipment.location_tag, location_tag=eq.location_tag,
start_date=start_date, start_date=start_date,
end_date=end_date, end_date=end_date,
token=token token=token
) )
foh_value = await get_equipment_foh( foh_value = await get_equipment_foh(
location_tag=eq.equipment.location_tag, location_tag=eq.location_tag,
token=token token=token
) )
@ -1310,7 +1310,7 @@ async def create_calculation_result_service(
service_cost=eq.service_cost, service_cost=eq.service_cost,
optimum_day=optimal_result['interval'], optimum_day=optimal_result['interval'],
calculation_data_id=calculation.id, calculation_data_id=calculation.id,
master_equipment=eq.equipment, master_equipment=eq.master_equipment,
) )
) )

@ -12,7 +12,7 @@ class ScopeEquipmentPart(Base, DefaultMixin):
required_stock = Column(Float, nullable=False, default=0) required_stock = Column(Float, nullable=False, default=0)
sparepart_id = Column(UUID(as_uuid=True), ForeignKey("oh_ms_sparepart.id"), nullable=False) sparepart_id = Column(UUID(as_uuid=True), ForeignKey("oh_ms_sparepart.id"), nullable=False)
assetnum = Column(String, nullable=False) location_tag = Column(String, nullable=False)
location_tag = Column(String, nullable=False) location_tag = Column(String, nullable=False)
part = relationship( part = relationship(

@ -7,8 +7,6 @@ from sqlalchemy.orm import selectinload
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.database.core import DbSession from src.database.core import DbSession
from src.database.service import CommonParameters, search_filter_sort_paginate from src.database.service import CommonParameters, search_filter_sort_paginate
from src.scope_equipment.model import MasterEquipment, MasterEquipmentTree
from src.scope_equipment.service import get_equipment_level_by_no
from .model import ScopeEquipmentPart from .model import ScopeEquipmentPart
from .schema import ScopeEquipmentActivityCreate, ScopeEquipmentActivityUpdate from .schema import ScopeEquipmentActivityCreate, ScopeEquipmentActivityUpdate

@ -0,0 +1,22 @@
from sqlalchemy import UUID, Column, Float, ForeignKey, Integer, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
from src.workorder.model import MasterWorkOrder
class EquipmentWorkscopeGroup(Base, DefaultMixin):
__tablename__ = "oh_tr_equipment_workscope_group"
workscope_group_id = Column(UUID(as_uuid=True), ForeignKey('oh_ms_workscope_group.id'))
location_tag = Column(String, nullable=False)
workscope_group = relationship("MasterActivity", lazy="selectin", back_populates="equipment_workscope_groups")
equipment = relationship(
"StandardScope",
lazy="raise",
primaryjoin="and_(EquipmentWorkscopeGroup.location_tag == foreign(StandardScope.location_tag))",
uselist=False, # Add this if it's a one-to-one relationship
)

@ -12,16 +12,16 @@ from .service import create, delete, get_all
router = APIRouter() router = APIRouter()
@router.get("/{assetnum}", response_model=StandardResponse[ScopeEquipmentJobPagination]) @router.get(
async def get_scope_equipment_jobs( "/{location_tag}", response_model=StandardResponse[OverhaulJobPagination]
db_session: DbSession, assetnum, common: CommonParameters )
): async def get_jobs(common: CommonParameters, location_tag: str, scope: Optional[str] = Query(None)):
"""Get all scope activity pagination.""" """Get all scope pagination."""
# return # return
data = await get_all(db_session=db_session, assetnum=assetnum, common=common) results = await get_all(common=common, location_tag=location_tag, scope=scope)
return StandardResponse( return StandardResponse(
data=data, data=results,
message="Data retrieved successfully", message="Data retrieved successfully",
) )

@ -22,32 +22,51 @@ from .schema import ScopeEquipmentJobCreate
# return result # return result
async def get_all(db_session: DbSession, assetnum: Optional[str], common): # async def get_all(db_session: DbSession, assetnum: Optional[str], common):
# Example usage # # Example usage
if not assetnum: # if not assetnum:
raise ValueError("assetnum parameter is required") # raise ValueError("assetnum parameter is required")
# First get the parent equipment # # First get the parent equipment
equipment_stmt = Select(MasterEquipment).where(MasterEquipment.assetnum == assetnum) # equipment_stmt = Select(MasterEquipment).where(MasterEquipment.assetnum == assetnum)
equipment: MasterEquipment = await db_session.scalar(equipment_stmt) # equipment: MasterEquipment = await db_session.scalar(equipment_stmt)
if not equipment: # if not equipment:
raise ValueError(f"No equipment found with assetnum: {assetnum}") # raise ValueError(f"No equipment found with assetnum: {assetnum}")
# Build query for parts # # Build query for parts
stmt = ( # stmt = (
Select(ScopeEquipmentJob) # Select(ScopeEquipmentJob)
.where(ScopeEquipmentJob.assetnum == assetnum) # .where(ScopeEquipmentJob.assetnum == assetnum)
.options( # .options(
selectinload(ScopeEquipmentJob.job), # selectinload(ScopeEquipmentJob.job),
selectinload(ScopeEquipmentJob.overhaul_jobs) # selectinload(ScopeEquipmentJob.overhaul_jobs)
.selectinload(OverhaulJob.overhaul_activity) # .selectinload(OverhaulJob.overhaul_activity)
.selectinload(OverhaulActivity.overhaul_scope), # .selectinload(OverhaulActivity.overhaul_scope),
) # )
# )
# results = await search_filter_sort_paginate(model=stmt, **common)
# return results
async def get_all(*, common, location_tag: str, scope: Optional[str] = None):
"""Returns all documents."""
query = (
Select(EquipmentWorkscopeGroup)
.where(EquipmentWorkscopeGroup.location_tag == location_tag)
) )
results = await search_filter_sort_paginate(model=stmt, **common) if scope:
query = (
query
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(MaintenanceType.name == scope)
)
results = await search_filter_sort_paginate(model=query, **common)
return results return results

@ -18,26 +18,26 @@ class OverhaulActivity(Base, DefaultMixin):
service_cost = Column(Float, nullable=False, default=0) service_cost = Column(Float, nullable=False, default=0)
status = Column(String, nullable=False, default="pending") status = Column(String, nullable=False, default="pending")
equipment = relationship( # equipment = relationship(
"MasterEquipment", # "MasterEquipment",
lazy="raise", # lazy="raise",
primaryjoin="and_(OverhaulActivity.assetnum == foreign(MasterEquipment.assetnum))", # primaryjoin="and_(OverhaulActivity.assetnum == foreign(MasterEquipment.assetnum))",
uselist=False, # Add this if it's a one-to-one relationship # uselist=False, # Add this if it's a one-to-one relationship
) # )
# sparepart_equipments = relationship( # # sparepart_equipments = relationship(
# "ScopeEquipmentPart", # # "ScopeEquipmentPart",
# lazy="select", # or "joined", "subquery", "dynamic" depending on your needs # # lazy="select", # or "joined", "subquery", "dynamic" depending on your needs
# primaryjoin="OverhaulActivity.assetnum == foreign(ScopeEquipmentPart.assetnum)", # # primaryjoin="OverhaulActivity.assetnum == foreign(ScopeEquipmentPart.assetnum)",
# uselist=True # # uselist=True
# ) # # )
overhaul_scope = relationship( # overhaul_scope = relationship(
"OverhaulScope", # "OverhaulScope",
lazy="raise", # lazy="raise",
) # )
overhaul_jobs = relationship( # overhaul_jobs = relationship(
"OverhaulJob", back_populates="overhaul_activity", lazy="raise" # "OverhaulJob", back_populates="overhaul_activity", lazy="raise"
) # )

@ -15,10 +15,10 @@ router = APIRouter()
@router.get( @router.get(
"/{overhaul_session}", response_model=StandardResponse[OverhaulActivityPagination] "/{overhaul_session}", response_model=StandardResponse[List[OverhaulActivityRead]]
) )
async def get_scope_equipments( async def get_scope_equipments(
common: CommonParameters, db_session: DbSession,
overhaul_session: str, overhaul_session: str,
assetnum: Optional[str] = Query(None), assetnum: Optional[str] = Query(None),
scope_name: Optional[str] = Query(None), scope_name: Optional[str] = Query(None),
@ -26,7 +26,7 @@ async def get_scope_equipments(
"""Get all scope activity pagination.""" """Get all scope activity pagination."""
# return # return
data = await get_all( data = await get_all(
common=common, db_session=db_session,
assetnum=assetnum, assetnum=assetnum,
scope_name=scope_name, scope_name=scope_name,
overhaul_session_id=overhaul_session, overhaul_session_id=overhaul_session,

@ -5,8 +5,8 @@ from uuid import UUID
from pydantic import Field from pydantic import Field
from src.models import DefultBase, Pagination from src.models import DefultBase, Pagination
from src.scope_equipment.schema import MasterEquipmentTree from src.standard_scope.schema import MasterEquipmentTree
from src.job.schema import ActivityMasterRead from src.workscope_group.schema import ActivityMasterRead
class OverhaulActivityBase(DefultBase): class OverhaulActivityBase(DefultBase):
pass pass
@ -38,11 +38,12 @@ class OverhaulActivityRead(OverhaulActivityBase):
id: UUID id: UUID
material_cost: Optional[float] = Field(0) material_cost: Optional[float] = Field(0)
service_cost: Optional[float] = Field(0) service_cost: Optional[float] = Field(0)
assetnum: str = Field(..., description="Assetnum is required") location_tag: str
status: str equipment_name: Optional[str]
equipment: MasterEquipmentTree oh_scope: str
overhaul_scope: OverhaulScope # equipment: MasterEquipmentTree
overhaul_jobs: Optional[List[OverhaulJob]] = Field([]) # overhaul_scope: OverhaulScope
# overhaul_jobs: Optional[List[OverhaulJob]] = Field([])
class OverhaulActivityPagination(Pagination): class OverhaulActivityPagination(Pagination):

@ -13,9 +13,10 @@ from src.database.service import CommonParameters, search_filter_sort_paginate
from src.overhaul_activity.utils import get_material_cost, get_service_cost from src.overhaul_activity.utils import get_material_cost, get_service_cost
from src.overhaul_scope.model import OverhaulScope from src.overhaul_scope.model import OverhaulScope
from src.overhaul_scope.service import get as get_session from src.overhaul_scope.service import get as get_session
from src.scope_equipment.model import MasterEquipment from src.standard_scope.model import MasterEquipment
from src.job.model import MasterActivity from src.standard_scope.service import get_by_oh_session_id
from src.scope_equipment_job.model import ScopeEquipmentJob from src.workscope_group.model import MasterActivity
from src.equipment_workscope_group.model import EquipmentWorkscopeGroup
from src.overhaul_job.model import OverhaulJob from src.overhaul_job.model import OverhaulJob
from .model import OverhaulActivity from .model import OverhaulActivity
@ -43,32 +44,50 @@ async def get(
async def get_all( async def get_all(
*, *,
common: CommonParameters, db_session: DbSession,
overhaul_session_id: UUID, overhaul_session_id: UUID,
assetnum: Optional[str] = None, assetnum: Optional[str] = None,
scope_name: Optional[str] = None scope_name: Optional[str] = None
): ):
query = ( # query = (
Select(OverhaulActivity) # Select(OverhaulActivity)
.where(OverhaulActivity.overhaul_scope_id == overhaul_session_id) # .where(OverhaulActivity.overhaul_scope_id == overhaul_session_id)
.options(joinedload(OverhaulActivity.equipment).options(joinedload(MasterEquipment.parent).options(joinedload(MasterEquipment.parent)))) # .options(joinedload(OverhaulActivity.equipment).options(joinedload(MasterEquipment.parent).options(joinedload(MasterEquipment.parent))))
.options(selectinload(OverhaulActivity.overhaul_scope)) # .options(selectinload(OverhaulActivity.overhaul_scope))
.options(selectinload(OverhaulActivity.overhaul_jobs).options(joinedload(OverhaulJob.scope_equipment_job).options(joinedload(ScopeEquipmentJob.job)))) # .options(selectinload(OverhaulActivity.overhaul_jobs).options(joinedload(OverhaulJob.scope_equipment_job).options(joinedload(ScopeEquipmentJob.job))))
# )
# if assetnum:
# query = query.filter(OverhaulActivity.assetnum == assetnum).options(
# joinedload(OverhaulActivity.overhaul_scope)
# )
# if scope_name:
# query = query.filter(OverhaulActivity.scope_name == scope_name).options(
# joinedload(OverhaulActivity.overhaul_scope)
# )
# results = await search_filter_sort_paginate(model=query, **common)
##raise Exception(results['items'][0].equipment.parent.__dict__)
equipments, overhaul = await get_by_oh_session_id(
db_session=db_session, oh_session_id=overhaul_session_id
) )
if assetnum: results = []
query = query.filter(OverhaulActivity.assetnum == assetnum).options(
joinedload(OverhaulActivity.overhaul_scope)
)
if scope_name: for equipment in equipments:
query = query.filter(OverhaulActivity.scope_name == scope_name).options( res = OverhaulActivityRead(
joinedload(OverhaulActivity.overhaul_scope) id=equipment.id,
material_cost=35000000000,
service_cost=200000000,
location_tag=equipment.location_tag,
equipment_name=equipment.master_equipment.name if equipment.master_equipment else None,
oh_scope=overhaul.maintenance_type.name,
) )
results = await search_filter_sort_paginate(model=query, **common) results.append(res)
##raise Exception(results['items'][0].equipment.parent.__dict__)
return results return results

@ -6,24 +6,38 @@ from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
class OverhaulJob(Base, DefaultMixin): class EquipmentWorkscopeGroup(Base, DefaultMixin):
__tablename__ = "oh_tr_overhaul_job" __tablename__ = "oh_tr_equipment_workscope_group"
overhaul_activity_id = Column( # overhaul_activity_id = Column(
UUID(as_uuid=True), ForeignKey("oh_tr_overhaul_activity.id"), nullable=False # UUID(as_uuid=True), ForeignKey("oh_tr_overhaul_activity.id"), nullable=False
# )
# scope_equipment_job_id = Column(
# UUID(as_uuid=True),
# ForeignKey("oh_ms_scope_equipment_job.id", ondelete="cascade"),
# nullable=False,
# )
# notes = Column(String, nullable=True)
# status = Column(String, nullable=True, default="pending")
workscope_group_id = Column(
UUID(as_uuid=True), ForeignKey("oh_ms_workscope_group.id"), nullable=False
) )
scope_equipment_job_id = Column( location_tag = Column(String, nullable=False)
UUID(as_uuid=True),
ForeignKey("oh_ms_scope_equipment_job.id", ondelete="cascade"), equipment = relationship(
nullable=False, "StandardScope",
lazy="selectin",
primaryjoin="and_(OverhaulJob.location_tag == foreign(StandardScope.location_tag))",
uselist=False, # Add this if it's a one-to-one relationship
) )
notes = Column(String, nullable=True) workscope_group = relationship("MasterActivity", lazy="selectin", back_populates="equipment_workscope_groups")
status = Column(String, nullable=True, default="pending")
scope_equipment_job = relationship( # scope_equipment_job = relationship(
"ScopeEquipmentJob", lazy="raise", back_populates="overhaul_jobs" # "ScopeEquipmentJob", lazy="raise", back_populates="overhaul_jobs"
) # )
overhaul_activity = relationship("OverhaulActivity", lazy="raise", back_populates="overhaul_jobs") # overhaul_activity = relationship("OverhaulActivity", lazy="raise", back_populates="overhaul_jobs")

@ -1,6 +1,6 @@
from typing import List, Optional from typing import List, Optional
from fastapi import APIRouter, HTTPException, status from fastapi import APIRouter, HTTPException, status, Query
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.database.core import DbSession from src.database.core import DbSession
@ -15,12 +15,12 @@ router = APIRouter()
@router.get( @router.get(
"/{overhaul_equipment_id}", response_model=StandardResponse[OverhaulJobPagination] "/{location_tag}", response_model=StandardResponse[OverhaulJobPagination]
) )
async def get_jobs(common: CommonParameters, overhaul_equipment_id: str): async def get_jobs(common: CommonParameters, location_tag: str, scope: Optional[str] = Query(None)):
"""Get all scope pagination.""" """Get all scope pagination."""
# return # return
results = await get_all(common=common, overhaul_equipment_id=overhaul_equipment_id) results = await get_all(common=common, location_tag=location_tag, scope=scope)
return StandardResponse( return StandardResponse(
data=results, data=results,

@ -7,26 +7,32 @@ from sqlalchemy.orm import selectinload
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.database.core import DbSession from src.database.core import DbSession
from src.database.service import search_filter_sort_paginate from src.database.service import search_filter_sort_paginate
from src.scope_equipment_job.model import ScopeEquipmentJob # from src.scope_equipment_job.model import ScopeEquipmentJob
from src.overhaul_activity.model import OverhaulActivity # from src.overhaul_activity.model import OverhaulActivity
from .model import OverhaulJob from src.workscope_group.model import MasterActivity
from src.workscope_group_maintenance_type.model import WorkscopeOHType
from src.overhaul_scope.model import MaintenanceType
from .model import EquipmentWorkscopeGroup
from .schema import OverhaulJobCreate from .schema import OverhaulJobCreate
async def get_all(*, common, overhaul_equipment_id: str): async def get_all(*, common, location_tag: str, scope: Optional[str] = None):
"""Returns all documents.""" """Returns all documents."""
query = ( query = (
Select(OverhaulJob) Select(EquipmentWorkscopeGroup)
.where(OverhaulJob.overhaul_activity_id == overhaul_equipment_id) .where(EquipmentWorkscopeGroup.location_tag == location_tag)
.options(
selectinload(OverhaulJob.scope_equipment_job).options(
selectinload(ScopeEquipmentJob.job)),
selectinload(OverhaulJob.overhaul_activity).options(
selectinload(OverhaulActivity.overhaul_scope)),
)
) )
if scope:
query = (
query
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(MaintenanceType.name == scope)
)
results = await search_filter_sort_paginate(model=query, **common) results = await search_filter_sort_paginate(model=query, **common)
return results return results

@ -1,4 +1,4 @@
from sqlalchemy import Column, DateTime, Float, Integer, String from sqlalchemy import Column, DateTime, Float, Integer, String, ForeignKey, UUID
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from src.database.core import Base from src.database.core import Base
@ -6,12 +6,20 @@ from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
class OverhaulScope(Base, DefaultMixin): class OverhaulScope(Base, DefaultMixin):
__tablename__ = "oh_ms_overhaul_scope" __tablename__ = "oh_ms_overhaul"
type = Column(String, nullable=False) # Changed to non-nullable to match the model
start_date = Column(DateTime(timezone=True), nullable=False) # Made non-nullable to match model start_date = Column(DateTime(timezone=True), nullable=False) # Made non-nullable to match model
end_date = Column(DateTime(timezone=True), nullable=True) # Already nullable end_date = Column(DateTime(timezone=True), nullable=True) # Already nullable
duration_oh = Column(Integer, nullable=True) duration_oh = Column(Integer, nullable=True)
crew_number = Column(Integer, nullable=True, default=1) crew_number = Column(Integer, nullable=True, default=1)
status = Column(String, nullable=False, default="Upcoming") status = Column(String, nullable=False, default="Upcoming")
maintenance_type_id = Column(
UUID(as_uuid=True), ForeignKey("oh_ms_maintenance_type.id"), nullable=False)
activity_equipments = relationship("OverhaulActivity", lazy="selectin") maintenance_type = relationship("MaintenanceType", lazy="selectin", backref="overhaul_scopes")
# activity_equipments = relationship("OverhaulActivity", lazy="selectin")
class MaintenanceType(Base, DefaultMixin):
__tablename__ = "oh_ms_maintenance_type"
code = Column(String, nullable=False, default="OH")
name = Column(String, nullable=False)

@ -11,9 +11,11 @@ class ScopeBase(DefultBase):
duration_oh: Optional[int] = Field(720, title="Duration OH") duration_oh: Optional[int] = Field(720, title="Duration OH")
crew_number: Optional[int] = Field(10, title="Crew") crew_number: Optional[int] = Field(10, title="Crew")
status: Optional[str] = Field("Upcoming") status: Optional[str] = Field("Upcoming")
type: str = Field(..., title="Type") # Added title
class MaintenanceType(DefultBase):
name: str
class ScopeCreate(ScopeBase): class ScopeCreate(ScopeBase):
start_date: datetime start_date: datetime
end_date: Optional[datetime] = Field(None) end_date: Optional[datetime] = Field(None)
@ -27,6 +29,7 @@ class ScopeRead(ScopeBase):
id: UUID id: UUID
start_date: datetime start_date: datetime
end_date: Optional[datetime] end_date: Optional[datetime]
maintenance_type: MaintenanceType
class ScopePagination(Pagination): class ScopePagination(Pagination):

@ -1,15 +1,19 @@
from typing import Optional from typing import Optional
from sqlalchemy import Delete, Select, func from sqlalchemy import Delete, Select, func
from sqlalchemy.orm import selectinload
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.database.core import DbSession from src.database.core import DbSession
from src.database.service import search_filter_sort_paginate from src.database.service import search_filter_sort_paginate
from src.overhaul_activity.model import OverhaulActivity from src.overhaul_activity.model import OverhaulActivity
from src.scope_equipment.service import get_by_scope_name
from src.utils import time_now from src.utils import time_now
from src.standard_scope.model import StandardScope, EquipmentOHHistory
from src.workscope_group.model import MasterActivity
from src.workscope_group_maintenance_type.model import WorkscopeOHType
from src.equipment_workscope_group.model import EquipmentWorkscopeGroup
from .model import OverhaulScope from .model import OverhaulScope, MaintenanceType
from .schema import ScopeCreate, ScopeUpdate from .schema import ScopeCreate, ScopeUpdate
from .utils import get_material_cost, get_service_cost from .utils import get_material_cost, get_service_cost
from datetime import datetime from datetime import datetime
@ -18,7 +22,7 @@ async def get(
*, db_session: DbSession, overhaul_session_id: str *, db_session: DbSession, overhaul_session_id: str
) -> Optional[OverhaulScope]: ) -> Optional[OverhaulScope]:
"""Returns a document based on the given document id.""" """Returns a document based on the given document id."""
query = Select(OverhaulScope).filter(OverhaulScope.id == overhaul_session_id) query = Select(OverhaulScope).filter(OverhaulScope.id == overhaul_session_id).options(selectinload(OverhaulScope.maintenance_type))
result = await db_session.execute(query) result = await db_session.execute(query)
return result.scalars().one_or_none() return result.scalars().one_or_none()
@ -34,7 +38,7 @@ async def get_all(*, common, scope_name: Optional[str] = None):
query = Select(OverhaulScope) query = Select(OverhaulScope)
if scope_name: if scope_name:
query = query.filter(OverhaulScope.type == scope_name) query = query.filter(OverhaulScope.maintenance_type.name == scope_name)
results = await search_filter_sort_paginate(model=query, **common) results = await search_filter_sort_paginate(model=query, **common)
return results return results
@ -66,12 +70,21 @@ async def create(*, db_session: DbSession, scope_in: ScopeCreate):
if start_date and end_date: if start_date and end_date:
duration_days = (end_date - start_date).days duration_days = (end_date - start_date).days
maintenance_type = Select(MaintenanceType).where(MaintenanceType.name == scope_in.type)
maintenance_type = await db_session.execute(maintenance_type)
maintenance_type = maintenance_type.scalars().one_or_none()
if maintenance_type is None:
maintenance_type = MaintenanceType(name=scope_in.type)
db_session.add(maintenance_type)
await db_session.flush()
# Create the OverhaulScope object with all hardcoded values # Create the OverhaulScope object with all hardcoded values
overhaul_session = OverhaulScope( overhaul_session = OverhaulScope(
start_date=scope_in.start_date, start_date=scope_in.start_date,
end_date=scope_in.end_date, end_date=scope_in.end_date,
type=scope_in.type, # Hardcoded type maintenance_type=maintenance_type,
duration_oh=duration_days, # Hardcoded duration (30 days) duration_oh=duration_days,
crew_number=scope_in.crew_number, # Hardcoded crew number crew_number=scope_in.crew_number, # Hardcoded crew number
status=scope_in.status # Hardcoded status status=scope_in.status # Hardcoded status
) )
@ -138,68 +151,117 @@ async def get_overview_overhaul(*, db_session: DbSession):
current_date = time_now().date() current_date = time_now().date()
# For ongoing overhaul with count # 1. Check for ongoing overhaul
ongoing_query = ( ongoing_query = (
Select(OverhaulScope, func.count(OverhaulActivity.id).label("equipment_count")) Select(OverhaulScope)
.outerjoin(OverhaulScope.activity_equipments)
.where( .where(
OverhaulScope.start_date <= current_date, OverhaulScope.start_date <= current_date,
OverhaulScope.end_date >= current_date, OverhaulScope.end_date >= current_date,
) )
.group_by(OverhaulScope.id)
) )
ongoing_result = await db_session.execute(ongoing_query.options(selectinload(OverhaulScope.maintenance_type)))
ongoing_result = await db_session.execute(ongoing_query) ongoing_overhaul = ongoing_result.first()
# Use first() instead of scalar_one_or_none()
ongoing_result = ongoing_result.first() # 2. If no ongoing overhaul, get the closest scheduled overhaul
if ongoing_overhaul is None:
# Get the closest future overhaul (next scheduled)
if ongoing_result: next_overhaul_query = (
ongoing_overhaul, equipment_count = ongoing_result # Unpack the result tuple Select(OverhaulScope)
return { .where(OverhaulScope.start_date > current_date)
"status": "Ongoing", .order_by(OverhaulScope.start_date.asc())
"overhaul": { .limit(1)
"id": ongoing_overhaul.id,
"type": ongoing_overhaul.type,
"start_date": ongoing_overhaul.start_date,
"end_date": ongoing_overhaul.end_date,
"duration_oh": ongoing_overhaul.duration_oh,
"crew_number": ongoing_overhaul.crew_number,
"remaining_days": (ongoing_overhaul.end_date - current_date).days,
"equipment_count": equipment_count,
},
}
# For upcoming overhaul with count
upcoming_query = (
Select(OverhaulScope, func.count(OverhaulActivity.id).label("equipment_count"))
.outerjoin(OverhaulScope.activity_equipments)
.where(
OverhaulScope.start_date > current_date,
) )
.group_by(OverhaulScope.id) next_result = await db_session.execute(next_overhaul_query.options(selectinload(OverhaulScope.maintenance_type)))
.order_by(OverhaulScope.start_date) next_overhaul = next_result.scalar_one_or_none()
if next_overhaul:
print(f"Next scheduled overhaul starts on: {next_overhaul.start_date}")
selected_overhaul = next_overhaul
else:
print("No upcoming overhauls scheduled")
selected_overhaul = None
else:
print(f"Ongoing overhaul found: {ongoing_overhaul.start_date} to {ongoing_overhaul.end_date}")
selected_overhaul = ongoing_overhaul
equipments = (
Select(StandardScope)
.outerjoin(StandardScope.oh_history) # Use outerjoin to handle None values
.join(StandardScope.workscope_groups)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.filter(WorkscopeOHType.maintenance_type_id == selected_overhaul.maintenance_type_id)
.filter(
(StandardScope.is_alternating_oh == False) |
(StandardScope.oh_history == None) |
(StandardScope.oh_history.has(EquipmentOHHistory.last_oh_type != selected_overhaul.maintenance_type.name))
).distinct()
) )
upcoming_result = await db_session.execute(upcoming_query) results = await db_session.execute(equipments)
upcoming_result = upcoming_result.first()
return {
if upcoming_result: "status": selected_overhaul.status,
upcoming_overhaul, equipment_count = upcoming_result # Unpack the result tuple "overhaul": {
days_until = (upcoming_overhaul.start_date - current_date).days "id": selected_overhaul.id,
"type": selected_overhaul.maintenance_type.name,
return { "start_date": selected_overhaul.start_date,
"status": "Upcoming", "end_date": selected_overhaul.end_date,
"overhaul": { "duration_oh": selected_overhaul.duration_oh,
"id": upcoming_overhaul.id, "crew_number": selected_overhaul.crew_number,
"type": upcoming_overhaul.type, "remaining_days": (selected_overhaul.end_date - current_date).days,
"start_date": upcoming_overhaul.start_date, "equipment_count": len(results.scalars().all()),
"end_date": upcoming_overhaul.end_date, },
"duration_oh": upcoming_overhaul.duration_oh, }
"crew_number": upcoming_overhaul.crew_number,
"remaining_days": days_until,
"equipment_count": equipment_count, # if ongoing_result:
}, # ongoing_overhaul, equipment_count = ongoing_result # Unpack the result tuple
} # return {
# "status": "Ongoing",
return {"status": "no_overhaul", "overhaul": None} # "overhaul": {
# "id": ongoing_overhaul.id,
# "type": ongoing_overhaul.maintenance_type.name,
# "start_date": ongoing_overhaul.start_date,
# "end_date": ongoing_overhaul.end_date,
# "duration_oh": ongoing_overhaul.duration_oh,
# "crew_number": ongoing_overhaul.crew_number,
# "remaining_days": (ongoing_overhaul.end_date - current_date).days,
# "equipment_count": equipment_count,
# },
# }
# # For upcoming overhaul with count
# upcoming_query = (
# Select(OverhaulScope, func.count(OverhaulActivity.id).label("equipment_count"))
# .outerjoin(OverhaulScope.activity_equipments)
# .where(
# OverhaulScope.start_date > current_date,
# )
# .group_by(OverhaulScope.id)
# .order_by(OverhaulScope.start_date)
# )
# upcoming_result = await db_session.execute(upcoming_query)
# upcoming_result = upcoming_result.first()
# if upcoming_result:
# upcoming_overhaul, equipment_count = upcoming_result # Unpack the result tuple
# days_until = (upcoming_overhaul.start_date - current_date).days
# return {
# "status": "Upcoming",
# "overhaul": {
# "id": upcoming_overhaul.id,
# "type": upcoming_overhaul.type,
# "start_date": upcoming_overhaul.start_date,
# "end_date": upcoming_overhaul.end_date,
# "duration_oh": upcoming_overhaul.duration_oh,
# "crew_number": upcoming_overhaul.crew_number,
# "remaining_days": days_until,
# "equipment_count": equipment_count,
# },
# }
# return {"status": "no_overhaul", "overhaul": None}

@ -1,202 +0,0 @@
from datetime import datetime, timedelta
from typing import Optional, Union
from fastapi import HTTPException, status
from sqlalchemy import Delete, Select, and_, desc, func, not_, or_
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import selectinload
from src.auth.service import CurrentUser
from src.database.core import DbSession
from src.database.service import CommonParameters, search_filter_sort_paginate
from src.overhaul_scope.model import OverhaulScope
from src.scope_equipment.enum import ScopeEquipmentType
from src.workorder.model import MasterWorkOrder
from .model import MasterEquipment, MasterEquipmentTree, ScopeEquipment
from .schema import ScopeEquipmentCreate, ScopeEquipmentUpdate
async def get_by_assetnum(*, db_session: DbSession, assetnum: str):
query = (
Select(ScopeEquipment)
.filter(ScopeEquipment.assetnum == assetnum)
.options(selectinload(ScopeEquipment.master_equipment))
)
result = await db_session.execute(query)
return result.unique().scalars().one_or_none()
async def get_all(*, common, scope_name: str = None):
"""Returns all documents."""
query = Select(ScopeEquipment).options(
selectinload(ScopeEquipment.master_equipment)
)
query = query.order_by(desc(ScopeEquipment.created_at))
if scope_name:
query = query.where(ScopeEquipment.scope_overhaul == scope_name)
results = await search_filter_sort_paginate(model=query, **common)
return results
async def create(*, db_session: DbSession, scope_equipment_in: ScopeEquipmentCreate):
"""Creates a new document."""
# scope_equipment = ScopeEquipment(**scope_equipment_in.model_dump())
assetnums = scope_equipment_in.assetnums
results = []
removal_date = scope_equipment_in.removal_date
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)
)
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,
scope_overhaul=scope_equipment_in.scope_name,
type=scope_equipment_in.type,
removal_date=removal_date,
)
stmt = stmt.on_conflict_do_nothing(
index_elements=["assetnum", "scope_overhaul"]
)
await db_session.execute(stmt)
results.append(assetnum)
await db_session.commit()
return results
async def update(
*,
db_session: DbSession,
scope_equipment: ScopeEquipment,
scope_equipment_in: ScopeEquipmentUpdate
):
"""Updates a document."""
data = scope_equipment_in.model_dump()
update_data = scope_equipment_in.model_dump(exclude_defaults=True)
for field in data:
if field in update_data:
setattr(scope_equipment, field, update_data[field])
await db_session.commit()
return scope_equipment
async def delete(*, db_session: DbSession, assetnum: str):
"""Deletes a document."""
query = Delete(ScopeEquipment).where(ScopeEquipment.assetnum == assetnum)
await db_session.execute(query)
await db_session.commit()
return assetnum
# 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()
# 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: Optional[str]
) -> Optional[ScopeEquipment]:
"""Returns a document based on the given document id."""
query = Select(ScopeEquipment).options(
selectinload(ScopeEquipment.master_equipment)
)
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)
# if scope:
# query = query.filter(ScopeEquipment.current_scope_id != scope.id)
# 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(*, 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 = Select(MasterEquipment).filter(MasterEquipment.assetnum.is_not(None))
# 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
async def get_equipment_level_by_no(*, db_session: DbSession, level: int):
query = (
Select(MasterEquipment)
.join(MasterEquipment.equipment_tree)
.where(MasterEquipmentTree.level_no == level)
)
result = await db_session.execute(query)
return result.scalars().all()

@ -1,20 +0,0 @@
from sqlalchemy import UUID, Column, Float, ForeignKey, Integer, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
from src.workorder.model import MasterWorkOrder
class ScopeEquipmentJob(Base, DefaultMixin):
__tablename__ = "oh_ms_scope_equipment_job"
assetnum = Column(String, nullable=False)
job_id = Column(UUID(as_uuid=True), ForeignKey("oh_ms_job.id", ondelete="cascade"))
job = relationship("MasterActivity", lazy="selectin")
overhaul_jobs = relationship(
"OverhaulJob", back_populates="scope_equipment_job", lazy="selectin"
)

@ -1,4 +1,4 @@
from sqlalchemy import UUID, Column, Date, Float, ForeignKey, Integer, String from sqlalchemy import UUID, Column, Date, Float, ForeignKey, Integer, String, Boolean
from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
@ -7,22 +7,40 @@ from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
from src.workorder.model import MasterWorkOrder from src.workorder.model import MasterWorkOrder
class ScopeEquipment(Base, DefaultMixin): class StandardScope(Base, DefaultMixin):
__tablename__ = "oh_ms_scope_equipment" __tablename__ = "oh_ms_standard_scope"
assetnum = Column(String, nullable=True) location_tag = Column(String, nullable=False)
scope_overhaul = Column(String, nullable=False) is_alternating_oh = Column(Boolean, nullable=False, default=False)
type = Column(String, nullable=False, default="Permanent")
removal_date = Column(Date, nullable=True)
assigned_date = Column(Date, nullable=True) assigned_date = Column(Date, nullable=True)
master_equipment = relationship( master_equipment = relationship(
"MasterEquipment", "MasterEquipment",
lazy="raise", lazy="selectin",
primaryjoin="and_(ScopeEquipment.assetnum == foreign(MasterEquipment.assetnum))", primaryjoin="and_(StandardScope.location_tag == foreign(MasterEquipment.location_tag))",
uselist=False, # Add this if it's a one-to-one relationship
)
oh_history = relationship(
"EquipmentOHHistory",
lazy="selectin",
primaryjoin="and_(StandardScope.location_tag == foreign(EquipmentOHHistory.location_tag))",
uselist=False, # Add this if it's a one-to-one relationship uselist=False, # Add this if it's a one-to-one relationship
) )
workscope_groups = relationship(
"EquipmentWorkscopeGroup",
lazy="selectin",
primaryjoin="and_(EquipmentWorkscopeGroup.location_tag == foreign(StandardScope.location_tag))",
uselist=True, # Add this if it's a one-to-one relationship
)
class EquipmentOHHistory(Base, DefaultMixin):
__tablename__ = "oh_ms_equipment_oh_history"
location_tag = Column(String, nullable=False)
last_oh_date = Column(Date, nullable=True)
last_oh_type = Column(String, nullable=True)
class MasterEquipment(Base, DefaultMixin): class MasterEquipment(Base, DefaultMixin):
__tablename__ = "ms_equipment_master" __tablename__ = "ms_equipment_master"

@ -8,12 +8,10 @@ from src.database.core import DbSession
from src.database.service import CommonParameters, search_filter_sort_paginate from src.database.service import CommonParameters, search_filter_sort_paginate
from src.models import StandardResponse from src.models import StandardResponse
from .model import ScopeEquipment
from .schema import (MasterEquipmentPagination, ScopeEquipmentCreate, from .schema import (MasterEquipmentPagination, ScopeEquipmentCreate,
ScopeEquipmentPagination, ScopeEquipmentRead, ScopeEquipmentPagination, ScopeEquipmentRead,
ScopeEquipmentUpdate) ScopeEquipmentUpdate)
from .service import (create, delete, get_all, get_all_master_equipment, from .service import (create, delete, get_all, get_all_master_equipment, update)
get_by_assetnum, update)
router = APIRouter() router = APIRouter()
@ -22,7 +20,7 @@ router = APIRouter()
async def get_scope_equipments(common: CommonParameters, scope_name: str = Query(None)): async def get_scope_equipments(common: CommonParameters, scope_name: str = Query(None)):
"""Get all scope pagination.""" """Get all scope pagination."""
# return # return
data = await get_all(common=common, scope_name=scope_name) data = await get_all(common=common, oh_scope=scope_name)
return StandardResponse( return StandardResponse(
data=data, data=data,
@ -49,38 +47,38 @@ async def create_scope_equipment(
return StandardResponse(data=scope, message="Data created successfully") return StandardResponse(data=scope, message="Data created successfully")
@router.put("/{assetnum}", response_model=StandardResponse[ScopeEquipmentRead]) # @router.put("/{assetnum}", response_model=StandardResponse[ScopeEquipmentRead])
async def update_scope_equipment( # async def update_scope_equipment(
db_session: DbSession, assetnum: str, scope__equipment_in: ScopeEquipmentUpdate # db_session: DbSession, assetnum: str, scope__equipment_in: ScopeEquipmentUpdate
): # ):
scope_equipment = await get_by_assetnum(db_session=db_session, assetnum=assetnum) # scope_equipment = await get_by_assetnum(db_session=db_session, assetnum=assetnum)
if not scope_equipment: # if not scope_equipment:
raise HTTPException( # raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, # status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.", # detail="A data with this id does not exist.",
) # )
return StandardResponse( # return StandardResponse(
data=await update( # data=await update(
db_session=db_session, # db_session=db_session,
scope_equipment=scope_equipment, # scope_equipment=scope_equipment,
scope__equipment_in=scope__equipment_in, # scope__equipment_in=scope__equipment_in,
), # ),
message="Data updated successfully", # message="Data updated successfully",
) # )
@router.delete("/{assetnum}", response_model=StandardResponse[None]) # @router.delete("/{assetnum}", response_model=StandardResponse[None])
async def delete_scope_equipment(db_session: DbSession, assetnum: str): # async def delete_scope_equipment(db_session: DbSession, assetnum: str):
scope_equipment = await get_by_assetnum(db_session=db_session, assetnum=assetnum) # scope_equipment = await get_by_assetnum(db_session=db_session, assetnum=assetnum)
if not scope_equipment: # if not scope_equipment:
raise HTTPException( # raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, # status_code=status.HTTP_404_NOT_FOUND,
detail=[{"msg": "A data with this id does not exist."}], # detail=[{"msg": "A data with this id does not exist."}],
) # )
await delete(db_session=db_session, assetnum=assetnum) # await delete(db_session=db_session, assetnum=assetnum)
return StandardResponse(message="Data deleted successfully", data=None) # return StandardResponse(message="Data deleted successfully", data=None)

@ -32,7 +32,7 @@ class ScopeEquipmentUpdate(ScopeEquipmentBase):
class ScopeEquipmentRead(ScopeEquipmentBase): class ScopeEquipmentRead(ScopeEquipmentBase):
id: UUID id: UUID
assetnum: str location_tag: str
assigned_date: datetime assigned_date: datetime
master_equipment: Optional[MasterEquipmentBase] = Field(None) master_equipment: Optional[MasterEquipmentBase] = Field(None)
@ -40,9 +40,6 @@ class ScopeEquipmentRead(ScopeEquipmentBase):
class ScopeEquipmentPagination(Pagination): class ScopeEquipmentPagination(Pagination):
items: List[ScopeEquipmentRead] = [] items: List[ScopeEquipmentRead] = []
class MasterEquipmentRead(DefultBase): class MasterEquipmentRead(DefultBase):
assetnum: Optional[str] = Field(None, title="Asset Number") assetnum: Optional[str] = Field(None, title="Asset Number")
location_tag: Optional[str] = Field(None, title="Location Tag") location_tag: Optional[str] = Field(None, title="Location Tag")

@ -0,0 +1,212 @@
from datetime import datetime, timedelta
from typing import Optional, Union
from fastapi import HTTPException, status
from sqlalchemy import Delete, Select, and_, desc, func, not_, or_
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import selectinload
from src.auth.service import CurrentUser
from src.database.core import DbSession
from src.database.service import CommonParameters, search_filter_sort_paginate
from src.overhaul_scope.model import OverhaulScope
from src.standard_scope.enum import ScopeEquipmentType
from src.standard_scope.model import EquipmentOHHistory
from src.workorder.model import MasterWorkOrder
from src.equipment_workscope_group.model import EquipmentWorkscopeGroup
from src.workscope_group.model import MasterActivity
from src.workscope_group_maintenance_type.model import WorkscopeOHType
from src.overhaul_scope.model import MaintenanceType
from src.overhaul_scope.service import get as get_overhaul
from .model import MasterEquipment, MasterEquipmentTree, StandardScope
from .schema import ScopeEquipmentCreate, ScopeEquipmentUpdate
from uuid import UUID
async def get_by_location_tag(*, db_session: DbSession, location_tag: str):
query = (
Select(StandardScope)
.filter(StandardScope.location_tag == location_tag)
.options(selectinload(StandardScope.master_equipment))
)
result = await db_session.execute(query)
return result.unique().scalars().one_or_none()
async def get_all(*, common, oh_scope: Optional[str] = None):
"""Returns all documents."""
query = Select(StandardScope).options(
selectinload(StandardScope.master_equipment)
)
query = query.order_by(desc(StandardScope.created_at)).options(selectinload(StandardScope.master_equipment))
if oh_scope:
query = (
query
.outerjoin(StandardScope.oh_history) # Use outerjoin to handle None values
.join(StandardScope.workscope_groups)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(MaintenanceType.name == oh_scope)
# .filter(
# (StandardScope.is_alternating_oh == False) |
# (StandardScope.oh_history == None) |
# (StandardScope.oh_history.has(EquipmentOHHistory.last_oh_type != selected_overhaul.maintenance_type.name))
# ).distinct()
)
results = await search_filter_sort_paginate(model=query, **common)
return results
async def get_by_oh_session_id(*, db_session: DbSession, oh_session_id: UUID):
overhaul = await get_overhaul(db_session=db_session, overhaul_session_id=oh_session_id)
query = (
Select(StandardScope)
.outerjoin(StandardScope.oh_history) # Use outerjoin to handle None values
.join(StandardScope.workscope_groups)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(MaintenanceType.name == overhaul.maintenance_type.name).filter(
(StandardScope.is_alternating_oh == False) |
(StandardScope.oh_history == None) |
(StandardScope.oh_history.has(EquipmentOHHistory.last_oh_type != overhaul.maintenance_type.name))
).distinct()
)
result = await db_session.execute(query)
return result.scalars().all(), overhaul
async def create(*, db_session: DbSession, scope_equipment_in: ScopeEquipmentCreate):
"""Creates a new document."""
# scope_equipment = StandardScope(**scope_equipment_in.model_dump())
assetnums = scope_equipment_in.assetnums
results = []
removal_date = scope_equipment_in.removal_date
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)
)
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(StandardScope).values(
assetnum=assetnum,
scope_overhaul=scope_equipment_in.scope_name,
type=scope_equipment_in.type,
removal_date=removal_date,
)
stmt = stmt.on_conflict_do_nothing(
index_elements=["assetnum", "scope_overhaul"]
)
await db_session.execute(stmt)
results.append(assetnum)
await db_session.commit()
return results
async def update(
*,
db_session: DbSession,
scope_equipment: StandardScope,
scope_equipment_in: ScopeEquipmentUpdate
):
"""Updates a document."""
data = scope_equipment_in.model_dump()
update_data = scope_equipment_in.model_dump(exclude_defaults=True)
for field in data:
if field in update_data:
setattr(scope_equipment, field, update_data[field])
await db_session.commit()
return scope_equipment
async def delete(*, db_session: DbSession, assetnum: str):
"""Deletes a document."""
query = Delete(StandardScope).where(StandardScope.assetnum == assetnum)
await db_session.execute(query)
await db_session.commit()
return assetnum
async def get_by_oh_scope(
*, db_session: DbSession, oh_scope: str
):
pass
query = (Select(StandardScope)
.outerjoin(StandardScope.oh_history) # Use outerjoin to handle None values
.join(StandardScope.workscope_groups)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(MaintenanceType.name == oh_scope)
# .filter(
# (StandardScope.is_alternating_oh == False) |
# (StandardScope.oh_history == None) |
# (StandardScope.oh_history.has(EquipmentOHHistory.last_oh_type != selected_overhaul.maintenance_type.name))
# ).distinct()
)
results = await db_session.execute(query)
return results.scalars().all()
async def get_all_master_equipment(*, common: CommonParameters, scope_name):
equipments_scope = [
equip.location_tag
for equip in await get_by_oh_scope(
db_session=common.get("db_session"), oh_scope=scope_name
)
]
query = Select(MasterEquipment).filter(MasterEquipment.location_tag.is_not(None))
# Only add not_in filter if there are items in equipments_scope
if equipments_scope:
query = query.filter(MasterEquipment.location_tag.not_in(equipments_scope))
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(MasterEquipment)
.join(MasterEquipment.equipment_tree)
.where(MasterEquipmentTree.level_no == level)
)
result = await db_session.execute(query)
return result.scalars().all()

@ -13,8 +13,8 @@ class MasterWorkOrder(Base, DefaultMixin):
workgroup = Column(String, nullable=True) workgroup = Column(String, nullable=True)
total_cost_max = Column(Float, nullable=True) total_cost_max = Column(Float, nullable=True)
scope_equipments = relationship( # scope_equipments = relationship(
"ScopeEquipment", # "ScopeEquipment",
lazy="raise", # lazy="raise",
primaryjoin="and_(MasterWorkOrder.assetnum == foreign(ScopeEquipment.assetnum))", # primaryjoin="and_(MasterWorkOrder.assetnum == foreign(ScopeEquipment.assetnum))",
) # )

@ -8,19 +8,20 @@ from src.workorder.model import MasterWorkOrder
class MasterActivitytask(Base, DefaultMixin): class MasterActivitytask(Base, DefaultMixin):
__tablename__ = "oh_ms_job_task" __tablename__ = "oh_ms_workscope_task"
description = Column(String, nullable=False) description = Column(String, nullable=False)
oh_type = Column(String, nullable=False)
job_id = Column( job_id = Column(
UUID(as_uuid=True), UUID(as_uuid=True),
ForeignKey("oh_ms_job.id", ondelete="cascade"), ForeignKey("oh_ms_workscope_group.id", ondelete="cascade"),
nullable=False, nullable=False,
) )
class MasterActivity(Base, DefaultMixin): class MasterActivity(Base, DefaultMixin):
__tablename__ = "oh_ms_job" __tablename__ = "oh_ms_workscope_group"
workscope = Column(String, nullable=True) workscope = Column(String, nullable=True)
system = Column(String, nullable=True) system = Column(String, nullable=True)
@ -31,6 +32,19 @@ class MasterActivity(Base, DefaultMixin):
lazy="selectin", lazy="selectin",
) )
equipment_workscope_groups = relationship(
"EquipmentWorkscopeGroup",
lazy="selectin",
back_populates="workscope_group",
)
oh_types = relationship(
"WorkscopeOHType",
lazy="selectin",
back_populates="workscope_group",
)
# details = relationship( # details = relationship(
# "MasterActivityDetail", # "MasterActivityDetail",
# lazy="raise", # lazy="raise",

@ -21,7 +21,6 @@ class ActivityMasterCreate(ActivityMaster):
class ActivityMasterTasks(DefultBase): class ActivityMasterTasks(DefultBase):
description: str description: str
oh_type: str
class ActivityMasterRead(ActivityMaster): class ActivityMasterRead(ActivityMaster):

@ -0,0 +1,18 @@
from sqlalchemy import UUID, Column, Float, ForeignKey, Integer, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from src.database.core import Base
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin
from src.workorder.model import MasterWorkOrder
class WorkscopeOHType(Base):
__tablename__ = 'oh_tr_workscope_maintenance_type'
id = Column(UUID(as_uuid=True), primary_key=True)
workscope_group_id = Column(UUID(as_uuid=True), ForeignKey('oh_ms_workscope_group.id'))
maintenance_type_id = Column(UUID(as_uuid=True), ForeignKey('oh_ms_maintenance_type.id'))
workscope_group = relationship('MasterActivity', back_populates='oh_types')
oh_type = relationship('MaintenanceType')

@ -0,0 +1,59 @@
from typing import Optional
from sqlalchemy import Delete, Select
from sqlalchemy.orm import joinedload, selectinload
from src.auth.service import CurrentUser
from src.database.core import DbSession
from src.database.service import CommonParameters, search_filter_sort_paginate
from .model import MasterActivity
from .schema import ActivityMaster, ActivityMasterCreate
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)
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()
Loading…
Cancel
Save