Diagnose Tekion Accounting Journal Entries stuck in ERROR status (auto-posting JEs that failed to post). Covers the JE list/detail URLs, reading GL posting lines out of the DOM, finding the blank/unmapped GL account, and tracing the root cause back to a missing row in GL Account Transaction Mapping. Use for "look at journal entries", "JEs in error", "auto posting failed", "GL account blank on journal entry".
Install
npx skillscat add joecastelino/jay-skill-pack/tekion-journal-entry-error-diagnosis Install via the SkillsCat registry.
Tekion Journal Entry ERROR Diagnosis
Joe's shorthand: "3.0" = Tekion (the DMS) — e.g. "I need a lot of 3.0 help today".
"GLAM" = GL Account Transaction Mapping (/accounting/glaccountmapping/list).
Joe applies GL config fixes himself and will say so mid-thread ("I fixed the glam") — always
re-verify the live mapping state before re-reporting a previously-diagnosed open item.
Joe's ask is usually "look at Journal entries, don't change anything, tell me what's wrong."
This is a READ-ONLY diagnosis. Never click Submit / Save as Draft / Perform action and move to next
unless he explicitly says to fix it.
All work through the :9223 persistent browser (/eval, /mouse, /type, /navigate).
Verify localStorage.currentActiveDealerId matches the target store first — the session drifts.
1. URLs (verified SCT 876, 2026-08-21)
| Screen | URL |
|---|---|
| Journal Entries list | ✅ /accounting/journalEntry/list (camelCase; /accounting/journalentry/list also works) |
| JE detail (Error/Draft, editable) | /accounting/journalEntry/transactionId/<txnId>/dealerId/<dealerId>/transactionType/AUTO_POSTING/edit |
| JE detail (Posted, read-only) | /accounting/journalEntry/transactionId/<txnId>/dealerId/<dealerId>/view |
⚠️
<txnId>IS NOT THE 7-DIGIT JE ID (burned ~6 turns 2026-08-24). The list/header shows a
display ID like1685170; the URL wants an internal 14-digit transaction id like60215445227271. Navigating with the 7-digit number silently fails — you stay on whatever
page you were on (often a stale RO detail) andbody.innerTextlooks like a real page, so it
reads as a false success. There is no way to derive txnId from the display ID — you must open
the row from the list. See §2 "Open a specific JE by its 7-digit ID".
Stale-route trap: the first POST /navigate to /accounting/journalEntry/list can land on a
previously-open JE detail (.../transactionId/.../view). Always assert location.href ends in/list; if not, navigate a second time.
| Chart of Accounts | /accounting/chartOfAccounts/list |
| GL Account Transaction Mapping | ✅ /accounting/glaccountmapping/list (all lowercase!) |
Dead ends — do NOT waste turns on these:
/accounting/journal-entry,/accounting/journal-entries,/accounting/glam→ silently redirect to chartOfAccounts/list (looks like it "worked", it didn't — always assertlocation.href)/accounting/journal/list,/accounting/glAccountMapping(camelCase) → render blank/accounting/accountSetup,/accounting/accountingSettings,/accounting/settings/glAccountMapping→ bounce to/ro/quotes/gl/journal-entry→ bounces to/home
Finding new accounting screens: App Grid (nine-dots at ~22,32) → search box input[placeholder='Search'] → type e.g. "account". Results list shows Apps / Analytics / Settings groups. Under Settings you get: Distribution Accounts, Accounting Global Settings, GL Account Mapping — all / Accounting Settings. Click the result text (find by innerText.startsWith(...), it's a multi-line card so exact-match on a leaf node fails).
2. Reading the Error queue
- Navigate
/accounting/journalEntry/list, sleep 8. - Status tabs render as leaf nodes at y≈158 (was y≈146 — coords drift, re-read them):
All(x≈124) ·Draft(x≈206) ·Error(x≈327) ·Pending Approval(x≈515)./mouseclick Error.
Find them live — note the filter picks the FIRST match by y, since "Error" also appears in every row:
The tab labels contain animated odometer digits (long[...document.querySelectorAll('*')].filter(e=>e.children.length===0 && ['All','Draft','Error','Pending Approval'].includes((e.innerText||'').trim()) && e.getBoundingClientRect().width>0) // tab row is y<200; rows are y>4000\n1\n2...runs ininnerText) —
the count is NOT readable from the tab; use theN Result(s)line instead. - Row count appears as
N Result(s)indocument.body.innerText. - Parse rows straight out of
body.innerText— the table is virtualized, there are no.ant-table-rownodes. Column order:Status · ID · Type · Accounting Date · Reference Type · Reference · Journal · Journal Type · Document Type · Description · Amount · Created By · Modified Time · Franchise - Row-open: the ID cell is a leaf
div.root_content_blackNormalContent__*at x≈344. Get coords with:
then[...document.querySelectorAll('*')].filter(e=>e.children.length===0 && /^\d{7}$/.test((e.innerText||'').trim()) && e.getBoundingClientRect().x>330 && e.getBoundingClientRect().x<380)/mouseclickx+10, y+8. Verifylocation.hrefcontainstransactionId— if not, the click missed.
Search box gotcha: the page-level expandable search starts at width 0. Click the magnifier.icon-search (x≈1095, y≈224 on the JE list; find it live and IGNORE the one at ~268,33 =
the global AI-search toggle) to expand, THEN type. /type with only {text:...} returns
HTTP 400 — always pass a selector:
/type {"selector":"input.root_expandableSearchField_expandableInput__3cvPtuyg2T","text":"..."}It's a prefix/contains match on the ID column only — searching a description string returns 0 rows.
Note the search box resets on every navigate and clicking a status tab; re-expand each time.
Open a specific JE by its 7-digit ID (the ONLY reliable path)
api("/navigate",{"url":".../accounting/journalEntry/list"}); sleep(9) # assert href ends /list
api("/mouse",{"x":1095,"y":224}); sleep(2) # expand search
api("/type",{"selector":"input.root_expandableSearchField_expandableInput__3cvPtuyg2T","text":"1685170"})
api("/press",{"key":"Enter"}); sleep(6) # → "1 Result(s)"
# click the ID leaf (lands ~x374,y314 for a single-result list)
coords = eval("""[...document.querySelectorAll('*')].filter(x=>x.children.length===0
&& (x.innerText||'').trim()==='1685170')[0].getBoundingClientRect()""")
api("/mouse", center(coords)); sleep(8)
# now location.href carries the real transactionId — verify it changedSearch works from the All tab too (no need to be on Error). ~25s per JE end-to-end, so batch
the pulls in ONE execute_code call.
Scraping the FULL error list (virtualized — you only get ~20 rows per read)
The scroll container is an unclassed <div> (className==='') with scrollHeight>clientHeight
and clientHeight>300. It is NOT findable by class. Loop: read body.innerText → regex rows →el.scrollTop += 350 → repeat until scrollTop stops advancing. ~45 iterations covers ~117 rows
in about 25s. Row regex that works (Type may be multi-word, and some rows carry an extraRev/Adj badge line — anchor on Error\n(\d{7})\n):
re.compile(r"Error\n(\d{7})\n([A-Za-z ]+)\n(\d\d/\d\d/\d\d)\n([^\n]+)\n([^\n]+)\n([^\n]+)\n"
r"([^\n]+)\n([^\n]+)\n([^\n]+)\n(\$[\d,\.]+)\n([^\n]+)\n([^\n]+)\n")Dedupe into a dict keyed by JE id (rows repeat across scroll reads). Then aggregate with Counter
on journal / reference-type / creator / accounting-date — that grouping IS the report Joe wants.
Persist to /tmp/<store>_je_errors.json since execute_code is stateless between calls.
3. Reading a JE's posting lines (the actual diagnosis)
On the detail page, document.body.innerText.split('General Information')[1] gives the header block
(Franchise / Journal Number-Name / Document Type / Description / Reference Type / Reference /
Accounting Date) plus Credit / Debit / Balance / Gross Profit and the posting-line table.
For an editable (Error/Draft) JE the GL cells are react-selects, not text. Pull them with
(use the loose [class*="tekion-select"][class*="container"] selector — the hashedtekion-select-b62m3t-container class changes between builds — and y>300, not y>500, or you
drop the first posting line):
(()=>{const o=[];[...document.querySelectorAll('[class*="tekion-select"][class*="container"]')]
.filter(e=>e.getBoundingClientRect().y>300).forEach(s=>o.push((s.innerText||'').trim()));
const a=[...document.querySelectorAll('input')].filter(i=>i.placeholder==='0.00'
&& i.getBoundingClientRect().width>0).map(i=>i.value);
return JSON.stringify({gl:o,amt:a})})()- The
glarray's first two entries are the header selects (Reference Type e.g."Parts Sales Order", and Reference e.g."331575") — posting lines start at index 2, andamt[0]pairs withgl[2]. Don't off-by-two the diagnosis. - A GL cell reading literally
"Select"= the blank/unmapped account. That is the error. - Amounts pair positionally with the GL list (index 0 ↔ index 0).
- A Posted JE renders the same table as plain text (no selects) — the JS above returns empty; just read
innerTextinstead. This difference is the tell for Posted vs Error. - Header line
"Auto Posting Journal Entry - <id> / Error / N of 10"confirms you're in the error set and gives your position. Gross Profitin the header does NOT match the line math (e.g. JE 1685205 shows $116.83 while revenue−cost = $46.58−$37.53 = $9.05; its deposit sibling shows $107.78; a posted wholesale JE shows −$70.85). Looks like a running/aggregate figure, not per-entry. Unverified — flag it to Joe as unexplained rather than inventing a definition (NEVER-GUESS rule).- The sale JE and its deposit JE are a pair per sales order and both carry the same defect. Always pull both: sale =
Dr Holding / Cr Revenue + Tax, deposit =Dr Cash (2045) / Cr Holding. Reference/control number on both = the parts SO number.
Cross-check with vision_analyze on a screenshot — it reliably calls out the red-highlighted blank
select. Screenshot endpoint is GET http://127.0.0.1:9223/screenshot returning {"screenshot": "<b64>"}
— POST /screenshot is 404.
4. Root-cause: find the missing GL mapping
The method that works: diff an errored JE against a POSTED JE from the same journal.
The posted one shows which account belongs in the slot the errored one left blank.
Then go to /accounting/glaccountmapping/list and find the mapping table that should have produced it.
Left-nav structure (accordion — parent sections expand to reveal counted children):
Variable Operations
New Vehicles (1) · Used Vehicles (1) · F&I Products (1) · Receivables (2) · Payables (5)
Fixed Operations
Services (3) · Part & Accessories (6) · Purchase Orders (1) · Warranty Credit (1) · Others (2)
Payment Receipts
Variable Operations (1) · Fixed Operations (6) · Tekion Pay (1)
PayrollKey leaves for parts/service JE errors:
- Fixed Operations → Part & Accessories → cards: Parts-Customer Pay / Parts-Toyota Care / Parts-Internal / Parts-Warranty / Online Parts Payments / Parts-Counter. Columns:
Service Type · Source Code · Tax Status · Sale Type (Fixed Ops) · Sales Subtype · Department · GL Account. - Fixed Operations → Others → Fixed Operations (Other) →
Freight charge,Restocking Fee,Other supplies,Service Cash Holding Account,Parts Cash Holding Account. Columns:Fixed Operations (Other) · Department · GL Account. ← cash-holding gaps live here - Payment Receipts → Fixed Operations (6) → Parts/Service Payment Methods by pay type. Columns:
Payment Method (Parts) · Sale Type (Fixed Ops) · GL Account.
Nav pitfalls (cost several turns)
- The section parents (
Variable Operations/Fixed Operations/Payment Receipts/Payroll)
are NOT leaf nodes — they'rediv.ant-menu-submenu-titleinside anli.ant-menu-submenuand
they wrap child text, so achildren.length===0leaf search returns nothing and you conclude
(wrongly) the item doesn't exist. Find them by exactinnerTextmatch onli,divand click the
title div (Fixed Operations≈ x230,y481 at SCT). The children (Others (2),Part & Accessories (6)) ARE matchable — take the LAST match (e[e.length-1]) since theli
and innerdivboth match; the inner div gives the correct clickable center. - Right-panel mapping cards (
Fixed Operations Other,Online Parts Payments,Parts-Counter)
ARE leaf nodes — click by exact leaf text, then re-readbody.innerText. Clicking the same card
title again collapses it, which is handy for iterating several cards in one loop. - Left-nav items live below the fold and their coords shift as sections expand/collapse. Always
scrollIntoView({block:'center'})the target, re-readgetBoundingClientRect(), THEN/mouseclick. Clicking a stale coordinate silently opens the previously selected section (you'll see e.g. "Receivables Mapping" when you asked for "Others"). - Clicking the same parent twice toggles it shut. Re-read the nav text after each click.
5. Triage FIRST: not every Error JE is a mapping gap
Before you go hunting mappings, split the error queue by Balance (header line on the detail page):
| Balance | Meaning | Fix owner |
|---|---|---|
$0.00 + one GL cell reads "Select" |
Mapping gap — Tekion built a balanced entry but couldn't resolve one account | Jay (config) |
| $0.00 + every GL resolved, no blank | Tekion posting-service defect — nothing to fix, the entry is valid. Just repost | Joe (repost) — see §5d |
| Non-zero (Dr ≠ Cr) | Malformed entry — lines are missing, not accounts. No mapping change will fix it | Accounting must rebuild |
COST_CENTER_NOT_FOUND + line-1 GL literally null |
Cost-centre not mapped (internal ROs) — add the centre in Setup Fields → Cost Centre Setup, then Refresh + Submit each JE | Joe (config) |
⚠️ Do not assume mapping gap. Two of the four buckets above look identical in the Error tab
(both Balance $0.00). The discriminator is whether a GL cell is blank — check before diagnosing.
Real example (SCT 8/24/2026) — 117 errors, 114 were the mapping gap, 2 were NOT:
1686422Warranty Credit Memo — Balance −$236,238.16: Dr3001 A/P-TOYOTA$261,581.49 vs only
$25,343.33 of credits across 152211 - PDIlines. Credit side truncated.1685915Used vehicle purchase, stock CT27020 — Balance −$26,660.00: single line
Dr2400 USD VEH INV - NON-CERT TOYOTA, no offsetting credit at all.
Call these out separately in the report. Saying "117 JEs, all the same mapping bug" when 2 aren't
is exactly the kind of wrong root cause Joe rejects instantly.
5b. Known root cause: department-scoped mapping gap
Symptom pattern seen at SCT 8/21/2026 — 10 Error JEs, all journal 32 - PARTS CASH SALES,
all Auto Posting, all same creator, from 5 sales orders × 2 JEs each (the sale + the deposit).
Blank line = the cash-holding / cash-sales account in both.
Root cause: the mapping row exists for one department but not the department the transaction ran under.
Here, Parts Cash Holding Account was mapped only for 05 - PARTS & ACCESSORIES (Parts) → 2045,
but ONLINE RETAIL parts sales post under 06 - Online Parts Sales (Parts). Revenue mapped fine
(4748 / 4731 both had dept-06 rows), so only the holding-account lookup came back empty → blank line.
Generalize: when a JE errors with ONE blank line and everything else resolves, look at theDepartment / Sale Type / Sales Subtype on the posted sibling vs the errored one. The blank is
almost always a mapping table that has rows for the common department but not the edge-case one.
A cluster of errors all starting the same day usually = a new sale type / channel went live and
only half its mappings were built.
Fix (only with explicit go-ahead): add the missing row via the mapping card's Add button, then
re-open each errored JE and Submit.
RESOLVED — SCT 876 — mapping fixed by Joe 2026-08-25 (was compounding 8/21→8/24)
Joe added the row himself on 2026-08-25:Parts Cash Holding Account | 06 - Online Parts Sales (Parts) | 2045 - CASH SALES
(Fixed Operations → Others → Fixed Operations (Other)). New online-retail sales post clean from
~8:20 AM 8/25. Last errors: SO 331926 (8:11) and 331930 (8:27, reworked as 331932).
"I don't want a holding account, can I just use 2045?" — YES. Answer Joe accepted:
Tekion ALWAYS writes the two-JE pair (sale + deposit); there is no toggle to suppress the deposit
leg. But pointing the holding mapping at the cash account is forgoing the holding account —
the deposit JE becomes a self-canceling wash (2045 +X / 2045 −X = net $0) and nothing ever
parks in a separate holding bucket. Structurally identical to how a normal counter sale already
posts. Verified on SO 331932: sale JE 1686453 = 2045 +24.88 / 4748 −22.62 / 6748 +17.40 / 2410 −17.40 / 3140 −2.26; deposit JE 1686452 = 2045 24.88 / 2045 −24.88. Reversals
(1686454/1686455, Chris) also clean.
CRITICAL: the mapping fix does NOT retroactively heal the backlog. Each already-errored JE has
the blank GL cell saved on the record. ~116 pre-fix JEs (57 SOs, $19.1K, 8/21–8/24) remained in
the Error queue after the fix. Cleanup = open one, set the blank line to the cash account, Submit,
then use "Perform action and move to next Journal Entry" to chain the rest (no list round-trips).
Do the first pair, screenshot for Joe, then chain.
Growth curve — this is the headline number when re-reporting:
| Date checked | Error JEs | Sales orders | $ |
|---|---|---|---|
| 2026-08-21 | 10 | 5 | ~$422 |
| 2026-08-24 | 114 (of 117 total in queue) | 57 | $19,104.60 |
By accounting date on 8/24: 8/21 = 30 · 8/22 = 50 · 8/23 = 22 · 8/24 = 12 (still generating at 7:35 AM).
Creators: Tiffany Dao 57 · Alfonso Morataya 39 · David Camacho 18. All journal 32 - PARTS CASH SALES,
Reference Type Parts Sales Order.
Confirmed mapping evidence (SCT, Fixed Operations → Part & Accessories): both the
Online Parts Payments and Parts-Counter cards route Retail/ONLINE RETAIL → dept06 - Online Parts Sales (Parts) → 4748, and Wholesale/ONLINE WHOLESALE → dept 06 → 4731.
So revenue resolves under dept 06 but the holding account has no dept-06 row → blank line.
Reference JEs 8/24: errored sale 1685170 (SO 331575, $30.74) / deposit 1685169 ($17.74);
errored 1686431/1686430 (SO 331922). Working posted control = 1686437 (SO 331924, a counter
sale, dept 05) which shows 2045 - CASH SALES $8.98 in exactly the slot the errored ones leave blank.
Errored sale lines pattern: [BLANK] +deposit$ · 4748 −sale$ · 6748 +cost$ · 2410 −cost$ · 3140 −tax$.
Deposit JE pattern: 2045 - CASH SALES +$ · [BLANK] −$.
Traces to the 8/19/2026 SCT parts tax-code-setup migration that also dropped the ONLINE sale types
(see tekion-parts-tax-not-calculating-diagnosis).
Before re-diagnosing: check whether the dept-06 row was ever added — if not, LEAD with the growth
number, not with a fresh walkthrough of the same evidence.
5c. VC (Volkswagen of Clovis, 1891) — SO 71581 case, 2026-08-24
Second confirmed instance of the same class of defect, different store/slot:
- Error queue = exactly 2 JEs, both journal
32 - PARTS CASH SALES, Reference TypeParts Sales Order, Reference71581-1, created by Weston Truesdail 8/24 1:14 PM.121568sale, $216.64, Balance $0.00 →[Select] +116.65 · 4764 SLS-P+A CNTR WHL −116.65 · 5764 C/S +99.99 · 1445 INVENTORY −99.99121567deposit, $116.65, Balance $0.00 →1188 CASH SALES +116.65 · [Select] −116.65
- Blank slot in both = the parts cash HOLDING/offset account.
- Working control: SO 71539 (Charge Customer, wholesale) JEs
121275sale1188 CASH SALES +152.33 / 4764 −152.33 / 5764 / 1445and121274deposit1304 RECEIVABLES-CUST-SP+A +152.33 / 1188 CASH SALES −152.33. Same slot resolves to
1188 - CASH SALES there. - Discriminator: SO 71581 is the only recent VC counter sale paid by Check. Every posted
control (71504/71500/71495/71432/71539/71555/71522) is Charge Customer. Charge routes to AR
(1304) via Payment Receipts → Fixed Operations → Parts Payment Methods; Cash/Check/Card all map
to1188 - CASH SALESthere — so on a Check sale the payment-method account and the holding
account are the same 1188, and the holding lookup comes back empty. - Structural diff vs SCT: VC's Fixed Operations → Others has one rule only
(FIXED OPERATIONS SALES TAX, 4 sales-tax rows). SCT has an additionalFixed Operations (Other)
rule that carries Parts Cash Holding Account / Service Cash Holding Account. VC has no
Parts Cash Holding Account mapping at all. ← most likely root cause, but NOT 100% proven
(unexplained: how 1188 resolved into that slot on the Charge JEs). Per NEVER-GUESS, flag the
residual uncertainty rather than asserting. - Correction path: SO is Closed+Paid → cannot reopen or void (see
tekion-parts-sales-orders).
Fix the mapping, then reopen each Error JE and Submit.
VC nav notes (cost ~10 turns)
/accounting/glaccountmapping/listrandomly redirects to whatever SPA route was last hot
(/parts/tax-code-setup,/parts/parts-settings,/parts/inventory/part,/parts/default-part-pricing).
Always loop the navigate up to 4–5× assertinglocation.hrefcontainsglaccountmapping.- Deep-link by module instead of clicking the nav:
?module=FO_OTHERS,?module=PAYMENT_METHODS_FIXED_OPS,?module=FO_SERVICES,?module=FO_WARRANTY_CREDIT. Far more reliable than the accordion. - Left-nav leaf clicks at x≈123 land on the label text and mis-fire; click at x≈300 (row
body) instead. Also collapseVariable Operationsfirst soOtherssits above the fold. - The mapping cards (
FIXED OPERATIONS SALES TAX,Parts Payment Methods) are collapsed by
default — click the card title leaf to expand before readinginnerText. - Sales Order list search: type into
input[placeholder='Ctrl + Shift + L']+ Enter. Filters
block it — clickClear(leaf at ≈396,181;Resetat ≈306,181 does NOT clear) first or you get0 Result(s)on a real SO. Results are prefix-ish and the previous rows stay below, so read only
the first block afterDep. Name.
5d. TL (Toyota of Lancaster, 1092) — SO 863805 / JE 877332, 2026-08-29 — the NON-defect bucket
This is the case that proves not every Error JE has anything wrong with it. Joe asked about
one SO going into JE error; the reflex was "another mapping gap like SCT/VC." It was not.
JE 877332 — journal 32 - PARTS CASH SALES, doc type 4 - Parts Invoice,WHOLESALE - Part Sale - 863805-1, 8/28/26, Jorge Belmontes:
2100 ACCTS RCVBLE-CUST +103.12 control 1322103
4750 SLS-PARTS WHSL-MECH -103.12
6750 C/S-PARTS WHSL-MECH +96.85
2410 PARTS-TOYOTA (EX TIRES) -96.85
Debit 199.97 = Credit 199.97 · Balance $0.00 · all 4 GLs resolved · NO blank lineHow it was ruled out as a defect (reuse this method):
- Diff against posted siblings with matching scope — same customer control (
1322103), same
day, same journal, same doc type. Found 7 posted twins (877289 877291 877293 877299 877305 877329) that are byte-for-byte the same shape, same accounts, same control type, samecount
flags. If a posted twin exists with an identical structure, it is not a config gap. - Ask Tekion's own validator. The Aug-2026 "Error Detection and Resolution" feature exposes an
/error-reportendpoint on the JE — it returnederrorCount: 0for 877332. Tekion itself
cannot name a defect on the record. Always hit this before writing a diagnosis; it's the fastest
discriminator between "bad record" and "failed to post." - Look at the posting-batch timeline. Errors and successes were interleaved second-by-second:
10:15:33 ERROR 877282 · 10:16:27 POSTED 877285 · 10:16:51 ERROR 877287 · 10:17:27 POSTED 877289 · 10:24:21 ERROR 877309 · 10:30:02 POSTED 877329 · 10:30:17 ERROR 877332. Interleaving = a
per-transaction failure on Tekion's posting service, not an outage and not a config gap
(a config gap fails 100% of the matching sale type, deterministically). That day: 21 wholesale
parts JEs failed, 45 identical ones posted.
Conclusion + remedy: the 21 are valid entries that fell over on Tekion's side → just repost.
Open the JE → tick "Perform action and move to next Journal Entry" (bottom left) → Submit,
which chains straight to the next error. Change no GL account on these. A repost that fails
again on an untouched entry is the proof for the Tekion ticket.
Full TL error queue that day (29 open and still growing — 6 appeared during the session):
| # | Bucket | Real defect? |
|---|---|---|
| 21 | Wholesale parts sales, journal 32 (incl. 877332) | No — balanced, mapped, errorCount 0 → repost |
| 5 | IMBALANCE_TRANSACTION — ROs 398883, 397786, 398859, 396920 + Warranty Credit Memo 874332 ($125,525.71) |
Yes — Dr ≠ Cr, lines truncated → accounting rebuilds |
| 3 | COST_CENTER_NOT_FOUND — internal ROs 398649, 398467, 394780 |
Yes — cost centre 66abf46265ab9216a9e72a0a unmapped, line-1 GL is null |
Escalation packet for a Tekion ticket (this framing is what makes it undeniable): pair
877332 (ERROR) against 877329 (POSTED) — same customer, same journal, same doc type, same
four GL accounts, 15 seconds apart, and Tekion's own error-report returns errorCount: 0 on
the failed one.
Pull the JE from the accounting API, not the DOM
This whole diagnosis was done read-only against the accounting API (captured axios headers replay
from plain urllib, same as the other internal Tekion endpoints). Much faster than the virtualized
list + react-select scraping in §2–3, and it gives you count flags, control numbers, error codes
(IMBALANCE_TRANSACTION, COST_CENTER_NOT_FOUND) and the /error-report result that the UI
never surfaces. Use the API for the diagnosis; use the UI only when Joe needs to click something.
5e. HARD RULE — Joe owns the GL writes
Established 2026-08-29 on this case: Jay offered to fire the 21 resubmits; Joe said "don't want
you to resubmit. What can I do on my end."
- Never resubmit/repost a journal entry, add a GL mapping row, or change accounting setup
without an explicit, unambiguous go-ahead. Reposting writes to the general ledger. - The general AUTOMATION MANDATE (run it yourself, ship automation) applies to reports, scrapers,
opcodes — not to posting to the GL. - Offer the action, state plainly that it's a real GL write, then stop and wait.
- Default deliverable for accounting issues = diagnosis + exact click-path Joe can execute,
split by who owns each bucket (Joe / accounting / Tekion), plus an offer to draft the vendor ticket. - Read-only lookups (resolving a cost-centre ID to its name, pulling JE lines) are fine unprompted —
say "read-only, no changes" so he knows.
6. Reporting to Joe
He wants: the count, the pattern (grouped by order/creator/journal — not 10 unrelated bullets), the
exact blank line quoted against a working posted example, the one-sentence root cause, and the fix
he could apply. Explicitly restate that you changed nothing. If an ID he gave doesn't resolve, say so
and ask what it is rather than guessing (7-digit JE IDs prefix-match, so a 6-digit number will return
a bogus 10-row "hit" — don't present that as the answer).
Split the queue by OWNER, not just by symptom (§5d table is the model): which JEs Joe can repost
himself, which need a config row, which accounting has to rebuild, and which are Tekion's defect.
Lead with the largest bucket and its remedy. Offer to draft the vendor ticket text.
Do NOT lead with a mapping-gap story until you've confirmed a GL cell is actually blank — SCT
and VC were mapping gaps, TL was not, and pattern-matching to the previous store's root cause is
exactly the kind of confident-wrong answer Joe rejects.
Related skills
tekion-sitemap— nav base; Accounting URLs above are mirrored theretekion-parts-sales-orders— the source documents behind PARTS CASH SALES JEstekion-parts-tax-not-calculating-diagnosis— sibling "config gap causes wrong posting" pattern