Skip to content

fix(email,ui): billing emails follow customer language + readable payment-check confirmation#763

Open
Luca-Timo wants to merge 2 commits into
PicPeak:mainfrom
Luca-Timo:fix/email-language-and-payment-confirm
Open

fix(email,ui): billing emails follow customer language + readable payment-check confirmation#763
Luca-Timo wants to merge 2 commits into
PicPeak:mainfrom
Luca-Timo:fix/email-language-and-payment-confirm

Conversation

@Luca-Timo

@Luca-Timo Luca-Timo commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Fixes three issues found while testing the invoice-dunning flow. Tested on the dev instance.

#760 — billing/dunning emails used the event's gallery language

emailProcessor.getRecipientLanguage() resolves language event-first, so an invoice tied to an English-gallery event sent the customer an English dunning email even for a German customer/invoice.

  • emailProcessor now honors an explicit __language in the email data (both the queue-processor and preview paths); otherwise it falls back to the existing event-first resolution — no change for gallery emails.
  • The invoice reminder (invoice/reminders.js) resolves the locale as customer.preferred_language || invoice.language || 'de' and passes it as __language.

#759 — payment-check confirmation card unreadable in dark mode

The "Action recorded" card hardcoded a dark-green title over a light-green color-mix background — muddy + illegible on dark surfaces. Now theme-adaptive: a green tint over --color-surface with --color-text title/body, readable on both light and dark.
Screenshot 2026-07-06 at 19 59 27

#761 — per-customer language

The per-customer "Preferred language" dropdown already exists (CustomerDetailPage), as does the global business-profile default. The gap was that emails ignored it (#760). Updated the field's helper text (en + de) to note billing emails now honor it.

Fixes #759, #760, #761.

…ment-check confirmation

- Billing/dunning emails no longer render in the gallery event's language.
  emailProcessor now honors an explicit `__language` in the email data
  (else falls back to the event-first recipient resolution), and the invoice
  reminder passes the customer/invoice locale (customer.preferred_language
  || invoice.language || 'de'). Fixes German customers getting English
  dunning notices. (PicPeak#760)
- Payment-check confirmation card ("Action recorded") is now theme-adaptive
  (green tint + readable text on both light and dark surfaces) instead of a
  hardcoded light-green mix + dark-green title that vanished in dark mode. (PicPeak#759)
- The per-customer "Preferred language" field already exists
  (CustomerDetailPage) plus the business-profile default; updated the helper
  text to note billing emails now honor it too. (PicPeak#761)
@Luca-Timo Luca-Timo requested a review from the-luap July 6, 2026 18:01
@the-luap

the-luap commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Verified the whole chain — the fix is correct.

__language is honored on both the queue (sendTemplateEmail) and preview (renderQueuedEmail) paths and falls back to the existing event-first resolution, so gallery emails are untouched. Leak-safe too: safeTemplateReplace only substitutes {{tokens}} present in the template, and nothing references {{__language}}, so the control key can't surface in the body. customer.preferred_language is a real column (loaded via the select * in applyReminder), and the precedence reads right. #759 card + #761 helper text (en/de/inline) all good.

One gap worth closing in the same PR — the sibling billing emails have the identical event-first bug and don't set __language:

  • invoice_sent (invoice/sending.js:121) — it even re-syncs invoice.language from the customer and formats amounts in ctx.locale, but the email body still resolves event-first, so a German customer on an English-gallery event gets an English invoice email with German-formatted amounts.
  • storno_issued (invoice/sending.js:365) — same shape.
  • payment-check (invoice/payments.js:180/280) — lower priority (admin-facing), but same pattern.

Each already computes the locale, so it's a one-liner per call: __language: ctx.locale (invoice_sent/storno) / __language: locale (payment-check). Worth folding in so billing-email language is consistent, not just dunning.

Otherwise merge cleared.

Addresses the PR PicPeak#763 review: the invoice_sent / storno_issued / payment-check
/ paid-admin-notification emails share the identical event-first language bug
and never set __language, so a German customer on an English-gallery event got
an English email body with German-formatted amounts.

Each call site already computes the locale it formats amounts in, so this is a
one-liner per call — the body language now matches the amount formatting:
- invoice_sent, storno_issued (sending.js) -> __language: ctx.locale
- payment-check, invoice_paid_admin_notification (payments.js) -> __language: locale

Leak-safe (no template references {{__language}}) and falls back to the
existing event-first resolution when unset, per the mechanism added in PicPeak#763.
@Luca-Timo

Copy link
Copy Markdown
Collaborator Author

@the-luap Folded in — c0008be. All the sibling billing emails now set __language and match the locale their amounts are formatted in, instead of resolving event-first:

  • invoice_sent (sending.js:132) → __language: ctx.locale
  • storno_issued (sending.js:375) → __language: ctx.locale
  • payment-check (payments.js:292) → __language: locale
  • invoice_paid_admin_notification (payments.js:189) — the other :180 site → __language: locale

Leak-safe (nothing references {{__language}}) and each falls back to the existing event-first resolution when unset. Ready for another look.

@the-luap

the-luap commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Re-verified c0008be. All four sibling emails now carry __language, each matching the locale their amounts are formatted in:

  • invoice_sent + storno_issuedctx.locale (sending.js:132 / :371)
  • payment-check + invoice_paid_admin_notificationlocale (payments.js:189 / :292)

Swept the invoice queueEmail sites — every event-scoped one (reminder, invoice_sent, storno) now sets it, so there's no event-first path left for billing. Nice catch folding in invoice_paid_admin_notification — I hadn't listed that one. CI green.

Merge cleared.

@Luca-Timo Luca-Timo enabled auto-merge July 6, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Payment-check confirmation view ("Action recorded") unreadable in dark mode

2 participants