|
|
|
@ -15,10 +15,8 @@ from dotenv import load_dotenv
|
|
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
from equipment.formula import rc_labor_cost, rc_lost_cost, rc_total_cost
|
|
|
|
from .formula import rc_labor_cost, rc_lost_cost, rc_total_cost
|
|
|
|
|
|
|
|
from src.modules.config import get_connection, get_production_connection
|
|
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
|
|
|
|
|
|
from config import get_connection, get_production_connection
|
|
|
|
|
|
|
|
import json
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
|
|
load_dotenv()
|
|
|
|
load_dotenv()
|
|
|
|
@ -97,6 +95,7 @@ class Prediksi:
|
|
|
|
FROM lcc_equipment_tr_data
|
|
|
|
FROM lcc_equipment_tr_data
|
|
|
|
WHERE assetnum = %s
|
|
|
|
WHERE assetnum = %s
|
|
|
|
and is_actual=1
|
|
|
|
and is_actual=1
|
|
|
|
|
|
|
|
and seq != 0
|
|
|
|
;
|
|
|
|
;
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
cursor.execute(query, (equipment_id,))
|
|
|
|
cursor.execute(query, (equipment_id,))
|
|
|
|
@ -240,51 +239,52 @@ class Prediksi:
|
|
|
|
# print(f"HTTP error occurred: {e}")
|
|
|
|
# print(f"HTTP error occurred: {e}")
|
|
|
|
# return {}
|
|
|
|
# return {}
|
|
|
|
|
|
|
|
|
|
|
|
# Menyiapkan data untuk batch insert
|
|
|
|
# Menyiapkan data untuk batch insert atau update
|
|
|
|
# print(f"Data to be inserted: {data}")
|
|
|
|
|
|
|
|
records_to_insert = []
|
|
|
|
records_to_insert = []
|
|
|
|
for _, row in data.iterrows():
|
|
|
|
|
|
|
|
max_seq = max_seq + 1
|
|
|
|
|
|
|
|
# (token already stored before defining fetch_api_data)
|
|
|
|
|
|
|
|
# maintain previous cm_interval between iterations using attribute on fetch_api_data
|
|
|
|
|
|
|
|
# if not hasattr(fetch_api_data, "prev_cm"):
|
|
|
|
|
|
|
|
# fetch_api_data.prev_cm = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Update values from API (current year)
|
|
|
|
|
|
|
|
# api_data = await fetch_api_data(equipment_id, row["year"])
|
|
|
|
|
|
|
|
# if api_data and "data" in api_data and isinstance(api_data["data"], list) and len(api_data["data"]) > 0:
|
|
|
|
|
|
|
|
# try:
|
|
|
|
|
|
|
|
# cur_cm = float(api_data["data"][0].get("num_fail", row.get("cm_interval", 1)))
|
|
|
|
|
|
|
|
# except Exception:
|
|
|
|
|
|
|
|
# cur_cm = float(row.get("cm_interval", 1)) if not pd.isna(row.get("cm_interval", None)) else 1.0
|
|
|
|
|
|
|
|
# else:
|
|
|
|
|
|
|
|
# try:
|
|
|
|
|
|
|
|
# val = float(row.get("cm_interval", 1))
|
|
|
|
|
|
|
|
# cur_cm = val if val >= 1 else 1.0
|
|
|
|
|
|
|
|
# except Exception:
|
|
|
|
|
|
|
|
# cur_cm = 1.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Determine previous cm_interval: prefer stored prev_cm, otherwise try API for previous year, else fallback to cur_cm
|
|
|
|
check_existence_query = """
|
|
|
|
# if fetch_api_data.prev_cm is not None:
|
|
|
|
SELECT id FROM lcc_equipment_tr_data
|
|
|
|
# prev_cm = float(fetch_api_data.prev_cm)
|
|
|
|
WHERE assetnum = %s AND tahun = %s AND is_actual = 0
|
|
|
|
# else:
|
|
|
|
"""
|
|
|
|
# try:
|
|
|
|
|
|
|
|
# api_prev = await fetch_api_data(equipment_id, int(row["year"]) - 1)
|
|
|
|
|
|
|
|
# if api_prev and "data" in api_prev and isinstance(api_prev["data"], list) and len(api_prev["data"]) > 0:
|
|
|
|
|
|
|
|
# prev_cm = float(api_prev["data"][0].get("num_fail", cur_cm))
|
|
|
|
|
|
|
|
# else:
|
|
|
|
|
|
|
|
# # attempt to use any available previous value from the row if present, otherwise fallback to current
|
|
|
|
|
|
|
|
# prev_cm = float(row.get("cm_interval", cur_cm)) if not pd.isna(row.get("cm_interval", None)) else cur_cm
|
|
|
|
|
|
|
|
# except Exception:
|
|
|
|
|
|
|
|
# prev_cm = cur_cm
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# compute difference: current year interval minus previous year interval
|
|
|
|
update_query = """
|
|
|
|
# try:
|
|
|
|
UPDATE lcc_equipment_tr_data
|
|
|
|
# cm_interval_diff = float(cur_cm) - float(prev_cm)
|
|
|
|
SET
|
|
|
|
# except Exception:
|
|
|
|
rc_cm_material_cost = %s,
|
|
|
|
# cm_interval_diff = 0.0
|
|
|
|
rc_cm_labor_cost = %s,
|
|
|
|
|
|
|
|
rc_pm_material_cost = %s,
|
|
|
|
|
|
|
|
rc_pm_labor_cost = %s,
|
|
|
|
|
|
|
|
rc_oh_material_cost = %s,
|
|
|
|
|
|
|
|
rc_oh_labor_cost = %s,
|
|
|
|
|
|
|
|
rc_predictive_material_cost = %s,
|
|
|
|
|
|
|
|
rc_predictive_labor_cost = %s,
|
|
|
|
|
|
|
|
updated_by = 'Sys',
|
|
|
|
|
|
|
|
updated_at = NOW()
|
|
|
|
|
|
|
|
WHERE id = %s
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# append record using the difference for raw_cm_interval
|
|
|
|
for _, row in data.iterrows():
|
|
|
|
|
|
|
|
# Check if data exists
|
|
|
|
|
|
|
|
cursor.execute(check_existence_query, (equipment_id, int(row["year"])))
|
|
|
|
|
|
|
|
existing_record = cursor.fetchone()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if existing_record:
|
|
|
|
|
|
|
|
# Update existing record
|
|
|
|
|
|
|
|
record_id = existing_record[0]
|
|
|
|
|
|
|
|
cursor.execute(update_query, (
|
|
|
|
|
|
|
|
float(row.get("rc_cm_material_cost", 0)) if not pd.isna(row.get("rc_cm_material_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_cm_labor_cost", 0)) if not pd.isna(row.get("rc_cm_labor_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_pm_material_cost", 0)) if not pd.isna(row.get("rc_pm_material_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_pm_labor_cost", 0)) if not pd.isna(row.get("rc_pm_labor_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_oh_material_cost", 0)) if not pd.isna(row.get("rc_oh_material_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_oh_labor_cost", 0)) if not pd.isna(row.get("rc_oh_labor_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_predictive_material_cost", 0)) if not pd.isna(row.get("rc_predictive_material_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
float(row.get("rc_predictive_labor_cost", 0)) if not pd.isna(row.get("rc_predictive_labor_cost", 0)) else 0.0,
|
|
|
|
|
|
|
|
record_id
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
max_seq = max_seq + 1
|
|
|
|
|
|
|
|
# Prepare for insert
|
|
|
|
records_to_insert.append(
|
|
|
|
records_to_insert.append(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
str(uuid4()), # id
|
|
|
|
str(uuid4()), # id
|
|
|
|
@ -302,13 +302,14 @@ class Prediksi:
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# store current cm for next iteration
|
|
|
|
# Eksekusi batch insert jika ada data baru
|
|
|
|
# fetch_api_data.prev_cm = cur_cm
|
|
|
|
if records_to_insert:
|
|
|
|
|
|
|
|
|
|
|
|
# Eksekusi batch insert
|
|
|
|
|
|
|
|
cursor.executemany(insert_query, records_to_insert)
|
|
|
|
cursor.executemany(insert_query, records_to_insert)
|
|
|
|
|
|
|
|
|
|
|
|
connection.commit()
|
|
|
|
connection.commit()
|
|
|
|
# print("Data proyeksi berhasil dimasukkan ke database.")
|
|
|
|
|
|
|
|
|
|
|
|
# Recalculate total costs and update asset criticality
|
|
|
|
|
|
|
|
self.__update_data_lcc(equipment_id)
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
print(f"Error saat menyimpan data ke database: {e}")
|
|
|
|
print(f"Error saat menyimpan data ke database: {e}")
|
|
|
|
@ -713,7 +714,6 @@ class Prediksi:
|
|
|
|
if df is None:
|
|
|
|
if df is None:
|
|
|
|
print("Data tidak tersedia untuk prediksi.")
|
|
|
|
print("Data tidak tersedia untuk prediksi.")
|
|
|
|
return
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# Mendapatkan tahun proyeksi dari DB
|
|
|
|
# Mendapatkan tahun proyeksi dari DB
|
|
|
|
par_tahun_target = self.__get_param(assetnum)
|
|
|
|
par_tahun_target = self.__get_param(assetnum)
|
|
|
|
|
|
|
|
|
|
|
|
@ -771,19 +771,14 @@ class Prediksi:
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
# Case untuk kolom yang terkait dengan corrective maintenance (cm)
|
|
|
|
# Case untuk kolom yang terkait dengan corrective maintenance (cm)
|
|
|
|
if "cm" in col_lower:
|
|
|
|
if "cm" in col_lower:
|
|
|
|
# Tentukan jumlah baris recent yang dianggap actual jika kolom is_actual ada
|
|
|
|
|
|
|
|
if "is_actual" in df.columns:
|
|
|
|
|
|
|
|
recent_df = df[df["is_actual"] == 1]
|
|
|
|
|
|
|
|
recent_n = recent_df.shape[0]
|
|
|
|
|
|
|
|
avg_recent = recent_df[column].mean()
|
|
|
|
|
|
|
|
print(f"avg_recent: {avg_recent}")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
recent_df = df
|
|
|
|
recent_df = df
|
|
|
|
recent_n = df.shape[0]
|
|
|
|
recent_n = df.shape[0]
|
|
|
|
|
|
|
|
|
|
|
|
recent_n = max(1, recent_n)
|
|
|
|
recent_n = max(1, recent_n)
|
|
|
|
recent_vals = (
|
|
|
|
recent_vals = (
|
|
|
|
recent_df.sort_values("year", ascending=True)
|
|
|
|
recent_df
|
|
|
|
|
|
|
|
.sort_values("year", ascending=True)
|
|
|
|
.head(recent_n)[column]
|
|
|
|
.head(recent_n)[column]
|
|
|
|
.dropna()
|
|
|
|
.dropna()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
@ -796,18 +791,11 @@ class Prediksi:
|
|
|
|
if recent_vals.empty:
|
|
|
|
if recent_vals.empty:
|
|
|
|
avg = 0.0
|
|
|
|
avg = 0.0
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
# Pastikan numeric; jika gagal, pakai mean dari yang bisa dikonversi
|
|
|
|
avg = pd.to_numeric(recent_vals, errors="coerce").fillna(0).mean()
|
|
|
|
try:
|
|
|
|
avg = 0.0 if pd.isna(avg) else float(avg)
|
|
|
|
avg = float(np.nanmean(recent_vals.astype(float)))
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
|
|
# jika conversion gagal gunakan mean pandas (objek mungkin numeric-like)
|
|
|
|
|
|
|
|
avg = float(recent_vals.mean())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if "interval" in col_lower:
|
|
|
|
|
|
|
|
avg = max(0.0, avg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
preds = np.repeat(float(avg), n_future)
|
|
|
|
preds = np.repeat(float(avg), n_future)
|
|
|
|
print(preds)
|
|
|
|
# print(preds)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
# Untuk kolom non-cm, gunakan nilai dari last actual year bila ada,
|
|
|
|
# Untuk kolom non-cm, gunakan nilai dari last actual year bila ada,
|
|
|
|
# jika tidak ada gunakan last available non-NA value, jika tidak ada pakai 0.0
|
|
|
|
# jika tidak ada gunakan last available non-NA value, jika tidak ada pakai 0.0
|
|
|
|
@ -944,7 +932,7 @@ class Prediksi:
|
|
|
|
predictions_df = pd.DataFrame(predictions)
|
|
|
|
predictions_df = pd.DataFrame(predictions)
|
|
|
|
# print(predictions_df)
|
|
|
|
# print(predictions_df)
|
|
|
|
# Hapus data prediksi yang ada sebelumnya
|
|
|
|
# Hapus data prediksi yang ada sebelumnya
|
|
|
|
self.__delete_predictions_from_db(assetnum)
|
|
|
|
# self.__delete_predictions_from_db(assetnum)
|
|
|
|
|
|
|
|
|
|
|
|
# Insert hasil prediksi ke database
|
|
|
|
# Insert hasil prediksi ke database
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
|