| 1234567891011121314151617181920212223242526272829303132333435363738 |
- """Simulation plan model."""
- import json
- from datetime import datetime
- from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey
- from sqlalchemy.orm import relationship, backref
- from ..database import Base
- class SimulationPlan(Base):
- """A simulation plan (simulation_plan.json format, compatible with local executor)."""
- __tablename__ = "simulation_plans"
- id = Column(Integer, primary_key=True, index=True)
- project_id = Column(Integer, ForeignKey("projects.id"), nullable=False, index=True)
- name = Column(String(200), nullable=False)
- plan_id = Column(String(100), unique=True, index=True) # e.g. SP-20260827-001
- status = Column(String(20), default="draft") # draft / confirmed / executing / completed / failed
- plan_json = Column(Text, nullable=False) # Full simulation_plan.json content
- variables_summary = Column(Text, default="") # JSON: variable names and ranges for display
- estimated_points = Column(Integer, default=0)
- estimated_time_min = Column(Integer, default=0)
- notes = Column(Text, default="")
- created_at = Column(DateTime, default=datetime.utcnow)
- updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
- # F2 fix: cascade delete from project -> plans -> results
- project = relationship("Project", backref=backref("plans", cascade="all, delete-orphan"))
- results = relationship("SimulationResult", backref="plan", cascade="all, delete-orphan")
- def get_plan_dict(self) -> dict:
- try:
- return json.loads(self.plan_json) if self.plan_json else {}
- except (json.JSONDecodeError, TypeError):
- return {}
- def set_plan_dict(self, data: dict) -> None:
- self.plan_json = json.dumps(data, ensure_ascii=False, indent=2)
|