Problem/Motivation
The MondayCreateItemWebformHandler calls create_item on every completed submission. When several submissions carry the same email address — the same form submitted twice, or two different forms that each populate a different subset of columns — each one produces a separate Monday item. The result is duplicate rows in the board and lost consolidation of a single contact's data.
A blind overwrite is not acceptable either: a board may have many columns populated by different forms (or by a prior CSV import), so re-writing the whole item on each submission would erase columns set by earlier submissions.
Steps to reproduce
- Configure the handler on a board with an email column, mapping a Webform email field to it.
- Submit the form with
a@example.com. - Submit again with the same email (same or a different form / field set).
- Observe two separate items on the board instead of one merged item.
Proposed resolution
Add an opt-in, email-keyed upsert to the handler:
- New per-handler config
dedup_email_column_id. Empty ⇒ current create-only behavior (fully backward-compatible). Set to a Monday column ID ⇒ upsert enabled. - On submission with dedup enabled, look up existing items by the email column value via a single server-side filter
(items_page_by_column_values):- No match ⇒
create_item(current behavior). - One match ⇒
change_multiple_column_valueswriting only the columns present in this submission; all other columns are left untouched (partial-field merge). Empty submitted fields are skipped, so they never overwrite existing values. - Multiple matches (legacy / imported duplicates) ⇒ merge into the oldest item (lowest item ID) and log a warning listing the other matches IDs.
- No match ⇒
- Item name, the lead-source column, and the target group are written on create only — never on merge — so a merge does not churn the identity column, overwrite lead provenance, or move the item between pipeline groups.
- Email matching relies on Monday's exact column match; no address normalization is applied.
- If the lookup call fails, the relay aborts through the existing failure path (logged; configurable user-facing message; local submission preserved) rather than falling back to a create, to avoid re-introducing duplicates during an API outage.
Remaining tasks
- Add
findItemsByColumnValue()andchangeColumnValues()toMondayClientInterface/
MondayClient. - Refactor
buildColumnValues()so the lead-source column is appended on the create path only. - Rewrite
relay()as the upsert described above. - Add
dedup_email_column_idto the config form andconfig/schema/monday_crm_integration.schema.yml. - Unit tests: new client methods (0 / 1 / many results, error paths); handler matrix (dedup off; 0 / 1 / many matches; missing-email;
empty-field-no-overwrite on merge; lookup-failure abort; assert name / group / lead-source are not sent on merge). - Update README.
- Manual verification of the cross-form merge against a real board.
User interface changes
One new optional field, "Dedup email column ID," on the handler configuration form. No change when left empty.
API changes
Two new methods on MondayClientInterface: findItemsByColumnValue(int $boardId, string $columnId, string $value): array and
changeColumnValues(int $boardId, int $itemId, array $columnValues): array. Additive — no existing signatures change.
Data model changes
One new handler config key dedup_email_column_id (string, default empty). No update hook required; existing handlers default to empty and
keep current behavior.
Issue fork monday_crm_integration-3616294
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #4
das.gautam commented