/* 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 — Funding. Tracks every POSTED deal to funded (ONE PATH: Posted → // Funded = DONE). Financed deals live in Contracts in Transit until the lender // pays — expected-vs-actual reconcile CODES any short-fund (bank fee, contract // error, product cancellation, holdback, write-off) before CIT can clear // (DMS.fundDealAmount). CASH deals were paid at delivery: no CIT, no JE — // "Fund" simply closes them out through window.jbFundDeal. const fwMoney = (n) => "$" + (Number(n) || 0).toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 0 }); const fwMoney2 = (n) => (n < 0 ? "-$" : "$") + Math.abs(Number(n) || 0).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); // "Sent for Funding" is what posting a financed / lease deal sets (DMS.postDeal). // "Not Submitted" stays only for legacy records. const FW_STATUSES = ["Sent for Funding", "Not Submitted", "Submitted", "Conditioned", "Missing Stips", "Approved to Fund", "Funded Short", "Funded Full", "Chargeback Risk", "Unwound"]; const FW_STIPS = ["Driver license", "Proof of income", "Proof of residence", "Insurance", "Signed contract", "Title app", "Trade documents", "Payoff authorization", "Bank approval", "Menu signed", "Products remitted"]; const fwDays = (iso) => iso ? Math.floor((Date.now() - new Date(iso)) / 86400000) : 0; // Legacy posted financed deals with no fundingStatus left the store at posting too. const fwStatus = (d) => d.fundingStatus || "Sent for Funding"; const fwSentDays = (d) => fwDays(d.sentForFundingAt || d.delivered); const fwDate = (iso) => iso ? new Date(iso).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : "—"; const fwIsCash = (d) => (+d.amtFinanced || 0) <= 0 || /cash/i.test(String(d.dealType || "")); const fwIsFunded = (d) => d.status === "Funded" || d.stage === "Funded" || ((window.DMS && window.DMS.dealStage) ? window.DMS.dealStage(d) === "Funded" : false); const FW_TONE = (d) => { if (/funded full/i.test(d.fundingStatus || "") || fwIsFunded(d)) return { bg: "#E6F7EC", fg: "#0E7A37" }; if (/funded short/i.test(d.fundingStatus || "")) return { bg: "#FBF3E0", fg: "#9A6700" }; if (/chargeback|unwound|missing/i.test(d.fundingStatus || "")) return { bg: "#FBE9E7", fg: "#B23A2E" }; if (/sent for funding/i.test(fwStatus(d))) return { bg: "var(--jb-navy, #11337A)", fg: "#FFF" }; return { bg: "var(--jb-blue-tint,#E5EFFA)", fg: "var(--jb-blue,#1B66A8)" }; }; // RC19 search chips on the posted-deals list (DealSearch.jsx.txt). "Aged" = the same rule as the "Aged > 14 days" tile. const fwThisMonth = (d) => { const t = Date.parse(d.delivered || d.created || ""); if (!isFinite(t)) return false; const a = new Date(t), n = new Date(); return a.getFullYear() === n.getFullYear() && a.getMonth() === n.getMonth(); }; const FW_SEARCH_CHIPS = [ { key: "unfunded", group: "fund", label: "Unfunded", test: (d) => !fwIsFunded(d) }, { key: "funded", group: "fund", label: "Funded", test: (d) => fwIsFunded(d) }, { key: "cash", group: "pay", label: "Cash", test: (d) => fwIsCash(d) }, { key: "financed", group: "pay", label: "Financed", test: (d) => !fwIsCash(d) }, { key: "aged", group: "aged", label: "Aged > 14 days", title: "Financed, not funded, delivered 14+ days ago (same as the tile above)", test: (d) => !fwIsFunded(d) && !fwIsCash(d) && fwDays(d.delivered) >= 14 }, { key: "month", group: "month", label: "This month", title: "Delivered this calendar month", test: fwThisMonth }, ]; const FundingWorkflow = ({ onClose, go }) => { const D = window.DMS; const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => (D && D.subscribe) ? D.subscribe(force) : undefined, []); const act = (r) => Promise.resolve(r).then(x => { window.k2bToast && window.k2bToast(x.msg, x.ok ? "ok" : "warn", 3600); return x; }); // RC33 (mpx): the deal's checks are SERVER commands (promises) // Every posted deal (cash AND financed); funded ones sort to the bottom. const deals = ((D && D.deals) ? D.deals().filter(d => d.postedToGL && d.status !== "Dead") : []) .slice().sort((a, b) => (fwIsFunded(a) ? 1 : 0) - (fwIsFunded(b) ? 1 : 0)); const pipeline = deals.filter(d => !fwIsFunded(d)); const [selId, setSelId] = React.useState(null); const [modal, setModal] = React.useState(null); React.useEffect(() => { if (selId && deals.find(d => d.id === selId)) return; if (pipeline[0]) setSelId(pipeline[0].id); else if (deals[0]) setSelId(deals[0].id); }, [deals.length]); const sel = deals.find(d => d.id === selId) || null; // RC19: one search box over the list (empty box = the list below exactly as before) const ds = dsUseDealSearch({ deals, chips: FW_SEARCH_CHIPS, selectedId: selId, onSelect: setSelId, onOpen: (d) => setSelId(d.id) }); // "In CIT" = financed deals only; cash deals have nothing in transit. const citTotal = pipeline.filter(d => !fwIsCash(d)).reduce((s, d) => s + (+d.amtFinanced || 0), 0); const cashCount = pipeline.filter(fwIsCash).length; const aged = pipeline.filter(d => !fwIsCash(d) && fwDays(d.delivered) >= 14).length; return (
{[["In CIT (financed, unfunded)", fwMoney(citTotal), "var(--jb-navy)"], ["Deals in pipeline", pipeline.length, "var(--jb-blue)"], ["Cash — awaiting close", cashCount, cashCount ? "var(--jb-green)" : "var(--jb-text-muted)"], ["Aged > 14 days", aged, aged ? "var(--k2b-maroon)" : "var(--jb-green)"]].map(([l, v, c], i) => (
{l}
{v}
))}
{deals.length > 0 && } {deals.length === 0 &&
No posted deals. Post a deal from the Cash Deal or Finance Deal screen to see it here.
} {ds.list.map(d => { const on = d.id === selId; const t = FW_TONE(d); const dd = fwDays(d.delivered); const funded = fwIsFunded(d); const cash = fwIsCash(d); return (
setSelId(d.id)} style={{ padding: "10px 14px", borderBottom: "1px solid var(--jb-border)", cursor: "pointer", background: on ? "var(--jb-blue-tint, #E5EFFA)" : "transparent", borderLeft: on ? "3px solid var(--jb-blue)" : "3px solid transparent", opacity: funded ? 0.7 : 1 }}>
{d.id} {cash && CASH}
{funded ? DONE ✓ : {cash ? "Paid at delivery" : `${fwStatus(d).toUpperCase()} · ${fwSentDays(d)}d`}}
{d.buyer}
{cash ? "Cash · " + fwMoney(d.cashDown) : (d.lender || "—") + " · " + fwMoney(d.amtFinanced)}
{!funded &&
= 14 ? "var(--k2b-maroon)" : "#999", marginTop: 2 }}>{d.delivered ? `delivered ${dd}d ago` : "not delivered"}{!cash && d.sentForFundingAt ? ` · sent ${fwDate(d.sentForFundingAt)}` : ""}{(d.adjustments || []).length ? ` · ${(d.adjustments || []).length} adj.` : ""}
}
); })}
{sel ? fwIsCash(sel) ? (window.jbFundDeal ? window.jbFundDeal(sel.id) : act({ ok: false, msg: "Ledger offline." })) : setModal({ type: "fund", deal: sel })} /> :
Select a deal.
}
ESC-Close go && go("deal")}>Deal Pipeline go && go("cashcommand")}>Cash Command go && go("accounting")}>General Ledger
{modal && modal.type === "fund" && setModal(null)} />}
); }; const FwDetail = ({ deal, act, go, onFund }) => { const D = window.DMS; const funded = fwIsFunded(deal); const cash = fwIsCash(deal); const check = deal.fundingCheck || {}; const doneCount = FW_STIPS.filter(s => check[s]).length; const stage = (D && D.dealStage) ? D.dealStage(deal) : (deal.stage || "Posted"); return (
{deal.id} {cash && CASH} {stage}
{deal.buyer}
{deal.vehicle} · {cash ? "no lender — paid in full" : (deal.lender || "no lender")}
{cash ? "Expected Funding" : "Expected Funding (CIT)"}
{cash ?
Cash — paid at delivery {fwMoney(deal.cashDown)}
:
{fwMoney(deal.amtFinanced)}
} {!cash && Array.isArray(deal.fundings) && (window.dcxLiveFundings ? window.dcxLiveFundings(deal).length > 0 : deal.fundings.some(f => f && f.kind === "lender")) && !funded && ( /* RC23 (corr): a reversed funding is not "partly funded" */
Partly funded — {fwMoney2(window.DMS.dealCitOpen ? window.DMS.dealCitOpen(deal) / 100 : 0)} still in transit
)}
{/* Big status line — financed / lease: where the contract is; cash: paid at delivery */} {!funded && (
{cash ? "CASH — paid at delivery" : (fwStatus(deal) === "Sent for Funding" ? "SENT OFF FOR FUNDING" : fwStatus(deal).toUpperCase())}
{cash ? `No lender — ${fwMoney(deal.cashDown)} collected${deal.delivered ? " on " + fwDate(deal.delivered) : ""}. Mark Funded to close it out.` : <>Sent off for funding to {deal.lender || "the lender"} on {fwDate(deal.sentForFundingAt || deal.delivered)} — expected {fwMoney2(deal.amtFinanced)} · {fwSentDays(deal)}d in transit}
{window.DealAdjustButton ? : null}
)} {/* RC23 (corr): Reverse funding (the office) — a funded deal is unwound only after its funding is reversed */} {window.DealCorrectButtons && window.dcxLiveFundings && window.dcxLiveFundings(deal).length > 0 && (
)} {funded && window.DealAdjustButton && (
)} {/* status pipeline — lender-facing; not applicable to a cash deal */} {!cash && (
Funding Status
{FW_STATUSES.filter(s => !/funded (short|full)/i.test(s) && (s !== "Not Submitted" || deal.fundingStatus === "Not Submitted")).map(s => ( ))}
)} {/* stip checklist */}
{cash ? "Delivery Checklist" : "Funding Checklist"}
{doneCount}/{FW_STIPS.length}
{FW_STIPS.map(s => ( ))}
{Array.isArray(deal.adjustments) && deal.adjustments.length > 0 && window.DealAdjustHistory && (
)} {deal.postedToGL && !deal.imported && } {funded ? (
DONE ✓ · {cash ? "Cash deal closed — paid in full" : (deal.fundingStatus || "Funded")}
{!cash && (
Expected{fwMoney2(deal.amtFinanced)} Received{fwMoney2(deal.fundedActual != null ? deal.fundedActual : deal.amtFinanced)} {Math.abs(deal.fundedDiff || 0) > 0.01 && <>Difference · {deal.fundedDiffReason}{fwMoney2(-(deal.fundedDiff || 0))}}
)}
) : ( )}
); }; // RC33 (mpx): the deal's own checks — the trade payoff (DR 303), the F&I product remittances (DR 302 / 302G) and a lender's over-funding paid // back (DR 331) — SERVER commands that write the check in the same step and keep the deal in step (a voided check reopens the amount). const FwDealChecks = ({ deal, act }) => { const D = window.DMS; if (!D || !D.dealPayoffCheck || !(D.can && D.can("acct"))) return null; const sumC = (l) => (Array.isArray(l) ? l : []).filter(x => x && !x.voided).reduce((t, x) => t + (+x.amountCents || 0), 0); const overLeft = Math.round((+deal.lenderOverpaid || 0) * 100) - sumC(deal.lenderRefunds); const payoffLeft = Math.round((+deal.tradePayoff || 0) * 100) - sumC(deal.payoffChecks); const ask = (q, d) => { const v = window.prompt(q, d || ""); return v === null ? null : String(v).trim(); }; const c2 = (c) => (c / 100).toFixed(2); return (
{payoffLeft > 0 && } {(+deal.vscSale || 0) + (+deal.gapSale || 0) > 0 && } {overLeft > 0 && }
); }; // RC21 (deals): the funding is recorded by the SERVER (POST /api/deals/fund): "Expected" = what is still in contracts in transit for the // deal; a short amount is either CODED (the CIT clears, the gap goes to the chosen account) or PARTIAL (the rest stays in transit — // the deal stays unfunded until the rest arrives). More than is in transit is refused (an overpayment is not booked here). const FW_PARTIAL = "__partial__"; const FwFundModal = ({ deal, act, onClose }) => { const expected = (window.DMS.dealCitOpen ? window.DMS.dealCitOpen(deal) / 100 : (+deal.amtFinanced || 0)); const [actual, setActual] = React.useState(String(expected.toFixed(2))); const [reason, setReason] = React.useState("Bank fee"); const [ref, setRef] = React.useState(""); const [busy, setBusy] = React.useState(false); const amt = parseFloat(String(actual).replace(/[^0-9.]/g, "")) || 0; const diff = +(expected - amt).toFixed(2); const needsReason = Math.abs(diff) > 0.01; const reasons = window.DMS.FUND_DIFF_ACCTS ? Object.keys(window.DMS.FUND_DIFF_ACCTS) : ["Bank fee", "Contract error", "Product cancellation", "Holdback", "Short fund"]; const submit = async () => { if (busy) return; setBusy(true); const over = diff < -0.01; // RC33 (mpx): the lender paid MORE than is in transit — the extra is held (331) for a refund to the lender const r = await window.DMS.fundDealAmount(deal.id, amt, needsReason && !over && reason !== FW_PARTIAL ? reason : null, { ref: ref.trim() || undefined, overpay: over ? "hold" : undefined }); setBusy(false); act(r); if (r.ok) onClose(); }; const inp = { width: "100%", boxSizing: "border-box", padding: "8px 10px", border: "1px solid #C8CCD2", borderRadius: 4, fontSize: 14, fontFamily: "var(--jb-mono)" }; return ( Cancel{busy ? "Posting…" : (needsReason && reason === FW_PARTIAL ? "Post Partial Funding" : "Post Funding (clear CIT)")}}>
Expected (CIT)
{fwMoney2(expected)}
Actual received
setActual(e.target.value.replace(/[^0-9.]/g, ""))} style={{ ...inp, background: "#FFFEF4" }} />
{diff > 0 ? "Funded SHORT by" : diff < 0 ? "Funded OVER by" : "Funds match"} {fwMoney2(Math.abs(diff))}
{diff < -0.01 && (
The lender paid {fwMoney2(-diff)} more than is in transit. Posting HOLDS the extra on 331 (owed back to the lender) — pay it back with “Refund lender over-funding” on this deal.
)} {needsReason && diff > 0.01 && ( )}
); }; Object.assign(window, { FundingWorkflow });