@ -126,35 +126,35 @@ class Prediksi:
return fv_values
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
def __delete_predictions_from_db ( 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
# def __delete_predictions_from_db(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 = connection.cursor()
# Query untuk menghapus data berdasarkan tahun proyeksi
delete_query = """
DELETE FROM lcc_equipment_tr_data
WHERE assetnum = % s AND is_actual = 0 ;
""" # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
# # Query untuk menghapus data berdasarkan tahun proyeksi
# delete_query = """
# DELETE FROM lcc_equipment_tr_data
# WHERE assetnum = %s AND is_actual = 0 ;
# """ # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
# Eksekusi query delete
cursor . execute ( delete_query , ( equipment_id , ) )
connection . commit ( )
# print(f"Data proyeksi untuk tahun {equipment_id} berhasil dihapus.")
# # Eksekusi query delete
# cursor.execute(delete_query, (equipment_id,) )
# connection.commit( )
# # print(f"Data proyeksi untuk tahun {equipment_id} berhasil dihapus.")
except Exception as e :
print ( f " Error saat menghapus data proyeksi dari database: { e } " )
# except Exception as e :
# print(f"Error saat menghapus data proyeksi dari database: {e}")
finally :
if connection :
connection . close ( )
# finally:
# if connection:
# connection.close( )
# Fungsi untuk menyimpan data proyeksi ke database
async def __insert_predictions_to_db ( self , data , equipment_id , token ) :
@ -707,6 +707,75 @@ class Prediksi:
# ======================================================================================================================================================
async def _fetch_api_data ( self , assetnum : str , year : int ) - > dict :
url = self . RELIABILITY_APP_URL
endpoint = f " { url } /main/number-of-failures/ { assetnum } / { int ( year ) } / { int ( year ) } "
async with httpx . AsyncClient ( ) as client :
try :
current_token = getattr ( self , " access_token " , None )
response = await client . get (
endpoint ,
timeout = 30.0 ,
headers = { " Authorization " : f " Bearer { current_token } " } if current_token else { } ,
)
response . raise_for_status ( )
return response . json ( )
except httpx . HTTPStatusError as e :
status = getattr ( e . response , " status_code " , None )
# If we get a 401 or 403, try to refresh the access token and retry once
if status in ( 401 , 403 ) :
print ( f " Received { status } from reliability API, attempting to refresh/re-login... " )
# Try refreshing token first
new_access = await self . refresh_access_token ( )
# If refresh failed (e.g. refresh token expired), try full sign-in
if not new_access :
print ( " Refresh failed, attempting full sign-in... " )
await self . sign_in ( )
new_access = getattr ( self , " access_token " , None )
if new_access :
try :
response = await client . get (
endpoint ,
timeout = 30.0 ,
headers = { " Authorization " : f " Bearer { new_access } " } ,
)
response . raise_for_status ( )
return response . json ( )
except httpx . HTTPError as e2 :
print ( f " HTTP error occurred after retry: { e2 } " )
return { }
print ( f " HTTP error occurred: { e } " )
return { }
except httpx . HTTPError as e :
print ( f " HTTP error occurred: { e } " )
return { }
def __get_man_hour_rate ( self , staff_level : str = " junior " ) :
connection = None
try :
connections = get_connection ( )
connection = (
connections [ 0 ] if isinstance ( connections , tuple ) else connections
)
if connection is None :
return 0.0
cursor = connection . cursor ( )
# Takes from salary_per_hour_idr on specific staff_job_level
query = " SELECT salary_per_hour_idr FROM lcc_manpower_cost WHERE staff_job_level = %s LIMIT 1 "
cursor . execute ( query , ( staff_level , ) )
result = cursor . fetchone ( )
if result :
return float ( result [ 0 ] )
return 0.0
except Exception as e :
print ( f " Error getting man hour rate for { staff_level } : { e } " )
return 0.0
finally :
if connection :
connection . close ( )
async def predict_equipment_data ( self , assetnum , token ) :
try :
# Mengambil data dari database
@ -759,6 +828,7 @@ class Prediksi:
# Mendapatkan rate dan tahun maksimal
rate , max_year = self . __get_rate_and_max_year ( assetnum )
man_hour_rate = self . __get_man_hour_rate ( ) # Defaults to 'junior'
pmt = 0
# Prediksi untuk setiap kolom
@ -788,8 +858,28 @@ class Prediksi:
recent_vals = df [ column ] . dropna ( )
# Jika masih kosong, pakai default (interval minimal 1, lainnya 0)
if recent_vals . empty :
if " labor " in col_lower :
preds_list = [ ]
for yr in future_years :
failures_data = await self . _fetch_api_data ( assetnum , yr )
# Interval from number of failures
interval = 0.0
if isinstance ( failures_data , dict ) :
val = failures_data . get ( " data " )
if val is not None :
try :
interval = float ( val )
except Exception :
interval = 0.0
# interval * labor_time(3) * labor_human(1) * man_hour_rate
cost = rc_labor_cost ( interval , 3.0 , 1.0 , man_hour_rate )
preds_list . append ( cost )
preds = np . array ( preds_list , dtype = float )
elif recent_vals . empty :
avg = 0.0
preds = np . repeat ( float ( avg ) , n_future )
else :
avg = pd . to_numeric ( recent_vals , errors = " coerce " ) . fillna ( 0 ) . mean ( )
avg = 0.0 if pd . isna ( avg ) else float ( avg )
@ -957,22 +1047,22 @@ async def main(RELIABILITY_APP_URL=RELIABILITY_APP_URL, assetnum=None, token=Non
prediksi = Prediksi ( RELIABILITY_APP_URL )
# If token not provided, sign in to obtain access_token/refresh_token
# if token is None :
# signin_res = await prediksi.sign_in()
# if not getattr(prediksi, "access_token", None):
# print("Failed to obtain access token; aborting." )
# return
# else :
# # Use provided token as access token
# prediksi.access_token = token
if token is None :
signin_res = await prediksi . sign_in ( )
if not getattr ( prediksi , " access_token " , None ) :
print ( " Failed to obtain access token; aborting. " )
return
else :
# Use provided token as access token
prediksi . access_token = token
# If an assetnum was provided, run only for that assetnum
if assetnum :
print ( f " Pr ocess ing single assetnum: { assetnum } " )
print ( f " Pr edict ing single assetnum: { assetnum } " )
try :
await prediksi . predict_equipment_data ( assetnum , prediksi . access_token )
except Exception as e :
print ( f " Error process ing { assetnum } : { e } " )
print ( f " Error Predict ing { assetnum } : { e } " )
print ( " Selesai. " )
return
@ -993,11 +1083,11 @@ async def main(RELIABILITY_APP_URL=RELIABILITY_APP_URL, assetnum=None, token=Non
if not current_asset or str ( current_asset ) . strip ( ) == " " :
print ( f " [ { idx } / { len ( results ) } ] Skipping empty assetnum " )
continue
print ( f " [ { idx } / { len ( results ) } ] Pr ocess ing assetnum: { current_asset } " )
print ( f " [ { idx } / { len ( results ) } ] Pr edict ing assetnum: { current_asset } " )
try :
await prediksi . predict_equipment_data ( current_asset , prediksi . access_token )
except Exception as e :
print ( f " Error process ing { current_asset } : { e } " )
print ( f " Error Predict ing { current_asset } : { e } " )
print ( " Selesai. " )
except Exception as e :