From d731390c9d5d1e8be23579ca977883247b28ba0e Mon Sep 17 00:00:00 2001 From: yiekheng Date: Sun, 10 May 2026 21:33:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20unpair=20soft-archives=20groups=20i?= =?UTF-8?q?nstead=20of=20DELETE=20=E2=80=94=20same=20FK=20abort?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Web error log showed unpairAccountAction failing with the same FK violation as group-sync: deleting whatsapp_groups rows that had been used in reminders blew up reminder_targets_group_id_whatsapp_groups_id_fk and aborted the unpair. Switch to UPDATE … SET is_archived=true. The bot's group-sync upsert already flips is_archived back to false on a re-pair (added in the group-sync companion fix in the previous commit), so behaviour is end-to-end equivalent to the old delete + repopulate path without the FK fragility. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web/src/actions/accounts.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/web/src/actions/accounts.ts b/apps/web/src/actions/accounts.ts index c159857..d77bc1d 100644 --- a/apps/web/src/actions/accounts.ts +++ b/apps/web/src/actions/accounts.ts @@ -172,8 +172,16 @@ export async function unpairAccountAction(formData: FormData): Promise { .update(whatsappAccounts) .set({ status: "unpaired", phoneNumber: null }) .where(eq(whatsappAccounts.id, accountId)); - // Wipe synced groups too — they belong to a different WA login now. - await db.delete(whatsappGroups).where(eq(whatsappGroups.accountId, accountId)); + // Soft-archive synced groups instead of DELETEing. Hard delete + // failed with "violates foreign key constraint + // reminder_targets_group_id_whatsapp_groups_id_fk" whenever any + // group had ever been used in a reminder, which aborted the + // unpair. Archived groups vanish from the picker; a re-pair flips + // them back via the on-conflict upsert in syncGroupsForAccount. + await db + .update(whatsappGroups) + .set({ isArchived: true }) + .where(eq(whatsappGroups.accountId, accountId)); revalidatePath("/accounts"); revalidatePath(`/accounts/${accountId}`); // eslint-disable-next-line @typescript-eslint/no-explicit-any