/* 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. */ // K2B DMS — Fixed Ops GL Posting (backend / accounting access). // Shows exactly how Service ROs and Parts activity hit the general ledger: // • Service tab — every RO with its ACTUAL posted journal entry (closed) // or a live PREVIEW of the entry closeRO will generate (open). // • Parts tab — every parts-sourced journal entry (counter sales PT-, // PO receipts AP-, count adjustments PI-, core returns CO-) + previews // for open POs. // • Posting map — the account templates each transaction type uses. const fo$ = (n) => (+n || 0).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const foAcctName = (acct) => { const a = String(acct); const coa = window.GM_COA || []; // GM_COA entries are arrays: ["202","Cash in Bank","A","Dr","Cash & Contracts"] const hit = coa.find(e => String(Array.isArray(e) ? e[0] : (e && (e.acct || e.num))) === a); if (hit) return Array.isArray(hit) ? (hit[1] || "") : (hit.name || hit.desc || ""); const fallback = { "999": "Labor applied / clearing", "300": "Accounts payable — trade", "483": "Parts — wholesale", "683": "Cost — parts wholesale", }; return fallback[a] || ""; }; /* One journal entry rendered as a DR/CR grid */ const FoJELines = ({ lines, preview }) => { const dr = lines.reduce((s, l) => s + (+l.dr || 0), 0); const cr = lines.reduce((s, l) => s + (+l.cr || 0), 0); return ( {lines.map((l, i) => ( ))}
Acct Account Memo DR CR
{l.acct} {foAcctName(l.acct)} {l.desc || ""} {l.dr ? fo$(l.dr) : ""} {l.cr ? "(" + fo$(l.cr) + ")" : ""}
{Math.abs(dr - cr) < 0.015 ? ✓ BALANCED : ⚠ OUT OF BALANCE {fo$(dr - cr)}} {preview && PREVIEW — posts when the document posts} {fo$(dr)} ({fo$(cr)})
); }; /* Rebuild closeRO's entry for an OPEN ro — RC20 (fops): the preview of the SERVER's close entry (DMS.roCloseLines = the shared FopsCalc map: payments to their payer accounts, the unpaid customer share to A/R 220, no cash plug). The old mirror below is only a fallback for a page without FopsCalc. */ function foPreviewRO(ro) { if (window.DMS && DMS.roCloseLines) { const pv = DMS.roCloseLines(ro.id); if (pv && Array.isArray(pv.lines)) return pv.lines; } const A = window.DMS_ACCT || {}; const isW = ro.payType === "Warranty", isI = ro.payType === "Internal"; const recv = isW ? A.warrantyRec : isI ? (ro.internalStock && ro.internalStock.startsWith("U") ? A.invUsedTruck : A.invUsedCar) : A.arCustomer; const gross = (+ro.laborSale || 0) + (+ro.partsSale || 0) + (+ro.tax || 0); const lines = [ { acct: recv, dr: gross, cr: 0, desc: isI ? "Internal — charge to vehicle" : "Receivable / cash" }, { acct: isW ? A.warrLabor : isI ? A.internalLabor : A.custLabor, dr: 0, cr: +ro.laborSale || 0, desc: "Labor sale" }, { acct: A.costLabor, dr: +ro.laborCost || 0, cr: 0, desc: "Cost of labor" }, ]; if (+ro.partsSale) { lines.push({ acct: A.partsCarRO, dr: 0, cr: +ro.partsSale, desc: "Parts on RO" }); lines.push({ acct: A.costPartsRO, dr: +ro.partsCost || 0, cr: 0, desc: "Cost of parts" }); lines.push({ acct: A.invParts, dr: 0, cr: +ro.partsCost || 0, desc: "Relieve parts inventory" }); } if (+ro.tax) lines.push({ acct: A.salesTaxPay, dr: 0, cr: +ro.tax, desc: "Sales tax payable" }); const dr = lines.reduce((s, l) => s + l.dr, 0), cr = lines.reduce((s, l) => s + l.cr, 0); const diff = +(dr - cr).toFixed(2); if (Math.abs(diff) > 0.01) lines.push({ acct: "999", dr: diff < 0 ? -diff : 0, cr: diff > 0 ? diff : 0, desc: "Labor applied / clearing" }); return lines; } const FO_MAP = [ { doc: "Service RO — Customer pay (jrn 30, ST-)", rows: [ ["DR", "arCustomer", "Receivable / cash — RO total"], ["CR", "custLabor", "Customer labor sale"], ["DR", "costLabor", "Cost of labor"], ["CR", "partsCarRO", "Parts on RO"], ["DR", "costPartsRO", "Cost of parts"], ["CR", "invParts", "Relieve parts inventory"], ["CR", "salesTaxPay", "Sales tax payable"], ["CR", "laborApplied", "Labor applied (offset to cost of labor)"], ["CR", "subletSale", "Sublet sale"], ["DR", "arCustomer", "Customer balance not paid at close → A/R (RC20: never cash)"]] }, { doc: "Service RO — Warranty (jrn 30, ST-)", rows: [ ["DR", "warrantyRec", "Warranty receivable (claim filed on close)"], ["CR", "warrLabor", "Warranty labor sale"], ["DR", "costLabor", "Cost of labor"], ["CR", "partsCarRO", "Parts on RO"]] }, { doc: "Service RO — Internal / recon (jrn 30, ST-)", rows: [ ["DR", "invUsedCar", "Charge to vehicle (adds recon to unit cost)"], ["CR", "internalLabor", "Internal labor sale"], ["DR", "costLabor", "Cost of labor"], ["CR", "partsCarRO", "Parts on RO"]] }, { doc: "Parts counter sale (jrn 35, PT-)", rows: [ ["DR", "cashOnHand", "Cash / till — sale + tax"], ["CR", "partsCounter", "Counter parts sale (483 wholesale)"], ["DR", "costPartsCounter", "Cost of parts (683 wholesale)"], ["CR", "invParts", "Relieve parts inventory"], ["CR", "salesTaxPay", "Sales tax payable (retail only)"]] }, { doc: "Receive purchase order (jrn 75, AP-)", rows: [ ["DR", "invParts", "Parts into inventory at cost"], ["CR", "300*", "Accounts payable — vendor"]] }, { doc: "Physical count adjustment (jrn 80, PI-)", rows: [ ["DR/CR", "invParts", "Inventory up/down by variance × cost"], ["CR/DR", "costPartsCounter", "Offset to cost of sales"]] }, { doc: "Core return credit (jrn 75, CO-)", rows: [ ["DR", "300*", "Vendor credit received"], ["CR", "invParts", "Core out of inventory"]] }, ]; const FixedOpsGL = ({ onClose, go }) => { const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => (window.DMS && window.DMS.subscribe) ? window.DMS.subscribe(force) : undefined, []); const [tab, setTab] = React.useState("service"); const [open, setOpen] = React.useState({}); const toggle = (k) => setOpen(o => ({ ...o, [k]: !o[k] })); const D = window.DMS; const ros = D ? D.repairOrders() : []; const jes = D ? D.journalEntries() : []; const jeById = {}; jes.forEach(j => { jeById[j.id] = j; }); const partsJEs = jes.filter(j => j.src === "Parts"); const openPOs = D ? (D.partsOrders() || []).filter(p => p.status === "Open") : []; const A = window.DMS_ACCT || {}; const tabBtn = (k, label) => ( ); const rowHead = { padding: "3px 8px", textAlign: "left", fontSize: 11, color: "var(--k2b-maroon)", borderBottom: "1px solid var(--jb-border)", whiteSpace: "nowrap" }; const cell = { padding: "3px 8px", fontSize: 12 }; return (
{tabBtn("service", "Service ROs → GL")} {tabBtn("parts", "Parts Activity → GL")} {tabBtn("map", "Posting Map")} INTERNAL — ACCOUNTING ACCESS go && go("accounting")}>GL Inquiry ▸
{tab === "service" && ( {ros.length === 0 && } {ros.map((ro) => { const stId = ro.id.replace("RO", "ST"); const je = jeById[stId]; const posted = ro.postedToGL && je; const k = "ro-" + ro.id; return ( toggle(k)} style={{ cursor: "pointer", borderBottom: "1px solid #EEE", background: open[k] ? "var(--jb-blue-tint, #E8F0FB)" : "#FFF" }}> {open[k] && ( )} ); })}
ROCustomerPay Type Labor Parts Total GL DocStatus
No repair orders on file.
{open[k] ? "▾" : "▸"} {ro.id} {ro.customer} {ro.payType} {fo$(ro.laborSale)} {fo$(ro.partsSale)} {fo$((+ro.laborSale || 0) + (+ro.partsSale || 0) + (+ro.tax || 0))} {posted ? stId : "—"} {posted ? "POSTED" : ro.status === "Open" ? "OPEN — preview" : "CLOSED (pre-ledger)"} {!posted && ro.status === "Open" && ( { e.stopPropagation(); const r = await D.closeRO(ro.id); // RC20 (fops): the server command; the toast is the committed answer window.k2bToast && window.k2bToast(r.msg, r.ok ? "ok" : "warn", 4000); }}>Close & Post )}
{posted ? : ro.status === "Open" ? :
Closed before the ledger existed — no JE on file.
}
)} {tab === "parts" && (
{partsJEs.length === 0 && } {partsJEs.map((j) => { const k = "je-" + j.id; const amt = (j.lines || []).reduce((s, l) => s + (+l.dr || 0), 0); return ( toggle(k)} style={{ cursor: "pointer", borderBottom: "1px solid #EEE", background: open[k] ? "var(--jb-blue-tint, #E8F0FB)" : "#FFF" }}> {open[k] && } ); })}
JEDateJrn DescriptionAmount
No parts journal entries yet — post a counter ticket, receive a PO, or run a count adjustment and it appears here instantly.
{open[k] ? "▾" : "▸"} {j.id} {j.date} {j.jrn} {j.desc} {fo$(amt)} {j.id.startsWith("PT") ? "counter sale" : j.id.startsWith("AP") ? "PO receipt" : j.id.startsWith("PI") ? "count adj" : j.id.startsWith("CO") ? "core return" : ""}
{openPOs.length > 0 && (
Open purchase orders — entry that will post on receipt
{openPOs.map(po => { const total = +(po.lines || []).reduce((s, l) => s + (+l.qty || 0) * (+l.cost || 0), 0).toFixed(2); return (
{po.po} — {po.vendor} ({po.type})
); })}
)}
)} {tab === "map" && (
{FO_MAP.map((m) => (
{m.doc}
{m.rows.map(([side, key, memo], i) => { const acct = A[key] || key.replace("*", ""); return ( ); })}
{side} {acct} {memo}
))}
* 999 = labor applied / WIP clearing (relieved at payroll) · 300 = vendor accounts payable. Vehicle-deal posting (jrn 20/70/71/80) is shown in Deals → Post to GL and GL Inquiry.
)}
); }; Object.assign(window, { FixedOpsGL });