Skip to content

Account merge: ACCOUNT_MERGE_REQUEST mail sent multiple times per merge event #3799

@TaprootFreak

Description

@TaprootFreak

Problem

Three independent code paths call AccountMergeService.sendMergeRequest(master, slave, reason) for what is logically the same merge event, and each call independently queues an ACCOUNT_MERGE_REQUEST mail through notificationService.sendMail (src/subdomains/generic/user/models/account-merge/account-merge.service.ts:63–88). The user receives the merge request mail more than once.

Triggers:

Reason Trigger location
MergeReason.IDENT_DOCUMENT src/subdomains/generic/kyc/services/kyc.service.ts:1253 and :1461 (ident step verification + the "Aktualisieren" / re-check path)
MergeReason.IBAN src/subdomains/generic/user/models/bank-data/bank-data.service.ts:443
MailContext.CHANGED_MAIL (separate path) user-data-notification.service.ts:98–151 called from user-data.service.ts:1235

The debounce: 60000 set on the mail (account-merge.service.ts:86) only suppresses sends with the same correlationId AND same context within 60 s — see the suppression rule in notification.entity.ts:53–58. The correlationId is set to request.id (the freshly-created AccountMerge row's id), so two sendMergeRequest calls for the same master/slave pair produce two different AccountMerge rows with two different ids, and the debounce never matches.

User impact

Reported as part of the post-merge UX: the user gets two identical "merge request" mails for one merge event, plus an additional notification on a subsequent app refresh. Erodes trust in the flow.

Suggested fix shape

Dedup at the sendMergeRequest entry, not at the mail layer. Before creating a new AccountMerge row + sending the mail, query for an existing open merge for the same {master, slave, reason} (and !isCompleted && !isExpired). If one exists, return early — reuse the existing request rather than minting a new one.

Subsequent improvement (optional): allow a follow-up reason to be added to an open merge (e.g. an IBAN conflict surfaces after an existing ident-document merge is already open) without sending another mail — the existing mail already directed the user to the confirmation URL.

Pair-PR

No app-side change. Pure backend deduplication.

Source

Surfaced in DFXswiss/realunit-app#611 (item 2) from the same test session as the other merge bugs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions