""" Landvex Admin Backend - Unified Models Includes: Content, quiXzoom, Economy, HR, Aid Intelligence """ from sqlalchemy import Column, Integer, String, Float, DateTime, Boolean, Text, JSON, ForeignKey, Enum, Numeric from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from datetime import datetime import enum Base = declarative_base() # ─── USER & AUTH ────────────────────────────────────────────────────────────── class UserRole(str, enum.Enum): SUPER_ADMIN = "super_admin" ADMIN = "admin" MANAGER = "manager" EDITOR = "editor" VIEWER = "viewer" ANALYST = "analyst" QUIXZOOM_MANAGER = "quixzoom_manager" ECONOMY_MANAGER = "economy_manager" HR_MANAGER = "hr_manager" AID_MANAGER = "aid_manager" class UserStatus(str, enum.Enum): ACTIVE = "active" INACTIVE = "inactive" SUSPENDED = "suspended" class TenantType(str, enum.Enum): ENTERPRISE = "enterprise" SMALL_BUSINESS = "small_business" INDIVIDUAL = "individual" MUNICIPALITY = "municipality" GOVERNMENT = "government" NGO = "ngo" class TenantStatus(str, enum.Enum): ACTIVE = "active" INACTIVE = "inactive" SUSPENDED = "suspended" PENDING = "pending" class Tenant(Base): __tablename__ = "tenants" id = Column(Integer, primary_key=True, index=True) tenant_id = Column(String(50), unique=True, nullable=False) name = Column(String(255), nullable=False) tenant_type = Column(Enum(TenantType), default=TenantType.ENTERPRISE) status = Column(Enum(TenantStatus), default=TenantStatus.ACTIVE) settings = Column(JSON) created_at = Column(DateTime, default=datetime.utcnow) class Invitation(Base): __tablename__ = "invitations" id = Column(Integer, primary_key=True, index=True) invitation_id = Column(String(50), unique=True, nullable=False) email = Column(String(255), nullable=False) role = Column(Enum(UserRole), default=UserRole.VIEWER) tenant_id = Column(Integer, ForeignKey("tenants.id")) invited_by = Column(Integer, ForeignKey("users.id")) status = Column(String(50), default="pending") # pending, accepted, expired expires_at = Column(DateTime) created_at = Column(DateTime, default=datetime.utcnow) class AuditAction(str, enum.Enum): CREATE = "create" UPDATE = "update" DELETE = "delete" LOGIN = "login" LOGOUT = "logout" INVITE = "invite" ACCEPT = "accept" class AuditLog(Base): __tablename__ = "audit_logs" id = Column(Integer, primary_key=True, index=True) action = Column(Enum(AuditAction), nullable=False) entity_type = Column(String(100)) # user, tenant, invitation, etc. entity_id = Column(String(100)) user_id = Column(Integer, ForeignKey("users.id")) tenant_id = Column(Integer, ForeignKey("tenants.id")) details = Column(JSON) ip_address = Column(String(50)) user_agent = Column(String(500)) created_at = Column(DateTime, default=datetime.utcnow) class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) email = Column(String(255), unique=True, index=True, nullable=False) hashed_password = Column(String(255), nullable=False) full_name = Column(String(255)) role = Column(Enum(UserRole), default=UserRole.VIEWER) tenant_id = Column(Integer, ForeignKey("tenants.id")) status = Column(Enum(UserStatus), default=UserStatus.ACTIVE) is_active = Column(Boolean, default=True) created_at = Column(DateTime, default=datetime.utcnow) last_login = Column(DateTime) # ─── CONTENT MODULE ─────────────────────────────────────────────────────────── class ArticleStatus(str, enum.Enum): DRAFT = "draft" REVIEW = "review" PUBLISHED = "published" ARCHIVED = "archived" class Article(Base): __tablename__ = "articles" id = Column(Integer, primary_key=True, index=True) title = Column(String(500), nullable=False) slug = Column(String(500), unique=True, index=True, nullable=False) content = Column(Text) excerpt = Column(String(1000)) author_id = Column(Integer, ForeignKey("users.id")) status = Column(Enum(ArticleStatus), default=ArticleStatus.DRAFT) seo_title = Column(String(70)) seo_description = Column(String(160)) keywords = Column(JSON) published_at = Column(DateTime) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) author = relationship("User") class SEOMetadata(Base): __tablename__ = "seo_metadata" id = Column(Integer, primary_key=True, index=True) page_path = Column(String(500), unique=True, nullable=False) title = Column(String(70)) description = Column(String(160)) canonical_url = Column(String(500)) og_image = Column(String(500)) schema_markup = Column(JSON) last_audit = Column(DateTime) audit_score = Column(Integer) # ─── QUIXZOOM MODULE ────────────────────────────────────────────────────────── class MissionStatus(str, enum.Enum): DRAFT = "draft" PENDING = "pending" ACTIVE = "active" PAUSED = "paused" COMPLETED = "completed" CANCELLED = "cancelled" class Mission(Base): __tablename__ = "missions" id = Column(Integer, primary_key=True, index=True) mission_id = Column(String(50), unique=True, nullable=False) title = Column(String(500), nullable=False) description = Column(Text) city = Column(String(255)) country = Column(String(255)) location = Column(JSON) reward_amount = Column(Numeric(10, 2)) reward_currency = Column(String(3), default="SEK") status = Column(Enum(MissionStatus), default=MissionStatus.DRAFT) requirements = Column(JSON) start_date = Column(DateTime) end_date = Column(DateTime) max_submissions = Column(Integer) created_by = Column(Integer, ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.utcnow) class Contributor(Base): __tablename__ = "contributors" id = Column(Integer, primary_key=True, index=True) contributor_id = Column(String(50), unique=True, nullable=False) email = Column(String(255), unique=True) full_name = Column(String(255)) phone = Column(String(50)) country = Column(String(255)) city = Column(String(255)) reputation_score = Column(Integer, default=0) total_earnings = Column(Numeric(10, 2), default=0) total_submissions = Column(Integer, default=0) verified = Column(Boolean, default=False) status = Column(String(50), default="active") created_at = Column(DateTime, default=datetime.utcnow) class Submission(Base): __tablename__ = "submissions" id = Column(Integer, primary_key=True, index=True) submission_id = Column(String(50), unique=True, nullable=False) mission_id = Column(Integer, ForeignKey("missions.id")) contributor_id = Column(Integer, ForeignKey("contributors.id")) status = Column(String(50), default="pending") media_urls = Column(JSON) location = Column(JSON) ai_score = Column(Float) reviewer_notes = Column(Text) submitted_at = Column(DateTime, default=datetime.utcnow) reviewed_at = Column(DateTime) reviewed_by = Column(Integer, ForeignKey("users.id")) # ─── ECONOMY MODULE ─────────────────────────────────────────────────────────── class AccountType(str, enum.Enum): ASSET = "asset" LIABILITY = "liability" EQUITY = "equity" REVENUE = "revenue" EXPENSE = "expense" class Account(Base): __tablename__ = "accounts" id = Column(Integer, primary_key=True, index=True) account_number = Column(String(20), unique=True, nullable=False) name = Column(String(255), nullable=False) account_type = Column(Enum(AccountType), nullable=False) parent_id = Column(Integer, ForeignKey("accounts.id")) balance = Column(Numeric(12, 2), default=0) currency = Column(String(3), default="SEK") description = Column(Text) is_active = Column(Boolean, default=True) parent = relationship("Account", remote_side=[id]) class Transaction(Base): __tablename__ = "transactions" id = Column(Integer, primary_key=True, index=True) transaction_id = Column(String(50), unique=True, nullable=False) date = Column(DateTime, nullable=False) description = Column(Text) reference = Column(String(255)) amount = Column(Numeric(12, 2), nullable=False) debit_account_id = Column(Integer, ForeignKey("accounts.id")) credit_account_id = Column(Integer, ForeignKey("accounts.id")) status = Column(String(50), default="posted") created_by = Column(Integer, ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.utcnow) class BankAccount(Base): __tablename__ = "bank_accounts" id = Column(Integer, primary_key=True, index=True) bank_name = Column(String(255), nullable=False) account_name = Column(String(255)) account_number = Column(String(100)) iban = Column(String(100)) bic = Column(String(20)) currency = Column(String(3), default="SEK") current_balance = Column(Numeric(12, 2), default=0) account_type = Column(String(50)) is_active = Column(Boolean, default=True) # ─── HR MODULE ──────────────────────────────────────────────────────────────── class EmployeeStatus(str, enum.Enum): ACTIVE = "active" ON_LEAVE = "on_leave" TERMINATED = "terminated" CONTRACT = "contract" class Employee(Base): __tablename__ = "employees" id = Column(Integer, primary_key=True, index=True) employee_id = Column(String(50), unique=True, nullable=False) first_name = Column(String(255), nullable=False) last_name = Column(String(255), nullable=False) email = Column(String(255), unique=True) phone = Column(String(50)) department = Column(String(255)) position = Column(String(255)) start_date = Column(DateTime) end_date = Column(DateTime) salary = Column(Numeric(10, 2)) salary_currency = Column(String(3), default="SEK") status = Column(Enum(EmployeeStatus), default=EmployeeStatus.ACTIVE) manager_id = Column(Integer, ForeignKey("employees.id")) created_at = Column(DateTime, default=datetime.utcnow) class Contractor(Base): __tablename__ = "contractors" id = Column(Integer, primary_key=True, index=True) contractor_id = Column(String(50), unique=True, nullable=False) company_name = Column(String(255)) contact_name = Column(String(255)) email = Column(String(255)) phone = Column(String(50)) services = Column(JSON) hourly_rate = Column(Numeric(10, 2)) currency = Column(String(3), default="SEK") contract_start = Column(DateTime) contract_end = Column(DateTime) status = Column(String(50), default="active") # ─── AID INTELLIGENCE MODULE ───────────────────────────────────────────────── class AidProjectType(str, enum.Enum): SCHOOL = "school" HOSPITAL = "hospital" ROAD = "road" BRIDGE = "bridge" WATER = "water" POWER = "power" AGRICULTURE = "agriculture" RENEWABLE = "renewable" HOUSING = "housing" SANITATION = "sanitation" DIGITAL = "digital" ENVIRONMENTAL = "environmental" EMERGENCY = "emergency" FOOD = "food" EDUCATION = "education" HEALTHCARE = "healthcare" MICROFINANCE = "microfinance" WOMEN_EMPOWERMENT = "women_empowerment" YOUTH_EMPLOYMENT = "youth_employment" class AidProjectStatus(str, enum.Enum): PLANNED = "planned" ACTIVE = "active" COMPLETED = "completed" DELAYED = "delayed" ABANDONED = "abandoned" UNDER_MAINTENANCE = "under_maintenance" class AidProject(Base): __tablename__ = "aid_projects" id = Column(Integer, primary_key=True, index=True) project_id = Column(String(50), unique=True, nullable=False) name = Column(String(500), nullable=False) description = Column(Text) country = Column(String(255), nullable=False) region = Column(String(255)) district = Column(String(255)) project_type = Column(Enum(AidProjectType), nullable=False) status = Column(Enum(AidProjectStatus), default=AidProjectStatus.PLANNED) funding_agency = Column(String(255)) implementing_partner = Column(String(255)) budget_usd = Column(Numeric(12, 2)) start_date = Column(DateTime) expected_completion = Column(DateTime) actual_completion = Column(DateTime) location = Column(JSON) aii_score = Column(Integer) confidence = Column(Integer) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class AidObservation(Base): __tablename__ = "aid_observations" id = Column(Integer, primary_key=True, index=True) observation_id = Column(String(50), unique=True, nullable=False) project_id = Column(Integer, ForeignKey("aid_projects.id")) observation_type = Column(String(50), nullable=False) date = Column(DateTime, nullable=False) contributor_id = Column(String(100)) location = Column(JSON) media_urls = Column(JSON) ai_analysis = Column(JSON) confidence = Column(Integer) verified = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) class AidAlert(Base): __tablename__ = "aid_alerts" id = Column(Integer, primary_key=True, index=True) alert_id = Column(String(50), unique=True, nullable=False) severity = Column(String(20), nullable=False) alert_type = Column(String(100), nullable=False) project_id = Column(Integer, ForeignKey("aid_projects.id")) description = Column(Text) detected_at = Column(DateTime, default=datetime.utcnow) confidence = Column(Integer) status = Column(String(50), default="open") resolved_at = Column(DateTime) resolved_by = Column(Integer, ForeignKey("users.id")) # ─── SYSTEM HEALTH ──────────────────────────────────────────────────────────── class ServiceHealth(Base): __tablename__ = "service_health" id = Column(Integer, primary_key=True, index=True) service_name = Column(String(255), nullable=False) service_url = Column(String(500)) status = Column(String(50), default="unknown") last_check = Column(DateTime, default=datetime.utcnow) response_time_ms = Column(Integer) error_rate = Column(Float) uptime_percentage = Column(Float)