|
|
|
|
@ -101,9 +101,7 @@ class Prediksi:
|
|
|
|
|
raw_predictive_material_cost AS predictive_material_cost,
|
|
|
|
|
raw_predictive_labor_time AS predictive_labor_time,
|
|
|
|
|
raw_predictive_labor_human AS predictive_labor_human,
|
|
|
|
|
raw_predictive_interval AS predictive_interval,
|
|
|
|
|
"raw_loss_output_MW" AS loss_output_mw,
|
|
|
|
|
raw_loss_output_price AS loss_price
|
|
|
|
|
raw_predictive_interval AS predictive_interval
|
|
|
|
|
FROM lcc_equipment_tr_data
|
|
|
|
|
WHERE assetnum = %s
|
|
|
|
|
and is_actual=1
|
|
|
|
|
@ -199,10 +197,9 @@ class Prediksi:
|
|
|
|
|
raw_pm_material_cost, raw_pm_labor_time, raw_pm_labor_human,
|
|
|
|
|
raw_oh_interval, raw_oh_material_cost, raw_oh_labor_time, raw_oh_labor_human,
|
|
|
|
|
raw_predictive_interval, raw_predictive_material_cost, raw_predictive_labor_time, raw_predictive_labor_human,
|
|
|
|
|
"raw_loss_output_MW", raw_loss_output_price
|
|
|
|
|
, created_by, created_at
|
|
|
|
|
created_by, created_at
|
|
|
|
|
) VALUES (
|
|
|
|
|
%s, %s, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'Sys', NOW()
|
|
|
|
|
%s, %s, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'Sys', NOW()
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
@ -431,112 +428,6 @@ class Prediksi:
|
|
|
|
|
if connection:
|
|
|
|
|
connection.close()
|
|
|
|
|
|
|
|
|
|
# Fungsi untuk mengambil labour cost
|
|
|
|
|
def __get_labour_cost(self, equipment_id, worktype, existing_connection=None):
|
|
|
|
|
"""Return labour cost totals per tahun for the given worktype."""
|
|
|
|
|
labour_costs = {}
|
|
|
|
|
connection = existing_connection
|
|
|
|
|
cursor = None
|
|
|
|
|
close_connection = False
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if connection is None:
|
|
|
|
|
connections = get_production_connection()
|
|
|
|
|
connection = connections[0] if isinstance(connections, tuple) else connections
|
|
|
|
|
close_connection = True
|
|
|
|
|
|
|
|
|
|
if connection is None:
|
|
|
|
|
print("Database connection failed.")
|
|
|
|
|
return labour_costs
|
|
|
|
|
|
|
|
|
|
cursor = connection.cursor()
|
|
|
|
|
|
|
|
|
|
worktype_upper = (worktype or "").upper()
|
|
|
|
|
worktype_condition = "AND a.worktype IN ('CM', 'PROACTIVE', 'WA')"
|
|
|
|
|
params = [equipment_id]
|
|
|
|
|
|
|
|
|
|
if worktype_upper != "CM":
|
|
|
|
|
worktype_condition = "AND a.worktype = %s"
|
|
|
|
|
params.append(worktype_upper)
|
|
|
|
|
|
|
|
|
|
exclude_condition = "AND a.wojp8 != 'S1'" if worktype_upper == "CM" else ""
|
|
|
|
|
|
|
|
|
|
query = f"""
|
|
|
|
|
SELECT
|
|
|
|
|
EXTRACT(YEAR FROM x.reportdate)::int AS tahun,
|
|
|
|
|
SUM(x.upah_per_wonum) AS total_upah_per_tahun
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT
|
|
|
|
|
bw.wonum,
|
|
|
|
|
bw.reportdate,
|
|
|
|
|
bw.jumlah_jam_kerja,
|
|
|
|
|
CASE
|
|
|
|
|
WHEN COUNT(b.laborcode) FILTER (WHERE b.laborcode IS NOT NULL) > 0 THEN
|
|
|
|
|
SUM(
|
|
|
|
|
COALESCE(emp_cost.salary_per_hour_idr,
|
|
|
|
|
(SELECT salary_per_hour_idr FROM lcc_manpower_cost WHERE UPPER(staff_job_level) = UPPER('Junior') LIMIT 1))
|
|
|
|
|
* bw.jumlah_jam_kerja
|
|
|
|
|
)
|
|
|
|
|
ELSE
|
|
|
|
|
3 * (SELECT salary_per_hour_idr FROM lcc_manpower_cost WHERE UPPER(staff_job_level) = UPPER('Junior') LIMIT 1) * bw.jumlah_jam_kerja
|
|
|
|
|
END AS upah_per_wonum
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT
|
|
|
|
|
a.wonum,
|
|
|
|
|
a.reportdate,
|
|
|
|
|
CASE
|
|
|
|
|
WHEN (EXTRACT(EPOCH FROM (a.actfinish - a.actstart)) / 3600.0) = 0
|
|
|
|
|
THEN 1
|
|
|
|
|
ELSE (EXTRACT(EPOCH FROM (a.actfinish - a.actstart)) / 3600.0)
|
|
|
|
|
END AS jumlah_jam_kerja
|
|
|
|
|
FROM public.wo_maximo a
|
|
|
|
|
WHERE
|
|
|
|
|
a.asset_unit = '3'
|
|
|
|
|
AND a.wonum NOT LIKE 'T%'
|
|
|
|
|
AND a.asset_assetnum = %s
|
|
|
|
|
AND (EXTRACT(EPOCH FROM (a.actfinish - a.actstart)) / 3600.0) <= 730
|
|
|
|
|
{worktype_condition}
|
|
|
|
|
{exclude_condition}
|
|
|
|
|
) bw
|
|
|
|
|
LEFT JOIN public.wo_maximo_labtrans b ON b.wonum = bw.wonum
|
|
|
|
|
LEFT JOIN lcc_ms_manpower emp ON UPPER(TRIM(emp."ID Number")) = UPPER(TRIM(b.laborcode))
|
|
|
|
|
LEFT JOIN lcc_manpower_cost emp_cost ON UPPER(TRIM(emp_cost.staff_job_level)) = UPPER(TRIM(emp."Position"))
|
|
|
|
|
GROUP BY bw.wonum, bw.reportdate, bw.jumlah_jam_kerja
|
|
|
|
|
) x
|
|
|
|
|
GROUP BY 1
|
|
|
|
|
ORDER BY 1;
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
cursor.execute(query, tuple(params))
|
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
|
for tahun, total in rows:
|
|
|
|
|
try:
|
|
|
|
|
year_int = int(tahun) if tahun is not None else None
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
year_int = None
|
|
|
|
|
if year_int is None:
|
|
|
|
|
continue
|
|
|
|
|
try:
|
|
|
|
|
labour_costs[year_int] = float(total) if total is not None else 0.0
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
labour_costs[year_int] = 0.0
|
|
|
|
|
|
|
|
|
|
return labour_costs
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error saat mendapatkan labour cost dari database: {e}")
|
|
|
|
|
return labour_costs
|
|
|
|
|
finally:
|
|
|
|
|
if cursor:
|
|
|
|
|
try:
|
|
|
|
|
cursor.close()
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
if close_connection and connection:
|
|
|
|
|
try:
|
|
|
|
|
connection.close()
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Fungsi untuk menghapus data proyeksi pada tahun tertentu
|
|
|
|
|
def __update_data_lcc(self, equipment_id):
|
|
|
|
|
@ -555,27 +446,14 @@ class Prediksi:
|
|
|
|
|
|
|
|
|
|
cursor = connection.cursor(cursor_factory=DictCursor)
|
|
|
|
|
|
|
|
|
|
labour_cost_maps = {
|
|
|
|
|
"CM": self.__get_labour_cost(equipment_id, "CM", production_connection),
|
|
|
|
|
"PM": self.__get_labour_cost(equipment_id, "PM", production_connection),
|
|
|
|
|
"PDM": self.__get_labour_cost(equipment_id, "PDM", production_connection),
|
|
|
|
|
"OH": self.__get_labour_cost(equipment_id, "OH", production_connection),
|
|
|
|
|
}
|
|
|
|
|
cm_labour_costs = labour_cost_maps.get("CM", {}) or {}
|
|
|
|
|
pm_labour_costs = labour_cost_maps.get("PM", {}) or {}
|
|
|
|
|
pdm_labour_costs = labour_cost_maps.get("PDM", {}) or {}
|
|
|
|
|
oh_labour_costs = labour_cost_maps.get("OH", {}) or {}
|
|
|
|
|
|
|
|
|
|
# Ambil semua baris untuk assetnum
|
|
|
|
|
select_q = '''
|
|
|
|
|
SELECT id, seq, tahun,
|
|
|
|
|
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_predictive_interval, raw_predictive_material_cost, raw_predictive_labor_time, raw_predictive_labor_human,
|
|
|
|
|
raw_oh_interval, raw_oh_material_cost, raw_oh_labor_time, raw_oh_labor_human,
|
|
|
|
|
raw_predictive_interval, raw_predictive_material_cost, raw_predictive_labor_time, raw_predictive_labor_human,
|
|
|
|
|
"raw_loss_output_MW" as raw_loss_output_mw, raw_loss_output_price,
|
|
|
|
|
raw_operational_cost, raw_maintenance_cost,
|
|
|
|
|
raw_cm_interval, raw_cm_material_cost, rc_cm_labor_cost,
|
|
|
|
|
raw_pm_interval, raw_pm_material_cost, rc_pm_labor_cost,
|
|
|
|
|
raw_predictive_interval, raw_predictive_material_cost, rc_predictive_labor_cost,
|
|
|
|
|
raw_oh_interval, raw_oh_material_cost, rc_oh_labor_cost,
|
|
|
|
|
raw_predictive_interval, raw_predictive_material_cost, rc_predictive_labor_cost,
|
|
|
|
|
efdh_equivalent_forced_derated_hours, foh_forced_outage_hours
|
|
|
|
|
FROM lcc_equipment_tr_data
|
|
|
|
|
WHERE assetnum = %s;
|
|
|
|
|
@ -623,30 +501,12 @@ class Prediksi:
|
|
|
|
|
|
|
|
|
|
seq = int(r.get("seq") or 0) if isinstance(r, dict) else int(r[1] or 0)
|
|
|
|
|
|
|
|
|
|
raw_cm_interval = float(r.get("raw_cm_interval") or 0.0)
|
|
|
|
|
raw_cm_labor_time = float(r.get("raw_cm_labor_time") or 0.0)
|
|
|
|
|
raw_cm_labor_human = float(r.get("raw_cm_labor_human") or 0.0)
|
|
|
|
|
|
|
|
|
|
raw_pm_interval = float(r.get("raw_pm_interval") or 0.0)
|
|
|
|
|
raw_pm_material_cost = float(r.get("raw_pm_material_cost") or 0.0)
|
|
|
|
|
raw_pm_labor_time = float(r.get("raw_pm_labor_time") or 0.0)
|
|
|
|
|
raw_pm_labor_human = float(r.get("raw_pm_labor_human") or 0.0)
|
|
|
|
|
|
|
|
|
|
raw_predictive_interval = float(r.get("raw_predictive_interval") or 0.0)
|
|
|
|
|
raw_pm_material_cost = float(r.get("raw_pm_material_cost") or 0.0)
|
|
|
|
|
raw_predictive_material_cost = float(r.get("raw_predictive_material_cost") or 0.0)
|
|
|
|
|
raw_predictive_labor_time = float(r.get("raw_predictive_labor_time") or 0.0)
|
|
|
|
|
raw_predictive_labor_human = float(r.get("raw_predictive_labor_human") or 0.0)
|
|
|
|
|
|
|
|
|
|
raw_oh_interval = float(r.get("raw_oh_interval") or 0.0)
|
|
|
|
|
raw_oh_material_cost = float(r.get("raw_oh_material_cost") or 0.0)
|
|
|
|
|
raw_oh_labor_time = float(r.get("raw_oh_labor_time") or 0.0)
|
|
|
|
|
raw_oh_labor_human = float(r.get("raw_oh_labor_human") or 0.0)
|
|
|
|
|
|
|
|
|
|
# raw_loss_output_mw = float(r.get("raw_loss_output_mw") or 0.0)
|
|
|
|
|
# raw_loss_output_price = float(r.get("raw_loss_output_price") or 0.0)
|
|
|
|
|
|
|
|
|
|
# raw_operational_cost = float(r.get("raw_operational_cost") or 0.0)
|
|
|
|
|
# raw_maintenance_cost = float(r.get("raw_maintenance_cost") or 0.0)
|
|
|
|
|
efdh_equivalent_forced_derated_hours = float(r.get("efdh_equivalent_forced_derated_hours") or 0.0)
|
|
|
|
|
foh_forced_outage_hours = float(r.get("foh_forced_outage_hours") or 0.0)
|
|
|
|
|
|
|
|
|
|
@ -654,13 +514,10 @@ class Prediksi:
|
|
|
|
|
|
|
|
|
|
# compute per-column costs using helpers
|
|
|
|
|
rc_cm_material = rc_cm_material_cost
|
|
|
|
|
rc_cm_labor = rc_labor_cost(raw_cm_interval, raw_cm_labor_time, raw_cm_labor_human, man_hour)
|
|
|
|
|
cm_labor_total = cm_labour_costs.get(yr)
|
|
|
|
|
if cm_labor_total is not None:
|
|
|
|
|
try:
|
|
|
|
|
rc_cm_labor = float(cm_labor_total)
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
rc_cm_labor = 0.0
|
|
|
|
|
rc_cm_labor = float(r.get("rc_cm_labor_cost") or 0.0)
|
|
|
|
|
rc_pm_labor = float(r.get("rc_pm_labor_cost") or 0.0)
|
|
|
|
|
rc_predictive_labor = float(r.get("rc_predictive_labor_cost") or 0.0)
|
|
|
|
|
rc_oh_labor = float(r.get("rc_oh_labor_cost") or 0.0)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# if np.isfinite(raw_pm_interval) and raw_pm_interval != 0:
|
|
|
|
|
@ -669,13 +526,7 @@ class Prediksi:
|
|
|
|
|
rc_pm_material = raw_pm_material_cost
|
|
|
|
|
except Exception:
|
|
|
|
|
rc_pm_material = 0.0
|
|
|
|
|
rc_pm_labor = rc_labor_cost(raw_pm_interval, raw_pm_labor_time, raw_pm_labor_human, man_hour)
|
|
|
|
|
pm_labor_total = pm_labour_costs.get(yr)
|
|
|
|
|
if pm_labor_total is not None:
|
|
|
|
|
try:
|
|
|
|
|
rc_pm_labor = float(pm_labor_total)
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
rc_pm_labor = 0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# if np.isfinite(raw_predictive_interval) and raw_predictive_interval != 0:
|
|
|
|
|
@ -685,31 +536,7 @@ class Prediksi:
|
|
|
|
|
except Exception:
|
|
|
|
|
rc_predictive_material = 0.0
|
|
|
|
|
|
|
|
|
|
rc_predictive_labor = raw_predictive_labor_human
|
|
|
|
|
try:
|
|
|
|
|
rc_predictive_labor = rc_labor_cost(raw_predictive_interval, raw_predictive_labor_time, raw_predictive_labor_human, man_hour)
|
|
|
|
|
except Exception:
|
|
|
|
|
rc_predictive_labor = 0.0
|
|
|
|
|
predictive_labor_total = pdm_labour_costs.get(yr)
|
|
|
|
|
if predictive_labor_total is not None:
|
|
|
|
|
try:
|
|
|
|
|
rc_predictive_labor = float(predictive_labor_total)
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
rc_predictive_labor = 0.0
|
|
|
|
|
|
|
|
|
|
rc_oh_material = raw_oh_material_cost
|
|
|
|
|
rc_oh_labor = rc_labor_cost(raw_oh_interval, raw_oh_labor_time, raw_oh_labor_human, man_hour)
|
|
|
|
|
oh_labor_total = oh_labour_costs.get(yr)
|
|
|
|
|
if oh_labor_total is not None:
|
|
|
|
|
try:
|
|
|
|
|
rc_oh_labor = float(oh_labor_total)
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
rc_oh_labor = 0.0
|
|
|
|
|
|
|
|
|
|
# rc_lost = rc_lost_cost(raw_loss_output_mw, raw_loss_output_price, raw_cm_interval)
|
|
|
|
|
|
|
|
|
|
# rc_operation = raw_operational_cost
|
|
|
|
|
# rc_maintenance = raw_maintenance_cost
|
|
|
|
|
|
|
|
|
|
asset_criticality_data = self.__get_asset_criticality_params(equipment_id)
|
|
|
|
|
asset_criticality_value = 0.0
|
|
|
|
|
@ -734,9 +561,6 @@ class Prediksi:
|
|
|
|
|
rc_pm=rc_pm_material + rc_pm_labor + ac_multiplier,
|
|
|
|
|
rc_predictive=rc_predictive_material + rc_predictive_labor + ac_multiplier,
|
|
|
|
|
rc_oh=rc_oh_material + rc_oh_labor + ac_multiplier,
|
|
|
|
|
# rc_lost=rc_lost,
|
|
|
|
|
# rc_operation=rc_operation,
|
|
|
|
|
# rc_maintenance=rc_maintenance,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
id_val = r.get("id") if isinstance(r, dict) else r[0]
|
|
|
|
|
@ -752,9 +576,6 @@ class Prediksi:
|
|
|
|
|
rc_predictive_labor,
|
|
|
|
|
rc_oh_material,
|
|
|
|
|
rc_oh_labor,
|
|
|
|
|
# rc_lost,
|
|
|
|
|
# rc_operation,
|
|
|
|
|
# rc_maintenance,
|
|
|
|
|
total,
|
|
|
|
|
id_val,
|
|
|
|
|
),
|
|
|
|
|
|