Objective
- Let automation authors express “duplicate contact” rules so they match real intent: block or allow per recipient based on whether that recipient’s contact is duplicated on the workorder—not whether some other contact appears twice under multiple roles.
- Preserve today’s behavior as an option where teams rely on job-wide duplicate detection (same contact on
peopletwice / multiple roles).
Background
- Today
contact-already-on-jobanswers a single global question: among everyone on the job (_conditionScopePeople), does any contact identity appear more than once? Identity comes fromresolveContactIdentity(contact id, else normalized email) inattik-backend/src/util/functions/actionFlows/recipientIdentity.ts. - The resolver in
attik-backend/src/util/functions/actionFlows/attributePathResolver.tscounts duplicates across_conditionScopePeople || inspection.people, so it does not mean “this To recipient is duplicated.” - Per-recipient email sending builds
jobForRecipientwithpeople: [toPerson]and_conditionScopePeople: jobData.peopleinattik-backend/src/util/functions/emailBuilder/renderEmail.ts, which is correct for role-scoped attributes—butcontact-already-on-jobstill reads the full list, so every recipient sees the same true/false when anyone on the job is duplicated. - Combining Contact Role with Contact Already On Job only gates who is evaluated for role; it does not narrow duplicate detection to that role’s contact or to the current recipient.
- The condition is exposed in
attik-frontend/src/components/conditions/templatingData.tsas a boolean with no extra parameters—UI/schema work may be needed if the behavior becomes configurable.
Scope
Backend
attik-backend/src/util/functions/actionFlows/attributePathResolver.ts—contact-already-on-jobresolver and how it uses_conditionScopePeoplevspeoplefor recipient-scoped evaluation.attik-backend/src/util/functions/emailBuilder/renderEmail.ts—sendToRecipient/jobForRecipientshape (already passes_conditionScopePeople); any new attribute must compose cleanly here.attik-backend/src/util/functions/actionFlows/conditionsResolver.ts(and related tests e.g.tests/unit/email.blockConditions.test.ts,tests/unit/attributePathResolver.test.ts) — ensure evaluation semantics and tests cover recipient-scoped duplicate vs job-wide duplicate.attik-backend/src/util/functions/emailBuilder/backendTemplatingData.ts— registry for template/condition keys if a new key is added alongside the existing one.
Frontend
attik-frontend/src/components/conditions/templatingData.ts— register display metadata,conditionType, and any enum or help text so authors understand global vs current-recipient (or similar) semantics.
Product / architecture decisions (for the implementer)
- Decision needed: Extend
contact-already-on-job(risk: changes meaning for existing flows) vs add a new condition (e.g. current contact duplicated on job) withcontact-already-on-jobunchanged for backward compatibility. - Decision needed: Should recipient-scoped duplicate mean “same
resolveContactIdentityappears in more than onepeoplerow on the job” while evaluating for that recipient only—regardless of which roles those rows are? - Decision needed: Is a future variant needed to restrict duplicates to specific role id(s) only, or is per-recipient sufficient for the reported use cases?
- Decision needed: Same behavior must apply consistently to SMS and any other channel that sets
_conditionScopePeople(e.g.attik-backend/src/util/functions/actionFlows/renderSms.ts) if those paths evaluate the same attributes.
References
- Duplicate detection implementation:
attik-backend/src/util/functions/actionFlows/attributePathResolver.ts(contact-already-on-job) - Recipient scoping for email:
attik-backend/src/util/functions/emailBuilder/renderEmail.ts(jobForRecipient,_conditionScopePeople) - Contact identity helper:
attik-backend/src/util/functions/actionFlows/recipientIdentity.ts(resolveContactIdentity) - Condition catalog (frontend):
attik-frontend/src/components/conditions/templatingData.ts - Tests:
tests/unit/email.blockConditions.test.ts,tests/unit/attributePathResolver.test.ts