add and delete scope q

feature/reliability_stat
Cizz22 3 months ago
parent 69bb64cf48
commit 94e362eecd

16
.env

@ -9,9 +9,15 @@ DATABASE_CREDENTIAL_USER=postgres
DATABASE_CREDENTIAL_PASSWORD=postgres
DATABASE_NAME=digital_twin
COLLECTOR_HOSTNAME=192.168.1.82
COLLECTOR_PORT=1111
COLLECTOR_CREDENTIAL_USER=digital_twin
COLLECTOR_CREDENTIAL_PASSWORD=Pr0jec7@D!g!tTwiN
COLLECTOR_NAME=digital_twin
# COLLECTOR_HOSTNAME=192.168.1.82
# COLLECTOR_PORT=1111
# COLLECTOR_CREDENTIAL_USER=digital_twin
# COLLECTOR_CREDENTIAL_PASSWORD=Pr0jec7@D!g!tTwiN
# COLLECTOR_NAME=digital_twin
COLLECTOR_HOSTNAME=192.168.1.86
COLLECTOR_PORT=5432
COLLECTOR_CREDENTIAL_USER=postgres
COLLECTOR_CREDENTIAL_PASSWORD=postgres
COLLECTOR_NAME=digital_twin

@ -10,7 +10,7 @@ from src.models import StandardResponse
from .schema import (OverhaulActivityCreate, OverhaulActivityPagination,
OverhaulActivityRead, OverhaulActivityUpdate)
from .service import add_multiple_equipment_to_session, create, delete, get, get_all, update
from .service import add_multiple_equipment_to_session, get, get_all, remove_equipment_from_session, update
router = APIRouter()
@ -79,46 +79,38 @@ async def get_overhaul_equipment(
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.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],
"/{overhaul_session}/{location_tag}",
response_model=StandardResponse[None],
)
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)
async def delete_scope(db_session: DbSession, location_tag: str, overhaul_session:UUID):
await remove_equipment_from_session(db_session=db_session, overhaul_session_id=overhaul_session, location_tag=location_tag)
return StandardResponse(message="Data deleted successfully", data=activity)
return StandardResponse(message="Data deleted successfully", data=None)

@ -1,8 +1,9 @@
import asyncio
import datetime
from typing import List, Optional
from uuid import UUID
from uuid import UUID, uuid4
from sqlalchemy import Delete, Select, func, select
from sqlalchemy import Delete, Select, and_, func, select
from sqlalchemy import update as sqlUpdate
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import joinedload, selectinload
@ -213,8 +214,8 @@ async def add_equipment_to_session(
) -> Optional[StandardScope]:
"""
Add a new equipment to an existing overhaul session.
Creates a dummy workscope group if needed.
Silently skips if equipment already exists in the session.
If equipment's workscope already maps to the overhaul type, skip.
Otherwise, attach a dummy workscope group for inclusion.
Args:
db_session: Database session
@ -223,99 +224,97 @@ async def add_equipment_to_session(
location_tag: The location tag of the equipment to add
Returns:
StandardScope: The newly created StandardScope record, or None if already exists
StandardScope: The newly created or updated StandardScope record, or None if skipped
"""
try:
# Get the overhaul session
overhaul = await get_session(db_session=db_session, overhaul_session_id=overhaul_session_id)
overhaul = await get_session(
db_session=db_session, overhaul_session_id=overhaul_session_id
)
# Check if MasterEquipment exists
master_eq_query = select(MasterEquipment).filter(
MasterEquipment.location_tag == location_tag
)
master_eq_result = await db_session.execute(master_eq_query)
master_equipment = master_eq_result.scalar_one_or_none()
if not master_equipment:
print("equipment not found in master")
print("Equipment not found in master")
return None
# Check if equipment already exists in StandardScope
existing_query = select(StandardScope).filter(
StandardScope.location_tag == location_tag
)
existing_result = await db_session.execute(existing_query)
existing_equipment = existing_result.scalar_one_or_none()
if existing_equipment:
# Equipment already in StandardScope, check if it's in current session
# by verifying if it matches the session's maintenance type criteria
check_query = (
Select(StandardScope)
.outerjoin(StandardScope.oh_history)
.join(StandardScope.workscope_groups)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(StandardScope.location_tag == location_tag)
.filter(MaintenanceType.name == overhaul.maintenance_type.name)
.filter(
(StandardScope.is_alternating_oh == False)
| (StandardScope.oh_history is None)
| (
StandardScope.oh_history.has(
EquipmentOHHistory.last_oh_type != overhaul.maintenance_type.name
)
)
)
# --- Step 1: Fetch equipment's actual workscope mappings ---
eq_workscope_query = (
select(EquipmentWorkscopeGroup)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(
WorkscopeOHType,
WorkscopeOHType.workscope_group_id == MasterActivity.id,
)
.join(
MaintenanceType,
MaintenanceType.id == WorkscopeOHType.maintenance_type_id,
)
.filter(EquipmentWorkscopeGroup.location_tag == location_tag)
)
eq_workscopes = (await db_session.execute(eq_workscope_query)).scalars().all()
# --- Step 2: Check if already included via natural workscope ---
is_already_included = any(
ws.workscope_group
and any(
wot.oh_type.name == overhaul.maintenance_type.name
for wot in ws.workscope_group.oh_types
)
check_result = await db_session.execute(check_query)
in_session = check_result.scalar_one_or_none()
if in_session:
# Already in current session, skip silently
return None
# Equipment exists but not in this session, need to add workscope
# Find or create dummy workscope group
for ws in eq_workscopes
)
if is_already_included:
# Already belongs to this overhaul naturally → skip
return None
# --- Step 3: Handle existing equipment ---
if existing_equipment:
# Add dummy workscope if not already attached
dummy_workscope = await get_or_create_dummy_workscope(
db_session=db_session,
maintenance_type_name=overhaul.maintenance_type.name
maintenance_type_name=overhaul.maintenance_type.name,
)
# Add the dummy workscope to existing equipment if not already there
if dummy_workscope not in existing_equipment.workscope_groups:
existing_equipment.workscope_groups.append(dummy_workscope)
dummy_workscope.location_tag = location_tag
await db_session.commit()
await db_session.refresh(existing_equipment)
return existing_equipment
# Equipment not in StandardScope at all, create new
# First, get or create dummy workscope group
# --- Step 4: Create new StandardScope for fresh equipment ---
dummy_workscope = await get_or_create_dummy_workscope(
db_session=db_session,
maintenance_type_name=overhaul.maintenance_type.name
maintenance_type_name=overhaul.maintenance_type.name,
)
# Create new StandardScope record
new_equipment = StandardScope(
location_tag=location_tag,
is_alternating_oh=False,
# Add other required fields based on your model
is_alternating_oh=True,
assigned_date=datetime.date.today(),
)
# Associate with dummy workscope group
new_equipment.workscope_groups = [dummy_workscope]
dummy_workscope.location_tag = location_tag
db_session.add(new_equipment)
await db_session.commit()
await db_session.refresh(new_equipment)
return new_equipment
except Exception as e:
# Log the error but don't raise it
print(f"Error adding equipment {location_tag}: {str(e)}")
await db_session.rollback()
return None
@ -324,7 +323,7 @@ async def add_equipment_to_session(
async def get_or_create_dummy_workscope(
*,
db_session: DbSession,
maintenance_type_name: str
maintenance_type_name: str,
) -> EquipmentWorkscopeGroup:
"""
Get or create a dummy workscope group for included equipment.
@ -337,50 +336,49 @@ async def get_or_create_dummy_workscope(
EquipmentWorkscopeGroup: The dummy workscope group
"""
dummy_name = f"Included Equipment Workscope - {maintenance_type_name}"
# Check if dummy workscope already exists
query = (
select(EquipmentWorkscopeGroup)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(MasterActivity.oh_types)
.join(WorkscopeOHType.oh_type)
.filter(MasterActivity.name == dummy_name)
.filter(MaintenanceType.name == maintenance_type_name)
)
# --- Step 1: Check if dummy MasterActivity exists ---
query = select(MasterActivity).filter(MasterActivity.workscope == dummy_name)
result = await db_session.execute(query)
existing = result.scalar_one_or_none()
if existing:
return existing
# Create dummy workscope group
# First, get the maintenance type
master_activity = result.scalar_one_or_none()
if not master_activity:
master_activity = MasterActivity(workscope=dummy_name)
db_session.add(master_activity)
await db_session.commit()
await db_session.refresh(master_activity)
# --- Step 2: Ensure WorkscopeOHType link exists ---
mt_query = select(MaintenanceType).filter(MaintenanceType.name == maintenance_type_name)
mt_result = await db_session.execute(mt_query)
maintenance_type = mt_result.scalar_one()
# Create MasterActivity (workscope_group)
master_activity = MasterActivity(
workscope=dummy_name,
)
# Create WorkscopeOHType relationship
workscope_oh_type = WorkscopeOHType(
workscope_group=master_activity,
oh_type=maintenance_type
wo_oh_type_query = select(WorkscopeOHType).filter(
and_(
WorkscopeOHType.workscope_group_id == master_activity.id,
WorkscopeOHType.maintenance_type_id == maintenance_type.id,
)
)
# Create EquipmentWorkscopeGroup
workscope_oh_type = (await db_session.execute(wo_oh_type_query)).scalar_one_or_none()
if not workscope_oh_type:
workscope_oh_type = WorkscopeOHType(
id=uuid4(),
workscope_group=master_activity,
oh_type=maintenance_type,
)
db_session.add(workscope_oh_type)
await db_session.commit()
await db_session.refresh(workscope_oh_type)
# --- Step 3: Create new EquipmentWorkscopeGroup ---
equipment_workscope_group = EquipmentWorkscopeGroup(
workscope_group=master_activity,
# Add other required fields
)
db_session.add(equipment_workscope_group)
await db_session.commit()
await db_session.refresh(equipment_workscope_group)
return equipment_workscope_group
@ -433,62 +431,6 @@ async def get_all_by_session_id(*, db_session: DbSession, overhaul_session_id):
async def create(
*,
db_session: DbSession,
overhaul_activty_in: OverhaulActivityCreate,
overhaul_session_id: UUID
):
"""Creates a new document."""
assetnums = overhaul_activty_in.assetnums
if not assetnums:
return []
# Get session and count in parallel
session = await get_session(
db_session=db_session, overhaul_session_id=overhaul_session_id
)
equipment_count = await db_session.scalar(
select(func.count())
.select_from(OverhaulActivity)
.where(OverhaulActivity.overhaul_scope_id == overhaul_session_id)
)
# Calculate costs for all records
total_equipment = equipment_count + len(assetnums)
material_cost = get_material_cost(
scope=session.type, total_equipment=total_equipment
)
service_cost = get_service_cost(scope=session.type, total_equipment=total_equipment)
# Create the insert statement
stmt = insert(OverhaulActivity).values(
[
{
"assetnum": assetnum,
"overhaul_scope_id": overhaul_session_id,
"material_cost": material_cost,
"service_cost": service_cost,
}
for assetnum in assetnums
]
)
# Add the ON CONFLICT DO NOTHING clause
stmt = stmt.on_conflict_do_nothing(index_elements=["assetnum", "overhaul_scope_id"])
# Execute the statement
await db_session.execute(stmt)
await db_session.execute(
sqlUpdate(OverhaulActivity)
.where(OverhaulActivity.overhaul_scope_id == overhaul_session_id)
.values(material_cost=material_cost, service_cost=service_cost)
)
await db_session.commit()
return assetnums
async def update(
*,
db_session: DbSession,
@ -509,8 +451,95 @@ async def update(
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()
async def remove_equipment_from_session(
*,
db_session: DbSession,
overhaul_session_id: UUID,
location_tag: str
) -> bool:
"""
Remove equipment from a given overhaul session.
Only removes dummy workscope group links; natural workscope mappings are preserved.
Args:
db_session: Database session
overhaul_session_id: The UUID of the overhaul session
location_tag: The location tag of the equipment to remove
Returns:
bool: True if removed, False if skipped (not found or naturally included)
"""
try:
# Get the overhaul session
overhaul = await get_session(
db_session=db_session, overhaul_session_id=overhaul_session_id
)
# Find the equipment in StandardScope
existing_query = select(StandardScope).filter(
StandardScope.location_tag == location_tag
)
existing_result = await db_session.execute(existing_query)
equipment = existing_result.scalar_one_or_none()
if not equipment:
print(f"Equipment {location_tag} not found in StandardScope")
return False
# --- Step 1: Check if equipment belongs naturally (exclude dummy groups) ---
eq_workscope_query = (
select(EquipmentWorkscopeGroup)
.join(EquipmentWorkscopeGroup.workscope_group)
.join(
WorkscopeOHType,
WorkscopeOHType.workscope_group_id == MasterActivity.id,
)
.join(
MaintenanceType,
MaintenanceType.id == WorkscopeOHType.maintenance_type_id,
)
.filter(EquipmentWorkscopeGroup.location_tag == location_tag)
.filter(~MasterActivity.workscope.like("Included Equipment Workscope%")) # 🚨 exclude dummy
)
eq_workscopes = (await db_session.execute(eq_workscope_query)).scalars().all()
is_natural_inclusion = any(
ws.workscope_group
and any(
wot.oh_type.name == overhaul.maintenance_type.name
for wot in ws.workscope_group.oh_types
)
for ws in eq_workscopes
)
if is_natural_inclusion:
print(f"Equipment {location_tag} is naturally part of OH {overhaul.maintenance_type.name}, skip removal")
return False
# --- Step 2: Remove dummy workscope group for this overhaul ---
dummy_name = f"Included Equipment Workscope - {overhaul.maintenance_type.name}"
dummy_group = next(
(wg for wg in equipment.workscope_groups if wg.workscope_group.workscope == dummy_name),
None,
)
if dummy_group:
equipment.workscope_groups.remove(dummy_group)
await db_session.commit()
await db_session.refresh(equipment)
# --- Step 3 (optional): Delete StandardScope if no groups left ---
if not equipment.workscope_groups:
await db_session.delete(equipment)
await db_session.commit()
print(f"Equipment {location_tag} completely removed from StandardScope")
return True
print(f"No dummy workscope group found for {location_tag} in OH {overhaul.maintenance_type.name}")
return False
except Exception as e:
print(f"Error removing equipment {location_tag}: {str(e)}")
await db_session.rollback()
return False

Loading…
Cancel
Save