From ec7182319d785fd0d7946d25e25a01b025d11345 Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Fri, 6 Dec 2024 15:06:41 -0500 Subject: [PATCH] membershipworks: Avoid duplicating Transactions with NULL sid field Treat NULL in Transaction.sid as non-distinct in the UNIQUE constraint --- ...ansaction_unique_sid_timestamp_and_more.py | 44 +++++++++++++++++++ membershipworks/models.py | 6 ++- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 membershipworks/migrations/0006_remove_transaction_unique_sid_timestamp_and_more.py diff --git a/membershipworks/migrations/0006_remove_transaction_unique_sid_timestamp_and_more.py b/membershipworks/migrations/0006_remove_transaction_unique_sid_timestamp_and_more.py new file mode 100644 index 0000000..5ea0027 --- /dev/null +++ b/membershipworks/migrations/0006_remove_transaction_unique_sid_timestamp_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 5.1.4 on 2024-12-06 19:44 + +import itertools + +from django.db import migrations, models + + +def remove_duplicates(apps, schema_editor): + Transaction = apps.get_model("membershipworks", "Transaction") + for _, group in itertools.groupby( + Transaction.objects.filter(sid=None), key=lambda t: t.timestamp + ): + dupes = list(group) + first_in_group = dupes.pop() + for t in dupes: + if any( + getattr(t, field.name) != getattr(first_in_group, field.name) + for field in Transaction._meta.get_fields() + if field.name != "id" + ): + raise Exception("Transaction doesn't match!") + t.delete() + + +class Migration(migrations.Migration): + dependencies = [ + ("membershipworks", "0005_historicalmember_nfc_card_number_and_more"), + ] + + operations = [ + migrations.RunPython(remove_duplicates, atomic=True), + migrations.RemoveConstraint( + model_name="transaction", + name="unique_sid_timestamp", + ), + migrations.AddConstraint( + model_name="transaction", + constraint=models.UniqueConstraint( + fields=("sid", "timestamp"), + name="unique_sid_timestamp", + nulls_distinct=False, + ), + ), + ] diff --git a/membershipworks/models.py b/membershipworks/models.py index cb67183..0df157f 100644 --- a/membershipworks/models.py +++ b/membershipworks/models.py @@ -377,7 +377,11 @@ class Transaction(BaseModel): class Meta: db_table = "transactions" constraints = [ - models.UniqueConstraint("sid", "timestamp", name="unique_sid_timestamp") + models.UniqueConstraint( + fields=["sid", "timestamp"], + name="unique_sid_timestamp", + nulls_distinct=False, + ) ] def __str__(self):