File size: 2,532 Bytes
00a69e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
 * Matches backend/app/main.py helpers used in _notify_tenant_admins_deal_won (won-deal email body).
 */

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';
}

/** Python {:g}-style qty for line display */
export function fmtQtyG(qf) {
    if (!Number.isFinite(qf)) return '0';
    return Number.isInteger(qf) ? String(qf) : String(qf);
}

/**
 * One numbered line item line, same text as the admin email (excluding leading newline).
 */
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 })}`;
}