Commit Graph

4 Commits

Author SHA1 Message Date
caaebd77fa fix(intake): client inquiry emails mirror website copy + never show "Port Nimara CRM"
All checks were successful
Build & Push Docker Images / lint (push) Successful in 2m55s
Build & Push Docker Images / build-and-push (push) Successful in 8m49s
Client-facing confirmation emails now:
- use the PUBLIC port name ("Port Nimara" via ports.name), never the CRM
  appName ("Port Nimara CRM") which is reserved for internal/staff surfaces
- mirror the website's wording verbatim ("Thank you for expressing
  interest…", "Best regards,") and drop the CRM-style headings
- sign off per category: berth → "Port Nimara Sales Team", contact →
  "Port Nimara Team", residential → "Port Nimara Residences Team"
- show + reply-to a public contact address, admin-configurable per category
  (inquiry_contact_email → sales@ for berth/residence,
  contact_form_contact_email → hello@ for contact form), never the noreply From

Internal alerts keep the CRM detail-line format + link (name fixed to
"Port Nimara"), EXCEPT the residential alert which drops all CRM mention
(it reaches an external recipient) and signs "- Port Nimara Residences".

sendEmail gains an optional per-message replyTo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L2qc3xZTfif7N4Wq3QDa8X
2026-06-25 22:07:47 +02:00
866930c943 feat(intake): residence-type capture + CRM-owned inquiry emails for website cutover
All checks were successful
Build & Push Docker Images / lint (push) Successful in 3m5s
Build & Push Docker Images / build-and-push (push) Successful in 9m17s
Website register-interest form now offers the 3 residence types as a
multi-select; the choice + preferred-contact flow into the CRM inquiry
payload, the inbox detail, and the residential emails.

- inquiry inbox detail surfaces residence type(s), preferred contact,
  type-of-interest, comments (full data capture)
- residential-inquiry emails: client confirmation names the chosen
  villa(s); sales alert converted to the canonical detail-line format
  (uniform with berth/contact) + residence type(s)/preferred contact +
  plain-text part
- website-intake-fields parses residence_types[] + method_of_contact
- contact_form alerts split to their own recipient key
  (contact_notification_recipients)
- Residential Interests section: new residence_type field (schema +
  migration 0099, validators, inline select on the detail)
- contact-form-alert email refactor shipped (interest-alert style)

Tests: website-intake-fields, residential-inquiry templates,
contact-form-alert, residential-interest validators.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L2qc3xZTfif7N4Wq3QDa8X
2026-06-25 20:58:53 +02:00
1c91d76c52 feat(signing): internal "who signed" + completion email alerts to configurable recipients
All checks were successful
Build & Push Docker Images / lint (push) Successful in 2m56s
Build & Push Docker Images / build-and-push (push) Successful in 8m56s
Adds a per-port `signing_notification_recipients` setting (users / roles /
explicit emails via the existing RecipientPicker) and fires a branded
internal email on (a) each party signing and (b) full completion —
replicating the legacy "Document Signed" / "EOI Complete Update Status"
Activepieces flows that staff relied on.

- New branded template `signing-status-notification.tsx` (per-signer
  progress + completion variants, deep-links into the CRM).
- New `sendSigningStatusNotification` resolver in document-signing-emails:
  resolves recipients, falls back to the port reply-to (sales@) when the
  list is empty so alerts are never silently dropped, per-recipient send.
- Wired into `handleRecipientSigned` (first signed transition) and
  `handleDocumentCompleted` (idempotent, fires once) — reached by both the
  Documenso webhook and the 5-min poll. Fully guarded so a notification
  failure never undoes a signing side effect. Respects EMAIL_REDIRECT_TO.
- Admin UI: `Document signing alerts` recipients card in settings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012iJPYbh5X53iBh9h7ffQoy
2026-06-24 21:38:22 +02:00
93989b1e1d feat(admin): single Sales role, welcome-email password setup, Director=sales
All checks were successful
Build & Push Docker Images / lint (push) Successful in 3m5s
Build & Push Docker Images / build-and-push (push) Successful in 9m24s
- Collapse the two sales roles in the create-user dropdown to one "Sales"
  (sales_manager relabelled). Hide super_admin + sales_agent from selection
  via NON_ASSIGNABLE_ROLE_NAMES; the form keeps a user's *current* role even
  if hidden so existing assignments stay editable.
- Director becomes a senior-title twin of Sales: DIRECTOR_PERMISSIONS now
  equals SALES_MANAGER_PERMISSIONS (no admin/settings — Super-Admin only).
  Migration 0097 updates the existing global director row (idempotent,
  data-only; 0 users assigned on prod, so no blast radius).
- Admin create-user defaults to emailing a set-password link instead of an
  inline password (manual entry still available via a toggle). createUserSchema:
  password optional + sendSetupEmail; createUser provisions with a throwaway
  password then triggers the set-password email.
- New users get a dedicated, unique WELCOME email (crmWelcomeEmail), not the
  self-service "reset your password" email. A pending-welcome flag routes the
  shared better-auth sendResetPassword callback via account-setup-email.ts.
- Phone confirmed already optional for staff accounts (no change needed).

Tests: +welcome-routing, +create-user-setup; permission-matrix director block
realigned to no-admin. 1662 vitest pass; tsc + eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 12:40:55 +02:00