Files
zeekay 74d77a3ebd migrations: create the two insights models that never had one, and make 0003 adoptable
THREE things, all pointing at the same wall — migrate could not run.

1. insights.userintegration and insights.userpushtoken are real managed models
   (insights/models/user_integration.py, user_push_token.py) with no CreateModel
   anywhere, so the products.tasks FKs pointing at them could not resolve and the
   whole project state failed to render. Neither table exists in any database —
   checked both the declared names (insights_user_integration,
   insights_user_push_token) and Django's defaults against production before
   writing — so these are ordinary CreateModels, not an adoption.

   Both FKs to insights_user carry db_constraint=False. That table is read on
   virtually every request and creating an FK constraint against it takes a
   SHARE ROW EXCLUSIVE lock that conflicts with every write. CASCADE still holds;
   Django's collector performs it.

2. The role FKs repointed at insights.role in the previous commit needed the same
   treatment for a different reason: insights.Role is managed=False on the legacy
   ee_role table, which Django never creates. A fresh database has nothing for the
   constraint to reference, and migrate died on: relation "ee_role" does not exist.
   Model and migration both drop the constraint, so one codebase migrates a fresh
   database and the live one.

3. insights_session.0003 added its columns with plain AddField. Those columns are
   already on django_session in production, applied by hand to restore login while
   the graph was broken, with nothing recorded — so 0003 would have failed on
   "column already exists". It now adopts them the way 0001 already does, with
   SeparateDatabaseAndState and ADD COLUMN IF NOT EXISTS.

   The usual escape, migrate --fake, is the wrong tool: it would also skip the
   columns on a database that does NOT have them, so the deploy would have to know
   which kind of database it was talking to. Guarded DDL is one path that is right
   on both, and the deploy has nothing to remember.

Verified against a Postgres seeded with production's own django_migrations
(1,166 rows): the plan builds and comes to 891 unapplied migrations, including all
three insights_session ones and insights.0005. Against a database patched by hand
exactly like production's, 0001-0003 apply clean and record themselves; the
pre-change 0003 fails on that same database with "column country_code of relation
django_session already exists".
2026-08-08 15:20:50 -07:00

22 lines
847 B
Python

from django.db import models
from insights.models.utils import UUIDTModel
class TicketAssignment(UUIDTModel):
ticket = models.OneToOneField("conversations.Ticket", on_delete=models.CASCADE, related_name="assignment")
user = models.ForeignKey("insights.User", null=True, on_delete=models.CASCADE)
role = models.ForeignKey("insights.Role", null=True, on_delete=models.CASCADE, db_constraint=False)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "insights_conversations_ticket_assignment"
constraints = [
models.CheckConstraint(
condition=(
models.Q(user__isnull=False, role__isnull=True) | models.Q(user__isnull=True, role__isnull=False)
),
name="exactly_one_assignee_type",
),
]