Add editable, previewable payment-due email template
CI / Coding Standards (pull_request) Successful in 29s
CI / Tests (PHP 8.2) (pull_request) Successful in 31s
CI / Tests (PHP 8.3) (pull_request) Successful in 31s
CI / Tests (PHP 8.5) (pull_request) Successful in 31s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.1) (pull_request) Successful in 44s
CI / Static Analysis (pull_request) Successful in 51s
CI / Build Plugin Zip (pull_request) Skipped

The "Payment due" notice the daily billing scan sends was fixed wording
baked into PaymentDueMailer. Studio admins can now view, edit and preview
its subject and body under Studio Settings -> Payment Due Email.

- PaymentDueEmailTemplate stores subject/body/item-line as us_payment_due_email_*
  options, each falling back to the built-in default when blank, and renders
  via {token} substitution.
- PaymentDueMailer now builds a token map from the same consolidated
  items/credit/e-transfer/reference data and renders the stored template; the
  default template reproduces the previous wording exactly.
- PaymentEmailController serves the view/edit/save/reset admin page
  (manage_billing, nonce-checked) with a server-rendered sample preview.
- PaymentEmailPreviewEndpoint (POST us-scheduler/v1/payment-email/preview,
  manage_billing) + payment-email-admin.js drive a live preview of unsaved edits.
- Submenu wired under Studio Settings; endpoint wired in RestRegistrar.
- Bump to 1.6.0 and add CHANGELOG entry. New options default gracefully, so
  existing sites need no migration and send the identical notice until edited.

Co-authored-by: anthropic/claude-opus-4-8
This commit is contained in:
2026-09-17 17:33:23 -03:00
co-authored by anthropic/claude-opus-4-8
parent ad4e4ae357
commit a2c609803e
14 changed files with 841 additions and 41 deletions
+60
View File
@@ -0,0 +1,60 @@
/**
* Payment due email editor: live preview.
*
* Posts the subject/body/item-line the admin is editing to the read-only preview
* REST endpoint and swaps the rendered result into the preview panel, debounced
* as they type. The server always renders from the same sample values, so this
* mirrors exactly what a real billing scan would send. Purely a convenience — the
* page already shows a server-rendered preview of the saved template without it.
*/
(function () {
'use strict';
const config = window.uscPaymentEmailPreview;
if (!config || !config.url) return;
const subjectEl = document.getElementById('usc-pe-subject');
const bodyEl = document.getElementById('usc-pe-body');
const itemLineEl = document.getElementById('usc-pe-item-line');
const outSubject = document.getElementById('usc-pe-preview-subject');
const outBody = document.getElementById('usc-pe-preview-body');
if (!subjectEl || !bodyEl || !itemLineEl || !outSubject || !outBody) return;
let timer = null;
function refresh() {
fetch(config.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': config.nonce
},
body: JSON.stringify({
subject: subjectEl.value,
body: bodyEl.value,
item_line: itemLineEl.value
})
})
.then(function (response) {
if (!response.ok) throw new Error('preview failed');
return response.json();
})
.then(function (data) {
outSubject.textContent = data.subject || '';
outBody.textContent = data.body || '';
})
.catch(function () {
// Leave the last good preview in place on error.
});
}
function schedule() {
if (timer) window.clearTimeout(timer);
timer = window.setTimeout(refresh, 300);
}
[subjectEl, bodyEl, itemLineEl].forEach(function (el) {
el.addEventListener('input', schedule);
});
})();