chore: fix all ruff lint errors + format — 0 errors, 306 tests pass
This commit is contained in:
+43
-20
@@ -1,32 +1,55 @@
|
||||
"""SQLAlchemy models for LeoCRM."""
|
||||
|
||||
from app.models.tenant import Tenant
|
||||
from app.models.user import User, UserTenant
|
||||
from app.models.audit import AuditLog, DeletionLog
|
||||
from app.models.auth import ApiToken, PasswordResetToken
|
||||
from app.models.company import Company
|
||||
from app.models.contact import CompanyContact, Contact
|
||||
from app.models.notification import Notification
|
||||
from app.models.plugin import Plugin, PluginMigration
|
||||
from app.models.role import Role
|
||||
from app.models.session import Session
|
||||
from app.models.audit import AuditLog, DeletionLog
|
||||
from app.models.notification import Notification
|
||||
from app.models.auth import PasswordResetToken, ApiToken
|
||||
from app.models.company import Company
|
||||
from app.models.contact import Contact, CompanyContact
|
||||
from app.models.plugin import Plugin, PluginMigration
|
||||
from app.models.tenant import Tenant
|
||||
from app.models.user import User, UserTenant
|
||||
|
||||
__all__ = [
|
||||
"Tenant", "User", "UserTenant", "Role", "Session",
|
||||
"AuditLog", "DeletionLog", "Notification",
|
||||
"PasswordResetToken", "ApiToken", "Company",
|
||||
"Contact", "CompanyContact",
|
||||
"Plugin", "PluginMigration",
|
||||
"Tenant",
|
||||
"User",
|
||||
"UserTenant",
|
||||
"Role",
|
||||
"Session",
|
||||
"AuditLog",
|
||||
"DeletionLog",
|
||||
"Notification",
|
||||
"PasswordResetToken",
|
||||
"ApiToken",
|
||||
"Company",
|
||||
"Contact",
|
||||
"CompanyContact",
|
||||
"Plugin",
|
||||
"PluginMigration",
|
||||
]
|
||||
from app.models.ai_conversation import AIConversation, AIMessage
|
||||
from app.models.workflow import Workflow, WorkflowInstance, WorkflowStepHistory
|
||||
|
||||
__all__ = [
|
||||
"Tenant", "User", "UserTenant", "Role", "Session",
|
||||
"AuditLog", "DeletionLog", "Notification",
|
||||
"PasswordResetToken", "ApiToken", "Company",
|
||||
"Contact", "CompanyContact",
|
||||
"Plugin", "PluginMigration",
|
||||
"AIConversation", "AIMessage",
|
||||
"Workflow", "WorkflowInstance", "WorkflowStepHistory",
|
||||
"Tenant",
|
||||
"User",
|
||||
"UserTenant",
|
||||
"Role",
|
||||
"Session",
|
||||
"AuditLog",
|
||||
"DeletionLog",
|
||||
"Notification",
|
||||
"PasswordResetToken",
|
||||
"ApiToken",
|
||||
"Company",
|
||||
"Contact",
|
||||
"CompanyContact",
|
||||
"Plugin",
|
||||
"PluginMigration",
|
||||
"AIConversation",
|
||||
"AIMessage",
|
||||
"Workflow",
|
||||
"WorkflowInstance",
|
||||
"WorkflowStepHistory",
|
||||
]
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, Text, DateTime, ForeignKey, func, Index, Integer
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, JSONB
|
||||
from sqlalchemy import ForeignKey, Index, Integer, String, Text
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.db import Base, TenantMixin
|
||||
@@ -17,9 +17,7 @@ class AIConversation(Base, TenantMixin):
|
||||
"""AI Copilot conversation thread — tenant-scoped."""
|
||||
|
||||
__tablename__ = "ai_conversations"
|
||||
__table_args__ = (
|
||||
Index("ix_ai_conversations_tenant_user", "tenant_id", "user_id"),
|
||||
)
|
||||
__table_args__ = (Index("ix_ai_conversations_tenant_user", "tenant_id", "user_id"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
@@ -35,15 +33,16 @@ class AIMessage(Base, TenantMixin):
|
||||
"""Individual messages within an AI conversation — user input, AI response, actions."""
|
||||
|
||||
__tablename__ = "ai_messages"
|
||||
__table_args__ = (
|
||||
Index("ix_ai_messages_tenant_conversation", "tenant_id", "conversation_id"),
|
||||
)
|
||||
__table_args__ = (Index("ix_ai_messages_tenant_conversation", "tenant_id", "conversation_id"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
conversation_id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), ForeignKey("ai_conversations.id", ondelete="CASCADE"), nullable=False, index=True
|
||||
PGUUID(as_uuid=True),
|
||||
ForeignKey("ai_conversations.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
role: Mapped[str] = mapped_column(String(20), nullable=False) # user, assistant, system
|
||||
content: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
|
||||
+3
-2
@@ -6,8 +6,9 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, DateTime, ForeignKey, func, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, JSONB
|
||||
from sqlalchemy import DateTime, ForeignKey, String, func
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.db import Base, TenantMixin
|
||||
|
||||
+4
-5
@@ -5,8 +5,9 @@ from __future__ import annotations
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import String, DateTime, ForeignKey, func, Index
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, JSONB
|
||||
from sqlalchemy import DateTime, ForeignKey, Index, String, func
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.db import Base, TenantMixin
|
||||
@@ -32,9 +33,7 @@ class ApiToken(Base, TenantMixin):
|
||||
"""API token for programmatic access."""
|
||||
|
||||
__tablename__ = "api_tokens"
|
||||
__table_args__ = (
|
||||
Index("ix_api_tokens_tenant_user", "tenant_id", "user_id"),
|
||||
)
|
||||
__table_args__ = (Index("ix_api_tokens_tenant_user", "tenant_id", "user_id"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
|
||||
@@ -6,8 +6,9 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, Text, DateTime, ForeignKey, Index, Computed
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, TSVECTOR
|
||||
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
|
||||
@@ -34,9 +35,7 @@ class Company(Base, TenantMixin):
|
||||
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)
|
||||
deleted_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
# FTS vector — PostgreSQL generated column, auto-updated on insert/update
|
||||
search_tsv: Mapped[Any] = mapped_column(
|
||||
TSVECTOR,
|
||||
|
||||
@@ -6,12 +6,12 @@ import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import (
|
||||
String,
|
||||
Text,
|
||||
DateTime,
|
||||
Boolean,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
Index,
|
||||
String,
|
||||
Text,
|
||||
UniqueConstraint,
|
||||
)
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
@@ -42,9 +42,7 @@ class Contact(Base, TenantMixin):
|
||||
department: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
||||
linkedin_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
||||
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
deleted_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
PGUUID(as_uuid=True),
|
||||
ForeignKey("users.id", ondelete="SET NULL"),
|
||||
@@ -62,9 +60,7 @@ class CompanyContact(Base, TenantMixin):
|
||||
|
||||
__tablename__ = "company_contacts"
|
||||
__table_args__ = (
|
||||
UniqueConstraint(
|
||||
"company_id", "contact_id", "tenant_id", name="uq_company_contact_tenant"
|
||||
),
|
||||
UniqueConstraint("company_id", "contact_id", "tenant_id", name="uq_company_contact_tenant"),
|
||||
Index("ix_cc_company", "company_id"),
|
||||
Index("ix_cc_contact", "contact_id"),
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import annotations
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import String, DateTime, ForeignKey, Text, func, Index
|
||||
from sqlalchemy import DateTime, ForeignKey, Index, String, Text, func
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
+8
-18
@@ -3,10 +3,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, Boolean, Text, DateTime, func, Index
|
||||
from sqlalchemy import Boolean, Index, String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
@@ -21,9 +20,7 @@ class Plugin(Base, TimestampMixin):
|
||||
"""
|
||||
|
||||
__tablename__ = "plugins"
|
||||
__table_args__ = (
|
||||
Index("ix_plugins_name", "name", unique=True),
|
||||
)
|
||||
__table_args__ = (Index("ix_plugins_name", "name", unique=True),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
@@ -31,17 +28,12 @@ class Plugin(Base, TimestampMixin):
|
||||
name: Mapped[str] = mapped_column(String(80), nullable=False, unique=True)
|
||||
display_name: Mapped[str] = mapped_column(String(120), nullable=False)
|
||||
version: Mapped[str] = mapped_column(String(40), nullable=False)
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(20), nullable=False, default="installed"
|
||||
)
|
||||
installed: Mapped[bool] = mapped_column(
|
||||
Boolean, nullable=False, default=True
|
||||
)
|
||||
active: Mapped[bool] = mapped_column(
|
||||
Boolean, nullable=False, default=False
|
||||
)
|
||||
status: Mapped[str] = mapped_column(String(20), nullable=False, default="installed")
|
||||
installed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
||||
active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
config: Mapped[dict[str, Any] | None] = mapped_column(
|
||||
Text, nullable=True # JSON string for plugin configuration
|
||||
Text,
|
||||
nullable=True, # JSON string for plugin configuration
|
||||
)
|
||||
|
||||
# Transient attribute for response (not persisted)
|
||||
@@ -63,6 +55,4 @@ class PluginMigration(Base, TimestampMixin):
|
||||
)
|
||||
plugin_name: Mapped[str] = mapped_column(String(80), nullable=False)
|
||||
migration_file: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(20), nullable=False, default="applied"
|
||||
)
|
||||
status: Mapped[str] = mapped_column(String(20), nullable=False, default="applied")
|
||||
|
||||
+3
-2
@@ -6,8 +6,9 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, DateTime, ForeignKey, func
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, JSONB
|
||||
from sqlalchemy import DateTime, String, func
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.db import Base, TenantMixin
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import annotations
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import String, DateTime, ForeignKey, func
|
||||
from sqlalchemy import DateTime, ForeignKey, String, func
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import annotations
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import String, DateTime, func
|
||||
from sqlalchemy import DateTime, String, func
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
+5
-6
@@ -6,9 +6,10 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, Boolean, DateTime, ForeignKey, func, UniqueConstraint
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, JSONB
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy import Boolean, DateTime, ForeignKey, String, UniqueConstraint, func
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.db import Base, TenantMixin
|
||||
|
||||
@@ -17,9 +18,7 @@ class User(Base, TenantMixin):
|
||||
"""User entity — belongs to a tenant, can be member of multiple tenants."""
|
||||
|
||||
__tablename__ = "users"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("tenant_id", "email", name="uq_users_tenant_email"),
|
||||
)
|
||||
__table_args__ = (UniqueConstraint("tenant_id", "email", name="uq_users_tenant_email"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
|
||||
+17
-14
@@ -6,8 +6,9 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import String, Text, DateTime, ForeignKey, func, Index, Integer, Boolean
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID, JSONB
|
||||
from sqlalchemy import Boolean, DateTime, ForeignKey, Index, Integer, String, Text
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.db import Base, TenantMixin
|
||||
@@ -48,7 +49,10 @@ class WorkflowInstance(Base, TenantMixin):
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
workflow_id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), ForeignKey("workflows.id", ondelete="CASCADE"), nullable=False, index=True
|
||||
PGUUID(as_uuid=True),
|
||||
ForeignKey("workflows.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
status: Mapped[str] = mapped_column(String(30), nullable=False, default="pending")
|
||||
# pending → in_progress → completed / rejected / cancelled
|
||||
@@ -57,32 +61,31 @@ class WorkflowInstance(Base, TenantMixin):
|
||||
initiated_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
PGUUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
|
||||
)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
timeout_hours: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
timeout_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
timeout_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
|
||||
|
||||
class WorkflowStepHistory(Base, TenantMixin):
|
||||
"""Immutable record of every step transition in a workflow instance."""
|
||||
|
||||
__tablename__ = "workflow_step_history"
|
||||
__table_args__ = (
|
||||
Index("ix_wf_step_history_tenant_instance", "tenant_id", "instance_id"),
|
||||
)
|
||||
__table_args__ = (Index("ix_wf_step_history_tenant_instance", "tenant_id", "instance_id"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
instance_id: Mapped[uuid.UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), ForeignKey("workflow_instances.id", ondelete="CASCADE"), nullable=False, index=True
|
||||
PGUUID(as_uuid=True),
|
||||
ForeignKey("workflow_instances.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
step_index: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
step_type: Mapped[str] = mapped_column(String(50), nullable=False)
|
||||
action: Mapped[str] = mapped_column(String(50), nullable=False) # entered, approved, rejected, skipped, cancelled
|
||||
action: Mapped[str] = mapped_column(
|
||||
String(50), nullable=False
|
||||
) # entered, approved, rejected, skipped, cancelled
|
||||
actor_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
PGUUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user