/* 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 — WE-OWES (due bills) — RC27 (lane dsk; owner decision 3 of 2026-10-19). // A deal's "we owe" lines (desk › Show gross › 💲 Profit) print a DUE BILL with the deal documents and, when the deal POSTS, // go on this list (the server's — routes/we-owes.js). Sales & F&I and Service see it; Service opens an INTERNAL RO from a // we-owe (the RO links back) and closing that RO marks it DONE with the actual cost next to the estimate. The money // (estimate / actual) only shows for the roles that see deal cost — the server never sends it to the others. // Every change is a server command (one Idempotency-Key each — a double click or a retry never does it twice). const wo$ = (c) => (c === null || c === undefined) ? "—" : (c < 0 ? "−$" : "$") + (Math.abs(+c || 0) / 100).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const WO_STATUS = { open: ["Open", "var(--jb-red)"], scheduled: ["Scheduled", "var(--jb-amber, #A66B00)"], done: ["Done", "var(--jb-green)"], voided: ["Voided", "var(--jb-text-muted)"] }; const WeOwes = ({ onClose, go }) => { const D = window.DMS; const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => (D && D.subscribe) ? D.subscribe(force) : undefined, []); const [filter, setFilter] = React.useState(() => { try { return localStorage.getItem("jb_weowes_filter") || "open"; } catch (e) { return "open"; } }); const [act, setAct] = React.useState(null); // { id, kind: "schedule" | "done" | "void", version } const [form, setForm] = React.useState({}); const [busy, setBusy] = React.useState(false); const [q, setQ] = React.useState(""); const load = (st) => D && D.loadWeOwes && D.loadWeOwes(st || filter); React.useEffect(() => { load(filter); try { localStorage.setItem("jb_weowes_filter", filter); } catch (e) {} }, [filter]); const cache = D && D.weOwesCached ? D.weOwesCached() : { list: [], may: null }; const may = cache.may || {}; const qq = q.trim().toLowerCase(); const list = (cache.list || []).filter(w => !qq || [w.item, w.customer, w.dealId, w.stock, w.vin, w.roId, w.salesperson].some(v => String(v || "").toLowerCase().includes(qq)) || (window.DMS && window.DMS.custQueryHit ? window.DMS.custQueryHit(qq, w.custNum) : false)); // RC31 (fx31, F6) const toast = (m, k) => window.k2bToast && window.k2bToast(m, k || "ok", 5200); const run = async (fn) => { setBusy(true); try { const r = await fn(); toast(r.msg || (r.ok ? "Done." : "Not done."), r.ok ? "ok" : "warn"); if (r.ok) { setAct(null); setForm({}); } return r; } finally { setBusy(false); } }; const openRo = (w) => run(async () => { const r = await D.weOweOpenRo(w.id, { version: w.version }); if (r.ok && r.roId) { try { localStorage.setItem("jb_ro_focus", r.roId); } catch (e) {} window.jbROFocus = r.roId; } return r; }); const goRo = (roId) => { try { localStorage.setItem("jb_ro_focus", roId); } catch (e) {} window.jbROFocus = roId; go && go("service"); }; const printBill = (w) => { const d = D && D.deals ? (D.deals() || []).find(x => x && x.id === w.dealId) : null; window.k2bPrintDueBill && window.k2bPrintDueBill(Object.assign({ id: w.dealId, buyer: w.customer, vehicle: w.vehicle, stock: w.stock, vin: w.vin }, d ? { buyer: d.buyer, street: d.street, city: d.city, state: d.state, zip: d.zip || d.postal, phone: d.phone } : {}, { weOwes: [w] })); }; const confirm = () => { const w = (cache.list || []).find(x => x.id === act.id); if (!w) return; if (act.kind === "schedule") return run(() => D.weOweSetStatus(w.id, "scheduled", { scheduledFor: form.date || "", note: form.note || "", version: w.version })); if (act.kind === "open") return run(() => D.weOweSetStatus(w.id, "open", { note: form.note || "", version: w.version })); if (act.kind === "done") return run(() => D.weOweSetStatus(w.id, "done", { note: form.note || "", actual: may.seeCost ? form.actual : undefined, version: w.version })); if (act.kind === "void") return run(() => D.weOweVoid(w.id, form.reason || "", { version: w.version })); }; const th = { padding: "7px 9px", fontWeight: 600, textAlign: "left", whiteSpace: "nowrap" }; const td = { padding: "7px 9px", verticalAlign: "top" }; return (
{}} onMax={() => {}} />
{[["open", "Open"], ["done", "Done"], ["voided", "Voided"], ["all", "All"]].map(([k, lab]) => ( ))} setQ(e.target.value)} placeholder="Find: customer, item, deal, stock #, VIN, RO" aria-label="Find a we-owe" style={{ flex: "1 1 220px", maxWidth: 360, fontSize: 13, height: 28, padding: "0 8px" }} />
{may.seeCost && cache.openEstimateCents != null && filter === "open" ? Set aside for the open ones: {wo$(cache.openEstimateCents)} : null}
{cache.msg ?
{cache.msg}
: null}
{may.seeCost ? <> : null} {list.map((w, i) => { const st = WO_STATUS[w.status] || [w.status, "#555"]; const live = w.status === "open" || w.status === "scheduled"; return ( {may.seeCost ? <> : null} {act && act.id === w.id ? ( ) : null} ); })} {!list.length ? : null}
Item owedCustomer · dealVehicleStatusRepair orderEstimateActualDifference
{w.item}
{w.id}
{w.note ?
{w.note}
: null}
{w.customer}
{w.dealId}{w.salesperson ? " · " + w.salesperson : ""}
{w.vehicle}
Stk {w.stock}{w.vin ? " · " + w.vin : ""}
{st[0]}{w.scheduledFor ?
for {w.scheduledFor}
: null}{w.status === "voided" && w.voidReason ?
{w.voidReason}
: null}
{w.roId ? : "—"}{wo$(w.estimateCents)} {wo$(w.actualCents)} 0 ? "var(--jb-red)" : w.diffCents < 0 ? "var(--jb-green)" : undefined }} data-wo="diff">{w.diffCents === null || w.diffCents === undefined ? "—" : (w.diffCents > 0 ? "+" : "") + wo$(w.diffCents)} {live && may.work && !w.roId ? : null} {live && may.work ? : null} {live && may.work ? : null} {live && may.void ? : null}
{act.kind === "schedule" ? "Schedule" : act.kind === "open" ? "Back to open" : act.kind === "done" ? "Mark done" : "Void"} — {w.item} {act.kind === "schedule" ? : null} {act.kind === "void" ? setForm(f => ({ ...f, reason: e.target.value }))} style={{ flex: "1 1 260px", height: 26 }} /> : setForm(f => ({ ...f, note: e.target.value }))} style={{ flex: "1 1 260px", height: 26 }} />} {act.kind === "done" && may.seeCost ? : null}
{act.kind === "done" && w.roId ?
{w.roId} is linked — closing it marks this done with the RO's internal total as the actual cost. Mark it done here only if the work was done somewhere else.
: null} {act.kind === "void" ?
The office only. The estimated cost set aside when the deal posted is taken back; the deal's posted figures and the commission are not refigured.
: null}
{filter === "open" ? "Nothing owed right now — no open we-owes." : "No we-owes match."}
A we-owe line on the desk (Show gross › 💲 Profit) prints a due bill with the deal documents and comes onto this list when the deal is posted. Service opens an internal RO from it; closing that RO marks it done{may.seeCost ? " and shows the actual cost next to the estimate (the difference is booked to the deal's cost account)" : ""}.
); }; Object.assign(window, { WeOwes });