from sqlalchemy import event, text from sqlalchemy import Column, Integer, Float, String, ForeignKey from sqlalchemy.orm import relationship from config.database import Base class Opex(Base): __tablename__ = "opex" id = Column(Integer, primary_key=True, index=True) scenario_id = Column(Integer, ForeignKey("scenario.id"), nullable=False) amount = Column(Float, nullable=False) description = Column(String, nullable=True) currency_id = Column(Integer, ForeignKey("currency.id"), nullable=False) scenario = relationship("Scenario", back_populates="opex_items") currency = relationship("Currency", back_populates="opex_items") def __repr__(self): return ( f"" ) @property def currency_code(self) -> str: return self.currency.code if self.currency else None @currency_code.setter def currency_code(self, value: str) -> None: setattr(self, "_currency_code_pending", (value or "USD").strip().upper()) def _resolve_currency_opex(mapper, connection, target): if getattr(target, "currency_id", None): return code = getattr(target, "_currency_code_pending", None) or "USD" row = connection.execute(text("SELECT id FROM currency WHERE code = :code"), { "code": code}).fetchone() if row: cid = row[0] else: res = connection.execute( text("INSERT INTO currency (code, name, symbol, is_active) VALUES (:code, :name, :symbol, :active)"), {"code": code, "name": code, "symbol": None, "active": True}, ) try: cid = res.lastrowid except Exception: cid = connection.execute(text("SELECT id FROM currency WHERE code = :code"), { "code": code}).scalar() target.currency_id = cid event.listen(Opex, "before_insert", _resolve_currency_opex) event.listen(Opex, "before_update", _resolve_currency_opex)