diff --git a/.changeset/eighty-eagles-reply.md b/.changeset/eighty-eagles-reply.md new file mode 100644 index 0000000000..0e76829cf6 --- /dev/null +++ b/.changeset/eighty-eagles-reply.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +bug: fix constraint on customer table to allow soft-deletes diff --git a/packages/medusa/src/migrations/1709888477798-alter-customer-unique-constraint.ts b/packages/medusa/src/migrations/1709888477798-alter-customer-unique-constraint.ts new file mode 100644 index 0000000000..70258ccc1a --- /dev/null +++ b/packages/medusa/src/migrations/1709888477798-alter-customer-unique-constraint.ts @@ -0,0 +1,37 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class AlterCustomerUniqueConstraint1709888477798 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "customer" DROP CONSTRAINT "UQ_unique_email_for_guests_and_customer_accounts"; + + CREATE UNIQUE INDEX "IDX_unique_email_for_guests_and_customer_accounts" ON "customer" ("email", "has_account") WHERE "deleted_at" IS NULL; + `) + } + + public async down(queryRunner: QueryRunner): Promise { + // ensure we dont have duplicated email,has_account to avoid violation of the previous unique constraint + await queryRunner.query(` + WITH RankedCustomers AS ( + SELECT + id, + ROW_NUMBER() OVER ( + PARTITION BY email, has_account + ORDER BY CASE WHEN deleted_at IS NULL THEN 0 ELSE 1 END, id + ) AS rn + FROM + customer + ) + DELETE FROM customer + WHERE id IN ( + SELECT id FROM RankedCustomers WHERE rn > 1 + ); + `); + + await queryRunner.query(` + DROP INDEX "IDX_unique_email_for_guests_and_customer_accounts"; + + ALTER TABLE "customer" ADD CONSTRAINT "UQ_unique_email_for_guests_and_customer_accounts" UNIQUE ("email", "has_account"); + `) + } +} diff --git a/packages/medusa/src/models/customer.ts b/packages/medusa/src/models/customer.ts index ef63794871..4a7897323e 100644 --- a/packages/medusa/src/models/customer.ts +++ b/packages/medusa/src/models/customer.ts @@ -19,7 +19,7 @@ import { SoftDeletableEntity } from "../interfaces/models/soft-deletable-entity" import { generateEntityId } from "../utils/generate-entity-id" @Entity() -@Unique(["email", "has_account"]) +@Index(["email", "has_account"], { unique: true, where: "deleted_at IS NULL" }) export class Customer extends SoftDeletableEntity { @Index() @Column()