diff --git a/src/equipment/__pycache__/router.cpython-311.pyc b/src/equipment/__pycache__/router.cpython-311.pyc index f8e1b4d..8fc6a3c 100644 Binary files a/src/equipment/__pycache__/router.cpython-311.pyc and b/src/equipment/__pycache__/router.cpython-311.pyc differ diff --git a/src/equipment/__pycache__/service.cpython-311.pyc b/src/equipment/__pycache__/service.cpython-311.pyc index 5377a84..1905fec 100644 Binary files a/src/equipment/__pycache__/service.cpython-311.pyc and b/src/equipment/__pycache__/service.cpython-311.pyc differ diff --git a/src/equipment/router.py b/src/equipment/router.py index c845735..262b47a 100644 --- a/src/equipment/router.py +++ b/src/equipment/router.py @@ -89,8 +89,6 @@ async def simulate_equipment(db_session: DbSession, assetnum: str): await update_initial_simulation_data(db_session=db_session, assetnum=assetnum) yield f"data: {json.dumps({'status':'completed','step':'checking update','message':'Initial data check completed'})}\n\n" except Exception as e: - # Log error but proceed? Or maybe yield an error? - # For now, we proceed as this is an enhancement check. print(f"Update simulation data failed: {e}") yield f"data: {json.dumps({'status':'error','step':'checking update','message':f'Update simulation data failed: {str(e)}'})}\n\n" diff --git a/src/equipment/service.py b/src/equipment/service.py index 7f5c44e..9c507d0 100644 --- a/src/equipment/service.py +++ b/src/equipment/service.py @@ -650,10 +650,11 @@ async def delete(*, db_session: DbSession, equipment_id: str): await db_session.commit() -async def update_initial_simulation_data(db_session: DbSession, assetnum: str): +async def check_and_update_acquisition_data(db_session: DbSession, assetnum: str) -> bool: """ - Update acquisition_year and acquisition_cost from wo_maximo and set default forecasting_target_year - before running simulation. + Check if acquisition year/cost in Maximo differs from local DB. + If changed, archive history, delete transaction data, update master, and return True. + Otherwise return False. """ conn = get_production_connection() first_year = None @@ -685,6 +686,8 @@ async def update_initial_simulation_data(db_session: DbSession, assetnum: str): except: pass + updates_performed = False + if first_year: # Fetch equipment to update eq = await get_by_assetnum(db_session=db_session, assetnum=assetnum) @@ -794,7 +797,17 @@ async def update_initial_simulation_data(db_session: DbSession, assetnum: str): eq.forecasting_target_year = first_year + current_life await db_session.commit() - # await db_session.refresh(eq) + updates_performed = True + + return updates_performed + - # Re-insert actual data using query_data - await query_data(target_assetnum=assetnum) +async def update_initial_simulation_data(db_session: DbSession, assetnum: str): + """ + Update acquisition_year and acquisition_cost from wo_maximo and set default forecasting_target_year + before running simulation. + """ + updated = await check_and_update_acquisition_data(db_session, assetnum) + if updated: + # Re-insert actual data using query_data + await query_data(target_assetnum=assetnum) diff --git a/src/modules/equipment/__pycache__/insert_actual_data.cpython-311.pyc b/src/modules/equipment/__pycache__/insert_actual_data.cpython-311.pyc index 307cb2d..2a6f165 100644 Binary files a/src/modules/equipment/__pycache__/insert_actual_data.cpython-311.pyc and b/src/modules/equipment/__pycache__/insert_actual_data.cpython-311.pyc differ diff --git a/src/modules/equipment/insert_actual_data.py b/src/modules/equipment/insert_actual_data.py index ec0a365..c289efc 100644 --- a/src/modules/equipment/insert_actual_data.py +++ b/src/modules/equipment/insert_actual_data.py @@ -862,183 +862,6 @@ async def insert_acquisition_cost_data(): except Exception: pass -async def update_equipment_acquisition_year(assetnum: str): - """ - Update acquisition_year from wo_maximo and set default forecasting_target_year - using raw SQL connections. - Refactored to archive historical data if acquisition year changes. - """ - try: - # 1. Fetch first acquisition year from wo_maximo (production db) - prod_conn = get_production_connection() - if not prod_conn: - print("Failed to connect to production DB for acquisition year update.") - return None - - first_year = None - try: - p_cursor = prod_conn.cursor() - query = """ - select DATE_PART('year', a.reportdate) AS year, a.replacecost - from wo_maximo a - where a.asset_replacecost > 0 - and a.asset_assetnum = %s - order by a.reportdate asc - limit 1; - """ - p_cursor.execute(query, (assetnum,)) - res = p_cursor.fetchone() - if res and res[0] is not None: - first_year = int(res[0]) - p_cursor.close() - finally: - prod_conn.close() - - if not first_year: - # No data, skip update - return None - - # 2. Update local DB - conn, _ = get_connection() - if not conn: - return None - - updated_acq = None - try: - cursor = conn.cursor(cursor_factory=DictCursor) - - # Fetch current values - cursor.execute("SELECT * FROM lcc_ms_equipment_data WHERE assetnum = %s", (assetnum,)) - current = cursor.fetchone() - - if current: - curr_acq = int(current["acquisition_year"]) - curr_life = int(current["design_life"]) - curr_target_val = current["forecasting_target_year"] - curr_target = int(curr_target_val) if curr_target_val is not None else (curr_acq + curr_life) # Fallback if none - curr_acq_cost = float(current["acquisition_cost"]) if current["acquisition_cost"] is not None else 0.0 - - - # Logic: if current_target matches the "old default" (old_acq + life), then update it too. - is_valid_default = (curr_target == (curr_acq + curr_life)) - - # Prepare target cost. If we fetched a new cost from WO, use it, else keep old. - # Note: first_acq_cost variable availability check - target_acq_cost = first_acq_cost if 'first_acq_cost' in locals() and first_acq_cost is not None else curr_acq_cost - - if curr_acq != first_year or curr_acq_cost != target_acq_cost: - print(f"Acquisition change detected for {assetnum}: Year {curr_acq}->{first_year}, Cost {curr_acq_cost}->{target_acq_cost}. Archiving history.") - - # Define reference for history - acq_year_ref = f"{curr_acq}_{curr_target}" - - # --- ARCHIVE HISTORICAL DATA --- - - # 1. Copy old equipment master data to history - history_ms_query = """ - INSERT INTO lcc_ms_equipment_historical_data ( - id, assetnum, acquisition_year, acquisition_cost, capital_cost_record_time, design_life, - forecasting_start_year, forecasting_target_year, manhours_rate, created_at, created_by, - updated_at, updated_by, min_eac_info, harga_saat_ini, minimum_eac_seq, minimum_eac_year, - minimum_eac, minimum_npv, minimum_pmt, minimum_pmt_aq_cost, minimum_is_actual, - efdh_equivalent_forced_derated_hours, foh_forced_outage_hours, category_no, proportion, - acquisition_year_ref - ) - SELECT - uuid_generate_v4(), assetnum, acquisition_year, acquisition_cost, capital_cost_record_time, design_life, - forecasting_start_year, forecasting_target_year, manhours_rate, created_at, created_by, - updated_at, updated_by, min_eac_info, harga_saat_ini, minimum_eac_seq, minimum_eac_year, - minimum_eac, minimum_npv, minimum_pmt, minimum_pmt_aq_cost, minimum_is_actual, - efdh_equivalent_forced_derated_hours, foh_forced_outage_hours, category_no, proportion, - %s - FROM lcc_ms_equipment_data - WHERE assetnum = %s - """ - cursor.execute(history_ms_query, (acq_year_ref, assetnum)) - - # 2. Copy old transaction data to lcc_equipment_historical_tr_data - # Format: {acquisition_year}_{forecasting_target_year} - - history_tr_query = """ - INSERT INTO lcc_equipment_historical_tr_data ( - id, assetnum, tahun, seq, is_actual, - raw_cm_interval, raw_cm_material_cost, raw_cm_labor_time, raw_cm_labor_human, - raw_pm_interval, raw_pm_material_cost, raw_pm_labor_time, raw_pm_labor_human, - raw_oh_interval, raw_oh_material_cost, raw_oh_labor_time, raw_oh_labor_human, - raw_predictive_interval, raw_predictive_material_cost, raw_predictive_labor_time, raw_predictive_labor_human, - raw_project_task_material_cost, "raw_loss_output_MW", raw_loss_output_price, - raw_operational_cost, raw_maintenance_cost, - rc_cm_material_cost, rc_cm_labor_cost, - rc_pm_material_cost, rc_pm_labor_cost, - rc_oh_material_cost, rc_oh_labor_cost, - rc_predictive_labor_cost, - rc_project_material_cost, rc_lost_cost, rc_operation_cost, rc_maintenance_cost, - rc_total_cost, - eac_npv, eac_annual_mnt_cost, eac_annual_acq_cost, eac_disposal_cost, eac_eac, - efdh_equivalent_forced_derated_hours, foh_forced_outage_hours, - created_by, created_at, acquisition_year_ref - ) - SELECT - uuid_generate_v4(), assetnum, tahun, seq, is_actual, - raw_cm_interval, raw_cm_material_cost, raw_cm_labor_time, raw_cm_labor_human, - raw_pm_interval, raw_pm_material_cost, raw_pm_labor_time, raw_pm_labor_human, - raw_oh_interval, raw_oh_material_cost, raw_oh_labor_time, raw_oh_labor_human, - raw_predictive_interval, raw_predictive_material_cost, raw_predictive_labor_time, raw_predictive_labor_human, - raw_project_task_material_cost, "raw_loss_output_MW", raw_loss_output_price, - raw_operational_cost, raw_maintenance_cost, - rc_cm_material_cost, rc_cm_labor_cost, - rc_pm_material_cost, rc_pm_labor_cost, - rc_oh_material_cost, rc_oh_labor_cost, - rc_predictive_labor_cost, - rc_project_material_cost, rc_lost_cost, rc_operation_cost, rc_maintenance_cost, - rc_total_cost, - eac_npv, eac_annual_mnt_cost, eac_annual_acq_cost, eac_disposal_cost, eac_eac, - efdh_equivalent_forced_derated_hours, foh_forced_outage_hours, - created_by, NOW(), %s - FROM lcc_equipment_tr_data - WHERE assetnum = %s - """ - - - cursor.execute(history_tr_query, (acq_year_ref, assetnum)) - - # 3. Delete old data - del_query = "DELETE FROM lcc_equipment_tr_data WHERE assetnum = %s" - cursor.execute(del_query, (assetnum,)) - - # 4. Update Equipment Master - new_target = curr_target - if is_valid_default: - new_target = first_year + curr_life - - update_q = """ - UPDATE lcc_ms_equipment_data - SET acquisition_year = %s, forecasting_target_year = %s, acquisition_cost = %s - WHERE assetnum = %s - """ - cursor.execute(update_q, (first_year, new_target, target_acq_cost, assetnum)) - - conn.commit() - print(f"Updated acquisition info for {assetnum}. History archived.") - updated_acq = first_year - else: - print(f"No acquisition info update needed for {assetnum}.") - updated_acq = curr_acq - else: - # Logic if equipment not found? Unlikely here. - pass - - cursor.close() - finally: - conn.close() - - return updated_acq - - except Exception as e: - print(f"Error updating acquisition year for {assetnum}: {e}") - return None - - async def query_data(target_assetnum: str = None): connection = None connection_wo_db = None @@ -1152,8 +975,16 @@ async def query_data(target_assetnum: str = None): continue # Check if there is acquisition year that need to be updated because of new equipment replacement - if assetnum: - await update_equipment_acquisition_year(assetnum) + # Only run this check if running in batch mode (no target_assetnum) + if assetnum and not target_assetnum: + from src.equipment.service import check_and_update_acquisition_data + from src.database.core import get_session + + try: + async with get_session() as session: + await check_and_update_acquisition_data(session, assetnum) + except Exception as exc: + print(f"Error checking acquisition data for {assetnum}: {exc}") forecasting_start_year_db = row.get("forecasting_start_year")