diff --git a/src/overhaul_gantt/router.py b/src/overhaul_gantt/router.py index 21972a2..8967895 100644 --- a/src/overhaul_gantt/router.py +++ b/src/overhaul_gantt/router.py @@ -14,16 +14,19 @@ router = APIRouter() @router.get( - "", response_model=StandardResponse[list] + "", response_model=StandardResponse[dict] ) async def get_gantt_performance(): """Get all scope pagination.""" # return - results = await get_gantt_performance_chart() + results, gantt_data = await get_gantt_performance_chart() return StandardResponse( - data=results, + data={ + "chart_data": results, + "gantt_data": gantt_data + }, message="Data retrieved successfully", ) diff --git a/src/overhaul_gantt/service.py b/src/overhaul_gantt/service.py index ae69552..00dd155 100644 --- a/src/overhaul_gantt/service.py +++ b/src/overhaul_gantt/service.py @@ -6,7 +6,7 @@ from sqlalchemy.orm import selectinload # from .model import OverhaulSchedule # from .schema import OverhaulScheduleCreate, OverhaulScheduleUpdate -from .utils import get_google_creds, get_spreatsheed_service, process_spreadsheet_data +from .utils import fetch_all_sections, get_google_creds, get_spreatsheed_service, process_spreadsheet_data # async def get_all(*, common): # """Returns all documents.""" @@ -54,6 +54,7 @@ from .utils import get_google_creds, get_spreatsheed_service, process_spreadshee async def get_gantt_performance_chart(*, spreadsheet_id = "1gZXuwA97zU1v4QBv56wKeiqadc6skHUucGKYG8qVFRk"): creds = get_google_creds() RANGE_NAME = "'2024 kurva s'!N79:BJ83" # Or just "2024 schedule" + GANTT_DATA_NAME = "2024 schedule" try: service = get_spreatsheed_service(creds) @@ -63,10 +64,13 @@ async def get_gantt_performance_chart(*, spreadsheet_id = "1gZXuwA97zU1v4QBv56wK keys = ['day', 'time', 'plan', 'actual', 'gap'] transposed = list(zip(*values)) results = [dict(zip(keys, result)) for result in transposed] + except Exception as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=e) processed_data = process_spreadsheet_data(results) + gantt_data = fetch_all_sections(service=service, spreadsheet_id=spreadsheet_id, sheet_name=GANTT_DATA_NAME) + - return processed_data + return processed_data, gantt_data diff --git a/src/overhaul_gantt/utils.py b/src/overhaul_gantt/utils.py index 89fdf6e..193a07e 100644 --- a/src/overhaul_gantt/utils.py +++ b/src/overhaul_gantt/utils.py @@ -63,3 +63,66 @@ def convert_spreadsheet_data(data): result[key] = float(value) / 100 # Divide by 100 to get the actual decimal value return result + +def fetch_all_sections(service, spreadsheet_id, sheet_name): + result = service.spreadsheets().values().get( + spreadsheetId=spreadsheet_id, + range=f"{sheet_name}!A18:1000" # start from row 19, adjust Z if needed + ).execute() + values = result.get("values", []) + if not values: + raise ValueError("No data found in sheet") + + data = [] + current_section = None + current_subsystem = None + header = None + + + for i, row in enumerate(values): + row = [c.strip() for c in row] # clean whitespace + + # Skip completely empty rows + if all(c == "" for c in row): + continue + + # Detect section headers (usually in col A, all caps) + if row[0]: + # skip unwanted section title + if row[0] == "U4 PLANNED OUTAGE 2024": + continue + current_section = row[0] + current_subsystem = None + header = None + continue + + # Detect subsystem (non-all-caps in col A) + if row[1]: + current_subsystem = row[1] + continue + + # Otherwise, treat as task row (must have header defined) + if row[2]: + task = row[2] + pic = row[3] + start_date = row[4] + finish_date = row[5] + duration = row[6] + plan = row[7] + actual = row[8] + gap = row[9] + + data.append({ + "section": current_section, + "subsystem": current_subsystem, + "task": task, + "PIC": pic, + "start_date": start_date, + "end_date": finish_date, + "duration": duration, + "plan": plan, + "actual": actual, + "gap": gap + }) + + return data \ No newline at end of file diff --git a/src/sparepart/service.py b/src/sparepart/service.py index d776038..79fb367 100644 --- a/src/sparepart/service.py +++ b/src/sparepart/service.py @@ -242,6 +242,7 @@ class SparepartRequirement: lead_time: int sparepart_name: str unit_cost: float + avg_cost: float @dataclass class SparepartStock: @@ -395,7 +396,7 @@ class SparepartManager: sparepart_id = requirement.sparepart_id needed_quantity = requirement.quantity_required sparepart_name = requirement.sparepart_name - unit_cost = requirement.unit_cost + unit_cost = requirement.avg_cost current_stock = adjusted_stocks.get(sparepart_id, 0) @@ -917,6 +918,12 @@ item_descriptions AS ( ) as description FROM public.maximo_sparepart_pr_po_line WHERE description IS NOT NULL +), +item_inventory as ( + SELECT + itemnum, + avgcost + FROM public.maximo_inventory ) SELECT lss.asset_location, @@ -927,6 +934,7 @@ SELECT ROUND(CAST(lss.avg_qty_per_wo AS NUMERIC), 2) as avg_qty_per_wo, lss.min_qty_used, lss.max_qty_used, + iin.avgcost, -- Lead time metrics COALESCE(lt.avg_leadtime_months, 0) as avg_leadtime_months, COALESCE(lt.min_leadtime_months, 0) as min_leadtime_months, @@ -947,6 +955,7 @@ FROM location_sparepart_stats lss LEFT JOIN item_descriptions id ON lss.itemnum = id.item_num LEFT JOIN leadtime_stats lt ON lss.itemnum = lt.item_num LEFT JOIN cost_stats cs ON lss.itemnum = cs.item_num +LEFT JOIN item_inventory iin ON lss.itemnum = iin.itemnum ORDER BY lss.asset_location, lss.itemnum;""") equipment_requirements_query = await db_session.execute(query) @@ -958,7 +967,8 @@ ORDER BY lss.asset_location, lss.itemnum;""") quantity_required=float(req_record.avg_qty_per_wo), lead_time=float(req_record.avg_leadtime_months), sparepart_name=req_record.item_description, - unit_cost=float(req_record.avg_unit_cost) + unit_cost=float(req_record.avg_unit_cost), + avg_cost=float(req_record.avgcost) ) equipment_requirements[req_record.asset_location].append(requirement)