127 lines
5.8 KiB
Python
127 lines
5.8 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import date, datetime, time
|
|
|
|
from sqlalchemy import String, Boolean, Integer, Time, Date, DateTime, ForeignKey, UniqueConstraint, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
from app.core.db.common import CommonBase
|
|
|
|
|
|
class Tenant(CommonBase):
|
|
__tablename__ = "tenants"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
code: Mapped[str] = mapped_column(String(50), unique=True, index=True)
|
|
name: Mapped[str] = mapped_column(String(200))
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
firm_type: Mapped[str] = mapped_column(String(30), default="proprietorship") # partnership|proprietorship|individual
|
|
|
|
# Tenant-level defaults
|
|
default_timezone: Mapped[str] = mapped_column(String(64), default="Asia/Kolkata")
|
|
default_session_duration_minutes: Mapped[int] = mapped_column(Integer, default=480)
|
|
default_otp_required_roles_csv: Mapped[str] = mapped_column(
|
|
String(200),
|
|
default="Partner,System Admin",
|
|
)
|
|
default_storage_mode: Mapped[str] = mapped_column(
|
|
String(20),
|
|
default="local_only",
|
|
) # local_only|cloud_only|hybrid
|
|
|
|
# Phase 7Q.2 - firm branding defaults
|
|
display_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
|
|
logo_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
favicon_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
primary_color: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
|
accent_color: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
|
website_url: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
contact_email: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
contact_mobile: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
|
|
|
|
|
class Branch(CommonBase):
|
|
__tablename__ = "branches"
|
|
__table_args__ = (
|
|
UniqueConstraint("tenant_id", "code", name="uq_branch_tenant_code"),
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
tenant_id: Mapped[int] = mapped_column(
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
index=True,
|
|
)
|
|
code: Mapped[str] = mapped_column(String(50), index=True)
|
|
name: Mapped[str] = mapped_column(String(200))
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
|
|
timezone: Mapped[str] = mapped_column(String(64), default="Asia/Kolkata")
|
|
office_start_time: Mapped[time | None] = mapped_column(Time, nullable=True)
|
|
office_end_time: Mapped[time | None] = mapped_column(Time, nullable=True)
|
|
|
|
# Branch control flags
|
|
allow_login: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
allow_new_assignments: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
is_head_office: Mapped[bool] = mapped_column(Boolean, default=False)
|
|
|
|
# SMTP (credentials here; policy in BranchSettings)
|
|
smtp_host: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
smtp_port: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
smtp_username: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
smtp_password: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
smtp_use_tls: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
|
|
# Local storage root for branch PC
|
|
local_storage_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
|
|
class FinancialYear(CommonBase):
|
|
__tablename__ = "financial_years"
|
|
__table_args__ = (
|
|
UniqueConstraint("tenant_id", "year_code", name="uq_financial_year_tenant_code"),
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
tenant_id: Mapped[int] = mapped_column(
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
index=True,
|
|
)
|
|
year_code: Mapped[str] = mapped_column(String(9), index=True) # e.g. 2025-26
|
|
assessment_year: Mapped[str] = mapped_column(String(9), index=True) # e.g. 2026-27
|
|
start_date: Mapped[date] = mapped_column(Date)
|
|
end_date: Mapped[date] = mapped_column(Date)
|
|
is_current: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
|
is_locked: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
|
locked_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
locked_by_user_id: Mapped[int | None] = mapped_column(
|
|
ForeignKey("users.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
)
|
|
created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=datetime.utcnow)
|
|
updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
|
|
class YearBackupExport(CommonBase):
|
|
__tablename__ = "year_backup_exports"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
tenant_id: Mapped[int] = mapped_column(
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
index=True,
|
|
)
|
|
financial_year_id: Mapped[int] = mapped_column(
|
|
ForeignKey("financial_years.id", ondelete="CASCADE"),
|
|
index=True,
|
|
)
|
|
year_code: Mapped[str] = mapped_column(String(9), index=True)
|
|
assessment_year: Mapped[str | None] = mapped_column(String(9), nullable=True, index=True)
|
|
export_status: Mapped[str] = mapped_column(String(30), default="completed", index=True)
|
|
export_file_path: Mapped[str] = mapped_column(String(1000))
|
|
file_size_bytes: Mapped[int] = mapped_column(Integer, default=0)
|
|
manifest_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
generated_by_user_id: Mapped[int | None] = mapped_column(
|
|
ForeignKey("users.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
)
|
|
generated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=datetime.utcnow)
|