// §3.9 Rebate Monitor — Contracts, Tiers, Accrual, Settlement, Dashboard function RebateMonitor({ user, perms }) { const [tab, setTab] = useState("dashboard"); const [openRebate, setOpenRebate] = useState(null); const [openSettlement, setOpenSettlement] = useState(false); const tabs = [ { id: "dashboard", label: "Dashboard" }, { id: "contracts", label: "Rebate Contracts", count: REBATES.length }, { id: "accrual", label: "Monthly Accrual" }, { id: "settlement", label: "Settlements", count: SETTLEMENTS.filter(s => s.status !== "Settled").length }, ]; return (
{(perms.admin || user.role === "procurement") && ( )} } /> {tab === "dashboard" && } {tab === "contracts" && } {tab === "accrual" && } {tab === "settlement" && setOpenSettlement(true)} perms={perms} />} {openRebate && setOpenRebate(null)} perms={perms} />} {openSettlement && setOpenSettlement(false)} />}
); } function RebateKPIs() { const totalUSD = REBATES.reduce((s, r) => s + r.accruedYTD, 0); const atRisk = REBATES.filter(r => r.atRisk || r.currentTier === 0).length; const eoyForecast = totalUSD * 2.4; const unsettled = SETTLEMENTS.filter(s => s.status !== "Settled").reduce((acc, s) => acc + (s.accrued / (ROE[s.ccy] || 1)), 0); return (
0 ? "trailing tier targets" : "all on pace"} deltaDir={atRisk > 0 ? "down" : "up"} /> s.status === "Overdue").length} overdue`} />
); } // ============== REBATE DASHBOARD ============== function RebateDashboard({ onOpen }) { return (
Updated 2 hours ago}>
{REBATES.filter(r => r.currentTier >= 0).map((r, i) => { const ytd = YTD_VOLUME[r.terminal] || 18000; const nextTier = r.tiers[r.currentTier]; const prevTier = r.tiers[r.currentTier - 1]; const min = prevTier?.max ? prevTier.max + 1 : 0; const max = nextTier?.max || ytd * 1.4; const pct = ((ytd - min) / (max - min)) * 100; const uplift = r.accruedYTD * 0.4; return (
0 ? "1px solid var(--line)" : 0, cursor: "pointer" }} onClick={() => onOpen(r)}>
{TERMINAL_BY_CODE[r.terminal]?.name}
{r.id}
{nextTier?.name || "Maxed"} @ {nextTier?.rate || "—"}%
70 ? "var(--green)" : pct > 30 ? "var(--teal)" : "var(--amber)" }} />
{fmt.num(ytd, 0)} TEU YTD → {fmt.num(max, 0)} TEU (next tier)
Reach next tier: +{fmt.usd(uplift)} uplift
); })}
{REBATES.filter(r => r.atRisk || r.currentTier === 0).map((r, i) => (
0 ? "1px solid var(--line)" : 0, display: "flex", alignItems: "center", gap: 10 }}>
{TERMINAL_BY_CODE[r.terminal]?.name}
{r.id} · {r.type}
-{fmt.usd(54200)}
if missed
))}
Adjust assumptions}>
YTD actual
{fmt.usd(403800)}
EoY projection
{fmt.usd(969100)}
vs Plan
+12%
{/* mini chart */}
Pace assumption: +0.5% MoM · Tier 3 reached at Shanghai by Sep 2025 (forecast)
{REGIONS.map(r => { const contracts = REBATES.filter(rb => TERMINAL_BY_CODE[rb.terminal]?.region === r); const accrued = contracts.reduce((s, c) => s + c.accruedYTD, 0); const prior = accrued * 0.85; const pct = ((accrued - prior) / prior) * 100; return ( ); })}
Region Contracts YTD Accrual (USD) Prior Year YTD % Change Pace
{r} {contracts.length} {fmt.usd(accrued)} {fmt.usd(prior)} 0 ? "var(--green)" : "var(--red)" }}> {pct > 0 ? "↑" : "↓"} {Math.abs(pct).toFixed(1)}%
); } // ============== CONTRACTS LIST ============== function RebateContracts({ onOpen }) { return (
{REBATES.map(r => ( onOpen(r)} style={{ cursor: "pointer" }}> ))}
ID Terminal Contract Ref Type Scope Period Settlement Current Tier YTD Accrual Status
{r.id}
{TERMINAL_BY_CODE[r.terminal]?.name}
{r.terminal}
{r.contractRef} {r.type} {r.scope} {r.period} {r.settlement} {r.tiers[r.currentTier]?.name.replace(" (Base)", "").replace(" (Elite)", "") || "—"}
@ {r.tiers[r.currentTier]?.rate}%
{fmt.usd(r.accruedYTD)}
{fmt.num(r.accruedYTDLocal)} {r.currency}
); } // ============== ACCRUAL VIEW ============== function AccrualView() { // Build a monthly accrual matrix per rebate const months = ["2025-01", "2025-02", "2025-03", "2025-04", "2025-05"]; return (
{months.map(m => )} {REBATES.map((r, ri) => { const monthly = months.map((m, i) => Math.round(r.accruedYTD / months.length * (0.7 + (ri + i) % 8 / 10))); const total = monthly.reduce((a, b) => a + b, 0); const hasUpgrade = ri === 0; return ( {monthly.map((v, i) => ( ))} ); })}
Rebate Terminal{m}YTD Total Notes
{r.id}
{r.type}
{TERMINAL_BY_CODE[r.terminal]?.name} {fmt.usd(v)} {i === 2 && hasUpgrade &&
↑ Tier upgrade adj.
}
{fmt.usd(total)} {hasUpgrade ? "Mar: Tier 3 crossed, retroactive uplift" : ""}
Auto-recalculation. Accruals refresh automatically after every Volume Tracker import. For retroactive tiers, when a threshold is crossed mid-period, the system writes a Tier Upgrade Adjustment for the prior-period delta and logs it in the audit trail.
); } // ============== SETTLEMENT ============== function SettlementTracker({ onNew, perms }) { return (
{(perms.admin || true) && }
{SETTLEMENTS.map(s => ( ))}
ID Rebate Period Calculated Claimed Variance Claimed Date Settled Date Reference Status
{s.id} {s.rebate} {s.period} {fmt.num(s.accrued, 0)} {s.ccy} {fmt.num(s.claimed, 0)} {s.ccy} 5 ? "var(--amber)" : "var(--ink-mute)", fontWeight: Math.abs(s.variance) > 5 ? 600 : 400 }}> {s.variance === 0 ? "—" : (s.variance > 0 ? "+" : "") + s.variance.toFixed(1) + "%"} {s.claimedDate} {s.settledDate || "—"} {s.ref} {s.status === "Settled" && Settled} {s.status === "Awaiting Credit" && Awaiting Credit} {s.status === "In Review" && In Review} {s.status === "Overdue" && Overdue · {s.daysOverdue}d}
); } // ============== REBATE DETAIL ============== function RebateDetail({ rebate, onClose, perms }) { const t = TERMINAL_BY_CODE[rebate.terminal]; const ytd = YTD_VOLUME[rebate.terminal] || 0; return (
{perms.admin && } {perms.admin && } } >
YTD Accrual
{fmt.usd(rebate.accruedYTD)}
{fmt.num(rebate.accruedYTDLocal)} {rebate.currency}
YTD Volume
{fmt.num(ytd, 0)} TEU
Current Tier
{rebate.tiers[rebate.currentTier]?.name || "—"}
@ {rebate.tiers[rebate.currentTier]?.rate}%
Add tier : null} style={{ marginBottom: 16 }}>
{rebate.tiers.map((t, i) => ( ))}
Tier Min Volume Max Volume Rate Type Status
{t.name} {fmt.num(t.min, 0)} {t.max ? fmt.num(t.max, 0) : "∞"} {t.rate.toFixed(1)}% {t.type} {i === rebate.currentTier ? Current : i < rebate.currentTier ? ✓ achieved : pending}
{t?.name} ({rebate.terminal})} /> {rebate.effective} → {rebate.expiry}} /> {rebate.currency}} />
); } function NewSettlement({ onClose }) { return ( } >