/* © 2026 K2B NETWORK SOLUTIONS LLC. All rights reserved. */ /* eslint-disable */ // MoneyCore — RC33 (lane mpx): the station side of the remaining money paths, now SERVER commands. // // Until RC33 this station did these itself as two saves (the record + a journal entry its role may not write, numbered from the clock): // a stock-in and a unit cost adjustment, a floorplan payoff, a warranty claim's payment / chargeback, a factory incentive receipt, // A/R charges / payments / memos / finance charges, a vendor bill and its payment, a tax deposit, the payroll posting. Each one is now // ONE server command (routes/money.js, money-office.js, money-fops.js): this file sends it with an Idempotency-Key, asks the server what // became of the key when the connection drops (GET /api/money/op/), shows success ONLY from the committed answer and takes the // server's records back. Nothing here writes a journal entry or a money mark by itself. // // Loaded after DMSCore.jsx.txt and ServiceCore.jsx.txt (index.html); it REPLACES DMSCore's old bodies (which are one-line stubs now — // DMSCore stays under the in-browser compiler's 500,000-character comfort limit). Every function returns a Promise of // { ok, msg, key, res? } — the screens await it. (function () { const D = window.DMS; if (!D || !D._command) return; const OP = "/money/op/"; const offline = () => !!(D.isOnline && !D.isOnline()); const refresh = () => { try { D._mutate(() => {}); } catch (e) { /* nothing to redraw */ } }; const m2 = (c) => "$" + (Math.abs(+c || 0) / 100).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const amt = (v) => (v === undefined || v === null || v === "" ? undefined : String(v).replace(/[$,\s]/g, "")); const read = (fn) => (D._read ? D._read(fn) : null); /** send one money command; the answer is the server's (committed / refused / unknown) */ async function money(path, body, prefix, what, opts) { const o = opts || {}; if (offline()) return { ok: false, msg: `${what} posts to the books, which needs the server. Connect to the server, then try again. Nothing was changed.` }; const key = o.key || D._newIdemKey(prefix); const r = await D._command(path, body, key, OP); if (!r.ok) { const e = r.err; const b = (e && e.body) || {}; if (r.unknown) return { ok: false, unknown: true, key, msg: `The server did not answer. Before trying ${what} again, look at the record (it may already be done) — the office can look up ${key}.` }; if (b.reload && e && e.status === 409) { /* an older copy of this page: the server's words say which button to use */ } if (e && e.status === 426) return { ok: false, key, reload: true, msg: b.error || "This station is running an older DMS. Reload the DMS (Ctrl+F5)." }; return { ok: false, key, code: b.code, status: e && e.status, body: b, msg: b.error || (e && e.message) || `The server refused ${what}. Nothing was changed.` }; } D._applyServerRecords(r.res.records || []); if (o.after) { try { o.after(r.res); } catch (err) { /* the screen redraws anyway */ } } refresh(); try { D._audit(o.audit || "Money command", `${what} — ${r.res.message || "committed"}${r.recovered ? " (answer recovered after a dropped connection)" : ""}`); } catch (err) { /* audit is best effort */ } const w = Array.isArray(r.res.warnings) && r.res.warnings.length ? " ⚠ " + r.res.warnings.join(" ") : ""; return Object.assign({}, r.res, { ok: true, key, recovered: !!r.recovered, res: r.res, msg: (r.res.message || "Done.") + w }); } /* ═══ B1 stock-in / B2 cost adjustment ═══ */ const EXTRA = ["trim", "description", "lot", "keyTag", "extColor", "intColor", "engine", "trans", "drive", "fuel", "notes", "msrp"]; function stockInVehicle(u) { u = u || {}; if (!u.stock) return Promise.resolve({ ok: false, msg: "Stock # is required." }); const extra = {}; EXTRA.forEach(k => { if (u[k] !== undefined && u[k] !== null && u[k] !== "") extra[k] = u[k]; }); const body = { stock: String(u.stock).toUpperCase().trim(), vin: String(u.vin || "").toUpperCase().trim(), yr: u.yr || undefined, mk: u.mk || undefined, mdl: u.mdl || "", body: u.body || "", color: u.color || "", miles: u.miles === undefined || u.miles === "" ? undefined : String(u.miles), type: u.type || "N", cost: amt(u.cost) || "0", floorAmt: amt(u.floorAmt), floorLender: u.floorLender || "", asking: amt(u.asking !== undefined ? u.asking : u.list), pack: amt(u.pack), recon: amt(u.recon), extra: Object.keys(extra).length ? extra : undefined }; return money("/inventory/stock-in", body, "si", "the stock-in of " + body.stock, { audit: "Vehicle Stocked In" }).then(r => r.ok ? Object.assign(r, { id: r.jeId, lines: r.lines }) : r); } function postUnitCostAdjustment(stockOrVin, offsetAcct, reason, newCost) { const u = D._unit ? D._unit(stockOrVin) : null; const stock = u ? u.stock : stockOrVin; if (!reason || !String(reason).trim()) return Promise.resolve({ ok: false, msg: "A reason is required." }); if (!offsetAcct) return Promise.resolve({ ok: false, msg: "Pick the offsetting account." }); return money("/inventory/cost-adjust", { stock, offsetAcct: String(offsetAcct), reason: String(reason).trim(), newCost: amt(newCost) }, "uc", "the cost adjustment of " + stock, { audit: "Unit Cost Adjusted" }) .then(r => r.ok ? Object.assign(r, { id: r.jeId, delta: r.delta }) : r); } /* ═══ B3 floorplan payoff / B5 factory + holdback receipt ═══ */ function payoffFloorplan(stock, opts) { const o = opts || {}; const body = { stock, method: o.method || (o.ref ? "ach" : "check"), ref: o.ref || undefined, amount: amt(o.amount), bankId: o.bankId || undefined, payee: o.payee || undefined, diffReason: o.diffReason || undefined, date: o.date || undefined }; return money("/deals/floorplan/payoff", body, "fpp", "the floorplan payoff of " + stock, { audit: "Floorplan Paid Off" }); } function receiveFactoryIncentive(deal, opts) { const o = opts || {}; const r0 = read(st => (st.factoryReceivables || []).find(x => (x.deal === deal || x.id === deal) && !x.cancelled && !(+x.received >= +x.claimed))); const body = { receivableId: r0 ? r0.id : undefined, dealId: r0 ? undefined : deal, amount: amt(o.amount), ref: o.ref || undefined, date: o.date || undefined, closeShort: o.closeShort === true ? true : undefined, diffAcct: o.diffAcct || undefined }; return money("/deals/factory/receive", body, "frc", "the factory receipt on " + deal, { audit: "Factory Incentive Received" }); } function receiveHoldback(dealId, amount, opts) { const o = opts || {}; return money("/deals/factory/receive", { kind: "holdback", dealId, amount: amt(amount), ref: o.ref || undefined, date: o.date || undefined }, "hbr", "the holdback receipt on " + dealId, { audit: "Lender Holdback Received" }); } /* ═══ B4 warranty claims ═══ */ const claimOf = (claimId) => read(st => (st.warrantyReceivables || []).find(x => x.claim === claimId && !x.voided)) || null; function payWarrantyClaim(claimId, opts) { const o = opts || {}; const w = claimOf(claimId); if (w && !w.submitted && !/^(submitted|authorized)$/i.test(String(w.status || ""))) return Promise.resolve({ ok: false, msg: "Submit the claim before it can be paid." }); return money("/fixedops/warranty/pay", { receivableId: w ? (w.id || w.ro) : undefined, claimId, amount: amt(o.amount), ref: o.ref || undefined, diffReason: o.diffReason || undefined, chargebacks: Array.isArray(o.chargebacks) && o.chargebacks.length ? o.chargebacks : undefined, date: o.date || undefined }, "wrp", "the payment of claim " + claimId, { audit: "Warranty Claim Paid" }); } function debitWarrantyClaim(claimId, code, opts) { const o = opts || {}; const w = claimOf(claimId); return money("/fixedops/warranty/debit", { receivableId: w ? (w.id || w.ro) : undefined, claimId, code: code || "95", amount: amt(o.amount), reason: o.reason || undefined }, "wrd", "the chargeback of claim " + claimId, { audit: "Warranty Claim Debited" }); } /* ═══ B6 A/R ═══ */ function arPostCharge(acct, f) { f = f || {}; return money("/ar/charge", { acct, amount: amt(f.amount), ref: f.ref || undefined, desc: f.desc || undefined, taxCode: f.taxCode || undefined, offsetAcct: f.offsetAcct || undefined }, "arc", "the charge to " + acct, { audit: "AR Charge" }); } function arTakePayment(acct, f) { f = f || {}; return money("/ar/payment", { acct, amount: amt(f.amount), method: f.method || "Check", ref: f.ref || undefined }, "arp", "the payment on " + acct, { audit: "AR Payment" }); } function arAdjust(acct, f) { f = f || {}; return money("/ar/adjust", { acct, amount: amt(f.amount), isCredit: !!f.isCredit, desc: f.desc || f.reason || undefined, offsetAcct: f.offsetAcct || undefined }, "ara", "the memo on " + acct, { audit: "AR Memo" }); } function arAssessFinanceCharges(asOf) { return money("/ar/finance-charges", { asOf: asOf || undefined }, "arf", "the finance-charge run", { audit: "AR Finance Charges" }); } function arRefundCredit(acct, f) { f = f || {}; return money("/ar/refund", { acct, amount: amt(f.amount), method: f.method || "check", bankId: f.bankId || undefined, payee: f.payee || undefined, memo: f.memo || undefined, reason: f.reason || "" }, "arr", "the refund of " + acct + "'s credit", { audit: "AR Credit Refunded" }); } /* ═══ B7 vendor bills ═══ */ function addPayable(rec) { rec = rec || {}; return money("/ap/bill", { vendor: rec.vendor || "", vendorId: rec.vendorId || undefined, inv: rec.inv || "", amount: amt(rec.amount), acct: rec.acct || undefined, lines: Array.isArray(rec.lines) && rec.lines.length ? rec.lines : undefined, due: rec.due || undefined, date: rec.date || undefined, desc: rec.desc || undefined }, "apb", "the bill " + (rec.inv || ""), { audit: "AP Bill Entered" }); } /** opts.method: "check" (default — Check Writing writes the check; the number is the server's) | "ach" | "card" | "wire" (opts.ref = the confirmation) */ async function payInvoice(inv, opts) { const o = opts || {}; const p = read(st => (st.payables || []).find(x => x.inv === inv && String(x.status || "Open") === "Open" && x.kind !== "credit")) || null; if (!p) return { ok: false, msg: "Open payable not found." }; const open = Math.max(0, Math.round((+p.amount || 0) * 100) - Math.round((+p.paidAmount || 0) * 100)); if ((o.method || "check") === "check") { if (!D.postCheck) return { ok: false, msg: "Check Writing is not available on this page — reload the DMS (Ctrl+F5)." }; const r = await D.postCheck({ payee: p.vendor, vendorId: p.vendorId || "", amount: (open / 100).toFixed(2), acct: "300", inv: p.inv, memo: "Invoice " + p.inv, bankId: o.bankId || undefined }); return r; } return money("/ap/pay", { billId: p.id, amount: amt(o.amount), method: o.method, ref: o.ref || "", bankId: o.bankId || undefined, partial: o.partial === true ? true : undefined }, "app", "the payment of bill " + inv, { audit: "AP Bill Paid" }); } /* ═══ B8 tax deposits ═══ */ async function loadTaxDeposits() { try { const r = await D._apiGet("/tax/deposits"); if (r && Array.isArray(r.deposits)) { D._mutate(st => { st.taxDeposits = r.deposits; }); return r.deposits; } } catch (e) { /* the office reads it; others see the screen empty */ } return null; } function payTaxDeposit(o) { o = o || {}; const kind = /^fed/i.test(String(o.kind || "")) ? "federal" : /^sales/i.test(String(o.kind || "")) ? "sales" : "state"; return money("/tax/deposit", { kind, period: o.period || "", amount: amt(o.amount), method: o.method || "eft", ref: o.ref || o.confirmation || "", bankId: o.bankId || undefined, payee: o.payee || undefined, breakdown: o.breakdown || undefined, memo: o.memo || undefined, date: o.date || undefined }, "td", "the " + kind + " tax deposit", { audit: "Tax Deposit", after: () => { loadTaxDeposits(); } }).then(r => r.ok ? Object.assign(r, { id: r.jeId }) : r); } function voidTaxDeposit(moveId, reason) { return money("/tax/deposit/void", { moveId, reason: reason || "" }, "tdv", "the void of tax deposit " + moveId, { audit: "Tax Deposit Voided", after: () => { loadTaxDeposits(); } }); } /* ═══ B9 payroll ═══ */ function postPayroll(o) { o = o || {}; return money("/payroll/post", { payDate: o.payDate || undefined, period: o.period || undefined, bankId: o.bankId || undefined, employees: o.employees || [], commissionIds: o.commissionIds || undefined, chargebackIds: o.chargebackIds || undefined }, "prl", "the payroll", { audit: "Payroll Posted" }); } function reversePayroll(runId, reason) { return money("/payroll/reverse", { runId, reason: reason || "" }, "prv", "the un-post of payroll " + runId, { audit: "Payroll Un-posted" }); } async function payrollRuns() { try { const r = await D._apiGet("/payroll/runs"); return (r && r.runs) || []; } catch (e) { return []; } } /* ═══ B10 body-shop money after the close ═══ */ function bodyShopPayment(jobId, p) { p = p || {}; return money("/fixedops/bodyshop/payment", { jobId, method: p.method, amount: amt(p.amount), ref: p.ref || undefined, drawerRef: p.drawerRef || undefined, last4: p.last4 || undefined, insurer: p.insurer || undefined, date: p.date || undefined }, "bsp", "the payment on " + jobId, { audit: "Body Shop Payment" }); } function voidBodyShopPayment(jobId, receiptNo, reason) { return money("/fixedops/bodyshop/void", { jobId, receiptNo, reason: reason || "" }, "bsv", "the void of " + receiptNo, { audit: "Body Shop Payment Void" }); } function refundBodyShopPayment(jobId, receiptNo, amount, method, reason, bankId) { return money("/fixedops/bodyshop/refund", { jobId, receiptNo, amount: amt(amount), method: method || "cash", reason: reason || "", bankId: bankId || undefined }, "bsr", "the refund of " + receiptNo, { audit: "Body Shop Refund" }); } /* ═══ B11 / B12 / B13 deals ═══ */ function dealPayoffCheck(dealId, o) { o = o || {}; return money("/deals/payoff-check", { dealId, payee: o.payee || "", amount: amt(o.amount), bankId: o.bankId || undefined, memo: o.memo || undefined, date: o.date || undefined }, "dpc", "the payoff check of " + dealId, { audit: "Trade Payoff Check" }); } function dealRemit(dealId, o) { o = o || {}; return money("/deals/remit", { dealId, payable: o.payable || "302", payee: o.payee || "", amount: amt(o.amount), bankId: o.bankId || undefined, memo: o.memo || undefined }, "drm", "the remittance of " + dealId, { audit: "F&I Remittance Check" }); } function lenderRefund(dealId, o) { o = o || {}; return money("/deals/lender-refund", { dealId, amount: amt(o.amount), method: o.method || "check", bankId: o.bankId || undefined, ref: o.ref || undefined, reason: o.reason || "", payee: o.payee || undefined }, "lrf", "the lender refund of " + dealId, { audit: "Lender Refund" }); } const dealRev = async (dealId) => { const s = D._fopsSaveFirst ? await D._fopsSaveFirst("deals", dealId) : null; return s && s.ok ? s.rev : undefined; }; // the deal's version on the server (its last save first) async function adjustPostedDeal(dealId, patch, reason) { if (!reason || !String(reason).trim()) return { ok: false, msg: "Give a reason for the correction (it goes on the deal's history and the audit trail)." }; return money("/deals/correct", { dealId, baseRev: await dealRev(dealId), patch: patch || {}, reason: String(reason).trim() }, "dcx", "the correction of " + dealId, { audit: "Deal Corrected" }); } async function correctDealPreview(dealId, patch, reason) { try { return await D._apiPost("/deals/correct/preview", { dealId, baseRev: await dealRev(dealId), patch: patch || {}, reason: String(reason || "preview").trim() || "preview" }); } catch (e) { const b = (e && e.body) || {}; return { ok: false, msg: b.error || (e && e.message) || "The preview could not be made." }; } } /* ═══ B15 special-order deposits / B16 core credit ═══ */ function specialOrderDeposit(o) { o = o || {}; return money("/parts/special-order/deposit", { custNum: o.custNum || "", partNo: o.partNo || undefined, soId: o.soId || undefined, amount: amt(o.amount), method: o.method || "cash", ref: o.ref || undefined, note: o.note || undefined }, "sod", "the special-order deposit", { audit: "Special Order Deposit" }); } function refundSpecialOrderDeposit(depositId, o) { o = o || {}; return money("/parts/special-order/deposit/refund", { depositId, amount: amt(o.amount), method: o.method || "cash", reason: o.reason || "", bankId: o.bankId || undefined }, "sor", "the refund of deposit " + depositId, { audit: "Special Order Deposit Refunded" }); } async function specialOrderDeposits(custNum) { try { const r = await D._apiGet("/parts/special-order/deposits" + (custNum ? "?custNum=" + encodeURIComponent(custNum) : "")); return (r && r.deposits) || []; } catch (e) { return []; } } const creditCore0 = D.creditCore; /** opts.amount: what the vendor credited (less than the core charge → a core loss with opts.reason; 0 → rejected) */ function creditCore(id, opts) { const o = opts || {}; if (o.amount === undefined || o.amount === null || o.amount === "") return creditCore0 ? creditCore0(id) : Promise.resolve({ ok: false, msg: "Reload the DMS (Ctrl+F5)." }); const c = D._coreOf ? D._coreOf(id) : null; if (!c) return Promise.resolve({ ok: false, msg: "Core not found." }); return D._partsCommand("/parts/cores/credit", { coreId: c.id, amount: amt(o.amount), reason: o.reason || "" }, "cog", "core " + c.id); } Object.assign(window.DMS, { _moneyCommand: money, MONEY_CORE: true, stockInVehicle, postUnitCostAdjustment, payoffFloorplan, receiveFactoryIncentive, receiveHoldback, payWarrantyClaim, debitWarrantyClaim, arPostCharge, arTakePayment, arAdjust, arAssessFinanceCharges, arRefundCredit, addPayable, payInvoice, payTaxDeposit, voidTaxDeposit, loadTaxDeposits, postPayroll, reversePayroll, payrollRuns, bodyShopPayment, voidBodyShopPayment, refundBodyShopPayment, dealPayoffCheck, dealRemit, lenderRefund, adjustPostedDeal, correctDealPreview, specialOrderDeposit, refundSpecialOrderDeposit, specialOrderDeposits, creditCore, }); })();