@ -18,6 +18,8 @@ import os
sys . path . append ( os . path . abspath ( os . path . join ( os . path . dirname ( __file__ ) , " .. " ) ) )
from config import get_connection
from modules . equipment . formula import rc_labor_cost , rc_lost_cost , rc_total_cost
import json
load_dotenv ( )
@ -332,6 +334,80 @@ class Prediksi:
finally :
if connection :
connection . close ( )
def __get_asset_criticality_params ( self , equipment_id ) :
try :
connections = get_connection ( )
connection = (
connections [ 0 ] if isinstance ( connections , tuple ) else connections
)
if connection is None :
print ( " Database connection failed. " )
return None
cursor = connection . cursor ( cursor_factory = DictCursor )
# Query untuk mendapatkan asset criticality
query = """
SELECT row_to_json ( t ) AS asset_criticality
FROM (
SELECT
asset_crit_ens_energy_not_served ,
asset_crit_bpp_system ,
asset_crit_bpp_pembangkit ,
asset_crit_dmn_daya_mampu_netto ,
asset_crit_marginal_cost ,
asset_crit_efdh_equivalent_force_derated_hours ,
asset_crit_foh_force_outage_hours ,
asset_crit_extra_fuel_cost
FROM lcc_ms_equipment_data
WHERE assetnum = % s
) t
"""
cursor . execute ( query , ( equipment_id , ) )
result = cursor . fetchone ( )
asset_crit = result . get ( " asset_criticality " ) if result else None
if not asset_crit :
return None
# asset_crit may already be a dict (from row_to_json) or a JSON string
try :
ac = asset_crit if isinstance ( asset_crit , dict ) else json . loads ( asset_crit )
except Exception :
ac = { }
def _f ( key ) :
try :
return float ( ac . get ( key ) or 0.0 )
except Exception :
return 0.0
ens = _f ( " asset_crit_ens_energy_not_served " ) # ENS
bpp_syst = _f ( " asset_crit_bpp_system " ) # BPP_SYST
dmn = _f ( " asset_crit_dmn_daya_mampu_netto " ) # DMN
extra_fuel = _f ( " asset_crit_extra_fuel_cost " ) # Extra Fuel Cost
# Formula from image:
# Asset Criticality = (ENS/1 hour * (7% * BPP_SYST)) + ((DMN - ENS/1 hour) * Extra Fuel Cost)
# ENS/1 hour is ENS (division by 1)
part1 = ens * ( 0.07 * bpp_syst )
part2 = max ( 0.0 , ( dmn - ens ) ) * extra_fuel
asset_criticality = part1 + part2
efdh = _f ( " asset_crit_efdh_equivalent_force_derated_hours " ) # EFDH
foh = _f ( " asset_crit_foh_force_outage_hours " )
return {
" asset_criticality " : asset_criticality ,
" efdh_oh_sum " : efdh + foh ,
}
except Exception as e :
print ( f " Error saat mendapatkan asset criticality dari database: { e } " )
return None
finally :
if connection :
connection . close ( )
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
def __update_data_lcc ( self , equipment_id ) :
@ -344,46 +420,181 @@ class Prediksi:
print ( " Database connection failed. " )
return None
cursor = connection . cursor ( )
cursor = connection . cursor ( cursor_factory = DictCursor )
# Query untuk menghapus data berdasarkan tahun proyeksi
up_query = """
update lcc_equipment_tr_data
set
rc_cm_material_cost = raw_cm_material_cost
, rc_cm_labor_cost = ( raw_cm_interval * raw_cm_labor_time * raw_cm_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) )
, rc_pm_material_cost = raw_pm_material_cost
, rc_pm_labor_cost = ( raw_pm_labor_time * raw_pm_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) )
, rc_predictive_labor_cost = COALESCE ( ( raw_predictive_labor_time * raw_predictive_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) ) , 0 )
, rc_oh_material_cost = raw_oh_material_cost
, rc_oh_labor_cost = ( raw_oh_labor_time * raw_oh_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) )
, rc_project_material_cost = coalesce ( raw_project_task_material_cost , 0 )
, rc_lost_cost = coalesce ( ( " raw_loss_output_MW " * raw_loss_output_price * raw_cm_interval ) , 0 ) * 1000
, rc_operation_cost = coalesce ( raw_operational_cost , 0 )
, rc_maintenance_cost = coalesce ( raw_maintenance_cost , 0 )
, rc_total_cost = (
raw_cm_material_cost
+ ( raw_cm_interval * raw_cm_labor_time * raw_cm_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) )
+ raw_pm_material_cost
+ ( raw_pm_labor_time * raw_pm_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) )
+ COALESCE ( ( raw_predictive_labor_time * raw_predictive_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) ) , 0 )
+ raw_oh_material_cost
+ ( raw_oh_labor_time * raw_oh_labor_human * COALESCE ( ( SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_equipment_tr_data . tahun ) , coalesce ( ( select value_num from lcc_ms_master where name = ' manhours_rate ' ) , 0 ) ) )
+ coalesce ( raw_project_task_material_cost , 0 )
+ coalesce ( ( " raw_loss_output_MW " * raw_loss_output_price * raw_cm_interval ) , 0 ) * 1000
+ coalesce ( raw_operational_cost , 0 )
+ coalesce ( raw_maintenance_cost , 0 )
# Ambil semua baris untuk assetnum
select_q = '''
SELECT id , seq , tahun ,
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_predictive_interval , raw_predictive_material_cost , raw_predictive_labor_time , raw_predictive_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_loss_output_MW " as raw_loss_output_mw , raw_loss_output_price ,
raw_operational_cost , raw_maintenance_cost , rc_material_cost
FROM lcc_equipment_tr_data
WHERE assetnum = % s ;
'''
cursor . execute ( select_q , ( equipment_id , ) )
rows = cursor . fetchall ( )
# Helper to get man_hour for a year (fallback to master 'manhours_rate')
def _get_man_hour_for_year ( year ) :
try :
cur = connection . cursor ( )
cur . execute ( " SELECT man_hour FROM lcc_ms_year_data WHERE year = %s " , ( year , ) )
r = cur . fetchone ( )
if r and r [ 0 ] is not None :
return float ( r [ 0 ] )
cur . execute ( " SELECT value_num FROM lcc_ms_master WHERE name= ' manhours_rate ' " )
r2 = cur . fetchone ( )
if r2 and r2 [ 0 ] is not None :
return float ( r2 [ 0 ] )
except Exception :
pass
return 0.0
update_q = '''
UPDATE lcc_equipment_tr_data
SET rc_cm_material_cost = % s ,
rc_cm_labor_cost = % s ,
rc_pm_material_cost = % s ,
rc_pm_labor_cost = % s ,
rc_predictive_material_cost = % s ,
rc_predictive_labor_cost = % s ,
rc_oh_material_cost = % s ,
rc_oh_labor_cost = % s ,
rc_lost_cost = % s ,
rc_operation_cost = % s ,
rc_maintenance_cost = % s ,
rc_total_cost = % s ,
updated_by = ' Sys ' , updated_at = NOW ( )
WHERE id = % s ;
'''
for r in rows :
try :
yr = r . get ( " tahun " ) if isinstance ( r , dict ) else r [ 2 ]
man_hour = _get_man_hour_for_year ( yr )
raw_cm_interval = float ( r . get ( " raw_cm_interval " ) or 0.0 )
raw_cm_labor_time = float ( r . get ( " raw_cm_labor_time " ) or 0.0 )
raw_cm_labor_human = float ( r . get ( " raw_cm_labor_human " ) or 0.0 )
raw_pm_interval = float ( r . get ( " raw_pm_interval " ) or 0.0 )
raw_pm_material_cost = float ( r . get ( " raw_pm_material_cost " ) or 0.0 )
raw_pm_labor_time = float ( r . get ( " raw_pm_labor_time " ) or 0.0 )
raw_pm_labor_human = float ( r . get ( " raw_pm_labor_human " ) or 0.0 )
raw_predictive_interval = float ( r . get ( " raw_predictive_interval " ) or 0.0 )
raw_predictive_material_cost = float ( r . get ( " raw_predictive_material_cost " ) or 0.0 )
raw_predictive_labor_time = float ( r . get ( " raw_predictive_labor_time " ) or 0.0 )
raw_predictive_labor_human = float ( r . get ( " raw_predictive_labor_human " ) or 0.0 )
raw_oh_interval = float ( r . get ( " raw_oh_interval " ) or 0.0 )
raw_oh_material_cost = float ( r . get ( " raw_oh_material_cost " ) or 0.0 )
raw_oh_labor_time = float ( r . get ( " raw_oh_labor_time " ) or 0.0 )
raw_oh_labor_human = float ( r . get ( " raw_oh_labor_human " ) or 0.0 )
raw_loss_output_mw = float ( r . get ( " raw_loss_output_mw " ) or 0.0 )
raw_loss_output_price = float ( r . get ( " raw_loss_output_price " ) or 0.0 )
raw_operational_cost = float ( r . get ( " raw_operational_cost " ) or 0.0 )
raw_maintenance_cost = float ( r . get ( " raw_maintenance_cost " ) or 0.0 )
rc_cm_material_cost = float ( r . get ( " rc_cm_material_cost " ) or 0.0 )
# compute per-column costs using helpers
rc_cm_material = rc_cm_material_cost
rc_cm_labor = rc_labor_cost ( raw_cm_interval , raw_cm_labor_time , raw_cm_labor_human , man_hour )
try :
if np . isfinite ( raw_pm_interval ) and raw_pm_interval != 0 :
rc_pm_material = raw_pm_material_cost * raw_pm_interval
else :
rc_pm_material = raw_pm_material_cost
except Exception :
rc_pm_material = 0.0
rc_pm_labor = rc_labor_cost ( raw_pm_interval , raw_pm_labor_time , raw_pm_labor_human , man_hour )
try :
if np . isfinite ( raw_predictive_interval ) and raw_predictive_interval != 0 :
rc_predictive_material = raw_predictive_material_cost * raw_predictive_interval
else :
rc_predictive_material = raw_predictive_material_cost
except Exception :
rc_predictive_material = 0.0
rc_predictive_labor = raw_predictive_labor_human
try :
rc_predictive_labor = rc_labor_cost ( raw_predictive_interval , raw_predictive_labor_time , raw_predictive_labor_human , man_hour )
except Exception :
rc_predictive_labor = 0.0
rc_oh_material = raw_oh_material_cost
rc_oh_labor = rc_labor_cost ( raw_oh_interval , raw_oh_labor_time , raw_oh_labor_human , man_hour )
rc_lost = rc_lost_cost ( raw_loss_output_mw , raw_loss_output_price , raw_cm_interval )
rc_operation = raw_operational_cost
rc_maintenance = raw_maintenance_cost
asset_criticality_data = self . __get_asset_criticality_params ( equipment_id )
asset_criticality_value = 0.0
# Simplify extraction and avoid repeating the multiplication
ac = asset_criticality_data if isinstance ( asset_criticality_data , dict ) else { }
try :
efdh_oh_sum = float ( ac . get ( " efdh_oh_sum " , 0.0 ) )
except Exception :
efdh_oh_sum = 0.0
try :
asset_criticality_value = float ( ac . get ( " asset_criticality " , 0.0 ) )
except Exception :
asset_criticality_value = 0.0
# single multiplier used for all RC groups
ac_multiplier = efdh_oh_sum * asset_criticality_value
total = rc_total_cost (
rc_cm = rc_cm_material + rc_cm_labor + ac_multiplier ,
rc_pm = rc_pm_material + rc_pm_labor + ac_multiplier ,
rc_predictive = rc_predictive_material + rc_predictive_labor + ac_multiplier ,
rc_oh = rc_oh_material + rc_oh_labor + ac_multiplier ,
rc_lost = rc_lost ,
rc_operation = rc_operation ,
rc_maintenance = rc_maintenance ,
)
, updated_by = ' Sys ' , updated_at = NOW ( )
where assetnum = % s ;
update lcc_equipment_tr_data set rc_total_cost = ( select acquisition_cost from lcc_ms_equipment_data where assetnum = lcc_equipment_tr_data . assetnum ) where assetnum = % s and seq = 0 ;
""" # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
id_val = r . get ( " id " ) if isinstance ( r , dict ) else r [ 0 ]
cursor . execute (
update_q ,
(
rc_cm_material ,
rc_cm_labor ,
rc_pm_material ,
rc_pm_labor ,
rc_predictive_material ,
rc_predictive_labor ,
rc_oh_material ,
rc_oh_labor ,
rc_lost ,
rc_operation ,
rc_maintenance ,
total ,
id_val ,
) ,
)
except Exception :
# ignore row-specific errors and continue
continue
# For seq=0 rows, set rc_total_cost to acquisition_cost
cursor . execute (
" update lcc_equipment_tr_data set rc_total_cost = (select acquisition_cost from lcc_ms_equipment_data where assetnum=lcc_equipment_tr_data.assetnum) where assetnum = %s and seq=0; " ,
( equipment_id , )
)
# Eksekusi query delete
cursor . execute ( up_query , ( equipment_id , equipment_id ) )
connection . commit ( )
# print(f"Data berhasil diupdate.")
except Exception as e :
print ( f " Error saat update data proyeksi dari database: { e } " )
@ -440,6 +651,9 @@ class Prediksi:
if connection :
connection . close ( )
# Authentication: sign-in and refresh helpers
async def sign_in ( self , username : str = " user14 " , password : str = " password " ) - > dict :
""" Sign in to AUTH_APP_URL/sign-in using provided username/password.