Update maximo
parent
8ae93be047
commit
536c8fc889
@ -0,0 +1,42 @@
|
|||||||
|
from sqlalchemy import Column, BigInteger, Integer, Float, String, Text, DateTime
|
||||||
|
from src.database.core import CollectorBase
|
||||||
|
|
||||||
|
|
||||||
|
class WorkOrderData(CollectorBase):
|
||||||
|
__tablename__ = "wo_staging_3"
|
||||||
|
|
||||||
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||||
|
assetnum = Column(Text, nullable=True)
|
||||||
|
description1 = Column(Text, nullable=True)
|
||||||
|
unit = Column(Integer, nullable=True)
|
||||||
|
location = Column(String(25), nullable=True)
|
||||||
|
system_tag = Column(String(25), nullable=True)
|
||||||
|
wonum = Column(String(10), nullable=True)
|
||||||
|
description2 = Column(Text, nullable=True)
|
||||||
|
wo_complt_comment = Column(Text, nullable=True)
|
||||||
|
worktype = Column(String(10), nullable=True)
|
||||||
|
jpnum = Column(String(10), nullable=True)
|
||||||
|
workgroup = Column(String(30), nullable=True)
|
||||||
|
mat_cost_max = Column(Float, nullable=True)
|
||||||
|
serv_cost_max = Column(Float, nullable=True)
|
||||||
|
total_cost_max = Column(Float, nullable=True)
|
||||||
|
wo_start = Column(DateTime, nullable=True)
|
||||||
|
wo_finish = Column(DateTime, nullable=True)
|
||||||
|
wo_start_olah = Column(DateTime, nullable=True)
|
||||||
|
wo_finish_olah = Column(DateTime, nullable=True)
|
||||||
|
reportdate = Column(DateTime, nullable=True)
|
||||||
|
reportdate_olah = Column(DateTime, nullable=True)
|
||||||
|
time_to_event = Column(Float, nullable=True)
|
||||||
|
actstart = Column(DateTime, nullable=True)
|
||||||
|
actfinish = Column(DateTime, nullable=True)
|
||||||
|
actstart_olah = Column(DateTime, nullable=True)
|
||||||
|
actfinish_olah = Column(DateTime, nullable=True)
|
||||||
|
act_repair_time = Column(Float, nullable=True)
|
||||||
|
jumlah_labor = Column(Integer, nullable=True)
|
||||||
|
need_downtime = Column(String(100), nullable=True)
|
||||||
|
validation_downtime = Column(Integer, nullable=True)
|
||||||
|
down_0_and_not_oh = Column(Integer, nullable=True)
|
||||||
|
downtime = Column(Integer, nullable=True)
|
||||||
|
failure_code = Column(String(10), nullable=True)
|
||||||
|
problem_code = Column(String(10), nullable=True)
|
||||||
|
act_finish_wo_start = Column(Float, nullable=True)
|
||||||
@ -1,154 +1,43 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime
|
||||||
from typing import Any, Dict
|
from sqlalchemy import select, func, cast, Numeric
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
import httpx
|
from sqlalchemy import and_
|
||||||
from fastapi import HTTPException
|
from sqlalchemy.sql import not_
|
||||||
from starlette.config import Config
|
from src.maximo.model import WorkOrderData # Assuming this is where your model is
|
||||||
|
from src.database.core import CollectorDbSession
|
||||||
from src.config import MAXIMO_API_KEY, MAXIMO_BASE_URL
|
|
||||||
|
|
||||||
|
async def get_cm_cost_summary(collector_db: CollectorDbSession, last_oh_date:datetime, upcoming_oh_date:datetime):
|
||||||
class MaximoDataMapper:
|
query = select(
|
||||||
"""
|
WorkOrderData.location,
|
||||||
Helper class to map MAXIMO API response to our data structure.
|
(func.sum(WorkOrderData.total_cost_max).cast(Numeric) / func.count(WorkOrderData.wonum)).label('avg_cost')
|
||||||
Update these mappings according to actual MAXIMO API documentation.
|
).where(
|
||||||
"""
|
and_(
|
||||||
|
# WorkOrderData.wo_start >= last_oh_date,
|
||||||
def __init__(self, maximo_data: Dict[Any, Any]):
|
# WorkOrderData.wo_start <= upcoming_oh_date,
|
||||||
self.data = maximo_data
|
WorkOrderData.worktype.in_(['CM', 'EM', 'PROACTIVE']),
|
||||||
|
WorkOrderData.system_tag.in_(['HPB', 'AH', 'APC', 'SCR', 'CL', 'DM', 'CRH', 'ASH', 'BAD', 'DS', 'WTP',
|
||||||
def get_start_date(self) -> datetime:
|
'MT', 'SUP', 'DCS', 'FF', 'EG', 'AI', 'SPS', 'EVM', 'SCW', 'KLH', 'CH',
|
||||||
"""
|
'TUR', 'LOT', 'HRH', 'ESP', 'CAE', 'GMC', 'BFT', 'LSH', 'CHB', 'BSS',
|
||||||
Extract start date from MAXIMO data.
|
'LOS', 'LPB', 'SAC', 'CP', 'EHS', 'RO', 'GG', 'MS', 'CW', 'SO', 'ATT',
|
||||||
TODO: Update this based on actual MAXIMO API response structure
|
'AFG', 'EHB', 'RP', 'FO', 'PC', 'APE', 'AF', 'DMW', 'BRS', 'GEN', 'ABS',
|
||||||
Example: might be data['startDate'] or data['SCHEDSTART'] etc.
|
'CHA', 'TR', 'H2', 'BDW', 'LOM', 'ACR', 'AL', 'FW', 'COND', 'CCCW', 'IA',
|
||||||
"""
|
'GSS', 'BOL', 'SSB', 'CO', 'OA', 'CTH-UPD', 'AS', 'DP']),
|
||||||
# This is a placeholder - update with actual MAXIMO field name
|
WorkOrderData.reportdate.is_not(None),
|
||||||
start_date_str = self.data.get("scheduleStart")
|
WorkOrderData.actstart.is_not(None),
|
||||||
if not start_date_str:
|
WorkOrderData.actfinish.is_not(None),
|
||||||
raise ValueError("Start date not found in MAXIMO data")
|
WorkOrderData.unit.in_([3, 0]),
|
||||||
return datetime.fromisoformat(start_date_str)
|
WorkOrderData.reportdate >= datetime.strptime('2015-01-01', '%Y-%m-%d'),
|
||||||
|
not_(WorkOrderData.wonum.like('T%'))
|
||||||
def get_end_date(self) -> datetime:
|
)
|
||||||
"""
|
).group_by(
|
||||||
Extract end date from MAXIMO data.
|
WorkOrderData.location
|
||||||
TODO: Update this based on actual MAXIMO API response structure
|
).order_by(
|
||||||
"""
|
func.count(WorkOrderData.wonum).desc()
|
||||||
# This is a placeholder - update with actual MAXIMO field name
|
)
|
||||||
end_date_str = self.data.get("scheduleEnd")
|
result = await collector_db.execute(query)
|
||||||
if not end_date_str:
|
data = result.all()
|
||||||
raise ValueError("End date not found in MAXIMO data")
|
|
||||||
return datetime.fromisoformat(end_date_str)
|
return {
|
||||||
|
data.location: data.avg_cost for data in data
|
||||||
def get_maximo_id(self) -> str:
|
}
|
||||||
"""
|
|
||||||
Extract MAXIMO ID from response.
|
|
||||||
TODO: Update this based on actual MAXIMO API response structure
|
|
||||||
"""
|
|
||||||
# This is a placeholder - update with actual MAXIMO field name
|
|
||||||
maximo_id = self.data.get("workOrderId")
|
|
||||||
if not maximo_id:
|
|
||||||
raise ValueError("MAXIMO ID not found in response")
|
|
||||||
return str(maximo_id)
|
|
||||||
|
|
||||||
def get_status(self) -> str:
|
|
||||||
"""
|
|
||||||
Extract status from MAXIMO data.
|
|
||||||
TODO: Update this based on actual MAXIMO API response structure
|
|
||||||
"""
|
|
||||||
# This is a placeholder - update with actual MAXIMO status field and values
|
|
||||||
status = self.data.get("status", "").upper()
|
|
||||||
return status
|
|
||||||
|
|
||||||
def get_total_cost(self) -> float:
|
|
||||||
"""
|
|
||||||
Extract total cost from MAXIMO data.
|
|
||||||
TODO: Update this based on actual MAXIMO API response structure
|
|
||||||
"""
|
|
||||||
# This is a placeholder - update with actual MAXIMO field name
|
|
||||||
cost = self.data.get("totalCost", 0)
|
|
||||||
return float(cost)
|
|
||||||
|
|
||||||
def get_scope_name(self) -> str:
|
|
||||||
scope_name = self.data.get("location", "A")
|
|
||||||
return scope_name
|
|
||||||
|
|
||||||
|
|
||||||
class MaximoService:
|
|
||||||
def __init__(self):
|
|
||||||
# TODO: Update these settings based on actual MAXIMO API configuration
|
|
||||||
self.base_url = MAXIMO_BASE_URL
|
|
||||||
self.api_key = MAXIMO_API_KEY
|
|
||||||
|
|
||||||
async def get_recent_overhaul(self) -> dict:
|
|
||||||
"""
|
|
||||||
Fetch most recent overhaul from MAXIMO.
|
|
||||||
TODO: Update this method based on actual MAXIMO API endpoints and parameters
|
|
||||||
"""
|
|
||||||
current_date = datetime.now()
|
|
||||||
schedule_start = current_date + timedelta(days=30) # Starting in 30 days
|
|
||||||
schedule_end = schedule_start + timedelta(days=90) # 90 day overhaul period
|
|
||||||
|
|
||||||
return {
|
|
||||||
"scheduleStart": schedule_start.isoformat(),
|
|
||||||
"scheduleEnd": schedule_end.isoformat(),
|
|
||||||
"workOrderId": "WO-2024-12345",
|
|
||||||
"status": "PLAN", # Common Maximo statuses: SCHEDULED, INPRG, COMP, CLOSE
|
|
||||||
"totalCost": 10000000.00,
|
|
||||||
"description": "Annual Turbine Overhaul",
|
|
||||||
"priority": 1,
|
|
||||||
"location": "A",
|
|
||||||
"assetDetails": [
|
|
||||||
{
|
|
||||||
"assetnum": "ASSET001",
|
|
||||||
"description": "Gas Turbine",
|
|
||||||
"status": "OPERATING",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"assetnum": "ASSET002",
|
|
||||||
"description": "Steam Turbine",
|
|
||||||
"status": "OPERATING",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"workType": "OH", # OH for Overhaul
|
|
||||||
"createdBy": "MAXADMIN",
|
|
||||||
"createdDate": (current_date - timedelta(days=10)).isoformat(),
|
|
||||||
"lastModifiedBy": "MAXADMIN",
|
|
||||||
"lastModifiedDate": current_date.isoformat(),
|
|
||||||
}
|
|
||||||
|
|
||||||
async with httpx.AsyncClient() as client:
|
|
||||||
try:
|
|
||||||
# TODO: Update endpoint and parameters based on actual MAXIMO API
|
|
||||||
response = await client.get(
|
|
||||||
f"{self.base_url}/your-endpoint-here",
|
|
||||||
headers={
|
|
||||||
"Authorization": f"Bearer {self.api_key}",
|
|
||||||
# Add any other required headers
|
|
||||||
},
|
|
||||||
params={
|
|
||||||
# Update these parameters based on actual MAXIMO API
|
|
||||||
"orderBy": "-scheduleEnd", # Example parameter
|
|
||||||
"limit": 1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=response.status_code,
|
|
||||||
detail=f"MAXIMO API error: {response.text}",
|
|
||||||
)
|
|
||||||
|
|
||||||
data = response.json()
|
|
||||||
if not data:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=404, detail="No recent overhaul found"
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: Update this based on actual MAXIMO response structure
|
|
||||||
return data[0] if isinstance(data, list) else data
|
|
||||||
|
|
||||||
except httpx.RequestError as e:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=503, detail=f"Failed to connect to MAXIMO: {str(e)}"
|
|
||||||
)
|
|
||||||
|
|||||||
Loading…
Reference in New Issue