/* 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 — Payroll Tax Center. // RC36 (sec36): the employee list comes from the SERVER (GET /api/payroll/employees — office only, every store its own list; the SSNs // are encrypted there and only their last 4 digits come to this screen; a W-2 print asks for that one employee's full SSN and address, // which the server records): employee master + the 'Import employees' button (CSV / Excel, templates/csv/Payroll_Employees.csv), the // "Pay Taxes" deposit flow (federal 941 / MO state withholding → posts to GL), // and form-ready generators for 941, W-2, and 8300. SSNs masked on screen. const pt$ = (n) => (+n || 0).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const ptMaskSSN = (s) => { const d = String(s || "").replace(/\D/g, "").padStart(9, "•"); return "•••-••-" + d.slice(-4); }; const ptFullSSN = (s) => { const d = String(s || "").replace(/\D/g, "").padStart(9, "0"); return d.slice(0,3)+"-"+d.slice(3,5)+"-"+d.slice(5); }; const ptEIN = (s) => { const d = String(s || "").replace(/\D/g, "").padStart(9, "0"); return d.slice(0,2)+"-"+d.slice(2); }; // 2024 payroll tax constants const SS_RATE_EE = 0.062, SS_RATE_TOTAL = 0.124, MED_RATE_EE = 0.0145, MED_RATE_TOTAL = 0.029; // RC36 (sec36): payroll-data.js (real staff records) is gone from the web for good. The list is the server's, per store, office only. const ptMaskEmp = (e) => "•••-••-" + (e && e.ssnLast4 ? String(e.ssnLast4) : "••••"); const ptC = (c) => (Number(c) || 0) / 100; const PT_MONEY = ["box1", "fit", "ssWages", "ssWH", "medWages", "medWH", "stateWages", "stateWH"]; const ptFromServer = (d) => { const emps = (d.employees || []).map((e) => { const o = { id: e.id, first: e.first || "", mid: e.mid || "", last: e.last || "", name: e.name || "", title: e.title || "", ftpt: e.ftpt || "", city: e.city || "", state: e.state || "", zip: e.zip || "", ssnLast4: e.ssnLast4 || "" }; PT_MONEY.forEach((k) => { o[k] = ptC(e[k + "Cents"]); }); return o; }); const T = d.totals || {}; const tot = { count: T.count || emps.length }; PT_MONEY.forEach((k) => { tot[k] = ptC(T[k + "Cents"]); }); return { year: d.year || null, years: d.years || [], employer: d.employer || null, emps, tot }; }; const ptApi = async (path, method, body, headers) => { try { return { ok: true, data: await apiFetch(path, { method: method || "GET", body, headers }) }; } catch (e) { return { ok: false, status: e.status || 0, code: e.body && e.body.code, data: e.body || {}, error: (e.body && e.body.error) || e.message || "The server could not be reached." }; } }; const ptLoadPayroll = async (year) => { const r = await ptApi("/payroll/employees" + (year ? "?year=" + encodeURIComponent(year) : "")); if (!r.ok) return { status: r.status === 403 ? "denied" : "error", error: r.error }; return { status: "ok", data: ptFromServer(r.data) }; }; const PayrollTax = ({ onClose, go }) => { const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => (window.DMS && window.DMS.subscribe) ? window.DMS.subscribe(force) : undefined, []); const [pr, setPr] = React.useState({ status: "loading" }); // RC36 (sec36): the server's employee list const [wantYear, setWantYear] = React.useState(null); const [importing, setImporting] = React.useState(false); const reloadPayroll = React.useCallback(async (y) => { setPr(await ptLoadPayroll(y === undefined ? wantYear : y)); }, [wantYear]); React.useEffect(() => { reloadPayroll(); }, [wantYear]); const [tab, setTab] = React.useState("pay"); const [sel, setSel] = React.useState(0); const ptB = window.K2BStore ? window.K2BStore.branding() : {}; const PD = pr.status === "ok" ? pr.data : null; // the employer block: the server's (imported with the employees); else the store's own branding (legal name, address, EIN, state id) const ER = (PD && PD.employer) || { name: ptB.legalName || "", addr: ptB.street || ptB.addr1 || "", city: ptB.city || "", state: ptB.state || "", zip: ptB.zip || "", ein: ptB.ein || "", stateId: ptB.stateEmployerId || "" }; const YEAR = (PD && PD.year) || (new Date().getFullYear() - 1); const EMPS = (PD && PD.emps) || []; const TOT = (PD && PD.tot) || {}; const officeOk = pr.status !== "denied"; const D = window.DMS; // Federal 941 liability from YTD figures (employee + employer match) const fed = { fit: TOT.fit || 0, ssTotal: +( (TOT.ssWages || 0) * SS_RATE_TOTAL ).toFixed(2), medTotal: +( (TOT.medWages || 0) * MED_RATE_TOTAL ).toFixed(2), }; fed.total = +(fed.fit + fed.ssTotal + fed.medTotal).toFixed(2); const stateTotal = TOT.stateWH || 0; const deposits = D ? D.taxDeposits() : []; const fedPaid = deposits.filter(d => !d.voided && /Federal/.test(d.kind)).reduce((s, d) => s + d.amount, 0); // RC33 (mpx): a voided deposit is not paid const statePaid = deposits.filter(d => !d.voided && /State/.test(d.kind)).reduce((s, d) => s + d.amount, 0); const tabBtn = (k, label) => ( ); const headHtml = () => `${window.dealerHeadHtml ? window.dealerHeadHtml() : ""}`; const erBlock = `${ER.name}
${ER.addr}
${ER.city}, ${ER.state} ${ER.zip}
EIN ${ptEIN(ER.ein)}`; // ── Make a tax deposit ── // RC33 (mpx): a SERVER command — the deposit is on the server's list every PC sees, with the REAL confirmation number the tax site gave // (typed here — never made up), and its entry debits the liability payroll credited (federal 323, state 323B — one server map) const makeDeposit = async (kind, amount, breakdown) => { if (!D) return; const conf = window.prompt(`${kind === "federal" ? "Federal 941 (EFTPS)" : "MO State Withholding"} deposit of $${pt$(amount)}.\n\nPay it on the tax site first, then type the CONFIRMATION number it gave you.\n(Leave blank to pay by CHECK instead — the server writes it; print it in Check Writing.)`, ""); if (conf === null) return; const r = await D.payTaxDeposit({ kind, amount: (+amount || 0).toFixed(2), period: `${YEAR} YTD`, breakdown, method: String(conf).trim() ? "eft" : "check", ref: String(conf).trim() || undefined }); window.k2bToast && window.k2bToast(r.msg, r.ok ? "ok" : "warn", 4200); }; React.useEffect(() => { if (D && D.loadTaxDeposits) D.loadTaxDeposits(); }, []); // RC33 (mpx): the server's deposit list // ── PRINT: 941 ── const print941 = () => { const ssWages = TOT.ssWages || 0, medWages = TOT.medWages || 0; const ssTax = fed.ssTotal, medTax = fed.medTotal; const line3 = TOT.fit || 0, line5e = ssTax + medTax, line6 = line3 + line5e; const html = `${headHtml()}
FORM 941 — Employer's Quarterly Federal Tax Return
${ER.name} · EIN ${ptEIN(ER.ein)} · Tax Year ${YEAR}
1 — Number of employees${TOT.count || EMPS.length}
2 — Wages, tips, and other compensation${pt$(TOT.box1)}
3 — Federal income tax withheld${pt$(line3)}
5a — Taxable social security wages${pt$(ssWages)}
5a — × 12.4%${pt$(ssTax)}
5c — Taxable Medicare wages & tips${pt$(medWages)}
5c — × 2.9%${pt$(medTax)}
5e — Total social security & Medicare${pt$(line5e)}
6 — TOTAL TAXES BEFORE ADJUSTMENTS${pt$(line6)}
13 — Total deposits for the year${pt$(fedPaid)}
14 — BALANCE DUE${pt$(Math.max(0, line6 - fedPaid))}
Signature of officer · Date
Print name & title
`; window.k2bPrint(html, { title: "Form 941" }); }; // ── PRINT: W-2 for one employee ── RC36 (sec36): the full SSN + street address come from the server for THIS print only (recorded there) const printW2 = async (e) => { const r = await ptApi("/payroll/employees/w2", "POST", { year: YEAR, ids: [e.id] }); const full = r.ok && r.data && Array.isArray(r.data.employees) ? r.data.employees.find((x) => x.id === e.id) : null; if (!full) { window.k2bToast && window.k2bToast(r.error || "The W-2 details could not be loaded.", "warn", 5000); return; } const esc = (v) => String(v === undefined || v === null ? "" : v).replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ }[c])); const html = `${headHtml()}
FORM W-2 — Wage and Tax Statement ${YEAR}
Employee SSN ${ptFullSSN(full.ssn)} · Employer EIN ${ptEIN(ER.ein)}
c — Employer${ER.name}, ${ER.city} ${ER.state}
e — Employee${esc(e.first)} ${esc(e.mid || "")} ${esc(e.last)}
f — Address${esc(full.addr)}, ${esc(e.city)} ${esc(e.state)} ${esc(e.zip)}
1 — Wages, tips, other comp${pt$(e.box1)}
2 — Federal income tax withheld${pt$(e.fit)}
3 — Social security wages${pt$(e.ssWages)}
4 — Social security tax withheld${pt$(e.ssWH)}
5 — Medicare wages and tips${pt$(e.medWages)}
6 — Medicare tax withheld${pt$(e.medWH)}
15 — State / Employer state ID${e.state} ${ER.stateId || ""}
16 — State wages, tips, etc.${pt$(e.stateWages)}
17 — State income tax${pt$(e.stateWH)}
`; window.k2bPrint(html, { title: "Form W-2 — " + e.last }); }; const cell = { padding: "3px 8px", fontSize: 12 }; const hd = { padding: "3px 8px", textAlign: "left", fontSize: 11, color: "var(--k2b-maroon)", borderBottom: "1px solid var(--jb-border)", whiteSpace: "nowrap" }; return (
{tabBtn("pay", "💵 Pay Taxes")} {tabBtn("emp", `Employees (${EMPS.length})`)} {tabBtn("941", "Form 941")} {tabBtn("w2", "W-2")} {tabBtn("8300", "Form 8300")} {tabBtn("checks", "Check Log")} {officeOk && } {PD && PD.years && PD.years.length > 1 && } {ER.name} · EIN {ptEIN(ER.ein)} · TY {YEAR}
{/* ───────── PAY TAXES ───────── */} {tab === "pay" && (
{/* Federal */}
Federal 941 — EFTPS
FIT + Social Security + Medicare (employer match included)
{/* State */}
Missouri Withholding
MO Dept. of Revenue · Employer ID {ER.stateId}
Deposit history
{deposits.length === 0 && } {deposits.map(d => ( ))}
RefTypePeriodAmountConfirmationDate
No tax deposits yet — make one above. Each posts to the GL automatically.
{d.id} {d.kind} {d.period} {pt$(d.amount)} {d.confirmation} {new Date(d.paidDate).toLocaleDateString()}
)} {/* RC36 (sec36): no list -> say why (still loading / office only / nothing imported yet) */} {(tab === "emp" || tab === "w2" || tab === "941") && !EMPS.length && setImporting(true)} />} {importing && setImporting(false)} onDone={() => { setImporting(false); reloadPayroll(); }} />} {/* ───────── EMPLOYEES ───────── */} {tab === "emp" && EMPS.length > 0 && (
{EMPS.map((e, i) => ( ))}
EmployeeTitleFT/PTSSN Box 1 WagesFIT SS W/HMedicare State W/H
{e.last}, {e.first} {e.title} {e.ftpt} {ptMaskEmp(e)} {pt$(e.box1)} {pt$(e.fit)} {pt$(e.ssWH)} {pt$(e.medWH)} {pt$(e.stateWH)}
TOTALS — {EMPS.length} employees {pt$(TOT.box1)} {pt$(TOT.fit)} {pt$(TOT.ssWH)} {pt$(TOT.medWH)} {pt$(TOT.stateWH)}
)} {/* ───────── 941 ───────── */} {tab === "941" && (
Form 941 — Employer's Quarterly Federal Tax Return
{ER.name} · EIN {ptEIN(ER.ein)} · Tax Year {YEAR}
🖨 Print 941 setTab("pay")}>Pay Now ▸
)} {/* ───────── W-2 ───────── */} {tab === "w2" && EMPS.length > 0 && (
{EMPS.map((e, i) => (
setSel(i)} style={{ padding: "6px 12px", cursor: "pointer", borderBottom: "1px dotted #EEE", background: sel === i ? "var(--jb-blue-tint, #E8F0FB)" : "transparent", fontWeight: sel === i ? 700 : 400, color: "var(--jb-navy)", fontSize: 13 }}> {e.last}, {e.first}
))}
{EMPS[sel] && (() => { const e = EMPS[sel]; return (
W-2 · {e.first} {e.last}
{e.title} · {e.ftpt} · SSN {ptMaskEmp(e)}
printW2(e)}>🖨 Print W-2
); })()}
)} {/* ───────── 8300 ───────── */} {tab === "8300" && } {/* ───────── CHECK LOG ───────── */} {tab === "checks" && }
); }; /* one labeled money line */ const PTLine = ({ label, val, bold, dim, plain, color }) => (
{label} {plain ? val : "$" + pt$(val)}
); /* ── Form 8300 — cash > $10,000 (links to deals with large cash down) ── */ const Form8300 = ({ ER, go, headHtml }) => { const D = window.DMS; const deals = D ? D.deals() : []; const cashDeals = deals.filter(d => (+d.cashDown || 0) > 10000); const print8300 = (d) => { const html = `${headHtml()}
FORM 8300 — Report of Cash Payments Over $10,000
Received in a Trade or Business · ${ER.name} · EIN ${ptEIN(ER.ein)}
Part I — Individual from whom cash was received${d ? d.buyer : "____________________"}
Amount of cash received${d ? "$" + pt$(d.cashDown) : "$ ____________"}
Date cash received${d && d.created ? new Date(d.created).toLocaleDateString() : "____________"}
Part II — Vehicle / transaction${d ? (d.vehicle || "") + " · " + (d.stock || "") : "____________________"}
Part III — Business that received cash${ER.name}, ${ER.city} ${ER.state}
File by the 15th day after the date the cash was received. Furnish a written statement to each person named by January 31 of the following year.
Authorized official · Title
Date of signature
`; window.k2bPrint(html, { title: "Form 8300" }); }; const cell = { padding: "4px 8px", fontSize: 12 }; const hd = { padding: "4px 8px", textAlign: "left", fontSize: 11, color: "var(--k2b-maroon)", borderBottom: "1px solid var(--jb-border)" }; return (
Form 8300 is required when a customer pays more than $10,000 in cash on a deal. Deals that cross the threshold appear here.
{cashDeals.length === 0 && } {cashDeals.map(d => ( ))}
DealBuyerVehicleCash Down
No deals with cash over $10,000. You can still print a blank 8300 below.
{d.id} {d.buyer} {d.vehicle} {pt$(d.cashDown)}
print8300(null)}>🖨 Print blank 8300
); }; /* ── Paper check log (persistent register) ── */ const CheckLog = () => { const KEY = "jb_check_log_v1"; const [rows, setRows] = React.useState(() => { try { return JSON.parse(localStorage.getItem(KEY) || "[]"); } catch (e) { return []; } }); const save = (next) => { setRows(next); try { localStorage.setItem(KEY, JSON.stringify(next)); } catch (e) {} }; const [f, setF] = React.useState({ date: "", num: "", payee: "", amount: "" }); const add = () => { if (!f.num || !f.payee) { window.k2bToast && window.k2bToast("Check # and payee are required.", "warn"); return; } save([{ ...f, amount: parseFloat(String(f.amount).replace(/[^0-9.]/g, "")) || 0, cleared: false, id: Date.now() }, ...rows]); setF({ date: "", num: "", payee: "", amount: "" }); }; const toggle = (id) => save(rows.map(r => r.id === id ? { ...r, cleared: !r.cleared } : r)); const total = rows.reduce((s, r) => s + (+r.amount || 0), 0); const ip = { padding: "5px 8px", border: "1px solid #C8CCD2", fontFamily: "var(--jb-mono, monospace)", fontSize: 13 }; const cell = { padding: "4px 8px", fontSize: 12 }; const hd = { padding: "4px 8px", textAlign: "left", fontSize: 11, color: "var(--k2b-maroon)", borderBottom: "1px solid var(--jb-border)" }; return (
setF(s => ({ ...s, date: e.target.value }))} placeholder="MM/DD/YY" style={{ ...ip, width: 100 }} /> setF(s => ({ ...s, num: e.target.value }))} placeholder="Check #" style={{ ...ip, width: 90 }} /> setF(s => ({ ...s, payee: e.target.value }))} placeholder="Check written to" style={{ ...ip, flex: 1, minWidth: 160 }} /> setF(s => ({ ...s, amount: e.target.value }))} placeholder="Amount" style={{ ...ip, width: 110, textAlign: "right" }} /> + Add
{rows.length === 0 && } {rows.map(r => ( ))}
DateCheck #Check Written ToAmountCleared
No checks logged. Add one above.
{r.date || "—"} {r.num} {r.payee} {pt$(r.amount)} toggle(r.id)} />
TOTAL — {rows.length} checks {pt$(total)}
); }; /* ══════════════ RC36 (sec36): the empty state + the 'Payroll employees' import (CSV / Excel → POST /api/payroll/employees/import) ══════════════ */ const PtEmpty = ({ pr, onImport }) => (
{pr.status === "loading" &&
Loading the employee list…
} {pr.status === "denied" &&
Payroll is kept for the office only.
Admin / F&I, the Office Manager and Accounting can see the employees here. Ask the office.
} {pr.status === "error" &&
⚠ {pr.error || "The employee list could not be loaded."}
} {pr.status === "ok" &&
No employees loaded
The W-2 / 941 amounts come from the employee list. Load it from your payroll company's year-end report: fill in the template (one row per employee) and press Import employees. The Social Security numbers are stored encrypted on the server; this screen only ever shows their last 4 digits.
Download the template (CSV)
}
); const PT_HEAD = { id: ["employee id", "employee #", "employee no", "employee number", "emp id", "emp #", "emp no", "id"], ssn: ["ssn", "social security number", "social security #", "social security no", "ss #", "ss number", "ssn #"], first: ["first", "first name", "firstname", "given name"], mid: ["mid", "middle", "middle name", "mi", "middle initial"], last: ["last", "last name", "lastname", "surname", "family name"], name: ["name", "full name", "employee name", "employee"], addr: ["address", "street", "street address", "addr", "home address", "address 1"], city: ["city"], state: ["state", "st"], zip: ["zip", "zip code", "zipcode", "postal", "postal code"], title: ["title", "job title", "position", "job"], ftpt: ["ft/pt", "ftpt", "full/part time", "full or part", "ft pt", "status"], box1: ["box 1", "box1", "box 1 wages", "wages", "wages tips other comp", "wages tips other compensation", "box 1 wages tips other comp"], fit: ["box 2", "box2", "fit", "federal income tax withheld", "federal tax withheld", "box 2 federal tax withheld", "box 2 federal income tax withheld", "federal withholding"], ssWages: ["box 3", "box3", "ss wages", "social security wages", "box 3 social security wages"], ssWH: ["box 4", "box4", "ss wh", "ss withheld", "social security tax withheld", "box 4 social security tax withheld"], medWages: ["box 5", "box5", "medicare wages", "medicare wages and tips", "med wages", "box 5 medicare wages", "box 5 medicare wages and tips"], medWH: ["box 6", "box6", "medicare wh", "medicare tax withheld", "med wh", "box 6 medicare tax withheld"], stateWages: ["box 16", "box16", "state wages", "state wages tips etc", "box 16 state wages"], stateWH: ["box 17", "box17", "state wh", "state income tax", "state tax withheld", "box 17 state income tax"] }; const ptNorm = (h) => String(h || "").toLowerCase().replace(/[^a-z0-9/# ]/g, " ").replace(/\s+/g, " ").trim(); const ptSsnOk = (v) => { const d = String(v || "").replace(/[\s-]/g, ""); return /^\d{9}$/.test(d) && !/^(000|666|9)/.test(d) && d.slice(3, 5) !== "00" && d.slice(5) !== "0000"; }; const ptMapRows = (rows) => { const headers = rows.length ? Object.keys(rows[0]) : []; const map = {}; headers.forEach((h) => { const n = ptNorm(h); const f = Object.keys(PT_HEAD).find((k) => PT_HEAD[k].indexOf(n) !== -1); if (f && !map[f]) map[f] = h; }); const out = [], problems = []; rows.forEach((r, i) => { const o = {}; Object.keys(map).forEach((f) => { const v = r[map[f]]; o[f] = v === undefined || v === null ? "" : String(v).trim(); }); if (!Object.values(o).some((v) => v)) return; const why = !o.id ? "no employee id" : !ptSsnOk(o.ssn) ? "the SSN is not a valid 9-digit number" : !(o.last || o.name) ? "no name" : null; if (why) problems.push({ row: i + 2, why }); out.push(o); }); return { map, headers, rows: out, problems }; }; const PtImportDialog = ({ year, onClose, onDone }) => { const [y, setY] = React.useState(String(year || new Date().getFullYear() - 1)); const [file, setFile] = React.useState(null); const [plan, setPlan] = React.useState(null); const [err, setErr] = React.useState(""); const [busy, setBusy] = React.useState(false); const [result, setResult] = React.useState(null); const [imports, setImports] = React.useState([]); const keyRef = React.useRef("pe-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10)); const loadImports = async () => { const r = await ptApi("/payroll/employees/imports"); if (r.ok) setImports(r.data.imports || []); }; React.useEffect(() => { loadImports(); }, []); const pick = async (f) => { setErr(""); setPlan(null); setResult(null); setFile(f || null); if (!f) return; try { const I = window.JBImporters; if (!I) throw new Error("The file reader is not loaded on this page."); let rows; if (/\.(xlsx|xls)$/i.test(f.name)) { const wb = await I.parseExcel(f); const names = Object.keys(wb); const nm = names.find((n) => /payroll|employee|w-?2/i.test(n)) || names[0]; rows = nm ? wb[nm] : []; } else rows = I.parseCSVText(await new Promise((res, rej) => { const r = new FileReader(); r.onload = () => res(String(r.result)); r.onerror = rej; r.readAsText(f); })); const p = ptMapRows(rows || []); if (!p.map.id || !p.map.ssn) throw new Error("This file has no 'Employee ID' and 'SSN' columns. Use the template's column names (Download the template)."); setPlan(p); } catch (e) { setErr(e.message || String(e)); } }; const go = async () => { if (!plan || busy) return; if (!/^\d{4}$/.test(y)) { setErr("Type the tax year (for example 2025)."); return; } setBusy(true); setErr(""); const r = await ptApi("/payroll/employees/import", "POST", { year: Number(y), rows: plan.rows }, { "Idempotency-Key": keyRef.current }); setBusy(false); if (!r.ok) { setErr(r.error); if (r.data && r.data.rejected) setResult({ counts: null, rejected: r.data.rejected }); return; } setResult(r.data); loadImports(); }; const undo = async (runId) => { if (!window.confirm("Undo this import? Every employee goes back to how it was before it (employees it added are removed).")) return; const r = await ptApi("/payroll/employees/undo", "POST", { runId }); window.k2bToast && window.k2bToast(r.ok ? `Import undone: ${r.data.removed} removed, ${r.data.restored} put back.` : r.error, r.ok ? "ok" : "warn", 5000); loadImports(); if (r.ok) onDone && onDone(); }; const lastUndoable = imports.find((x) => !x.undone); const box = { position: "fixed", inset: 0, background: "rgba(0,0,0,.35)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 9000, padding: 12 }; return (
{ if (e.target === e.currentTarget) onClose(); }}>
Import payroll employees
One row per employee with the year's W-2 amounts (boxes 1-6, 16, 17). The same employee ID again updates that employee. SSNs are stored encrypted; this screen never shows them. Template (CSV)
pick(e.target.files && e.target.files[0])} />
{plan && !result &&
{plan.rows.length} employee row(s) in {file && file.name}{plan.problems.length ? — {plan.problems.length} with a problem (they are not imported): : — no problems found.} {plan.problems.length > 0 &&
    {plan.problems.slice(0, 10).map((p, i) =>
  • row {p.row}: {p.why}
  • )}
}
Columns read: {Object.keys(plan.map).join(", ")}
} {result &&
{result.counts &&
Imported: {result.counts.added} added, {result.counts.updated} updated, {result.counts.unchanged} unchanged{result.counts.rejected ? ", " + result.counts.rejected + " not imported" : ""}.
} {result.rejected && result.rejected.length > 0 &&
    {result.rejected.slice(0, 10).map((p, i) =>
  • row {p.row}: {p.why}
  • )}
}
} {err &&
⚠ {err}
}
{lastUndoable && } {!result && }
); }; Object.assign(window, { PayrollTax });