Create/edit service discount coupons in Tekion's Coupon Management app (e.g. tire promos like Bridgestone B3G1, $-off or %-off labor/parts coupons). Covers the real URLs, form mechanics (old antd calendar, react-select GL account), toggle defaults, GL split conventions, and verification. Verified live at SCT 2026-08-02.
Install
npx skillscat add joecastelino/jay-skill-pack/tekion-coupon-management Install via the SkillsCat registry.
STOP — is it actually a coupon? Manufacturer tire promos (e.g. SCT's B3G1 Bridgestone Buy-3-Get-1) are often existing OPCODES, not coupons — "update the promo" means editing the opcode's Description verbiage at
/ro/opcode/edit/<CODE>. Search Opcode Management for the promo code FIRST before building anything in Coupon Management. (Burned 2026-08-03: built a B3G1 coupon; Joe: "NO!! no coupon. that was an opcode" — had to deactivate it. SCT B3G1 opcode customer desc = "MOUNT AND BALANCE FOUR TIRES"; promo verbiage rotates per promo period.)
Tekion Coupon Management — create/edit coupons
Verified live at SCT (dealer 876) 2026-08-02 building the Bridgestone B3G1 coupon.
All work via the :9223 persistent browser (load tekion-sitemap + persistent-browser-server first).
URLs (the real ones)
- Coupon List =
/core/coupons✅ — reach via nine-dots App Grid (icon at ~30,32) → search "coupon" → Coupon Management tile (/ Core). ⚠/core/coupon-managementrenders BLANK (107 chars);/coupon-managementbounces to /home. - Create =
/core/coupons/create - Edit =
/core/coupons/edit/<base64(couponCode)>— e.g. FLUID →RkxVSUQ=. Direct nav works; also clicking the coupon-code cell in the list opens it. - Permissions: Coupon Management Edit + View (KB0025143).
"Failed to apply coupon" on an RO? → load
tekion-coupon-not-applying-diagnosis.
The coupon is usually INNOCENT. The blocker is the OPCODE's Discount Eligible
checkbox (Opcode Management → Default → Labor Rate Configuration), which maps topriceDetails[].eligibleForPromotionsin the opcode search API — readable in
seconds without clicking anything. Verified TL 2026-08-25 (CABIN= false whileROTATE= true).
Reading an existing coupon fast
Edit URL = /core/coupons/edit/<base64(couponCode)> (LB10 → TEIxMA==). Dump the
whole config in one /eval:
(()=>{const i=[];document.querySelectorAll('input').forEach(e=>{if(e.offsetParent)i.push([e.id||e.placeholder,e.value])});
const s=[...document.querySelectorAll('.ant-switch')].map(x=>[x.parentElement.innerText.slice(0,55),x.className.includes('ant-switch-checked')]);
return JSON.stringify({i,s,txt:document.body.innerText.slice(document.body.innerText.indexOf('Edit Coupon'))});})()Gives coupon code/description/dates/value, every toggle state, and the Include
Services → Opcodes scope in one shot. Blank Expiry Date = never expires.
KB anchors
- KB0025143 — create-a-coupon field list.
- KB0026638 — coupon eligibility is gated at the OPCODE level ("Coupon Eligible" toggle in Opcode Management). If a valid active coupon won't attach to a job, check the opcode first. Also documents coupon Split (Customer Discount % vs Dealer Absorb %) and the not-applying checklist: Active? opcode in Applicable Opcodes? date range? usage limit?
Form mechanics (order matters!)
- Text fields (
#couponCode,#description): native value-setter + input+blur events works. - Dates — OLD antd calendar, NOT ant-picker.
/typeinto the "Select Date" input → HTTP 500. Instead:/mousethe date input to open the popup, then/mousethe day cell. Cells =.ant-calendar-date(there are 42; duplicates of a day number = current-month vs next-month cell — pick the one WITHOUTant-calendar-next-month-btn-dayon its parent). Next-month arrow =.ant-calendar-next-month-btn; header month check =.ant-calendar-my-select(reads e.g. "Sep2026"). - Dropdowns (Coupon Type / Applied On / Pricing Method): classic ant-select.
/mousethe select, options render as.ant-select-dropdown li— /mouse the option. Coupon Type = Flat | Target Selling Price. Applied On = Labor | Parts | Labor & Parts. Pricing Method = $ | %. - PITFALL — set dropdowns BEFORE value fields. The value input's id depends on Pricing Method:
$→#flatAmount,%→#percentage. A fallback regex like/flat|value/ican silently match#couponCode(contains no… it matched viavalue_undefined/couponCode fallback and OVERWROTE the coupon code with "25"). Always target the exact id and RE-VERIFY#couponCodeafterward. - GL Account (Cost Center split row) — react-select with a ~4px-wide invisible input. Find it by bounding-rect zone (the empty input in the split table row),
setAttribute('data-jay','gl'),/mouseits container, then/type {selector:"input[data-jay='gl']", text:"4702"}→ option "4702 - SLS - ASM DISCOUNT" appears →/mouseit. Then set the "Account Split" placeholder input to100via native setter. - Toggles (
.ant-switch, checked =ant-switch-checked): scrollIntoView +/mousecenter. Default state trap: "Allow Coupon to be added to the same RO more than once" starts ON — turn OFF unless multi-use wanted. "Apply coupon at RO, Appointment, Quote level" starts OFF — SCT convention is ON (matches FLUID/CABINANDAIRFILTER). - Save = bottom-right button (~1211,689). Success = toast "Coupon successfully created" and redirect to
/core/coupons. Verify with a true remount (nav /home → back to /core/coupons → find the code in the list) per the SAVE-VERIFY TRAP.
SCT conventions (from existing 27 coupons)
- GL split accounts: Labor → 4402 - SLS - ASM DISCOUNT, Parts → 4702 - SLS - ASM DISCOUNT, 100% split, Split By = Flat (Gross also used on % coupons e.g. CABINANDAIRFILTER).
- Pay Type = CP/Customer Pay, Pre-Tax.
- "Include Services" (service-type/opcode/skill filters) and "Include Parts" filters exist under Overrides once Applied On includes that side — CABINANDAIRFILTER uses Include Services w/ opcode list. Leaving filters empty = advisor applies manually to the right job.
Buy-3-get-1 (B3G1) pattern
4th-tire-free = 25% off Parts on the tire job (mathematically identical when all 4 tires are the same model, which the OEM promo requires). Decisions to flag to Joe: expiry = install-by date (grace week) vs sale-end date; optional Cap Amount as a guardrail since the % hits ALL parts on the job it's applied to.
Pitfalls recap
/core/coupon-management= blank trap; use/core/coupons./typeinto date fields = 500; use calendar cell clicks.- Value-field id switches with Pricing Method; verify couponCode wasn't clobbered.
- "Allow more than once" defaults ON.
- Edit-page reads are the fastest way to clone store conventions — open an existing similar coupon first and record its GL/toggles before creating.