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,14 +71,90 @@ def main():
sys.exit(1) sys.exit(1)
try: try:
# ### LOCKING: pastikan transaksi manual (non-autocommit)
try:
conn.autocommit = False
except Exception:
# Kalau driver tidak punya autocommit, abaikan
pass
cur = conn.cursor() cur = conn.cursor()
# ### LOCKING: kunci tabel lcc_plant_tr_data
# Mode SHARE ROW EXCLUSIVE:
# - Menghalangi INSERT/UPDATE/DELETE di tabel ini
# - Menghalangi lock SHARE ROW EXCLUSIVE lain → script ngantri satu per satu
cur.execute("LOCK TABLE lcc_plant_tr_data IN SHARE ROW EXCLUSIVE MODE")
# 0 Mendapatkan master parameter dari tabel lcc_ms_master
cur.execute("""
SELECT name,
value_num AS value
FROM lcc_ms_master
""")
param_rows = cur.fetchall()
param_map = {name: val for (name, val) in param_rows}
# helper biar aman
def get_param(name, default=0.0):
v = param_map.get(name, 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 # 1. Ambil data awal
select_sql = """ select_sql = """
SELECT SELECT *
*
FROM lcc_plant_tr_data FROM lcc_plant_tr_data
ORDER BY seq ORDER BY seq \
""" """
cur.execute(select_sql) cur.execute(select_sql)
@ -78,8 +166,7 @@ def main():
# 2. Siapkan data untuk bulk UPDATE # 2. Siapkan data untuk bulk UPDATE
update_sql = """ update_sql = """
UPDATE lcc_plant_tr_data UPDATE lcc_plant_tr_data
SET SET net_capacity_factor = %s,
net_capacity_factor = %s,
eaf = %s, eaf = %s,
production_bruto = %s, production_bruto = %s,
production_netto = %s, production_netto = %s,
@ -145,22 +232,9 @@ def main():
chart_capex_biaya_investasi_tambahan = %s, chart_capex_biaya_investasi_tambahan = %s,
chart_capex_acquisition_cost = %s, chart_capex_acquisition_cost = %s,
chart_capex_annualized = %s chart_capex_annualized = %s
WHERE seq = %s WHERE seq = %s \
""" """
cur.execute("""
SELECT name,
value_num AS value
FROM lcc_ms_master
""")
param_rows = cur.fetchall()
param_map = {name: val for (name, val) in param_rows}
# helper biar aman
def get_param(name, default=0.0):
v = param_map.get(name, default)
return float(v) if v is not None else float(default)
# 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")
@ -255,7 +329,6 @@ def main():
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
if seq > 0: if seq > 0:
@ -491,7 +564,8 @@ def main():
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