chore: fix all ruff lint errors + format — 0 errors, 306 tests pass

This commit is contained in:
leocrm-bot
2026-06-29 17:43:56 +02:00
parent 316f323ff4
commit a2452cc04b
81 changed files with 2317 additions and 1128 deletions
+43 -20
View File
@@ -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",
]
+9 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
+4 -5
View File
@@ -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,
+5 -9
View File
@@ -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"),
)
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
)