"""Company model — with soft-delete, FTS tsvector, and tenant scoping.""" from __future__ import annotations import uuid from datetime import datetime from typing import Any from sqlalchemy import Computed, DateTime, ForeignKey, Index, String, Text from sqlalchemy.dialects.postgresql import TSVECTOR from sqlalchemy.dialects.postgresql import UUID as PGUUID from sqlalchemy.orm import Mapped, mapped_column from app.core.db import Base, TenantMixin class Company(Base, TenantMixin): """Company entity with full-text search support.""" __tablename__ = "companies" __table_args__ = ( Index("ix_companies_tenant_deleted", "tenant_id", "deleted_at"), Index("ix_companies_tenant_name", "tenant_id", "name"), Index("ix_companies_industry", "tenant_id", "industry"), Index("ix_companies_search_vec", "search_tsv", postgresql_using="gin"), ) id: Mapped[uuid.UUID] = mapped_column( PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) name: Mapped[str] = mapped_column(String(100), nullable=False) account_number: Mapped[str | None] = mapped_column(String(40), nullable=True) industry: Mapped[str | None] = mapped_column(String(50), nullable=True) phone: Mapped[str | None] = mapped_column(String(30), nullable=True) email: Mapped[str | None] = mapped_column(String(255), nullable=True) website: Mapped[str | None] = mapped_column(String(500), nullable=True) description: Mapped[str | None] = mapped_column(Text, nullable=True) # Address fields address_street: Mapped[str | None] = mapped_column(String(255), nullable=True) address_city: Mapped[str | None] = mapped_column(String(100), nullable=True) address_zip: Mapped[str | None] = mapped_column(String(20), nullable=True) address_country: Mapped[str | None] = mapped_column(String(2), nullable=True) address_state: Mapped[str | None] = mapped_column(String(100), nullable=True) deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) # FTS vector search_tsv: Mapped[Any] = mapped_column( TSVECTOR, Computed( "to_tsvector('english', coalesce(name, '') || ' ' || coalesce(description, '') || ' ' || coalesce(industry, ''))", persisted=True, ), nullable=True, ) created_by: Mapped[uuid.UUID | None] = mapped_column( PGUUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True ) updated_by: Mapped[uuid.UUID | None] = mapped_column( PGUUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True )