From 6418a1d1e48fb193b2cfe2736322df7eec42dc8e Mon Sep 17 00:00:00 2001 From: Cizz22 Date: Fri, 20 Jun 2025 13:32:03 +0700 Subject: [PATCH] add sparepart --- src/calculation_time_constrains/model.py | 1 + src/calculation_time_constrains/schema.py | 1 + src/calculation_time_constrains/service.py | 53 +++++++++++++--------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/calculation_time_constrains/model.py b/src/calculation_time_constrains/model.py index 11d8e95..f61272d 100644 --- a/src/calculation_time_constrains/model.py +++ b/src/calculation_time_constrains/model.py @@ -149,6 +149,7 @@ class CalculationEquipmentResult(Base, DefaultMixin): ) optimum_day = Column(Integer, default=1) is_included = Column(Boolean, default=True) + procurement_details = Column(JSON, nullable=True) master_equipment = relationship( "MasterEquipment", diff --git a/src/calculation_time_constrains/schema.py b/src/calculation_time_constrains/schema.py index e9cd2f7..426b3c4 100644 --- a/src/calculation_time_constrains/schema.py +++ b/src/calculation_time_constrains/schema.py @@ -50,6 +50,7 @@ class CalculationResultsRead(CalculationTimeConstrainsBase): corrective_cost: float overhaul_cost: float procurement_cost: float + procurement_details: Optional[Dict[str, Any]] num_failures: int diff --git a/src/calculation_time_constrains/service.py b/src/calculation_time_constrains/service.py index 2b029ba..3c17bba 100644 --- a/src/calculation_time_constrains/service.py +++ b/src/calculation_time_constrains/service.py @@ -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))