| |
| |
| |
|
|
| export function wonCurrencyLabel(raw) { |
| const c = String(raw || 'USD').trim().toUpperCase(); |
| return c === 'CAD' ? 'CAD' : 'USD'; |
| } |
|
|
| export function fmtWonMoney(amount, currencyRaw) { |
| const lab = wonCurrencyLabel(currencyRaw); |
| const sym = lab === 'CAD' ? 'CA$' : '$'; |
| let n = Number(amount); |
| if (!Number.isFinite(n)) n = 0; |
| const s = n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); |
| return `${sym}${s} ${lab}`; |
| } |
|
|
| export function wonBillingIntervalLabel(raw) { |
| const s = String(raw || 'monthly').trim().toLowerCase(); |
| if (['one_time', 'onetime', 'one-time', 'non-recurring'].includes(s)) return 'One-time'; |
| if (['quarterly', 'quarter', 'every 3 months'].includes(s)) return 'Every 3 months'; |
| if (['annual', 'year', 'yearly', 'every year'].includes(s)) return 'Every year'; |
| return 'Every month'; |
| } |
|
|
| |
| export function fmtQtyG(qf) { |
| if (!Number.isFinite(qf)) return '0'; |
| return Number.isInteger(qf) ? String(qf) : String(qf); |
| } |
|
|
| |
| |
| |
| export function wonEmailLineItemBodyLine(index1, li) { |
| const ps = String(li.product_service || '').trim(); |
| const cur = wonCurrencyLabel(li.currency); |
| let qf = Number(li.qty); |
| let rf = Number(li.rate); |
| let af = Number(li.amount); |
| if (!Number.isFinite(qf)) qf = 0; |
| if (!Number.isFinite(rf)) rf = 0; |
| if (!Number.isFinite(af)) af = 0; |
| const cadence = wonBillingIntervalLabel(li.billing_interval); |
| return ` ${index1}. ${ps} | ${cadence} | Qty ${fmtQtyG(qf)} × ${fmtWonMoney(rf, cur)} = ${fmtWonMoney(af, cur)}`; |
| } |
|
|
| export function wonEmailSubtotalLine(lines, subtotal) { |
| const st = Number(subtotal); |
| const sum = Number.isFinite(st) ? st : 0; |
| if (!lines?.length) { |
| return `Subtotal: ${sum.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; |
| } |
| const distinct = new Set(lines.map((li) => wonCurrencyLabel(li.currency))); |
| if (distinct.size === 1) { |
| const only = distinct.values().next().value; |
| return `Subtotal: ${fmtWonMoney(sum, only)}`; |
| } |
| return `Subtotal (numeric sum of line amounts; USD and CAD lines are not converted between currencies): ${sum.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; |
| } |
|
|