feat: enforce communication channel from routing config

Resolved 💬 2 comments Opened Mar 5, 2026 by eliagentili Closed Mar 9, 2026

Context

The multi-contact system includes a communication_routing table with a channel field (EMAIL, SMS, EMAIL_AND_SMS) per communication type. Currently this field is saved but not enforced — the decision to send email vs SMS is hardcoded in each service.

Current behavior

  • resolveContact(customerId, communicationType) returns the contact (email/phone) but not the channel
  • Each sender independently decides whether to send email, SMS, or both
  • The channel column in communication_routing is purely documentative

Desired behavior

  • resolveContact should also return the configured channel
  • Each sender should respect the channel setting:
  • EMAIL → only send email, skip SMS
  • SMS → only send SMS, skip email
  • EMAIL_AND_SMS → send both (current default behavior)
  • The routing UI (/settings/communication-routing) already allows changing the channel — it just needs to be wired up

Affected services

All services that call resolveContact and send communications:

  • contract-signing.service.ts (CONTRACT_INVITE, CONTRACT_OTP, CONTRACT_SIGNED_COPY)
  • contract-reminders.ts (CONTRACT_REMINDER)
  • delivery.service.ts (DELIVERY_CONFIRMATION)
  • availability.service.ts (AVAILABILITY_REQUEST/CONFIRMATION/CANCELLATION)
  • collection-manager.ts (COLLECTION_REMINDER_AUTO)
  • collections.ts (COLLECTION_REMINDER_MANUAL)
  • invoices.ts (INVOICE_EMAIL)
  • invoice-courtesy.service.ts (INVOICE_COURTESY_COPY)
  • ddts.ts (DDT_CONFIRMATION)
  • auto-pay.service.ts (AUTOPAY_*)
  • draft-notifier.ts, printing-orders.ts, portal.ts

Implementation plan

  1. Extend resolveContact return type to include channel: string
  2. Update ResolvedContact interface
  3. Each sender checks contact.channel before deciding email/SMS
  4. Add helper: shouldSendEmail(channel), shouldSendSms(channel)

Priority

Low — the system works correctly now, this is an optimization for configurability.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗