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.")
|
||||
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