update run2 & export plant

main
ariwahyunahar 1 month ago
parent cb229086e8
commit bb70d7b445

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/be-lcca.iml" filepath="$PROJECT_DIR$/.idea/be-lcca.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -110,7 +110,7 @@ def fetch_param_map(cur) -> Dict[str, Param]:
'wacc_on_equity','wacc_on_project','calc_on_equity_irr','calc_on_equity_npv', 'wacc_on_equity','wacc_on_project','calc_on_equity_irr','calc_on_equity_npv',
'calc_on_project_irr','calc_on_project_npv','calc_roa_all','calc_roa_current' 'calc_on_project_irr','calc_on_project_npv','calc_roa_all','calc_roa_current'
) )
ORDER BY name ORDER BY seq ASC
""" """
) )
rows = cur.fetchall() rows = cur.fetchall()

@ -1,14 +1,19 @@
import os import os
import sys import sys
# Tambah path ke config.py (seperti di kode-kode kamu sebelumnya) # Tambah path ke config.py (seperti di kode-kode kamu sebelumnya)
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from config import get_connection # harus mengembalikan koneksi psycopg2 from config import get_connection # harus mengembalikan koneksi psycopg2
from math import pow from math import pow
import numpy_financial as npf import numpy_financial as npf
import math
import uuid
def validate_number(n): def validate_number(n):
return n if n is not None else 0 return n if n is not None else 0
def cumulative_npv(values, rate, initial_cf0=0.0): def cumulative_npv(values, rate, initial_cf0=0.0):
""" """
Penggunaan: Penggunaan:
@ -24,6 +29,8 @@ def cumulative_npv(values, rate, initial_cf0=0.0):
cumulative_results.append(initial_cf0 + running_npv) cumulative_results.append(initial_cf0 + running_npv)
return cumulative_results return cumulative_results
def pmt_excel_style(rate, periods, pv): def pmt_excel_style(rate, periods, pv):
""" """
Fungsi ini menghasilkan nilai setara Excel: Fungsi ini menghasilkan nilai setara Excel:
@ -46,12 +53,17 @@ def pmt_excel_style(rate, periods, pv):
# Excel memberi hasil negatif, tapi rumusmu pakai -PMT, maka hasilnya positif # Excel memberi hasil negatif, tapi rumusmu pakai -PMT, maka hasilnya positif
return abs(payment) return abs(payment)
def hitung_pv(rate, nper, fv): def hitung_pv(rate, nper, fv):
pv = npf.pv(rate, nper, pmt=0, fv=fv) pv = npf.pv(rate, nper, pmt=0, fv=fv)
return -pv return -pv
def hitung_irr(cashflows: list): def hitung_irr(cashflows: list):
return npf.irr(cashflows) return npf.irr(cashflows)
def main(): def main():
conn = get_connection() conn = get_connection()
if conn is None: if conn is None:
@ -59,95 +71,22 @@ def main():
sys.exit(1) sys.exit(1)
try: try:
cur = conn.cursor() # ### LOCKING: pastikan transaksi manual (non-autocommit)
try:
# 1. Ambil data awal conn.autocommit = False
select_sql = """ except Exception:
SELECT # Kalau driver tidak punya autocommit, abaikan
* pass
FROM lcc_plant_tr_data
ORDER BY seq
"""
cur.execute(select_sql)
col_names = [desc[0] for desc in cur.description]
rows = cur.fetchall()
print(f"Jumlah baris yang akan di-update: {len(rows)}") cur = conn.cursor()
# 2. Siapkan data untuk bulk UPDATE # ### LOCKING: kunci tabel lcc_plant_tr_data
update_sql = """ # Mode SHARE ROW EXCLUSIVE:
UPDATE lcc_plant_tr_data # - Menghalangi INSERT/UPDATE/DELETE di tabel ini
SET # - Menghalangi lock SHARE ROW EXCLUSIVE lain → script ngantri satu per satu
net_capacity_factor = %s, cur.execute("LOCK TABLE lcc_plant_tr_data IN SHARE ROW EXCLUSIVE MODE")
eaf = %s,
production_bruto = %s,
production_netto = %s,
energy_sales = %s,
fuel_consumption = %s,
revenue_a = %s,
revenue_b = %s,
revenue_c = %s,
revenue_d = %s,
revenue_total = %s,
revenue_pv = %s,
revenue_annualized = %s,
cost_a_replacement = %s,
cost_a_pm = %s,
cost_a_acquisition = %s,
cost_a_pinjaman = %s,
cost_a_depreciation = %s,
cost_a_total = %s,
cost_a_pv = %s,
cost_a_annualized = %s,
cost_c_fuel = %s,
cost_c_pv = %s,
cost_c_annualized = %s,
cost_bd_om = %s,
cost_bd_pm_nonmi = %s,
cost_bd_bd = %s,
cost_bd_total = %s,
cost_bd_pv = %s,
cost_bd_annualized = %s,
total_expense = %s,
total_cost_eac = %s,
total_profit_loss = %s,
total_residual_value = %s,
calc_depreciation = %s,
calc_interest_payment = %s,
calc_principal_payment = %s,
calc_dept_amount = %s,
calc2_ebitda = %s,
calc2_earning_before_tax = %s,
calc2_tax = %s,
calc2_earning_after_tax = %s,
calc2_nopat = %s,
calc3_interest_after_tax = %s,
calc3_free_cash_flow_on_project = %s,
calc3_discounted_fcf_on_project = %s,
calc4_principal_repayment = %s,
calc4_free_cash_flow_on_equity = %s,
calc4_discounted_fcf_on_equity = %s,
chart_total_revenue = %s,
chart_revenue_a = %s,
chart_revenue_b = %s,
chart_revenue_c = %s,
chart_revenue_d = %s,
chart_revenue_annualized = %s,
chart_fuel_cost_component_c = %s,
chart_fuel_cost = %s,
chart_fuel_cost_annualized = %s,
chart_oem_component_bd = %s,
chart_oem_bd_cost = %s,
chart_oem_periodic_maintenance_cost = %s,
chart_oem_annualized = %s,
chart_capex_component_a = %s,
chart_capex_biaya_investasi_tambahan = %s,
chart_capex_acquisition_cost = %s,
chart_capex_annualized = %s
WHERE seq = %s
"""
# 0 Mendapatkan master parameter dari tabel lcc_ms_master
cur.execute(""" cur.execute("""
SELECT name, SELECT name,
value_num AS value value_num AS value
@ -161,6 +100,141 @@ def main():
v = param_map.get(name, default) v = param_map.get(name, default)
return float(v) if v is not None else float(default) return float(v) if v is not None else float(default)
# 0-1 Generate New data Projection (is_actual=0) if not exist
# Hapus data projection lama (is_actual = 0)
cur.execute("""
DELETE
FROM lcc_plant_tr_data
WHERE is_actual = 0
""")
# Hitung kebutuhan jumlah baris projection baru agar total (actual + projection)
# sama dengan parameter umur_teknis
cur.execute("""
SELECT COALESCE(COUNT(*), 0)
FROM lcc_plant_tr_data
WHERE is_actual = 1
""")
count_actual = cur.fetchone()[0] if cur.rowcount != -1 else 0
umur_teknis = int(get_param("umur_teknis"))
proj_needed = max(0, umur_teknis - int(count_actual))
# Ambil seq dan tahun terakhir sebagai titik awal penomoran berikutnya
cur.execute("SELECT COALESCE(MAX(seq), 0) FROM lcc_plant_tr_data")
last_seq = int(cur.fetchone()[0])
cur.execute("SELECT COALESCE(MAX(tahun), 0) FROM lcc_plant_tr_data")
last_year = int(cur.fetchone()[0])
# Jika belum ada tahun sama sekali, gunakan tahun_cod-1 sebagai dasar
if last_year == 0:
try:
last_year = int(get_param("tahun_cod")) - 1
except Exception:
last_year = 0
if proj_needed > 0:
# Siapkan rows untuk INSERT projection baru
values = []
next_seq = last_seq + 1
next_year = last_year + 1
for _ in range(proj_needed):
values.append((str(uuid.uuid4()), next_seq, next_year))
next_seq += 1
next_year += 1
insert_sql = (
"INSERT INTO lcc_plant_tr_data (id, seq, tahun, is_actual, created_at, created_by) "
"VALUES (%s, %s, %s, 0, CURRENT_TIMESTAMP, 'SYS')"
)
cur.executemany(insert_sql, values)
# 1. Ambil data awal
select_sql = """
SELECT *
FROM lcc_plant_tr_data
ORDER BY seq \
"""
cur.execute(select_sql)
col_names = [desc[0] for desc in cur.description]
rows = cur.fetchall()
print(f"Jumlah baris yang akan di-update: {len(rows)}")
# 2. Siapkan data untuk bulk UPDATE
update_sql = """
UPDATE lcc_plant_tr_data
SET net_capacity_factor = %s,
eaf = %s,
production_bruto = %s,
production_netto = %s,
energy_sales = %s,
fuel_consumption = %s,
revenue_a = %s,
revenue_b = %s,
revenue_c = %s,
revenue_d = %s,
revenue_total = %s,
revenue_pv = %s,
revenue_annualized = %s,
cost_a_replacement = %s,
cost_a_pm = %s,
cost_a_acquisition = %s,
cost_a_pinjaman = %s,
cost_a_depreciation = %s,
cost_a_total = %s,
cost_a_pv = %s,
cost_a_annualized = %s,
cost_c_fuel = %s,
cost_c_pv = %s,
cost_c_annualized = %s,
cost_bd_om = %s,
cost_bd_pm_nonmi = %s,
cost_bd_bd = %s,
cost_bd_total = %s,
cost_bd_pv = %s,
cost_bd_annualized = %s,
total_expense = %s,
total_cost_eac = %s,
total_profit_loss = %s,
total_residual_value = %s,
calc_depreciation = %s,
calc_interest_payment = %s,
calc_principal_payment = %s,
calc_dept_amount = %s,
calc2_ebitda = %s,
calc2_earning_before_tax = %s,
calc2_tax = %s,
calc2_earning_after_tax = %s,
calc2_nopat = %s,
calc3_interest_after_tax = %s,
calc3_free_cash_flow_on_project = %s,
calc3_discounted_fcf_on_project = %s,
calc4_principal_repayment = %s,
calc4_free_cash_flow_on_equity = %s,
calc4_discounted_fcf_on_equity = %s,
chart_total_revenue = %s,
chart_revenue_a = %s,
chart_revenue_b = %s,
chart_revenue_c = %s,
chart_revenue_d = %s,
chart_revenue_annualized = %s,
chart_fuel_cost_component_c = %s,
chart_fuel_cost = %s,
chart_fuel_cost_annualized = %s,
chart_oem_component_bd = %s,
chart_oem_bd_cost = %s,
chart_oem_periodic_maintenance_cost = %s,
chart_oem_annualized = %s,
chart_capex_component_a = %s,
chart_capex_biaya_investasi_tambahan = %s,
chart_capex_acquisition_cost = %s,
chart_capex_annualized = %s
WHERE seq = %s \
"""
# Ambil parameter dari tabel (fungsi get_param sudah kamu buat sebelumnya) # Ambil parameter dari tabel (fungsi get_param sudah kamu buat sebelumnya)
discount_rate = get_param("discount_rate") / 100 discount_rate = get_param("discount_rate") / 100
total_project_cost = get_param("total_project_cost") total_project_cost = get_param("total_project_cost")
@ -198,10 +272,10 @@ def main():
cost_a_acquisition_array = [] cost_a_acquisition_array = []
cost_c_fuel_array = [] cost_c_fuel_array = []
cost_bd_total_array = [] cost_bd_total_array = []
total_residual_value = 0 # nilai awal dari total_residual_value total_residual_value = 0 # nilai awal dari total_residual_value
calc_dept_amount = 0 # nilai awal dari calc_dept_amount calc_dept_amount = 0 # nilai awal dari calc_dept_amount
revenue_total_start = 0 # nilai awal dari revenue_total_start revenue_total_start = 0 # nilai awal dari revenue_total_start
calc4_free_cash_flow_on_equity = 0 # nilai awal dari calc4_free_cash_flow_on_equity calc4_free_cash_flow_on_equity = 0 # nilai awal dari calc4_free_cash_flow_on_equity
calc3_free_cash_flow_on_project_array = [] calc3_free_cash_flow_on_project_array = []
calc4_free_cash_flow_on_equity_array = [] calc4_free_cash_flow_on_equity_array = []
total_residual_value_array = [] total_residual_value_array = []
@ -240,10 +314,10 @@ def main():
cost_bd_pm_nonmi = validate_number(data["cost_bd_pm_nonmi"]) cost_bd_pm_nonmi = validate_number(data["cost_bd_pm_nonmi"])
cost_bd_bd = validate_number(data["cost_bd_bd"]) cost_bd_bd = validate_number(data["cost_bd_bd"])
else: else:
net_capacity_factor = net_capacity_factor #last value net_capacity_factor = net_capacity_factor # last value
eaf = eaf #last value eaf = eaf # last value
production_netto = net_capacity_factor * 8760 * daya_mampu_netto / 100 production_netto = net_capacity_factor * 8760 * daya_mampu_netto / 100
production_bruto = production_netto/(100-(auxiliary+susut_trafo))*100 production_bruto = production_netto / (100 - (auxiliary + susut_trafo)) * 100
energy_sales = production_netto energy_sales = production_netto
fuel_consumption = production_bruto * sfc fuel_consumption = production_bruto * sfc
revenue_a = (price_a * eaf * daya_mampu_netto * 1000 * 12 / 100) / 1000000 revenue_a = (price_a * eaf * daya_mampu_netto * 1000 * 12 / 100) / 1000000
@ -251,10 +325,9 @@ def main():
revenue_c = price_c * production_netto * 1000 / 1000000 revenue_c = price_c * production_netto * 1000 / 1000000
revenue_d = price_d * production_netto * 1000 / 1000000 revenue_d = price_d * production_netto * 1000 / 1000000
cost_c_fuel = fuel_consumption * harga_bahan_bakar / 1000000 cost_c_fuel = fuel_consumption * harga_bahan_bakar / 1000000
cost_bd_om = cost_bd_om #last value cost_bd_om = cost_bd_om # last value
cost_bd_pm_nonmi = cost_bd_pm_nonmi #last value cost_bd_pm_nonmi = cost_bd_pm_nonmi # last value
cost_bd_bd = cost_bd_bd #last value cost_bd_bd = cost_bd_bd # last value
# ++++++ REVENUE +++++++ # ++++++ REVENUE +++++++
revenue_total = revenue_a + revenue_b + revenue_c + revenue_d revenue_total = revenue_a + revenue_b + revenue_c + revenue_d
@ -283,19 +356,19 @@ def main():
if data["is_actual"] == 1: if data["is_actual"] == 1:
cost_a_replacement = validate_number(data["cost_a_replacement"]) cost_a_replacement = validate_number(data["cost_a_replacement"])
cost_a_pm = validate_number(data["cost_a_pm"]) cost_a_pm = validate_number(data["cost_a_pm"])
cost_a_pinjaman = 0 # validate_number(data["cost_a_pinjaman"]) cost_a_pinjaman = 0 # validate_number(data["cost_a_pinjaman"])
cost_a_depreciation = 0 # validate_number(data["cost_a_depreciation"]) cost_a_depreciation = 0 # validate_number(data["cost_a_depreciation"])
else: else:
cost_a_replacement = cost_a_replacement cost_a_replacement = cost_a_replacement
cost_a_pm = cost_a_pm cost_a_pm = cost_a_pm
cost_a_pinjaman = 0 #cost_a_pinjaman cost_a_pinjaman = 0 # cost_a_pinjaman
cost_a_depreciation = 0 # cost_a_depreciation cost_a_depreciation = 0 # cost_a_depreciation
cost_a_total = validate_number(data["cost_a_total"]) cost_a_total = validate_number(data["cost_a_total"])
cost_a_acquisition = ( cost_a_acquisition = (
cost_a_replacement cost_a_replacement
+ cost_a_pm + cost_a_pm
# + cost_a_pinjaman # + cost_a_pinjaman
# + cost_a_depreciation # + cost_a_depreciation
) )
else: else:
cost_a_replacement = 0 cost_a_replacement = 0
@ -395,7 +468,7 @@ def main():
calc4_principal_repayment = -calc_principal_payment calc4_principal_repayment = -calc_principal_payment
if seq > 0: if seq > 0:
calc4_free_cash_flow_on_equity = calc4_principal_repayment+calc2_earning_after_tax+calc_depreciation - cost_a_replacement calc4_free_cash_flow_on_equity = calc4_principal_repayment + calc2_earning_after_tax + calc_depreciation - cost_a_replacement
else: else:
calc4_free_cash_flow_on_equity = -equity calc4_free_cash_flow_on_equity = -equity
calc4_free_cash_flow_on_equity_array.append(calc4_free_cash_flow_on_equity) calc4_free_cash_flow_on_equity_array.append(calc4_free_cash_flow_on_equity)
@ -482,16 +555,17 @@ def main():
# =========================================================================== # ===========================================================================
# ----- ==== HITUNGAN TERAKHIR LCC PLANT ==== ----- # ----- ==== HITUNGAN TERAKHIR LCC PLANT ==== -----
# =========================================================================== # ===========================================================================
IRR_ON_PROJECT = hitung_irr(calc3_free_cash_flow_on_project_array) # dalam % IRR_ON_PROJECT = hitung_irr(calc3_free_cash_flow_on_project_array) # dalam %
NPV_ON_PROJECT = cumulative_npv(calc3_free_cash_flow_on_project_array[1:], wacc_on_project)[-1] + \ NPV_ON_PROJECT = cumulative_npv(calc3_free_cash_flow_on_project_array[1:], wacc_on_project)[-1] + \
calc3_free_cash_flow_on_project_array[0] calc3_free_cash_flow_on_project_array[0]
IRR_ON_EQUITY = hitung_irr(calc4_free_cash_flow_on_equity_array) # dalam % IRR_ON_EQUITY = hitung_irr(calc4_free_cash_flow_on_equity_array) # dalam %
NPV_ON_EQUITY = cumulative_npv(calc4_free_cash_flow_on_equity_array[1:], wacc_on_equity)[-1] + \ NPV_ON_EQUITY = cumulative_npv(calc4_free_cash_flow_on_equity_array[1:], wacc_on_equity)[-1] + \
calc4_free_cash_flow_on_equity_array[0] calc4_free_cash_flow_on_equity_array[0]
ROA_ALL = sum(calc2_earning_after_tax_array) / sum(total_residual_value_array) * 100 # dalam % ROA_ALL = sum(calc2_earning_after_tax_array) / sum(total_residual_value_array) * 100 # dalam %
ROA_TO_L = sum(calc2_earning_after_tax_array_sampai_sekarang) / sum(total_residual_value_array_sampai_sekarang) * 100 # dalam % ROA_TO_L = sum(calc2_earning_after_tax_array_sampai_sekarang) / sum(
total_residual_value_array_sampai_sekarang) * 100 # dalam %
update_kpi_sql = """ update_kpi_sql = """
UPDATE lcc_ms_master UPDATE lcc_ms_master
@ -499,7 +573,7 @@ def main():
WHERE name = %s \ WHERE name = %s \
""" """
kpi_params = [ kpi_params_raw = [
(IRR_ON_EQUITY * 100, "calc_on_equity_irr"), (IRR_ON_EQUITY * 100, "calc_on_equity_irr"),
(NPV_ON_EQUITY, "calc_on_equity_npv"), (NPV_ON_EQUITY, "calc_on_equity_npv"),
(IRR_ON_PROJECT * 100, "calc_on_project_irr"), (IRR_ON_PROJECT * 100, "calc_on_project_irr"),
@ -508,6 +582,11 @@ def main():
(ROA_TO_L, "calc_roa_current"), (ROA_TO_L, "calc_roa_current"),
] ]
kpi_params = [
(None if (value is None or isinstance(value, float) and math.isnan(value)) else value, key)
for value, key in kpi_params_raw
]
cur.executemany(update_kpi_sql, kpi_params) cur.executemany(update_kpi_sql, kpi_params)
conn.commit() conn.commit()
# =========================================================================== # ===========================================================================

Loading…
Cancel
Save