|
|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
import datetime
|
|
|
|
|
from typing import Coroutine, List, Optional, Tuple,Dict
|
|
|
|
|
from typing import defaultdict, Coroutine, List, Optional, Tuple,Dict
|
|
|
|
|
from uuid import UUID
|
|
|
|
|
import calendar
|
|
|
|
|
|
|
|
|
|
@ -182,10 +182,10 @@ class SparePartsService:
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
spare_part = self.spare_parts_db[sparepart_id]
|
|
|
|
|
projected_stock = spare_part.stock
|
|
|
|
|
projected_stock = spare_part["stock"]
|
|
|
|
|
|
|
|
|
|
# Add all procurements that arrive by target_date
|
|
|
|
|
for procurement in spare_part.data.sparepart_procurements:
|
|
|
|
|
for procurement in spare_part["data"].sparepart_procurements:
|
|
|
|
|
eta_date = getattr(procurement, procurement.status, None)
|
|
|
|
|
if eta_date and eta_date <= target_date:
|
|
|
|
|
projected_stock += procurement.quantity
|
|
|
|
|
@ -221,14 +221,14 @@ class SparePartsService:
|
|
|
|
|
if sparepart_id not in self.spare_parts_db:
|
|
|
|
|
raise Exception(f"Spare part {sparepart_id} not found in database")
|
|
|
|
|
|
|
|
|
|
spare_part = self.spare_parts_db[sparepart_id]
|
|
|
|
|
spare_part = self.spare_parts_db[sparepart_id]["data"]
|
|
|
|
|
available_stock = self.calculate_stock_at_date(sparepart_id, overhaul_date)
|
|
|
|
|
|
|
|
|
|
if available_stock < quantity_needed:
|
|
|
|
|
# Need to procure additional stock
|
|
|
|
|
shortage = quantity_needed - available_stock
|
|
|
|
|
procurement_cost = {
|
|
|
|
|
"sparepart_id": sparepart_id,
|
|
|
|
|
"sparepart_id": str(sparepart_id),
|
|
|
|
|
"sparepart_name": spare_part.name,
|
|
|
|
|
"quantity": shortage,
|
|
|
|
|
"cost_per_unit": spare_part.cost_per_stock,
|
|
|
|
|
@ -290,20 +290,6 @@ class OverhaulCalculator:
|
|
|
|
|
if months_since_overhaul >= interval_months:
|
|
|
|
|
# Perform preventive overhaul
|
|
|
|
|
total_preventive_cost += preventive_cost
|
|
|
|
|
|
|
|
|
|
# Check spare parts availability and calculate procurement costs
|
|
|
|
|
parts_available, procurement_costs = await self.spare_parts_service.check_spare_parts_availability(
|
|
|
|
|
db_session,
|
|
|
|
|
equipment,
|
|
|
|
|
current_date
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Add procurement costs if parts are not available
|
|
|
|
|
if not parts_available:
|
|
|
|
|
month_procurement_cost = sum(pc["total_cost"] for pc in procurement_costs)
|
|
|
|
|
total_procurement_cost += month_procurement_cost
|
|
|
|
|
all_procurement_details.extend(procurement_costs)
|
|
|
|
|
|
|
|
|
|
months_since_overhaul = 0
|
|
|
|
|
|
|
|
|
|
# Calculate corrective costs
|
|
|
|
|
@ -321,17 +307,32 @@ class OverhaulCalculator:
|
|
|
|
|
|
|
|
|
|
months_since_overhaul += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
overhaul_target_date = self._add_months_to_date(start_date, interval_months)
|
|
|
|
|
# Check spare parts availability and calculate procurement costs
|
|
|
|
|
parts_available, procurement_costs = await self.spare_parts_service.check_spare_parts_availability(
|
|
|
|
|
db_session,
|
|
|
|
|
equipment,
|
|
|
|
|
overhaul_target_date
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Add procurement costs if parts are not available
|
|
|
|
|
if not parts_available:
|
|
|
|
|
month_procurement_cost = sum(pc["total_cost"] for pc in procurement_costs)
|
|
|
|
|
total_procurement_cost += month_procurement_cost
|
|
|
|
|
all_procurement_details.extend(procurement_costs)
|
|
|
|
|
|
|
|
|
|
# Calculate monthly averages
|
|
|
|
|
monthly_preventive_cost = total_preventive_cost / total_months
|
|
|
|
|
monthly_corrective_cost = total_corrective_cost / total_months
|
|
|
|
|
monthly_procurement_cost = total_procurement_cost / total_months
|
|
|
|
|
monthly_total_cost = monthly_preventive_cost + monthly_corrective_cost + monthly_procurement_cost
|
|
|
|
|
monthly_total_cost = monthly_preventive_cost + monthly_corrective_cost + total_procurement_cost
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"interval_months":interval_months,
|
|
|
|
|
"preventive_cost":monthly_preventive_cost,
|
|
|
|
|
"corrective_cost":monthly_corrective_cost,
|
|
|
|
|
"procurement_cost":monthly_procurement_cost,
|
|
|
|
|
"procurement_cost":total_procurement_cost,
|
|
|
|
|
"total_cost":monthly_total_cost,
|
|
|
|
|
"procurement_details":all_procurement_details
|
|
|
|
|
}
|
|
|
|
|
@ -417,10 +418,12 @@ class OverhaulCalculator:
|
|
|
|
|
max_interval=max_interval
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Aggregate costs
|
|
|
|
|
corrective_costs = [r["corrective_cost"] for r in all_results]
|
|
|
|
|
preventive_costs = [r["preventive_cost"] for r in all_results]
|
|
|
|
|
procurement_costs = [r["procurement_cost"] for r in all_results]
|
|
|
|
|
procurement_details = [r["procurement_details"] for r in all_results]
|
|
|
|
|
failures = list(predicted_failures.values())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -436,6 +439,7 @@ class OverhaulCalculator:
|
|
|
|
|
optimum_day=optimal_result["interval_months"],
|
|
|
|
|
calculation_data_id=calculation.id,
|
|
|
|
|
master_equipment=equipment.equipment,
|
|
|
|
|
procurement_details=procurement_details
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@ -446,6 +450,8 @@ class OverhaulCalculator:
|
|
|
|
|
# Calculate fleet optimal interval
|
|
|
|
|
total_costs = total_corrective_costs + total_preventive_costs + total_procurement_costs
|
|
|
|
|
fleet_optimal_index = np.argmin(total_costs)
|
|
|
|
|
calculation.optimum_oh_day =fleet_optimal_index + 1
|
|
|
|
|
|
|
|
|
|
db_session.add_all(fleet_results)
|
|
|
|
|
await db_session.commit()
|
|
|
|
|
|
|
|
|
|
@ -934,6 +940,7 @@ async def get_calculation_result(db_session: DbSession, calculation_id: str):
|
|
|
|
|
"procurement_cost": 0,
|
|
|
|
|
"num_failures": 0,
|
|
|
|
|
"day": i + 1,
|
|
|
|
|
"procurement_details": {},
|
|
|
|
|
}
|
|
|
|
|
## Add risk Cost
|
|
|
|
|
# risk cost = ((Down Time1 * MW Loss 1) + (Downtime2 * Mw 2) + .... (DowntimeN * MwN) ) * Harga listrik (Efficicency HL App)
|
|
|
|
|
@ -945,6 +952,8 @@ async def get_calculation_result(db_session: DbSession, calculation_id: str):
|
|
|
|
|
result["overhaul_cost"] += float(eq.overhaul_costs[i])
|
|
|
|
|
result["procurement_cost"] += float(eq.procurement_costs[i])
|
|
|
|
|
result["num_failures"] += int(eq.daily_failures[i])
|
|
|
|
|
if eq.procurement_details[i]:
|
|
|
|
|
result["procurement_details"][eq.assetnum] = eq.procurement_details[i]
|
|
|
|
|
|
|
|
|
|
calculation_results.append(CalculationResultsRead(**result))
|
|
|
|
|
|
|
|
|
|
|