/* eslint-disable */ /* © 2026 K2B NETWORK SOLUTIONS LLC. All rights reserved. Proprietary and confidential. Unauthorized copying, distribution, or use of this file, via any medium, is strictly prohibited. Original work product. */ // JBREWS DMS — Banks / Lenders registry (Sales & F&I). // Manages the dealership's lender book stored in window.jbLenders. Edits here // drive the lender dropdowns in Desking and the Finance Worksheet. const bk$ = (n) => "$" + (Number(n) || 0).toLocaleString("en-US", { maximumFractionDigits: 0 }); const BK_TYPE_COLOR = { "Captive": "var(--jb-blue)", "Prime Bank": "var(--jb-green)", "Credit Union": "var(--jb-amber)", "Subprime": "var(--jb-red)", "Buy-Here Pay-Here": "var(--jb-navy)", }; // RC27 (dsk): the lender's DEFAULT FEE (acquisition / bank / flat fee, discount points) — kept on the SERVER for every station (the lender book // itself is still this station's), suggested on the desk when the lender is picked on a finance / lease deal, editable per deal there. const bkFeeText = (f) => !f ? "" : ((window.DealCalc && window.DealCalc.LENDER_FEE_KINDS[f.kind]) || f.kind) + " " + (f.kind === "points" ? f.points + " pts" : "$" + ((+f.amountCents || 0) / 100).toFixed(2)) + (f.passed ? " · passed to customer" : " · store pays"); const BkFeeDefault = ({ name }) => { const D = window.DMS; const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => (D && D.subscribe) ? D.subscribe(force) : undefined, []); const cur = D && D.lenderFeeFor ? D.lenderFeeFor(name) : null; const seed = (c) => c ? { kind: c.kind, amount: c.amountCents ? (c.amountCents / 100).toFixed(2) : "", points: c.points != null ? String(c.points) : "", passed: !!c.passed } : { kind: "acquisition", amount: "", points: "", passed: false }; const [f, setF] = React.useState(() => seed(cur)); const curSig = JSON.stringify(cur || null); React.useEffect(() => { setF(seed(cur)); }, [curSig]); const [busy, setBusy] = React.useState(false); const may = !!(D && D.can && (D.can("fi") || D.can("acct"))); const kinds = (window.DealCalc && window.DealCalc.LENDER_FEE_KINDS) || { acquisition: "Acquisition fee", bank: "Bank fee", flat: "Flat fee", points: "Discount points" }; if (!String(name || "").trim()) return null; const save = async (remove) => { setBusy(true); const r = await D.saveLenderFee(remove ? { lender: name, remove: true } : { lender: name, kind: f.kind, amount: f.kind === "points" ? undefined : f.amount, points: f.kind === "points" ? f.points : undefined, passed: f.passed }); setBusy(false); window.k2bToast && window.k2bToast(r.msg || (r.ok ? "Saved." : "Not saved."), r.ok ? "ok" : "warn", 5200); }; return (
Lender fee default — suggested on the desk when {name} is picked (every station)
{cur ? "Now: " + bkFeeText(cur) : "No default fee for this lender."} A fee the store pays comes out of the front gross (desk › Show gross › Profit); switched to "passed to customer" it goes on the customer's fee line instead.
{f.kind === "points" ? : } {may && } {may && cur && } {!may && F&I and the office set lender fees.}
); }; const Banks = ({ onClose, go }) => { const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => window.jbLenders ? window.jbLenders.subscribe(force) : undefined, []); React.useEffect(() => { try { if (window.DMS && window.DMS.loadLenderFees) window.DMS.loadLenderFees(); } catch (e) {} return (window.DMS && window.DMS.subscribe) ? window.DMS.subscribe(force) : undefined; }, []); // RC27 (dsk) const list = window.jbLenders ? window.jbLenders.list() : []; const TYPES = window.jbLenders ? window.jbLenders.TYPES : []; const [edit, setEdit] = React.useState(null); // record being edited (or {} for new) const [filter, setFilter] = React.useState("All"); const blank = { name: "", short: "", type: "Prime Bank", active: true, buyRate: 6.49, sellRateCap: 8.49, reserveSplit: "70/30", flat: 0, acqFee: 0, minFico: 640, maxAdvance: 125, maxTermMo: 75, phone: "", contact: "", notes: "", addr: "", city: "", state: "", zip: "", role: "", parent: "" }; const filtered = filter === "All" ? list : list.filter(l => l.type === filter); const activeCount = list.filter(l => l.active).length; return (
{}} onMax={() => {}} />
{/* summary */}
{[["Lenders on book", list.length, "var(--jb-navy)"], ["Active", activeCount, "var(--jb-green)"], ["Subprime", list.filter(l => l.type === "Subprime").length, "var(--jb-red)"], ["Best buy rate", (Math.min(...list.filter(l => l.active).map(l => l.buyRate)) || 0).toFixed(2) + "%", "var(--jb-blue)"]].map(([lab, val, c], i) => (
{lab}
{val}
))}
{/* toolbar */}
Filter {["All", ...TYPES].map(t => ( ))}
{/* table */}
{["Lender", "Type", "Buy Rate", "Sell Cap", "Reserve", "Max Adv.", "Max Term", "Min FICO", "Contact", "Lender fee", ""].map((h, i) => ( ))} {filtered.map((l, i) => ( setEdit({ ...l })} style={{ background: i % 2 ? "var(--jb-surface-2)" : "#fff", cursor: "pointer", opacity: l.active ? 1 : 0.5 }}> ))} {filtered.length === 0 && }
= 2 && i <= 7 ? "right" : "left" }}>{h}
{l.name}
{l.short}{l.phone ? " · " + l.phone : ""}{l.addr ? " · " + [l.addr, [l.city, l.state].filter(Boolean).join(", "), l.zip].filter(Boolean).join(", ") : ""}
{l.type} {l.role &&
{l.role === "lease-lessor" ? "Lease Lessor / Titled Owner" : "Retail Lienholder"}
}
{l.buyRate.toFixed(2)}% {l.sellRateCap.toFixed(2)}% {l.reserveSplit}{l.flat ? " · " + bk$(l.flat) : ""} {l.maxAdvance}% {l.maxTermMo}mo {l.minFico} {l.contact} {window.DMS && window.DMS.lenderFeeFor ? bkFeeText(window.DMS.lenderFeeFor(l.name)) || "—" : "—"} {!l.active && inactive}
No lenders match this filter.
Click any row to edit. Active lenders appear in the Desking and Finance Worksheet lender menus.
{edit && setEdit(null)} onSave={(r) => { window.jbLenders.upsert(r); setEdit(null); window.k2bToast && window.k2bToast(`${r.name} saved.`, "ok"); }} onDelete={edit.id ? () => { window.jbLenders.remove(edit.id); setEdit(null); window.k2bToast && window.k2bToast("Lender removed.", "warn"); } : null} />}
); }; const BankEditor = ({ rec, TYPES, onClose, onSave, onDelete }) => { const [r, setR] = React.useState({ ...rec }); const set = (k, v) => setR(p => ({ ...p, [k]: v })); const valid = (r.name || "").trim().length > 0; return ( {onDelete && Delete} Cancel valid ? onSave(r) : window.k2bToast && window.k2bToast("Lender name is required.", "warn")}>Save }>
{r.role &&
Titling entity: auto-selected as the deal's {r.role === "lease-lessor" ? "lessor / titled owner on LEASE deals" : "lienholder on retail FINANCE deals"} whenever the funding lender is {r.parent || "its parent lender"}. Kept out of the Desking lender menu.
}