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 typing import Any, Dict
|
||||
|
||||
import httpx
|
||||
from fastapi import HTTPException
|
||||
from starlette.config import Config
|
||||
|
||||
from src.config import MAXIMO_API_KEY, MAXIMO_BASE_URL
|
||||
|
||||
|
||||
class MaximoDataMapper:
|
||||
"""
|
||||
Helper class to map MAXIMO API response to our data structure.
|
||||
Update these mappings according to actual MAXIMO API documentation.
|
||||
"""
|
||||
|
||||
def __init__(self, maximo_data: Dict[Any, Any]):
|
||||
self.data = maximo_data
|
||||
|
||||
def get_start_date(self) -> datetime:
|
||||
"""
|
||||
Extract start date from MAXIMO data.
|
||||
TODO: Update this based on actual MAXIMO API response structure
|
||||
Example: might be data['startDate'] or data['SCHEDSTART'] etc.
|
||||
"""
|
||||
# This is a placeholder - update with actual MAXIMO field name
|
||||
start_date_str = self.data.get("scheduleStart")
|
||||
if not start_date_str:
|
||||
raise ValueError("Start date not found in MAXIMO data")
|
||||
return datetime.fromisoformat(start_date_str)
|
||||
|
||||
def get_end_date(self) -> datetime:
|
||||
"""
|
||||
Extract end date from MAXIMO data.
|
||||
TODO: Update this based on actual MAXIMO API response structure
|
||||
"""
|
||||
# This is a placeholder - update with actual MAXIMO field name
|
||||
end_date_str = self.data.get("scheduleEnd")
|
||||
if not end_date_str:
|
||||
raise ValueError("End date not found in MAXIMO data")
|
||||
return datetime.fromisoformat(end_date_str)
|
||||
|
||||
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)}"
|
||||
)
|
||||
from datetime import datetime
|
||||
from sqlalchemy import select, func, cast, Numeric
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.sql import not_
|
||||
from src.maximo.model import WorkOrderData # Assuming this is where your model is
|
||||
from src.database.core import CollectorDbSession
|
||||
|
||||
|
||||
async def get_cm_cost_summary(collector_db: CollectorDbSession, last_oh_date:datetime, upcoming_oh_date:datetime):
|
||||
query = select(
|
||||
WorkOrderData.location,
|
||||
(func.sum(WorkOrderData.total_cost_max).cast(Numeric) / func.count(WorkOrderData.wonum)).label('avg_cost')
|
||||
).where(
|
||||
and_(
|
||||
# WorkOrderData.wo_start >= last_oh_date,
|
||||
# WorkOrderData.wo_start <= upcoming_oh_date,
|
||||
WorkOrderData.worktype.in_(['CM', 'EM', 'PROACTIVE']),
|
||||
WorkOrderData.system_tag.in_(['HPB', 'AH', 'APC', 'SCR', 'CL', 'DM', 'CRH', 'ASH', 'BAD', 'DS', 'WTP',
|
||||
'MT', 'SUP', 'DCS', 'FF', 'EG', 'AI', 'SPS', 'EVM', 'SCW', 'KLH', 'CH',
|
||||
'TUR', 'LOT', 'HRH', 'ESP', 'CAE', 'GMC', 'BFT', 'LSH', 'CHB', 'BSS',
|
||||
'LOS', 'LPB', 'SAC', 'CP', 'EHS', 'RO', 'GG', 'MS', 'CW', 'SO', 'ATT',
|
||||
'AFG', 'EHB', 'RP', 'FO', 'PC', 'APE', 'AF', 'DMW', 'BRS', 'GEN', 'ABS',
|
||||
'CHA', 'TR', 'H2', 'BDW', 'LOM', 'ACR', 'AL', 'FW', 'COND', 'CCCW', 'IA',
|
||||
'GSS', 'BOL', 'SSB', 'CO', 'OA', 'CTH-UPD', 'AS', 'DP']),
|
||||
WorkOrderData.reportdate.is_not(None),
|
||||
WorkOrderData.actstart.is_not(None),
|
||||
WorkOrderData.actfinish.is_not(None),
|
||||
WorkOrderData.unit.in_([3, 0]),
|
||||
WorkOrderData.reportdate >= datetime.strptime('2015-01-01', '%Y-%m-%d'),
|
||||
not_(WorkOrderData.wonum.like('T%'))
|
||||
)
|
||||
).group_by(
|
||||
WorkOrderData.location
|
||||
).order_by(
|
||||
func.count(WorkOrderData.wonum).desc()
|
||||
)
|
||||
result = await collector_db.execute(query)
|
||||
data = result.all()
|
||||
|
||||
return {
|
||||
data.location: data.avg_cost for data in data
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue