Refactor test cases for improved readability and consistency
- Updated test functions in various test files to enhance code clarity by formatting long lines and improving indentation. - Adjusted assertions to use multi-line formatting for better readability. - Added new test cases for theme settings API to ensure proper functionality. - Ensured consistent use of line breaks and spacing across test files for uniformity.
This commit is contained in:
@@ -2,5 +2,9 @@
|
||||
models package initializer. Import key models so they're registered
|
||||
with the shared Base.metadata when the package is imported by tests.
|
||||
"""
|
||||
|
||||
from . import application_setting # noqa: F401
|
||||
from . import currency # noqa: F401
|
||||
from . import role # noqa: F401
|
||||
from . import user # noqa: F401
|
||||
from . import theme_setting # noqa: F401
|
||||
|
||||
@@ -14,15 +14,24 @@ class ApplicationSetting(Base):
|
||||
id: Mapped[int] = mapped_column(primary_key=True, index=True)
|
||||
key: Mapped[str] = mapped_column(String(128), unique=True, nullable=False)
|
||||
value: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
value_type: Mapped[str] = mapped_column(String(32), nullable=False, default="string")
|
||||
category: Mapped[str] = mapped_column(String(32), nullable=False, default="general")
|
||||
value_type: Mapped[str] = mapped_column(
|
||||
String(32), nullable=False, default="string"
|
||||
)
|
||||
category: Mapped[str] = mapped_column(
|
||||
String(32), nullable=False, default="general"
|
||||
)
|
||||
description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
||||
is_editable: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
||||
is_editable: Mapped[bool] = mapped_column(
|
||||
Boolean, nullable=False, default=True
|
||||
)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||
)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False
|
||||
DateTime(timezone=True),
|
||||
server_default=func.now(),
|
||||
onupdate=func.now(),
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
||||
@@ -29,8 +29,9 @@ class Capex(Base):
|
||||
@currency_code.setter
|
||||
def currency_code(self, value: str) -> None:
|
||||
# store pending code so application code or migrations can pick it up
|
||||
setattr(self, "_currency_code_pending",
|
||||
(value or "USD").strip().upper())
|
||||
setattr(
|
||||
self, "_currency_code_pending", (value or "USD").strip().upper()
|
||||
)
|
||||
|
||||
|
||||
# SQLAlchemy event handlers to ensure currency_id is set before insert/update
|
||||
@@ -42,22 +43,27 @@ def _resolve_currency(mapper, connection, target):
|
||||
return
|
||||
code = getattr(target, "_currency_code_pending", None) or "USD"
|
||||
# Try to find existing currency id
|
||||
row = connection.execute(text("SELECT id FROM currency WHERE code = :code"), {
|
||||
"code": code}).fetchone()
|
||||
row = connection.execute(
|
||||
text("SELECT id FROM currency WHERE code = :code"), {"code": code}
|
||||
).fetchone()
|
||||
if row:
|
||||
cid = row[0]
|
||||
else:
|
||||
# Insert new currency and attempt to get lastrowid
|
||||
res = connection.execute(
|
||||
text("INSERT INTO currency (code, name, symbol, is_active) VALUES (:code, :name, :symbol, :active)"),
|
||||
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:
|
||||
# fallback: select after insert
|
||||
cid = connection.execute(text("SELECT id FROM currency WHERE code = :code"), {
|
||||
"code": code}).scalar()
|
||||
cid = connection.execute(
|
||||
text("SELECT id FROM currency WHERE code = :code"),
|
||||
{"code": code},
|
||||
).scalar()
|
||||
target.currency_id = cid
|
||||
|
||||
|
||||
|
||||
@@ -14,8 +14,11 @@ class Currency(Base):
|
||||
|
||||
# reverse relationships (optional)
|
||||
capex_items = relationship(
|
||||
"Capex", back_populates="currency", lazy="select")
|
||||
"Capex", back_populates="currency", lazy="select"
|
||||
)
|
||||
opex_items = relationship("Opex", back_populates="currency", lazy="select")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Currency code={self.code} name={self.name} symbol={self.symbol}>"
|
||||
return (
|
||||
f"<Currency code={self.code} name={self.name} symbol={self.symbol}>"
|
||||
)
|
||||
|
||||
@@ -28,28 +28,34 @@ class Opex(Base):
|
||||
|
||||
@currency_code.setter
|
||||
def currency_code(self, value: str) -> None:
|
||||
setattr(self, "_currency_code_pending",
|
||||
(value or "USD").strip().upper())
|
||||
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()
|
||||
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)"),
|
||||
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()
|
||||
cid = connection.execute(
|
||||
text("SELECT id FROM currency WHERE code = :code"),
|
||||
{"code": code},
|
||||
).scalar()
|
||||
target.currency_id = cid
|
||||
|
||||
|
||||
|
||||
@@ -10,14 +10,17 @@ class Parameter(Base):
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, index=True)
|
||||
scenario_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("scenario.id"), nullable=False)
|
||||
ForeignKey("scenario.id"), nullable=False
|
||||
)
|
||||
name: Mapped[str] = mapped_column(nullable=False)
|
||||
value: Mapped[float] = mapped_column(nullable=False)
|
||||
distribution_id: Mapped[Optional[int]] = mapped_column(
|
||||
ForeignKey("distribution.id"), nullable=True)
|
||||
ForeignKey("distribution.id"), nullable=True
|
||||
)
|
||||
distribution_type: Mapped[Optional[str]] = mapped_column(nullable=True)
|
||||
distribution_parameters: Mapped[Optional[Dict[str, Any]]] = mapped_column(
|
||||
JSON, nullable=True)
|
||||
JSON, nullable=True
|
||||
)
|
||||
|
||||
scenario = relationship("Scenario", back_populates="parameters")
|
||||
distribution = relationship("Distribution")
|
||||
|
||||
@@ -14,7 +14,8 @@ class ProductionOutput(Base):
|
||||
unit_symbol = Column(String(16), nullable=True)
|
||||
|
||||
scenario = relationship(
|
||||
"Scenario", back_populates="production_output_items")
|
||||
"Scenario", back_populates="production_output_items"
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
|
||||
13
models/role.py
Normal file
13
models/role.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from sqlalchemy import Column, Integer, String
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from config.database import Base
|
||||
|
||||
|
||||
class Role(Base):
|
||||
__tablename__ = "roles"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String, unique=True, index=True)
|
||||
|
||||
users = relationship("User", back_populates="role")
|
||||
@@ -20,19 +20,16 @@ class Scenario(Base):
|
||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
parameters = relationship("Parameter", back_populates="scenario")
|
||||
simulation_results = relationship(
|
||||
SimulationResult, back_populates="scenario")
|
||||
capex_items = relationship(
|
||||
Capex, back_populates="scenario")
|
||||
opex_items = relationship(
|
||||
Opex, back_populates="scenario")
|
||||
consumption_items = relationship(
|
||||
Consumption, back_populates="scenario")
|
||||
SimulationResult, back_populates="scenario"
|
||||
)
|
||||
capex_items = relationship(Capex, back_populates="scenario")
|
||||
opex_items = relationship(Opex, back_populates="scenario")
|
||||
consumption_items = relationship(Consumption, back_populates="scenario")
|
||||
production_output_items = relationship(
|
||||
ProductionOutput, back_populates="scenario")
|
||||
equipment_items = relationship(
|
||||
Equipment, back_populates="scenario")
|
||||
maintenance_items = relationship(
|
||||
Maintenance, back_populates="scenario")
|
||||
ProductionOutput, back_populates="scenario"
|
||||
)
|
||||
equipment_items = relationship(Equipment, back_populates="scenario")
|
||||
maintenance_items = relationship(Maintenance, back_populates="scenario")
|
||||
|
||||
# relationships can be defined later
|
||||
def __repr__(self):
|
||||
|
||||
15
models/theme_setting.py
Normal file
15
models/theme_setting.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from config.database import Base
|
||||
|
||||
|
||||
class ThemeSetting(Base):
|
||||
__tablename__ = "theme_settings"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
theme_name = Column(String, unique=True, index=True)
|
||||
primary_color = Column(String)
|
||||
secondary_color = Column(String)
|
||||
accent_color = Column(String)
|
||||
background_color = Column(String)
|
||||
text_color = Column(String)
|
||||
23
models/user.py
Normal file
23
models/user.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from config.database import Base
|
||||
from services.security import get_password_hash, verify_password
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
username = Column(String, unique=True, index=True)
|
||||
email = Column(String, unique=True, index=True)
|
||||
hashed_password = Column(String)
|
||||
role_id = Column(Integer, ForeignKey("roles.id"))
|
||||
|
||||
role = relationship("Role", back_populates="users")
|
||||
|
||||
def set_password(self, password: str):
|
||||
self.hashed_password = get_password_hash(password)
|
||||
|
||||
def check_password(self, password: str) -> bool:
|
||||
return verify_password(password, str(self.hashed_password))
|
||||
Reference in New Issue
Block a user