|
|
|
|
@ -862,6 +862,178 @@ 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
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Logic: if current_target matches the "old default" (old_acq + life), then update it too.
|
|
|
|
|
is_valid_default = (curr_target == (curr_acq + curr_life))
|
|
|
|
|
|
|
|
|
|
if curr_acq != first_year:
|
|
|
|
|
print(f"Acquisition year change detected for {assetnum}: {curr_acq} -> {first_year}. 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
|
|
|
|
|
WHERE assetnum = %s
|
|
|
|
|
"""
|
|
|
|
|
cursor.execute(update_q, (first_year, new_target, assetnum))
|
|
|
|
|
|
|
|
|
|
conn.commit()
|
|
|
|
|
print(f"Updated acquisition_year for {assetnum}: {curr_acq} -> {first_year}. History archived.")
|
|
|
|
|
updated_acq = first_year
|
|
|
|
|
else:
|
|
|
|
|
print(f"No acquisition year update needed for {assetnum}. Current: {curr_acq}, New: {first_year}")
|
|
|
|
|
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
|
|
|
|
|
@ -874,6 +1046,7 @@ async def query_data(target_assetnum: str = None):
|
|
|
|
|
print("Database connection failed.")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Membuat cursor menggunakan DictCursor
|
|
|
|
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
|
|
|
|
cursor_wo = connection_production_wo.cursor(cursor_factory=DictCursor)
|
|
|
|
|
@ -973,6 +1146,11 @@ async def query_data(target_assetnum: str = None):
|
|
|
|
|
print(f"[{idx}/{total_assets}] Skipping empty assetnum")
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
forecasting_start_year_db = row.get("forecasting_start_year")
|
|
|
|
|
acquisition_year = row.get("acquisition_year")
|
|
|
|
|
|
|
|
|
|
|