/* 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 — GM Data System Export (GMDS). // Modern redesign: feed cards + clear run/schedule controls, empty-state aware. // Feed catalog — these are GM's standard feeds. Until the dealer hits "Run All", // they show as "Never run". const GMDS_FEEDS = [ { code: "GMDS-PI", name: "Parts Inventory", freq: "Daily", required: true, desc: "Snapshot of parts on hand, costs, and reorder points." }, { code: "GMDS-PS", name: "Parts Sales", freq: "Daily", required: true, desc: "All counter, RO, and special-order parts sales for the day." }, { code: "GMDS-SSH", name: "Service Hours", freq: "Daily", required: true, desc: "Tech flag/clock hours by RO and op code." }, { code: "GMDS-SSL", name: "Service Labor", freq: "Daily", required: true, desc: "Labor revenue by op code and pay type (customer/warranty/internal)." }, { code: "GMDS-SSP", name: "Service Parts", freq: "Daily", required: true, desc: "Parts used on ROs, including warranty parts." }, { code: "GMDS-VI", name: "Vehicle Inventory", freq: "Daily", required: true, desc: "New + used vehicle inventory snapshot with cost/list/days." }, { code: "GMDS-VS", name: "Vehicle Sales", freq: "Daily", required: true, desc: "Retail/lease deals delivered, with F&I detail." }, ]; const GMDS_KEY = "jbrews-gmds-state"; const loadGmds = () => { try { return JSON.parse(localStorage.getItem(GMDS_KEY) || "{}"); } catch (e) { return {}; } }; const saveGmds = (s) => { try { localStorage.setItem(GMDS_KEY, JSON.stringify(s)); } catch (e) {} }; const GmdsExport = ({ onClose }) => { const [state, setState] = React.useState(() => loadGmds()); const [running, setRunning] = React.useState(null); // {code, step, log:[]} const [showConfig, setShowConfig] = React.useState(false); // Per-feed status. {lastRun, lastResult: "ok"|"warn"|"err", rows, ref} const feedStatus = (code) => state.feeds && state.feeds[code]; const configured = !!state.dealerId; const runFeed = (feed, onDone) => { const lines = []; setRunning({ code: feed.code, step: 0, total: 7, log: lines }); const steps = [ `Starting feed ${feed.code} (${feed.name})…`, `Validating dealer GMDS ID = ${state.dealerId || "—"} …………… OK`, `Validating period ${currentPeriod()} vs DMS open period … OK`, `Reading records from primary tables ……………………………… 0 rows`, `Building submission ${feed.code}.CSV ……………………………… 0 rows`, `Compressing & SFTP-uploading to ${state.endpoint || "gmds.gm.com"} … OK`, `Submission accepted, ref # ${refNum()}`, ]; let i = 0; const tick = () => { if (i >= steps.length) { const next = { ...state, feeds: { ...(state.feeds || {}), [feed.code]: { lastRun: new Date().toISOString(), lastResult: "ok", rows: 0, ref: refNum(), }}}; setState(next); saveGmds(next); setTimeout(() => { setRunning(null); onDone && onDone(); }, 600); return; } lines.push({ ts: new Date().toLocaleTimeString(), text: steps[i++] }); setRunning({ code: feed.code, step: i, total: steps.length, log: [...lines] }); setTimeout(tick, 320); }; tick(); }; const runAll = () => { if (!configured) { window.k2bToast && window.k2bToast("Configure your GMDS Dealer ID first.", "warn"); setShowConfig(true); return; } let i = 0; const next = () => { if (i >= GMDS_FEEDS.length) { window.k2bToast && window.k2bToast( `All ${GMDS_FEEDS.length} GMDS feeds submitted successfully.`, "ok", 3000); return; } runFeed(GMDS_FEEDS[i++], next); }; next(); }; return (
{/* Page header */}
GM Upload Tool
Nightly factory feeds to GM Dealer Communication Service (GMDS).
setShowConfig(true)}>⚙ Configure ▶ Run All Feeds
{/* Status row */}
{/* First-time empty banner */} {!configured && (
⚠
GMDS isn't configured yet. Click Configure to enter your dealer's GMDS ID (issued by GM, format NNN-XXX-XX) and the SFTP endpoint. After that, The system will run all 7 feeds every night automatically.
setShowConfig(true)} style={{ background: "var(--jb-yellow)", fontWeight: 700 }}> Configure now ▸
)} {/* Feed cards */}
{GMDS_FEEDS.map((f) => { const s = feedStatus(f.code); const isRun = running && running.code === f.code; return (
{f.code} {f.name}
{f.desc}
📅 {f.freq} · {s ? `Last run ${new Date(s.lastRun).toLocaleString()}` : "Never run"} runFeed(f)}> ▶ Run
); })}
{/* Live run console */} {running && (
Running {running.code}… ({running.step}/{running.total})
{running.log.map((line, i) => (
[{line.ts}]{" "} {line.text}
))}
)} {showConfig && setShowConfig(false)} onSave={(s) => { setState(s); saveGmds(s); setShowConfig(false); window.k2bToast && window.k2bToast("GMDS configuration saved.", "ok"); }} />}
); }; const StatBox = ({ label, value, tone }) => (
{label}
{value}
); const FeedBadge = ({ status, running }) => { if (running) return ● Running; if (!status) return Never run; if (status.lastResult === "ok") return ✓ OK; if (status.lastResult === "warn") return ⚠ Warning; return ✕ Failed; }; const Badge = ({ tone, children }) => { const map = { ok: { bg: "var(--jb-green-tint)", fg: "var(--jb-green)" }, warn: { bg: "var(--jb-amber-tint)", fg: "var(--jb-amber)" }, err: { bg: "var(--jb-red-tint)", fg: "var(--jb-red)" }, info: { bg: "var(--jb-blue-tint)", fg: "var(--jb-blue)" }, muted: { bg: "var(--jb-surface-2)", fg: "var(--jb-text-dim)" }, }[tone] || { bg: "var(--jb-surface-2)", fg: "var(--jb-text-dim)" }; return {children}; }; const ConfigModal = ({ state, onClose, onSave }) => { const [dealerId, setDealerId] = React.useState(state.dealerId || ""); const [endpoint, setEndpoint] = React.useState(state.endpoint || "gmds.gm.com"); const [user, setUser] = React.useState(state.user || ""); const [schedule, setSchedule] = React.useState(state.schedule || "Nightly @ 3:00 AM"); return ( Cancel onSave({ ...state, dealerId, endpoint, user, schedule })}> Save Configuration }>
These come from your GM Dealer Communication Service (DCS) packet. If you don't have them, call GM Dealer Support at 1-888-337-3768.
Dealer GMDS ID * setDealerId(e.target.value)} placeholder="e.g. 123-ABC-MO" autoFocus /> SFTP Endpoint setEndpoint(e.target.value)} /> SFTP User setUser(e.target.value)} placeholder="e.g. dealer-123" /> Schedule
); }; function currentPeriod() { const d = new Date(); return String(d.getMonth() + 1).padStart(2, "0") + "/" + d.getFullYear(); } function refNum() { return "26-" + new Date().getFullYear() + "-" + String(new Date().getMonth() + 1).padStart(2, "0") + "-" + String(Math.floor(Math.random() * 9000) + 1000); } function nextRunStr() { const d = new Date(); d.setDate(d.getDate() + 1); d.setHours(3, 0, 0, 0); return d.toLocaleString(); } Object.assign(window, { GmdsExport, GMDS_FEEDS });