feat: prediction data equipment transaction
parent
4fd187237a
commit
62eb892f7e
Binary file not shown.
Binary file not shown.
@ -1,227 +0,0 @@
|
|||||||
import psycopg2
|
|
||||||
from psycopg2.extras import DictCursor
|
|
||||||
from uuid import uuid4
|
|
||||||
from datetime import datetime
|
|
||||||
from config import get_connection
|
|
||||||
|
|
||||||
|
|
||||||
def get_recursive_query(cursor, equipment_id, worktype='CM'):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Fungsi untuk menjalankan query rekursif berdasarkan equipment_id dan worktype.
|
|
||||||
worktype memiliki nilai default 'CM'.
|
|
||||||
"""
|
|
||||||
query = f"""
|
|
||||||
SELECT
|
|
||||||
ROW_NUMBER() OVER (ORDER BY tbl.assetnum, tbl.year, tbl.worktype) AS seq,
|
|
||||||
*
|
|
||||||
FROM
|
|
||||||
(
|
|
||||||
SELECT
|
|
||||||
a.worktype,
|
|
||||||
a.assetnum,
|
|
||||||
DATE_PART('year', TO_TIMESTAMP(a.reportdate, 'YYYY-MM-DD HH24:MI:SS.US')) AS year,
|
|
||||||
COUNT(a.wonum) AS raw_corrective_failure_interval,
|
|
||||||
SUM(a.total_cost_max) AS raw_corrective_material_cost,
|
|
||||||
-- SUM(
|
|
||||||
-- (
|
|
||||||
-- (EXTRACT(HOUR FROM TO_TIMESTAMP(wo_finish, 'YYYY-MM-DD-HH24.MI.SS.US')) +
|
|
||||||
-- EXTRACT(MINUTE FROM TO_TIMESTAMP(wo_finish, 'YYYY-MM-DD-HH24.MI.SS.US')) / 60)
|
|
||||||
-- -
|
|
||||||
-- (EXTRACT(HOUR FROM TO_TIMESTAMP(wo_start, 'YYYY-MM-DD-HH24.MI.SS.US')) +
|
|
||||||
-- EXTRACT(MINUTE FROM TO_TIMESTAMP(wo_start, 'YYYY-MM-DD-HH24.MI.SS.US')) / 60)
|
|
||||||
-- )
|
|
||||||
-- *
|
|
||||||
-- ((DATE_PART('day', TO_TIMESTAMP(a.wo_finish, 'YYYY-MM-DD-HH24.MI.SS.US') -
|
|
||||||
-- TO_TIMESTAMP(a.wo_start, 'YYYY-MM-DD-HH24.MI.SS.US'))) + 1)
|
|
||||||
-- ) AS raw_corrective_labor_time_jam,
|
|
||||||
ROUND(SUM(EXTRACT(EPOCH FROM (TO_TIMESTAMP(a.actfinish, 'YYYY-MM-DD HH24:MI:SS') - TO_TIMESTAMP(a.actstart, 'YYYY-MM-DD HH24:MI:SS'))) / 3600), 2) AS raw_corrective_labor_time_jam,
|
|
||||||
SUM(a.jumlah_labor) AS raw_corrective_labor_technician
|
|
||||||
FROM
|
|
||||||
public.dl_wo_staging AS a
|
|
||||||
WHERE
|
|
||||||
a.unit = '3'
|
|
||||||
GROUP BY
|
|
||||||
a.assetnum,
|
|
||||||
DATE_PART('year', TO_TIMESTAMP(a.reportdate, 'YYYY-MM-DD HH24:MI:SS.US')),
|
|
||||||
a.worktype
|
|
||||||
) AS tbl
|
|
||||||
WHERE
|
|
||||||
tbl.worktype = '{worktype}'
|
|
||||||
AND tbl.assetnum = '{equipment_id}'
|
|
||||||
ORDER BY
|
|
||||||
tbl.assetnum,
|
|
||||||
tbl.year,
|
|
||||||
tbl.worktype;
|
|
||||||
"""
|
|
||||||
# Eksekusi query dan fetch hasil
|
|
||||||
cursor.execute(query)
|
|
||||||
return cursor.fetchall()
|
|
||||||
|
|
||||||
|
|
||||||
def get_data_tahun(cursor):
|
|
||||||
query = f"""
|
|
||||||
select * from lcc_ms_year_data
|
|
||||||
"""
|
|
||||||
# Eksekusi query dan fetch hasil
|
|
||||||
cursor.execute(query)
|
|
||||||
return cursor.fetchall()
|
|
||||||
|
|
||||||
def query_data():
|
|
||||||
connection = None
|
|
||||||
try:
|
|
||||||
# Mendapatkan koneksi dari config.py
|
|
||||||
connection = get_connection()
|
|
||||||
if connection is None:
|
|
||||||
print("Koneksi ke database gagal.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Membuat cursor menggunakan DictCursor
|
|
||||||
cursor = connection.cursor(cursor_factory=DictCursor)
|
|
||||||
|
|
||||||
|
|
||||||
# TRUNCATE DATA
|
|
||||||
truncate_query = "TRUNCATE TABLE lcc_tr_data"
|
|
||||||
cursor.execute(truncate_query)
|
|
||||||
|
|
||||||
# Query untuk mendapatkan semua data dari tabel `lcc_ms_equipment_data`
|
|
||||||
query_main = "SELECT * FROM lcc_ms_equipment_data"
|
|
||||||
cursor.execute(query_main)
|
|
||||||
|
|
||||||
# Fetch semua hasil query
|
|
||||||
results = cursor.fetchall()
|
|
||||||
|
|
||||||
# Tahun sekarang
|
|
||||||
current_year = datetime.now().year
|
|
||||||
|
|
||||||
# Looping untuk setiap equipment_id
|
|
||||||
for row in results:
|
|
||||||
equipment_id = row['equipment_id'] # Mengambil equipment_id dari hasil query
|
|
||||||
forecasting_start_year = row['forecasting_start_year'] - 1
|
|
||||||
|
|
||||||
# CM
|
|
||||||
recursive_results = get_recursive_query(cursor, equipment_id, worktype='CM')
|
|
||||||
# PM
|
|
||||||
data_pm = get_recursive_query(cursor, equipment_id, worktype='PM')
|
|
||||||
# OH
|
|
||||||
data_oh = get_recursive_query(cursor, equipment_id, worktype='OH')
|
|
||||||
# Data Tahun
|
|
||||||
data_tahunan = get_data_tahun(cursor)
|
|
||||||
|
|
||||||
seq = 0
|
|
||||||
# Looping untuk setiap tahun
|
|
||||||
for year in range(forecasting_start_year, current_year + 1):
|
|
||||||
# Filter data berdasarkan tahun
|
|
||||||
recursive_row = next((r for r in recursive_results if r['year'] == year), None) # CM Corrective Maintenance
|
|
||||||
data_pm_row = next((r for r in data_pm if r['year'] == year), None)
|
|
||||||
data_oh_row = next((r for r in data_oh if r['year'] == year), None)
|
|
||||||
data_tahunan_row = next((r for r in data_tahunan if r['year'] == year), None)
|
|
||||||
|
|
||||||
# Cek apakah data sudah ada
|
|
||||||
check_query = """
|
|
||||||
SELECT COUNT(*) FROM lcc_tr_data
|
|
||||||
WHERE equipment_id = %s AND tahun = %s
|
|
||||||
"""
|
|
||||||
cursor.execute(check_query, (equipment_id, year))
|
|
||||||
data_exists = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
|
|
||||||
if not data_exists:
|
|
||||||
# Insert data jika belum ada
|
|
||||||
if not recursive_row and not data_pm_row and not data_oh_row:
|
|
||||||
# Jika data recursive_row tidak ada
|
|
||||||
insert_query = """
|
|
||||||
INSERT INTO lcc_tr_data (
|
|
||||||
id, equipment_id, 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_material_cost, raw_oh_labor_time, raw_oh_labor_human
|
|
||||||
, "raw_loss_output_MW", raw_loss_output_price
|
|
||||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s
|
|
||||||
, %s, %s, %s, %s
|
|
||||||
, %s, %s, %s
|
|
||||||
, %s, %s
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
cursor.execute(
|
|
||||||
insert_query,
|
|
||||||
(
|
|
||||||
str(uuid4()), # id
|
|
||||||
equipment_id, # equipment_id
|
|
||||||
year, # tahun
|
|
||||||
seq, # seq
|
|
||||||
1, # is_actual
|
|
||||||
1, # raw_cm_interval (minimal 1 karena minimal 1x OH)
|
|
||||||
0, # raw_cm_material_cost
|
|
||||||
0, # raw_cm_labor_time
|
|
||||||
0 # raw_cm_labor_human
|
|
||||||
, 1 # pm interval set default 1
|
|
||||||
,0,0,0
|
|
||||||
, 0,0,0
|
|
||||||
, (data_tahunan_row['total_lost'] if data_tahunan_row else 0)
|
|
||||||
, data_tahunan_row['rp_per_kwh'] if data_tahunan_row else 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Jika data recursive_row ada
|
|
||||||
insert_query = """
|
|
||||||
INSERT INTO lcc_tr_data (
|
|
||||||
id, equipment_id, 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_material_cost, raw_oh_labor_time, raw_oh_labor_human
|
|
||||||
, "raw_loss_output_MW", raw_loss_output_price
|
|
||||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s
|
|
||||||
, %s, %s, %s, %s
|
|
||||||
, %s, %s, %s
|
|
||||||
, %s, %s
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
cursor.execute(
|
|
||||||
insert_query,
|
|
||||||
(
|
|
||||||
str(uuid4()), # id
|
|
||||||
equipment_id, # equipment_id
|
|
||||||
year, # tahun
|
|
||||||
seq, # seq
|
|
||||||
1, # is_actual
|
|
||||||
recursive_row['raw_corrective_failure_interval']+1 if recursive_row else 1, # raw_cm_interval
|
|
||||||
recursive_row['raw_corrective_material_cost'] if recursive_row else 0, # raw_cm_material_cost
|
|
||||||
(recursive_row['raw_corrective_labor_time_jam'] or 0) if recursive_row else 0, # raw_cm_labor_time
|
|
||||||
(max(recursive_row['raw_corrective_labor_technician'], 1) if recursive_row['raw_corrective_labor_time_jam'] else 0) if recursive_row else 0, # raw_cm_labor_human
|
|
||||||
|
|
||||||
1, # raw_pm_interval
|
|
||||||
data_pm_row['raw_corrective_material_cost'] if data_pm_row else 0, # raw_pm_material_cost
|
|
||||||
(data_pm_row['raw_corrective_labor_time_jam'] or 0) if data_pm_row else 0, # raw_pm_labor_time
|
|
||||||
(max(data_pm_row['raw_corrective_labor_technician'], 1) if data_pm_row['raw_corrective_labor_time_jam'] else 0) if data_pm_row else 0, # raw_pm_labor_human
|
|
||||||
|
|
||||||
data_oh_row['raw_corrective_material_cost'] if data_oh_row else 0, # raw_oh_material_cost
|
|
||||||
(data_oh_row['raw_corrective_labor_time_jam'] or 0) if data_oh_row else 0, # raw_oh_labor_time
|
|
||||||
(max(data_oh_row['raw_corrective_labor_technician'], 1) if data_oh_row['raw_corrective_labor_time_jam'] else 0) if data_oh_row else 0, # raw_oh_labor_human
|
|
||||||
|
|
||||||
(data_tahunan_row['total_lost'] if data_tahunan_row else 0)/(recursive_row['raw_corrective_failure_interval']+1 if recursive_row else 1), # raw_loss_output_MW
|
|
||||||
data_tahunan_row['rp_per_kwh'] if data_tahunan_row else 0
|
|
||||||
|
|
||||||
)
|
|
||||||
)
|
|
||||||
print(f"Data inserted for {equipment_id} in year {year}")
|
|
||||||
|
|
||||||
seq = seq+1
|
|
||||||
|
|
||||||
# Commit perubahan
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print("Error saat menjalankan query:", e)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
# Menutup koneksi
|
|
||||||
if connection:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# Panggil fungsi
|
|
||||||
if __name__ == "__main__":
|
|
||||||
query_data()
|
|
||||||
@ -1,180 +0,0 @@
|
|||||||
from modules.config import get_connection
|
|
||||||
from psycopg2.extras import DictCursor
|
|
||||||
import numpy_financial as npf
|
|
||||||
import json
|
|
||||||
|
|
||||||
class Eac:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __calculate_npv_with_db_inflation_rate(self, equipment_id):
|
|
||||||
try:
|
|
||||||
# Mendapatkan koneksi dari config.py
|
|
||||||
connection = get_connection()
|
|
||||||
if connection is None:
|
|
||||||
print("Koneksi ke database gagal.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Membuat cursor menggunakan DictCursor
|
|
||||||
cursor = connection.cursor(cursor_factory=DictCursor)
|
|
||||||
|
|
||||||
# Query untuk mendapatkan data2 dasar
|
|
||||||
query_inflation_rate = """
|
|
||||||
select
|
|
||||||
(SELECT value_num / 100 FROM lcc_ms_master WHERE name = 'inflation_rate') as inflation_rate
|
|
||||||
, (SELECT value_num / 100 FROM lcc_ms_master WHERE name = 'discount_rate') as discount_rate
|
|
||||||
, (select COALESCE(rc_total_cost,0) from lcc_tr_data ltd where equipment_id = %s and seq = 0) as rc_total_cost_0
|
|
||||||
;
|
|
||||||
"""
|
|
||||||
cursor.execute(query_inflation_rate, (equipment_id,))
|
|
||||||
inflation_rate_result = cursor.fetchone()
|
|
||||||
|
|
||||||
if not inflation_rate_result:
|
|
||||||
print("Inflation rate tidak ditemukan.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
inflation_rate = inflation_rate_result['inflation_rate']
|
|
||||||
disc_rate = inflation_rate_result['discount_rate']
|
|
||||||
rc_total_cost_0 = inflation_rate_result['rc_total_cost_0']
|
|
||||||
|
|
||||||
last_seq = 0
|
|
||||||
last_npv = 0
|
|
||||||
# Query untuk mendapatkan data dengan seq dan is_actual
|
|
||||||
query_data_actual = """
|
|
||||||
SELECT equipment_id, tahun, seq, is_actual, rc_total_cost
|
|
||||||
FROM lcc_tr_data
|
|
||||||
WHERE is_actual = 1 AND seq != 0
|
|
||||||
AND equipment_id = %s
|
|
||||||
ORDER BY seq;
|
|
||||||
"""
|
|
||||||
cursor.execute(query_data_actual, (equipment_id,))
|
|
||||||
data_actual = cursor.fetchall()
|
|
||||||
|
|
||||||
# Variabel untuk menyimpan hasil NPV dan PMT per baris
|
|
||||||
npv_results = []
|
|
||||||
cumulative_values = [] # Menyimpan nilai kumulatif hingga baris ke-n
|
|
||||||
# Menghitung NPV dan PMT secara bertahap untuk data aktual
|
|
||||||
for idx, row in enumerate(data_actual):
|
|
||||||
cumulative_values.append(row['rc_total_cost'])
|
|
||||||
# Menghitung NPV menggunakan rumus diskonto
|
|
||||||
final_value = sum(
|
|
||||||
value / ((1 + inflation_rate) ** (i + 1)) for i, value in enumerate(cumulative_values))
|
|
||||||
# Menghitung PMT
|
|
||||||
pmt_value = -npf.pmt(inflation_rate, row['seq'], final_value)
|
|
||||||
pmt_aq_cost = -npf.pmt(disc_rate, row['seq'], rc_total_cost_0)
|
|
||||||
eac = pmt_value + pmt_aq_cost
|
|
||||||
|
|
||||||
npv_results.append({
|
|
||||||
'seq': row['seq'],
|
|
||||||
'year': row['tahun'],
|
|
||||||
'npv': final_value,
|
|
||||||
'pmt': pmt_value,
|
|
||||||
'pmt_aq_cost': pmt_aq_cost,
|
|
||||||
'eac': eac,
|
|
||||||
'is_actual': 1
|
|
||||||
})
|
|
||||||
|
|
||||||
# Update lcc_tr_data
|
|
||||||
update_query = """
|
|
||||||
UPDATE lcc_tr_data
|
|
||||||
SET eac_npv = %s, eac_annual_mnt_cost = %s, eac_annual_acq_cost = %s, eac_eac = %s
|
|
||||||
, updated_by = 'Sys', updated_at = NOW()
|
|
||||||
WHERE equipment_id = %s AND tahun = %s;
|
|
||||||
"""
|
|
||||||
cursor.execute(update_query, (final_value, pmt_value, pmt_aq_cost, eac, equipment_id, row['tahun']))
|
|
||||||
|
|
||||||
last_seq = row['seq']
|
|
||||||
last_npv = final_value
|
|
||||||
|
|
||||||
# Commit perubahan
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
# Query untuk mendapatkan data dengan seq dan is_actual = 0
|
|
||||||
query_data_proyeksi = """
|
|
||||||
SELECT equipment_id, tahun, seq, is_actual, rc_total_cost
|
|
||||||
FROM lcc_tr_data
|
|
||||||
WHERE is_actual = 0
|
|
||||||
ORDER BY seq;
|
|
||||||
"""
|
|
||||||
cursor.execute(query_data_proyeksi)
|
|
||||||
data_proyeksi = cursor.fetchall()
|
|
||||||
cumulative_values = []
|
|
||||||
|
|
||||||
# Menghitung NPV dan PMT secara bertahap untuk data proyeksi
|
|
||||||
for idx, row in enumerate(data_proyeksi):
|
|
||||||
cumulative_values.append(row['rc_total_cost'])
|
|
||||||
npv_value = sum(value / ((1 + inflation_rate) ** (i + 1)) for i, value in enumerate(cumulative_values))
|
|
||||||
pv_value = npf.pv(inflation_rate, last_seq, 0, npv_value)
|
|
||||||
final_value = -pv_value + last_npv
|
|
||||||
# Menghitung PMT
|
|
||||||
pmt_value = -npf.pmt(inflation_rate, row['seq'], final_value)
|
|
||||||
pmt_aq_cost = -npf.pmt(disc_rate, row['seq'], rc_total_cost_0)
|
|
||||||
eac = pmt_value + pmt_aq_cost
|
|
||||||
|
|
||||||
npv_results.append({
|
|
||||||
'seq': row['seq'],
|
|
||||||
'year': row['tahun'],
|
|
||||||
'npv': final_value,
|
|
||||||
'pmt': pmt_value,
|
|
||||||
'pmt_aq_cost': pmt_aq_cost,
|
|
||||||
'eac': eac,
|
|
||||||
'is_actual': 0
|
|
||||||
})
|
|
||||||
|
|
||||||
# Update lcc_tr_data
|
|
||||||
update_query = """
|
|
||||||
UPDATE lcc_tr_data
|
|
||||||
SET eac_npv = %s, eac_annual_mnt_cost = %s, eac_annual_acq_cost = %s, eac_eac = %s
|
|
||||||
, updated_by = 'Sys', updated_at = NOW()
|
|
||||||
WHERE equipment_id = %s AND tahun = %s;
|
|
||||||
"""
|
|
||||||
cursor.execute(update_query, (final_value, pmt_value, pmt_aq_cost, eac, equipment_id, row['tahun']))
|
|
||||||
|
|
||||||
# Commit perubahan
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
# Menutup koneksi
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# Menampilkan hasil
|
|
||||||
for result in npv_results:
|
|
||||||
print(
|
|
||||||
f"Seq: {result['seq']}, Is Actual: {result['is_actual']}, NPV: {result['npv']:.2f}, PMT: {result['pmt']:.2f}, AQ_COST: {result['pmt_aq_cost']:.2f}, EAC: {result['eac']:.2f}")
|
|
||||||
|
|
||||||
return npv_results
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print("Terjadi kesalahan:", str(e))
|
|
||||||
|
|
||||||
# ======================================================================================================================================================
|
|
||||||
|
|
||||||
def hitung_eac_equipment(self, p_equipment_id):
|
|
||||||
try:
|
|
||||||
# Mendapatkan koneksi dari config.py
|
|
||||||
connection = get_connection()
|
|
||||||
if connection is None:
|
|
||||||
print("Koneksi ke database gagal.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
cursor = connection.cursor(cursor_factory=DictCursor)
|
|
||||||
|
|
||||||
rslt = self.__calculate_npv_with_db_inflation_rate(p_equipment_id)
|
|
||||||
|
|
||||||
lowest_eac_record = min(rslt, key=lambda x: x['eac'])
|
|
||||||
print(json.dumps(lowest_eac_record))
|
|
||||||
# Update lcc_tr_data
|
|
||||||
update_query = """
|
|
||||||
UPDATE lcc_ms_equipment_data
|
|
||||||
SET min_eac_info = %s, updated_by = 'Sys', updated_at = NOW()
|
|
||||||
WHERE equipment_id = %s;
|
|
||||||
"""
|
|
||||||
cursor.execute(update_query, (json.dumps(lowest_eac_record), p_equipment_id))
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print("Terjadi kesalahan saat memproses semua equipment:", str(e))
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,231 @@
|
|||||||
|
from psycopg2.extras import DictCursor
|
||||||
|
import numpy_financial as npf
|
||||||
|
import json
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
from config import get_connection
|
||||||
|
|
||||||
|
|
||||||
|
class Eac:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __calculate_npv_with_db_inflation_rate(self, equipment_id):
|
||||||
|
try:
|
||||||
|
# Mendapatkan koneksi dari config.py
|
||||||
|
connections = get_connection()
|
||||||
|
connection = (
|
||||||
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
|
)
|
||||||
|
if connection is None:
|
||||||
|
print("Database connection failed.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Membuat cursor menggunakan DictCursor
|
||||||
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
||||||
|
|
||||||
|
# Query untuk mendapatkan data2 dasar
|
||||||
|
query_inflation_rate = """
|
||||||
|
select
|
||||||
|
(SELECT value_num / 100 FROM lcc_ms_master WHERE name = 'inflation_rate') as inflation_rate
|
||||||
|
, (SELECT value_num / 100 FROM lcc_ms_master WHERE name = 'discount_rate') as discount_rate
|
||||||
|
, (select COALESCE(rc_total_cost,0) from lcc_equipment_tr_data ltd where assetnum = %s and seq = 0) as rc_total_cost_0
|
||||||
|
;
|
||||||
|
"""
|
||||||
|
cursor.execute(query_inflation_rate, (equipment_id,))
|
||||||
|
inflation_rate_result = cursor.fetchone()
|
||||||
|
|
||||||
|
if not inflation_rate_result:
|
||||||
|
print("Inflation rate tidak ditemukan.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
inflation_rate = inflation_rate_result["inflation_rate"]
|
||||||
|
disc_rate = inflation_rate_result["discount_rate"]
|
||||||
|
rc_total_cost_0 = inflation_rate_result["rc_total_cost_0"]
|
||||||
|
|
||||||
|
last_seq = 0
|
||||||
|
last_npv = 0
|
||||||
|
# Query untuk mendapatkan data dengan seq dan is_actual
|
||||||
|
query_data_actual = """
|
||||||
|
SELECT assetnum, tahun, seq, is_actual, rc_total_cost
|
||||||
|
FROM lcc_equipment_tr_data
|
||||||
|
WHERE is_actual = 1 AND seq != 0
|
||||||
|
AND assetnum = %s
|
||||||
|
ORDER BY seq;
|
||||||
|
"""
|
||||||
|
cursor.execute(query_data_actual, (equipment_id,))
|
||||||
|
data_actual = cursor.fetchall()
|
||||||
|
|
||||||
|
# Variabel untuk menyimpan hasil NPV dan PMT per baris
|
||||||
|
npv_results = []
|
||||||
|
cumulative_values = [] # Menyimpan nilai kumulatif hingga baris ke-n
|
||||||
|
# Menghitung NPV dan PMT secara bertahap untuk data aktual
|
||||||
|
for idx, row in enumerate(data_actual):
|
||||||
|
cumulative_values.append(row["rc_total_cost"])
|
||||||
|
# Menghitung NPV menggunakan rumus diskonto
|
||||||
|
final_value = sum(
|
||||||
|
value / ((1 + inflation_rate) ** (i + 1))
|
||||||
|
for i, value in enumerate(cumulative_values)
|
||||||
|
)
|
||||||
|
# Menghitung PMT
|
||||||
|
pmt_value = -npf.pmt(inflation_rate, row["seq"], final_value)
|
||||||
|
pmt_aq_cost = -npf.pmt(disc_rate, row["seq"], rc_total_cost_0)
|
||||||
|
eac = pmt_value + pmt_aq_cost
|
||||||
|
|
||||||
|
npv_results.append(
|
||||||
|
{
|
||||||
|
"seq": row["seq"],
|
||||||
|
"year": row["tahun"],
|
||||||
|
"npv": final_value,
|
||||||
|
"pmt": pmt_value,
|
||||||
|
"pmt_aq_cost": pmt_aq_cost,
|
||||||
|
"eac": eac,
|
||||||
|
"is_actual": 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update lcc_equipment_tr_data
|
||||||
|
update_query = """
|
||||||
|
UPDATE lcc_equipment_tr_data
|
||||||
|
SET eac_npv = %s, eac_annual_mnt_cost = %s, eac_annual_acq_cost = %s, eac_eac = %s
|
||||||
|
, updated_by = 'Sys', updated_at = NOW()
|
||||||
|
WHERE assetnum = %s AND tahun = %s;
|
||||||
|
"""
|
||||||
|
cursor.execute(
|
||||||
|
update_query,
|
||||||
|
(
|
||||||
|
float(final_value),
|
||||||
|
float(pmt_value),
|
||||||
|
float(pmt_aq_cost),
|
||||||
|
float(eac),
|
||||||
|
equipment_id,
|
||||||
|
row["tahun"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
last_seq = row["seq"]
|
||||||
|
last_npv = float(final_value)
|
||||||
|
|
||||||
|
# Commit perubahan
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
# Query untuk mendapatkan data dengan seq dan is_actual = 0
|
||||||
|
query_data_proyeksi = """
|
||||||
|
SELECT assetnum, tahun, seq, is_actual, rc_total_cost
|
||||||
|
FROM lcc_equipment_tr_data
|
||||||
|
WHERE assetnum = %s AND is_actual = 0
|
||||||
|
ORDER BY seq;
|
||||||
|
"""
|
||||||
|
cursor.execute(query_data_proyeksi, (equipment_id,))
|
||||||
|
data_proyeksi = cursor.fetchall()
|
||||||
|
cumulative_values = []
|
||||||
|
|
||||||
|
# Menghitung NPV dan PMT secara bertahap untuk data proyeksi
|
||||||
|
for idx, row in enumerate(data_proyeksi):
|
||||||
|
# print(row)
|
||||||
|
cumulative_values.append(row["rc_total_cost"])
|
||||||
|
npv_value = sum(
|
||||||
|
value / ((1 + inflation_rate) ** (i + 1))
|
||||||
|
for i, value in enumerate(cumulative_values)
|
||||||
|
)
|
||||||
|
pv_value = npf.pv(inflation_rate, last_seq, 0, npv_value)
|
||||||
|
final_value = -pv_value + last_npv
|
||||||
|
# Menghitung PMT
|
||||||
|
pmt_value = -npf.pmt(inflation_rate, row["seq"], final_value)
|
||||||
|
pmt_aq_cost = -npf.pmt(disc_rate, row["seq"], rc_total_cost_0)
|
||||||
|
eac = pmt_value + pmt_aq_cost
|
||||||
|
|
||||||
|
npv_results.append(
|
||||||
|
{
|
||||||
|
"seq": row["seq"],
|
||||||
|
"year": row["tahun"],
|
||||||
|
"npv": final_value,
|
||||||
|
"pmt": pmt_value,
|
||||||
|
"pmt_aq_cost": pmt_aq_cost,
|
||||||
|
"eac": eac,
|
||||||
|
"is_actual": 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update lcc_equipment_tr_data
|
||||||
|
update_query = """
|
||||||
|
UPDATE lcc_equipment_tr_data
|
||||||
|
SET eac_npv = %s, eac_annual_mnt_cost = %s, eac_annual_acq_cost = %s, eac_eac = %s
|
||||||
|
, updated_by = 'Sys', updated_at = NOW()
|
||||||
|
WHERE assetnum = %s AND tahun = %s;
|
||||||
|
"""
|
||||||
|
cursor.execute(
|
||||||
|
update_query,
|
||||||
|
(
|
||||||
|
float(final_value),
|
||||||
|
float(pmt_value),
|
||||||
|
float(pmt_aq_cost),
|
||||||
|
float(eac),
|
||||||
|
equipment_id,
|
||||||
|
row["tahun"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Commit perubahan
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
# Menutup koneksi
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# Menampilkan hasil
|
||||||
|
# for result in npv_results:
|
||||||
|
# print(
|
||||||
|
# f"Seq: {result['seq']}, Is Actual: {result['is_actual']}, NPV: {result['npv']:.2f}, PMT: {result['pmt']:.2f}, AQ_COST: {result['pmt_aq_cost']:.2f}, EAC: {result['eac']:.2f}"
|
||||||
|
# )
|
||||||
|
|
||||||
|
return npv_results
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("Terjadi kesalahan:", str(e))
|
||||||
|
|
||||||
|
# ======================================================================================================================================================
|
||||||
|
|
||||||
|
def hitung_eac_equipment(self, p_equipment_id):
|
||||||
|
try:
|
||||||
|
# Mendapatkan koneksi dari config.py
|
||||||
|
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)
|
||||||
|
|
||||||
|
rslt = self.__calculate_npv_with_db_inflation_rate(p_equipment_id)
|
||||||
|
# print(rslt)
|
||||||
|
lowest_eac_record = min(rslt, key=lambda x: x["eac"])
|
||||||
|
# print(json.dumps(lowest_eac_record))
|
||||||
|
# Update lcc_equipment_tr_data
|
||||||
|
update_query = """
|
||||||
|
UPDATE lcc_ms_equipment_data
|
||||||
|
SET min_eac_info = %s, updated_by = 'Sys', updated_at = NOW()
|
||||||
|
WHERE assetnum = %s;
|
||||||
|
"""
|
||||||
|
cursor.execute(
|
||||||
|
update_query, (json.dumps(lowest_eac_record), p_equipment_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
connection.commit()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("Terjadi kesalahan saat memproses semua equipment:", str(e))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
eac = Eac()
|
||||||
|
eac.hitung_eac_equipment("A22277")
|
||||||
|
print("EAC calculation finished.")
|
||||||
@ -1,367 +1,480 @@
|
|||||||
import pandas as pd
|
import os
|
||||||
import numpy as np
|
import pandas as pd
|
||||||
import numpy_financial as npf # Gunakan numpy-financial untuk fungsi keuangan
|
import numpy as np
|
||||||
from statsmodels.tsa.holtwinters import ExponentialSmoothing
|
import numpy_financial as npf # Gunakan numpy-financial untuk fungsi keuangan
|
||||||
from sklearn.linear_model import LinearRegression
|
from statsmodels.tsa.holtwinters import ExponentialSmoothing
|
||||||
from sklearn.tree import DecisionTreeRegressor
|
from sklearn.linear_model import LinearRegression
|
||||||
import matplotlib.pyplot as plt
|
from sklearn.tree import DecisionTreeRegressor
|
||||||
from uuid import uuid4
|
import matplotlib.pyplot as plt
|
||||||
from modules.config import get_connection
|
from starlette.config import Config
|
||||||
from psycopg2.extras import DictCursor
|
from uuid import uuid4
|
||||||
|
from psycopg2.extras import DictCursor
|
||||||
class Prediksi:
|
import httpx
|
||||||
def __init__(self):
|
from dotenv import load_dotenv
|
||||||
pass
|
|
||||||
|
import sys
|
||||||
# Fungsi untuk mengambil data dari database
|
import os
|
||||||
def __get_param(self, equipment_id):
|
|
||||||
try:
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
# Mendapatkan koneksi dari config.py
|
from config import get_connection
|
||||||
connection = get_connection()
|
|
||||||
if connection is None:
|
load_dotenv()
|
||||||
print("Koneksi ke database gagal.")
|
|
||||||
return None
|
|
||||||
# Membuat cursor menggunakan DictCursor
|
class Prediksi:
|
||||||
cursor = connection.cursor(cursor_factory=DictCursor)
|
def __init__(self, RELIABILITY_APP_URL):
|
||||||
# Query untuk mendapatkan data
|
self.RELIABILITY_APP_URL = RELIABILITY_APP_URL
|
||||||
query = """
|
|
||||||
SELECT
|
# Fungsi untuk mengambil data dari database
|
||||||
(select COALESCE(forecasting_target_year, 2060) from lcc_ms_equipment_data where equipment_id = %s) AS forecasting_target_year
|
def __get_param(self, equipment_id):
|
||||||
"""
|
try:
|
||||||
cursor.execute(query, (equipment_id,))
|
# Mendapatkan koneksi dari config.py
|
||||||
par1 = cursor.fetchone()
|
connections = get_connection()
|
||||||
return par1["forecasting_target_year"]
|
connection = (
|
||||||
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
except Exception as e:
|
)
|
||||||
print(f"Error saat mengambil data dari database: {e}")
|
if connection is None:
|
||||||
return None
|
print("Database connection failed.")
|
||||||
|
return None
|
||||||
finally:
|
# Membuat cursor menggunakan DictCursor
|
||||||
if connection:
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
||||||
connection.close()
|
# print(f"Getting params for equipment_id: {equipment_id}")
|
||||||
|
# Query untuk mendapatkan data
|
||||||
# Fungsi untuk mengambil data dari database
|
query = """
|
||||||
def __fetch_data_from_db(self, equipment_id):
|
SELECT
|
||||||
try:
|
(select COALESCE(forecasting_target_year, 2060) from lcc_ms_equipment_data where assetnum = %s) AS forecasting_target_year
|
||||||
# Mendapatkan koneksi dari config.py
|
"""
|
||||||
connection = get_connection()
|
cursor.execute(query, (equipment_id,))
|
||||||
if connection is None:
|
par1 = cursor.fetchone()
|
||||||
print("Koneksi ke database gagal.")
|
return par1["forecasting_target_year"]
|
||||||
return None
|
|
||||||
|
except Exception as e:
|
||||||
# Membuat cursor menggunakan DictCursor
|
print(f"Error saat get params dari database: {e}")
|
||||||
cursor = connection.cursor(cursor_factory=DictCursor)
|
return None
|
||||||
|
|
||||||
# Query untuk mendapatkan data
|
finally:
|
||||||
query = """
|
if connection:
|
||||||
SELECT
|
connection.close()
|
||||||
tahun AS year,
|
|
||||||
raw_cm_interval AS cm_interval,
|
# Fungsi untuk mengambil data dari database
|
||||||
raw_cm_material_cost AS cm_cost,
|
def __fetch_data_from_db(self, equipment_id):
|
||||||
raw_cm_labor_time AS cm_labor_time,
|
try:
|
||||||
raw_cm_labor_human AS cm_labor_human,
|
# Get connection from config.py (using only the first connection)
|
||||||
raw_pm_material_cost AS pm_cost,
|
connections = get_connection()
|
||||||
raw_pm_labor_time AS pm_labor_time,
|
connection = (
|
||||||
raw_pm_labor_human AS pm_labor_human,
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
raw_oh_material_cost AS oh_cost,
|
)
|
||||||
raw_oh_labor_time AS oh_labor_time,
|
if connection is None:
|
||||||
raw_oh_labor_human AS oh_labor_human,
|
print("Database connection failed.")
|
||||||
"raw_loss_output_MW" AS loss_output_mw,
|
return None
|
||||||
raw_loss_output_price AS loss_price
|
|
||||||
FROM lcc_tr_data
|
# Membuat cursor menggunakan DictCursor
|
||||||
WHERE equipment_id = %s
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
||||||
and is_actual=1
|
# print(f"Fetcing data for equipment_id: {equipment_id}")
|
||||||
;
|
# Query untuk mendapatkan data
|
||||||
"""
|
query = """
|
||||||
cursor.execute(query, (equipment_id,))
|
SELECT
|
||||||
|
tahun AS year,
|
||||||
# Mengambil hasil dan mengonversi ke DataFrame pandas
|
raw_cm_interval AS cm_interval,
|
||||||
data = cursor.fetchall()
|
raw_cm_material_cost AS cm_cost,
|
||||||
columns = [desc[0] for desc in cursor.description] # Mengambil nama kolom dari hasil query
|
raw_cm_labor_time AS cm_labor_time,
|
||||||
df = pd.DataFrame(data, columns=columns)
|
raw_cm_labor_human AS cm_labor_human,
|
||||||
return df
|
raw_pm_material_cost AS pm_cost,
|
||||||
|
raw_pm_labor_time AS pm_labor_time,
|
||||||
except Exception as e:
|
raw_pm_labor_human AS pm_labor_human,
|
||||||
print(f"Error saat mengambil data dari database: {e}")
|
raw_oh_material_cost AS oh_cost,
|
||||||
return None
|
raw_oh_labor_time AS oh_labor_time,
|
||||||
|
raw_oh_labor_human AS oh_labor_human,
|
||||||
finally:
|
"raw_loss_output_MW" AS loss_output_mw,
|
||||||
if connection:
|
raw_loss_output_price AS loss_price
|
||||||
connection.close()
|
FROM lcc_equipment_tr_data
|
||||||
|
WHERE assetnum = %s
|
||||||
# Fungsi untuk prediksi menggunakan Future Value (FV)
|
and is_actual=1
|
||||||
def __future_value_predict(self, rate, nper, pmt, pv, years):
|
;
|
||||||
# Hitung Future Value untuk tahun-tahun proyeksi
|
"""
|
||||||
fv_values = []
|
cursor.execute(query, (equipment_id,))
|
||||||
for i in range(len(years)):
|
|
||||||
fv = npf.fv(rate, nper + i, pmt, pv) # Menggunakan numpy_financial.fv
|
# Mengambil hasil dan mengonversi ke DataFrame pandas
|
||||||
fv_values.append(fv)
|
data = cursor.fetchall()
|
||||||
return fv_values
|
columns = [
|
||||||
|
desc[0] for desc in cursor.description
|
||||||
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
|
] # Mengambil nama kolom dari hasil query
|
||||||
def __delete_predictions_from_db(self, equipment_id):
|
df = pd.DataFrame(data, columns=columns)
|
||||||
try:
|
return df
|
||||||
connection = get_connection()
|
|
||||||
if connection is None:
|
except Exception as e:
|
||||||
print("Koneksi ke database gagal.")
|
print(f"Error saat mengambil data dari database: {e}")
|
||||||
return
|
return None
|
||||||
|
|
||||||
cursor = connection.cursor()
|
finally:
|
||||||
|
if connection:
|
||||||
# Query untuk menghapus data berdasarkan tahun proyeksi
|
connection.close()
|
||||||
delete_query = """
|
|
||||||
DELETE FROM lcc_tr_data
|
# Fungsi untuk prediksi menggunakan Future Value (FV)
|
||||||
WHERE equipment_id = %s AND is_actual = 0;
|
def __future_value_predict(self, rate, nper, pmt, pv, years):
|
||||||
""" # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
|
# Hitung Future Value untuk tahun-tahun proyeksi
|
||||||
|
fv_values = []
|
||||||
# Eksekusi query delete
|
for i in range(len(years)):
|
||||||
cursor.execute(delete_query, (equipment_id,))
|
fv = npf.fv(rate, nper + i, pmt, pv) # Menggunakan numpy_financial.fv
|
||||||
connection.commit()
|
fv_values.append(fv)
|
||||||
print(f"Data proyeksi untuk tahun {equipment_id} berhasil dihapus.")
|
return fv_values
|
||||||
|
|
||||||
except Exception as e:
|
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
|
||||||
print(f"Error saat menghapus data proyeksi dari database: {e}")
|
def __delete_predictions_from_db(self, equipment_id):
|
||||||
|
try:
|
||||||
finally:
|
connections = get_connection()
|
||||||
if connection:
|
connection = (
|
||||||
connection.close()
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
|
)
|
||||||
# Fungsi untuk menyimpan data proyeksi ke database
|
if connection is None:
|
||||||
def __insert_predictions_to_db(self, data, equipment_id):
|
print("Database connection failed.")
|
||||||
try:
|
return None
|
||||||
connection = get_connection()
|
|
||||||
if connection is None:
|
cursor = connection.cursor()
|
||||||
print("Koneksi ke database gagal.")
|
|
||||||
return
|
# Query untuk menghapus data berdasarkan tahun proyeksi
|
||||||
|
delete_query = """
|
||||||
cursor = connection.cursor()
|
DELETE FROM lcc_equipment_tr_data
|
||||||
|
WHERE assetnum = %s AND is_actual = 0;
|
||||||
# Query untuk mendapatkan nilai maksimum seq
|
""" # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
|
||||||
get_max_seq_query = """
|
|
||||||
SELECT COALESCE(MAX(seq), 0) FROM lcc_tr_data WHERE equipment_id = %s
|
# Eksekusi query delete
|
||||||
"""
|
cursor.execute(delete_query, (equipment_id,))
|
||||||
cursor.execute(get_max_seq_query, (equipment_id,))
|
connection.commit()
|
||||||
max_seq = cursor.fetchone()[0]
|
# print(f"Data proyeksi untuk tahun {equipment_id} berhasil dihapus.")
|
||||||
|
|
||||||
# Query untuk insert data
|
except Exception as e:
|
||||||
insert_query = """
|
print(f"Error saat menghapus data proyeksi dari database: {e}")
|
||||||
INSERT INTO lcc_tr_data (
|
|
||||||
id,
|
finally:
|
||||||
seq,
|
if connection:
|
||||||
is_actual,
|
connection.close()
|
||||||
raw_pm_interval,
|
|
||||||
tahun, equipment_id,
|
# Fungsi untuk menyimpan data proyeksi ke database
|
||||||
raw_cm_interval, raw_cm_material_cost, raw_cm_labor_time, raw_cm_labor_human,
|
async def __insert_predictions_to_db(self, data, equipment_id, token):
|
||||||
raw_pm_material_cost, raw_pm_labor_time, raw_pm_labor_human,
|
try:
|
||||||
raw_oh_material_cost, raw_oh_labor_time, raw_oh_labor_human,
|
connections = get_connection()
|
||||||
"raw_loss_output_MW", raw_loss_output_price
|
connection = (
|
||||||
, created_by, created_at
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
) VALUES (
|
)
|
||||||
%s, %s, 0, 1, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'Sys', NOW()
|
if connection is None:
|
||||||
)
|
print("Database connection failed.")
|
||||||
"""
|
return None
|
||||||
|
|
||||||
# Menyiapkan data untuk batch insert
|
cursor = connection.cursor()
|
||||||
records_to_insert = []
|
|
||||||
for _, row in data.iterrows():
|
# Query untuk mendapatkan nilai maksimum seq
|
||||||
max_seq = max_seq + 1
|
get_max_seq_query = """
|
||||||
records_to_insert.append((
|
SELECT COALESCE(MAX(seq), 0) FROM lcc_equipment_tr_data WHERE assetnum = %s
|
||||||
str(uuid4()), max_seq, row["year"], equipment_id,
|
"""
|
||||||
row["cm_interval"] if row["cm_interval"] >= 1 else 1, row["cm_cost"], row["cm_labor_time"],
|
cursor.execute(get_max_seq_query, (equipment_id,))
|
||||||
row["cm_labor_human"],
|
max_seq = cursor.fetchone()[0]
|
||||||
row["pm_cost"], row["pm_labor_time"], row["pm_labor_human"],
|
|
||||||
row["oh_cost"], row["oh_labor_time"], row["oh_labor_human"],
|
# Query untuk insert data
|
||||||
row["loss_output_mw"], row["loss_price"]
|
insert_query = """
|
||||||
))
|
INSERT INTO lcc_equipment_tr_data (
|
||||||
|
id,
|
||||||
# Eksekusi batch insert
|
seq,
|
||||||
cursor.executemany(insert_query, records_to_insert)
|
is_actual,
|
||||||
connection.commit()
|
raw_pm_interval,
|
||||||
print("Data proyeksi berhasil dimasukkan ke database.")
|
tahun, assetnum,
|
||||||
|
raw_cm_interval, raw_cm_material_cost, raw_cm_labor_time, raw_cm_labor_human,
|
||||||
except Exception as e:
|
raw_pm_material_cost, raw_pm_labor_time, raw_pm_labor_human,
|
||||||
print(f"Error saat menyimpan data ke database: {e}")
|
raw_oh_material_cost, raw_oh_labor_time, raw_oh_labor_human,
|
||||||
|
"raw_loss_output_MW", raw_loss_output_price
|
||||||
finally:
|
, created_by, created_at
|
||||||
if connection:
|
) VALUES (
|
||||||
connection.close()
|
%s, %s, 0, 1, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'Sys', NOW()
|
||||||
|
)
|
||||||
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
|
"""
|
||||||
def __update_date_lcc(self, equipment_id):
|
|
||||||
try:
|
# Fetch data from external API
|
||||||
connection = get_connection()
|
async def fetch_api_data(assetnum: str, year: int) -> dict:
|
||||||
if connection is None:
|
url = self.RELIABILITY_APP_URL
|
||||||
print("Koneksi ke database gagal.")
|
# print(f"Using URL: {url}") # Add this for debugging
|
||||||
return
|
async with httpx.AsyncClient() as client:
|
||||||
|
# print(
|
||||||
cursor = connection.cursor()
|
# f"{url}/main/number-of-failures/{assetnum}/{int(year)}/{int(year)}"
|
||||||
|
# )
|
||||||
# Query untuk menghapus data berdasarkan tahun proyeksi
|
try:
|
||||||
up_query = """
|
response = await client.get(
|
||||||
update lcc_tr_data
|
f"{url}/main/number-of-failures/{assetnum}/{int(year)}/{int(year)}",
|
||||||
set
|
timeout=30.0,
|
||||||
rc_cm_material_cost = raw_cm_material_cost
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
,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_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) )
|
)
|
||||||
,rc_pm_material_cost = raw_pm_material_cost
|
response.raise_for_status()
|
||||||
,rc_pm_labor_cost = (raw_pm_labor_time * raw_pm_labor_human * COALESCE((SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) )
|
return response.json()
|
||||||
,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_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) ) , 0)
|
except httpx.HTTPError as e:
|
||||||
,rc_oh_material_cost = raw_oh_material_cost
|
print(f"HTTP error occurred: {e}")
|
||||||
,rc_oh_labor_cost = (raw_oh_labor_time * raw_oh_labor_human * COALESCE((SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) )
|
return {}
|
||||||
,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
|
# Menyiapkan data untuk batch insert
|
||||||
,rc_operation_cost = coalesce(raw_operational_cost, 0)
|
# print(f"Data to be inserted: {data}")
|
||||||
,rc_maintenance_cost = coalesce(raw_maintenance_cost, 0)
|
records_to_insert = []
|
||||||
,rc_total_cost = (
|
for _, row in data.iterrows():
|
||||||
raw_cm_material_cost
|
max_seq = max_seq + 1
|
||||||
+ (raw_cm_interval * raw_cm_labor_time * raw_cm_labor_human * COALESCE((SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) )
|
# Update values from API
|
||||||
+ raw_pm_material_cost
|
api_data = await fetch_api_data(equipment_id, row["year"])
|
||||||
+ (raw_pm_labor_time * raw_pm_labor_human * COALESCE((SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) )
|
if api_data:
|
||||||
+ COALESCE( (raw_predictive_labor_time * raw_predictive_labor_human * COALESCE((SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) ) , 0)
|
# # Get current num_fail
|
||||||
+ raw_oh_material_cost
|
cm_interval_prediction = api_data["data"][0]["num_fail"]
|
||||||
+ (raw_oh_labor_time * raw_oh_labor_human * COALESCE((SELECT man_hour FROM lcc_ms_year_data WHERE year = lcc_tr_data.tahun), coalesce((select value_num from lcc_ms_master where name='manhours_rate'), 0)) )
|
else:
|
||||||
+ coalesce(raw_project_task_material_cost, 0)
|
cm_interval_prediction = (
|
||||||
+ coalesce(("raw_loss_output_MW" * raw_loss_output_price * raw_cm_interval), 0) * 1000
|
(
|
||||||
+ coalesce(raw_operational_cost, 0)
|
float(row["cm_interval"])
|
||||||
+ coalesce(raw_maintenance_cost, 0)
|
if float(row["cm_interval"]) >= 1
|
||||||
)
|
else 1
|
||||||
, updated_by = 'Sys', updated_at = NOW()
|
),
|
||||||
where equipment_id = %s;
|
)
|
||||||
|
records_to_insert.append(
|
||||||
update lcc_tr_data set rc_total_cost = (select acquisition_cost from lcc_ms_equipment_data where equipment_id=lcc_tr_data.equipment_id) where equipment_id = %s and seq=0;
|
(
|
||||||
""" # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
|
str(uuid4()),
|
||||||
|
int(max_seq),
|
||||||
# Eksekusi query delete
|
float(row["year"]),
|
||||||
cursor.execute(up_query, (equipment_id, equipment_id))
|
equipment_id,
|
||||||
connection.commit()
|
cm_interval_prediction,
|
||||||
print(f"Data berhasil diupdate.")
|
float(row["cm_cost"]),
|
||||||
|
float(row["cm_labor_time"]),
|
||||||
except Exception as e:
|
float(row["cm_labor_human"]),
|
||||||
print(f"Error saat update data proyeksi dari database: {e}")
|
float(row["pm_cost"]),
|
||||||
|
float(row["pm_labor_time"]),
|
||||||
finally:
|
float(row["pm_labor_human"]),
|
||||||
if connection:
|
float(row["oh_cost"]),
|
||||||
connection.close()
|
float(row["oh_labor_time"]),
|
||||||
|
float(row["oh_labor_human"]),
|
||||||
# Fungsi untuk mengambil parameter dari database
|
float(row["loss_output_mw"]),
|
||||||
def __get_rate_and_max_year(self, equipment_id):
|
float(row["loss_price"]),
|
||||||
try:
|
)
|
||||||
connection = get_connection()
|
)
|
||||||
if connection is None:
|
|
||||||
print("Koneksi ke database gagal.")
|
# Eksekusi batch insert
|
||||||
return None, None
|
cursor.executemany(insert_query, records_to_insert)
|
||||||
|
connection.commit()
|
||||||
cursor = connection.cursor(cursor_factory=DictCursor)
|
# print("Data proyeksi berhasil dimasukkan ke database.")
|
||||||
|
|
||||||
# Query untuk mendapatkan rate dan max_year
|
except Exception as e:
|
||||||
query = """
|
print(f"Error saat menyimpan data ke database: {e}")
|
||||||
SELECT
|
|
||||||
(SELECT value_num / 100 FROM lcc_ms_master where name='inflation_rate') AS rate,
|
finally:
|
||||||
(SELECT MAX(tahun) FROM lcc_tr_data WHERE is_actual = 1 AND equipment_id = %s) AS max_year
|
if connection:
|
||||||
"""
|
connection.close()
|
||||||
cursor.execute(query, (equipment_id,))
|
|
||||||
result = cursor.fetchone()
|
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
|
||||||
|
def __update_date_lcc(self, equipment_id):
|
||||||
# Debug hasil query
|
try:
|
||||||
print(f"Result: {result}")
|
connections = get_connection()
|
||||||
|
connection = (
|
||||||
rate = result["rate"]
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
max_year = result["max_year"]
|
)
|
||||||
|
if connection is None:
|
||||||
# Validasi nilai rate dan max_year
|
print("Database connection failed.")
|
||||||
if rate is None:
|
return None
|
||||||
raise Exception("Nilai 'rate' tidak boleh kosong. Periksa tabel 'lcc_ms_master'.")
|
|
||||||
if max_year is None:
|
cursor = connection.cursor()
|
||||||
raise Exception("Nilai 'max_year' tidak boleh kosong. Periksa tabel 'lcc_tr_data'.")
|
|
||||||
|
# Query untuk menghapus data berdasarkan tahun proyeksi
|
||||||
return rate, max_year
|
up_query = """
|
||||||
|
update lcc_equipment_tr_data
|
||||||
except Exception as e:
|
set
|
||||||
print(f"Error saat mendapatkan parameter dari database: {e}")
|
rc_cm_material_cost = raw_cm_material_cost
|
||||||
raise # Lempar kembali exception agar program berhenti
|
,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
|
||||||
finally:
|
,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)) )
|
||||||
if connection:
|
,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)
|
||||||
connection.close()
|
,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
|
||||||
def predict_equipment_data(self, p_equipment_id):
|
,rc_operation_cost = coalesce(raw_operational_cost, 0)
|
||||||
try:
|
,rc_maintenance_cost = coalesce(raw_maintenance_cost, 0)
|
||||||
# Mengambil data dari database
|
,rc_total_cost = (
|
||||||
df = self.__fetch_data_from_db(p_equipment_id)
|
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)) )
|
||||||
if df is None:
|
+ raw_pm_material_cost
|
||||||
print("Data tidak tersedia untuk prediksi.")
|
+ (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)) )
|
||||||
return
|
+ 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
|
||||||
# Mendapatkan tahun proyeksi dari DB
|
+ (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)) )
|
||||||
par_tahun_target = self.__get_param(p_equipment_id)
|
+ coalesce(raw_project_task_material_cost, 0)
|
||||||
|
+ coalesce(("raw_loss_output_MW" * raw_loss_output_price * raw_cm_interval), 0) * 1000
|
||||||
# Tahun proyeksi
|
+ coalesce(raw_operational_cost, 0)
|
||||||
future_years = list(range(df["year"].max() + 1, par_tahun_target + 1))
|
+ coalesce(raw_maintenance_cost, 0)
|
||||||
|
)
|
||||||
# Hasil prediksi
|
, updated_by = 'Sys', updated_at = NOW()
|
||||||
predictions = {"year": future_years}
|
where assetnum = %s;
|
||||||
|
|
||||||
# Fungsi untuk prediksi menggunakan Linear Regression
|
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;
|
||||||
def linear_regression_predict(column, years):
|
""" # Asumsikan kolom is_actual digunakan untuk membedakan data proyeksi dan data aktual
|
||||||
x = df["year"].values.reshape(-1, 1)
|
|
||||||
y = df[column].fillna(0).values
|
# Eksekusi query delete
|
||||||
model = LinearRegression()
|
cursor.execute(up_query, (equipment_id, equipment_id))
|
||||||
model.fit(x, y)
|
connection.commit()
|
||||||
future_x = np.array(years).reshape(-1, 1)
|
# print(f"Data berhasil diupdate.")
|
||||||
preds = model.predict(future_x)
|
|
||||||
return np.abs(preds)
|
except Exception as e:
|
||||||
|
print(f"Error saat update data proyeksi dari database: {e}")
|
||||||
# Fungsi untuk prediksi menggunakan Exponential Smoothing
|
|
||||||
def exponential_smoothing_predict(column, years):
|
finally:
|
||||||
data_series = df[column].fillna(0).values
|
if connection:
|
||||||
model = ExponentialSmoothing(data_series, trend="add", seasonal=None, seasonal_periods=None)
|
connection.close()
|
||||||
model_fit = model.fit()
|
|
||||||
preds = model_fit.forecast(len(years))
|
# Fungsi untuk mengambil parameter dari database
|
||||||
return np.abs(preds)
|
def __get_rate_and_max_year(self, equipment_id):
|
||||||
|
try:
|
||||||
# Fungsi untuk prediksi menggunakan Decision Tree
|
connections = get_connection()
|
||||||
def decision_tree_predict(column, years):
|
connection = (
|
||||||
x = df["year"].values.reshape(-1, 1)
|
connections[0] if isinstance(connections, tuple) else connections
|
||||||
y = df[column].fillna(0).values
|
)
|
||||||
model = DecisionTreeRegressor()
|
if connection is None:
|
||||||
model.fit(x, y)
|
print("Database connection failed.")
|
||||||
future_x = np.array(years).reshape(-1, 1)
|
return None
|
||||||
preds = model.predict(future_x)
|
|
||||||
return np.abs(preds)
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
||||||
|
|
||||||
# Mendapatkan rate dan tahun maksimal
|
# Query untuk mendapatkan rate dan max_year
|
||||||
rate, max_year = self.__get_rate_and_max_year(p_equipment_id)
|
query = """
|
||||||
pmt = 0
|
SELECT
|
||||||
|
(SELECT value_num / 100 FROM lcc_ms_master where name='inflation_rate') AS rate,
|
||||||
# Prediksi untuk setiap kolom
|
(SELECT MAX(tahun) FROM lcc_equipment_tr_data WHERE is_actual = 1 AND assetnum = %s) AS max_year
|
||||||
for column in df.columns:
|
"""
|
||||||
if column != "year":
|
cursor.execute(query, (equipment_id,))
|
||||||
if "cost" in column.lower():
|
result = cursor.fetchone()
|
||||||
# Prediksi Future Value
|
|
||||||
nper = max_year - df["year"].max()
|
# Debug hasil query
|
||||||
pv = -df[column].iloc[-1]
|
# print(f"Result: {result}")
|
||||||
predictions[column] = self.__future_value_predict(rate, nper, pmt, pv, future_years)
|
|
||||||
elif df[column].nunique() < 5:
|
rate = result["rate"]
|
||||||
predictions[column] = exponential_smoothing_predict(column, future_years)
|
max_year = result["max_year"]
|
||||||
elif df[column].isnull().sum() > 0:
|
|
||||||
predictions[column] = decision_tree_predict(column, future_years)
|
# Validasi nilai rate dan max_year
|
||||||
else:
|
if rate is None:
|
||||||
predictions[column] = linear_regression_predict(column, future_years)
|
raise Exception(
|
||||||
|
"Nilai 'rate' tidak boleh kosong. Periksa tabel 'lcc_ms_master'."
|
||||||
# Konversi hasil ke DataFrame
|
)
|
||||||
predictions_df = pd.DataFrame(predictions)
|
if max_year is None:
|
||||||
|
raise Exception(
|
||||||
# Hapus data prediksi yang ada sebelumnya
|
"Nilai 'max_year' tidak boleh kosong. Periksa tabel 'lcc_equipment_tr_data'."
|
||||||
self.__delete_predictions_from_db(p_equipment_id)
|
)
|
||||||
|
|
||||||
# Insert hasil prediksi ke database
|
return rate, max_year
|
||||||
self.__insert_predictions_to_db(predictions_df, p_equipment_id)
|
|
||||||
|
except Exception as e:
|
||||||
# Update data untuk total RiskCost per tahun
|
print(f"Error saat mendapatkan parameter dari database: {e}")
|
||||||
self.__update_date_lcc(p_equipment_id)
|
raise # Lempar kembali exception agar program berhenti
|
||||||
|
|
||||||
except Exception as e:
|
finally:
|
||||||
print(f"Program dihentikan: {e}")
|
if connection:
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# ======================================================================================================================================================
|
||||||
|
|
||||||
|
async def predict_equipment_data(self, p_equipment_id, token):
|
||||||
|
try:
|
||||||
|
# Mengambil data dari database
|
||||||
|
df = self.__fetch_data_from_db(p_equipment_id)
|
||||||
|
|
||||||
|
if df is None:
|
||||||
|
print("Data tidak tersedia untuk prediksi.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Mendapatkan tahun proyeksi dari DB
|
||||||
|
par_tahun_target = self.__get_param(p_equipment_id)
|
||||||
|
|
||||||
|
# Tahun proyeksi
|
||||||
|
future_years = list(range(df["year"].max() + 1, par_tahun_target + 1))
|
||||||
|
|
||||||
|
# Hasil prediksi
|
||||||
|
predictions = {"year": future_years}
|
||||||
|
|
||||||
|
# Fungsi untuk prediksi menggunakan Linear Regression
|
||||||
|
def linear_regression_predict(column, years):
|
||||||
|
x = df["year"].values.reshape(-1, 1)
|
||||||
|
y = df[column].fillna(0).values
|
||||||
|
model = LinearRegression()
|
||||||
|
model.fit(x, y)
|
||||||
|
future_x = np.array(years).reshape(-1, 1)
|
||||||
|
preds = model.predict(future_x)
|
||||||
|
return np.abs(preds)
|
||||||
|
|
||||||
|
# Fungsi untuk prediksi menggunakan Exponential Smoothing
|
||||||
|
def exponential_smoothing_predict(column, years):
|
||||||
|
data_series = df[column].fillna(0).values
|
||||||
|
model = ExponentialSmoothing(
|
||||||
|
data_series, trend="add", seasonal=None, seasonal_periods=None
|
||||||
|
)
|
||||||
|
model_fit = model.fit()
|
||||||
|
preds = model_fit.forecast(len(years))
|
||||||
|
return np.abs(preds)
|
||||||
|
|
||||||
|
# Fungsi untuk prediksi menggunakan Decision Tree
|
||||||
|
def decision_tree_predict(column, years):
|
||||||
|
x = df["year"].values.reshape(-1, 1)
|
||||||
|
y = df[column].fillna(0).values
|
||||||
|
model = DecisionTreeRegressor()
|
||||||
|
model.fit(x, y)
|
||||||
|
future_x = np.array(years).reshape(-1, 1)
|
||||||
|
preds = model.predict(future_x)
|
||||||
|
return np.abs(preds)
|
||||||
|
|
||||||
|
# Mendapatkan rate dan tahun maksimal
|
||||||
|
rate, max_year = self.__get_rate_and_max_year(p_equipment_id)
|
||||||
|
pmt = 0
|
||||||
|
|
||||||
|
# Prediksi untuk setiap kolom
|
||||||
|
for column in df.columns:
|
||||||
|
if column != "year":
|
||||||
|
if "cost" in column.lower():
|
||||||
|
# Prediksi Future Value
|
||||||
|
nper = max_year - df["year"].max()
|
||||||
|
pv = -df[column].iloc[-1]
|
||||||
|
predictions[column] = self.__future_value_predict(
|
||||||
|
rate, nper, pmt, pv, future_years
|
||||||
|
)
|
||||||
|
elif df[column].nunique() < 5:
|
||||||
|
predictions[column] = exponential_smoothing_predict(
|
||||||
|
column, future_years
|
||||||
|
)
|
||||||
|
elif df[column].isnull().sum() > 0:
|
||||||
|
predictions[column] = decision_tree_predict(
|
||||||
|
column, future_years
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
predictions[column] = linear_regression_predict(
|
||||||
|
column, future_years
|
||||||
|
)
|
||||||
|
|
||||||
|
# Konversi hasil ke DataFrame
|
||||||
|
predictions_df = pd.DataFrame(predictions)
|
||||||
|
# print(predictions_df)
|
||||||
|
# Hapus data prediksi yang ada sebelumnya
|
||||||
|
self.__delete_predictions_from_db(p_equipment_id)
|
||||||
|
|
||||||
|
# Insert hasil prediksi ke database
|
||||||
|
try:
|
||||||
|
await self.__insert_predictions_to_db(
|
||||||
|
predictions_df, p_equipment_id, token
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error saat insert data ke database: {e}")
|
||||||
|
# self.__insert_predictions_to_db(predictions_df, p_equipment_id)
|
||||||
|
|
||||||
|
# Update data untuk total RiskCost per tahun
|
||||||
|
self.__update_date_lcc(p_equipment_id)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Program dihentikan: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
prediksi = Prediksi()
|
||||||
|
await prediksi.predict_equipment_data(
|
||||||
|
"A22277",
|
||||||
|
token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczOTUxODc4Ni4yOTM5ODUsImp0aSI6Ilo5clRUOFhGa3RweFZUQlBmNGxvRmciLCJ0eXBlIjoiYWNjZXNzIiwic3ViIjoiNWUxNmY4YTgtMWEwMy00MTVjLWIwZjItMTVmZjczOWY1OGE4IiwibmJmIjoxNzM5NTE4Nzg2LCJjc3JmIjoiZWI0MjAzOTMtYTg1ZS00NDJjLWIyMjItZTU5MGU5MGVkYjkyIiwiZXhwIjoxNzM5NjA1MTg2LCJub25jZSI6IjVkZDdhOGYyMWIzZWUxZDZmYmI1YThhMDBlMmYyYjczIn0.3Jv943cU5FuxJ9K92JmVoOtTBqexF4Dke8TrrC4l0Uk",
|
||||||
|
)
|
||||||
|
print("Selesai.")
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,331 @@
|
|||||||
|
import psycopg2
|
||||||
|
from psycopg2.extras import DictCursor
|
||||||
|
from uuid import uuid4
|
||||||
|
from datetime import datetime
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
from config import get_connection
|
||||||
|
|
||||||
|
|
||||||
|
def get_recursive_query(cursor, equipment_id, worktype="CM"):
|
||||||
|
"""
|
||||||
|
Fungsi untuk menjalankan query rekursif berdasarkan equipment_id dan worktype.
|
||||||
|
worktype memiliki nilai default 'CM'.
|
||||||
|
"""
|
||||||
|
query = f"""
|
||||||
|
SELECT
|
||||||
|
ROW_NUMBER() OVER (ORDER BY tbl.assetnum, tbl.year, tbl.worktype) AS seq,
|
||||||
|
*
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
a.worktype,
|
||||||
|
a.assetnum,
|
||||||
|
EXTRACT(YEAR FROM a.reportdate) AS year,
|
||||||
|
COUNT(a.wonum) AS raw_corrective_failure_interval,
|
||||||
|
SUM(a.total_cost_max) AS raw_corrective_material_cost,
|
||||||
|
ROUND(
|
||||||
|
SUM(
|
||||||
|
EXTRACT(EPOCH FROM (
|
||||||
|
a.actfinish -
|
||||||
|
a.actstart
|
||||||
|
))
|
||||||
|
) / 3600
|
||||||
|
, 2) AS raw_corrective_labor_time_jam,
|
||||||
|
SUM(a.jumlah_labor) AS raw_corrective_labor_technician
|
||||||
|
FROM
|
||||||
|
public.wo_staging_3 AS a
|
||||||
|
WHERE
|
||||||
|
a.unit = '3'
|
||||||
|
GROUP BY
|
||||||
|
a.worktype,
|
||||||
|
a.assetnum,
|
||||||
|
EXTRACT(YEAR FROM a.reportdate)
|
||||||
|
) AS tbl
|
||||||
|
WHERE
|
||||||
|
tbl.worktype = '{worktype}'
|
||||||
|
AND tbl.assetnum = '{equipment_id}'
|
||||||
|
ORDER BY
|
||||||
|
tbl.assetnum,
|
||||||
|
tbl.year,
|
||||||
|
tbl.worktype
|
||||||
|
"""
|
||||||
|
# Eksekusi query dan fetch hasil
|
||||||
|
cursor.execute(query)
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_tahun(cursor):
|
||||||
|
query = f"""
|
||||||
|
select * from lcc_ms_year_data
|
||||||
|
"""
|
||||||
|
# Eksekusi query dan fetch hasil
|
||||||
|
cursor.execute(query)
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
|
||||||
|
def query_data():
|
||||||
|
connection = None
|
||||||
|
try:
|
||||||
|
# Mendapatkan koneksi dari config.py
|
||||||
|
connection, connection_wo_db = get_connection()
|
||||||
|
if connection is None or connection_wo_db is None:
|
||||||
|
print("Database connection failed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Membuat cursor menggunakan DictCursor
|
||||||
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
||||||
|
cursor_wo = connection_wo_db.cursor(cursor_factory=DictCursor)
|
||||||
|
# TRUNCATE DATA
|
||||||
|
# truncate_query = "TRUNCATE TABLE lcc_equipment_tr_data"
|
||||||
|
# cursor.execute(truncate_query)
|
||||||
|
|
||||||
|
# Query untuk mendapatkan semua data dari tabel `lcc_ms_equipment_data`
|
||||||
|
query_main = "SELECT * FROM lcc_ms_equipment_data"
|
||||||
|
cursor.execute(query_main)
|
||||||
|
|
||||||
|
# Fetch semua hasil query
|
||||||
|
results = cursor.fetchall()
|
||||||
|
|
||||||
|
# Tahun sekarang
|
||||||
|
current_year = datetime.now().year
|
||||||
|
|
||||||
|
# Looping untuk setiap equipment_id
|
||||||
|
for row in results:
|
||||||
|
equipment_id = row["assetnum"] # Mengambil equipment_id dari hasil query
|
||||||
|
forecasting_start_year = row["forecasting_start_year"] - 1
|
||||||
|
|
||||||
|
# CM
|
||||||
|
recursive_results = get_recursive_query(
|
||||||
|
cursor_wo, equipment_id, worktype="CM"
|
||||||
|
)
|
||||||
|
# PM
|
||||||
|
data_pm = get_recursive_query(cursor_wo, equipment_id, worktype="PM")
|
||||||
|
# OH
|
||||||
|
data_oh = get_recursive_query(cursor_wo, equipment_id, worktype="OH")
|
||||||
|
# Data Tahun
|
||||||
|
data_tahunan = get_data_tahun(cursor)
|
||||||
|
|
||||||
|
seq = 0
|
||||||
|
# Looping untuk setiap tahun
|
||||||
|
for year in range(forecasting_start_year, current_year + 1):
|
||||||
|
# print(f"Processing equipment_id {equipment_id} in year {year}")
|
||||||
|
# Filter data berdasarkan tahun
|
||||||
|
recursive_row = next(
|
||||||
|
(r for r in recursive_results if r["year"] == year), None
|
||||||
|
) # CM Corrective Maintenance
|
||||||
|
data_pm_row = next((r for r in data_pm if r["year"] == year), None)
|
||||||
|
data_oh_row = next((r for r in data_oh if r["year"] == year), None)
|
||||||
|
data_tahunan_row = next(
|
||||||
|
(r for r in data_tahunan if r["year"] == year), None
|
||||||
|
)
|
||||||
|
|
||||||
|
# Cek apakah data sudah ada
|
||||||
|
check_query = """
|
||||||
|
SELECT COUNT(*) FROM lcc_equipment_tr_data
|
||||||
|
WHERE assetnum = %s AND tahun = %s
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute(check_query, (equipment_id, year))
|
||||||
|
data_exists = cursor.fetchone()[0]
|
||||||
|
# print("Data exists for equipment_id", equipment_id)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error checking data for equipment_id {equipment_id}: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not data_exists:
|
||||||
|
print("Data not exists for equipment_id", equipment_id)
|
||||||
|
# Insert data jika belum ada
|
||||||
|
if not recursive_row and not data_pm_row and not data_oh_row:
|
||||||
|
# Jika data recursive_row tidak ada
|
||||||
|
insert_query = """
|
||||||
|
INSERT INTO lcc_equipment_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_material_cost, raw_oh_labor_time, raw_oh_labor_human
|
||||||
|
, "raw_loss_output_MW", raw_loss_output_price
|
||||||
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s
|
||||||
|
, %s, %s, %s, %s
|
||||||
|
, %s, %s, %s
|
||||||
|
, %s, %s
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
cursor.execute(
|
||||||
|
insert_query,
|
||||||
|
(
|
||||||
|
str(uuid4()), # id
|
||||||
|
equipment_id, # equipment_id
|
||||||
|
year, # tahun
|
||||||
|
seq, # seq
|
||||||
|
1, # is_actual
|
||||||
|
1, # raw_cm_interval (minimal 1 karena minimal 1x OH)
|
||||||
|
0, # raw_cm_material_cost
|
||||||
|
0, # raw_cm_labor_time
|
||||||
|
0, # raw_cm_labor_human
|
||||||
|
1, # pm interval set default 1
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(
|
||||||
|
data_tahunan_row["total_lost"]
|
||||||
|
if data_tahunan_row
|
||||||
|
else 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
data_tahunan_row["rp_per_kwh"]
|
||||||
|
if data_tahunan_row
|
||||||
|
else 0
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print("Data exists for equipment_id", equipment_id)
|
||||||
|
# Jika data recursive_row ada
|
||||||
|
# raw_cm_interval ambil dari reliability predict
|
||||||
|
insert_query = """
|
||||||
|
INSERT INTO lcc_equipment_tr_data (
|
||||||
|
id, equipment_id, 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_material_cost, raw_oh_labor_time, raw_oh_labor_human
|
||||||
|
, "raw_loss_output_MW", raw_loss_output_price
|
||||||
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s
|
||||||
|
, %s, %s, %s, %s
|
||||||
|
, %s, %s, %s
|
||||||
|
, %s, %s
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
cursor.execute(
|
||||||
|
insert_query,
|
||||||
|
(
|
||||||
|
str(uuid4()), # id
|
||||||
|
equipment_id, # equipment_id
|
||||||
|
year, # tahun
|
||||||
|
seq, # seq
|
||||||
|
1, # is_actual
|
||||||
|
(
|
||||||
|
recursive_row["raw_corrective_failure_interval"] + 1
|
||||||
|
if recursive_row
|
||||||
|
else 1
|
||||||
|
), # raw_cm_interval nanti ambil dari API reliability predict
|
||||||
|
(
|
||||||
|
recursive_row["raw_corrective_material_cost"]
|
||||||
|
if recursive_row
|
||||||
|
else 0
|
||||||
|
), # raw_cm_material_cost
|
||||||
|
(
|
||||||
|
(
|
||||||
|
recursive_row["raw_corrective_labor_time_jam"]
|
||||||
|
or 0
|
||||||
|
)
|
||||||
|
if recursive_row
|
||||||
|
else 0
|
||||||
|
), # raw_cm_labor_time
|
||||||
|
(
|
||||||
|
(
|
||||||
|
max(
|
||||||
|
recursive_row[
|
||||||
|
"raw_corrective_labor_technician"
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
if recursive_row[
|
||||||
|
"raw_corrective_labor_time_jam"
|
||||||
|
]
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
if recursive_row
|
||||||
|
else 0
|
||||||
|
), # raw_cm_labor_human
|
||||||
|
1, # raw_pm_interval
|
||||||
|
(
|
||||||
|
data_pm_row["raw_corrective_material_cost"]
|
||||||
|
if data_pm_row
|
||||||
|
else 0
|
||||||
|
), # raw_pm_material_cost
|
||||||
|
(
|
||||||
|
(data_pm_row["raw_corrective_labor_time_jam"] or 0)
|
||||||
|
if data_pm_row
|
||||||
|
else 0
|
||||||
|
), # raw_pm_labor_time
|
||||||
|
(
|
||||||
|
(
|
||||||
|
max(
|
||||||
|
data_pm_row[
|
||||||
|
"raw_corrective_labor_technician"
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
if data_pm_row["raw_corrective_labor_time_jam"]
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
if data_pm_row
|
||||||
|
else 0
|
||||||
|
), # raw_pm_labor_human
|
||||||
|
(
|
||||||
|
data_oh_row["raw_corrective_material_cost"]
|
||||||
|
if data_oh_row
|
||||||
|
else 0
|
||||||
|
), # raw_oh_material_cost
|
||||||
|
(
|
||||||
|
(data_oh_row["raw_corrective_labor_time_jam"] or 0)
|
||||||
|
if data_oh_row
|
||||||
|
else 0
|
||||||
|
), # raw_oh_labor_time
|
||||||
|
(
|
||||||
|
(
|
||||||
|
max(
|
||||||
|
data_oh_row[
|
||||||
|
"raw_corrective_labor_technician"
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
if data_oh_row["raw_corrective_labor_time_jam"]
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
if data_oh_row
|
||||||
|
else 0
|
||||||
|
), # raw_oh_labor_human
|
||||||
|
(
|
||||||
|
data_tahunan_row["total_lost"]
|
||||||
|
if data_tahunan_row
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
/ (
|
||||||
|
recursive_row["raw_corrective_failure_interval"] + 1
|
||||||
|
if recursive_row
|
||||||
|
else 1
|
||||||
|
), # raw_loss_output_MW
|
||||||
|
(
|
||||||
|
data_tahunan_row["rp_per_kwh"]
|
||||||
|
if data_tahunan_row
|
||||||
|
else 0
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
print(f"Data inserted for {equipment_id} in year {year}")
|
||||||
|
|
||||||
|
seq = seq + 1
|
||||||
|
|
||||||
|
# Commit perubahan
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("Error saat menjalankan query:", e)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Menutup koneksi
|
||||||
|
if connection or connection_wo_db:
|
||||||
|
cursor.close()
|
||||||
|
cursor_wo.close()
|
||||||
|
connection.close()
|
||||||
|
connection_wo_db.close()
|
||||||
|
# print("========Process finished and connection closed.========")
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
from .insert_actual_data import query_data
|
||||||
|
from .Prediksi import Prediksi
|
||||||
|
from .Eac import Eac
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
# Panggil fungsi
|
||||||
|
async def main(assetnum, token, RELIABILITY_APP_URL):
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
query_data()
|
||||||
|
prediksi = Prediksi(RELIABILITY_APP_URL)
|
||||||
|
await prediksi.predict_equipment_data(
|
||||||
|
assetnum,
|
||||||
|
token=token,
|
||||||
|
)
|
||||||
|
eac = Eac()
|
||||||
|
eac.hitung_eac_equipment(assetnum)
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
execution_time = end_time - start_time
|
||||||
|
print(f"EAC calculation finished in {execution_time:.2f} seconds.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(
|
||||||
|
main(
|
||||||
|
"A22277",
|
||||||
|
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczOTUxODc4Ni4yOTM5ODUsImp0aSI6Ilo5clRUOFhGa3RweFZUQlBmNGxvRmciLCJ0eXBlIjoiYWNjZXNzIiwic3ViIjoiNWUxNmY4YTgtMWEwMy00MTVjLWIwZjItMTVmZjczOWY1OGE4IiwibmJmIjoxNzM5NTE4Nzg2LCJjc3JmIjoiZWI0MjAzOTMtYTg1ZS00NDJjLWIyMjItZTU5MGU5MGVkYjkyIiwiZXhwIjoxNzM5NjA1MTg2LCJub25jZSI6IjVkZDdhOGYyMWIzZWUxZDZmYmI1YThhMDBlMmYyYjczIn0.3Jv943cU5FuxJ9K92JmVoOtTBqexF4Dke8TrrC4l0Uk",
|
||||||
|
)
|
||||||
|
)
|
||||||
Binary file not shown.
Loading…
Reference in New Issue