58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
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"<Opex id={self.id} scenario_id={self.scenario_id} "
|
|
f"amount={self.amount} currency_id={self.currency_id}>"
|
|
)
|
|
|
|
@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)
|