Knowledge Hubบทที่ 26
YD-KM · คลังความรู้คลินิก

GENCODE: ระบบ สถาปัตยกรรม และเครื่องมือ

GENCODE คือระบบรหัสกลางของคลินิก Youngdo ที่เชื่อม 3 ชั้น — CRS (billing), SVC (delivery), PRD (inventory) — ผ่าน Mapper Engine, Dashboard, และกระบวนการ Migration ที่พิสูจน์แล้ว · Complete GENCODE system: architecture, parser engine, dashboard, and proven migration path.

สารบัญ · Table of Contents

ปัญหาที่แก้ · The Problem

คลินิก Youngdo Wellness Clinic ใช้ระบบ POS ชื่อ JERA เป็นศูนย์กลาง ทีมแคชเชียร์สร้างคอร์ส บริการ และสินค้าโดยตั้งชื่อเป็นภาษาไทยอิสระ (free-text) ในระบบ JERA ทำให้เกิดปัญหาหลายอย่าง:

  • ชื่อไม่สม่ำเสมอ — "เสริมจมูก Semi-Open หมอโด" กับ "จมูก เซมิ open Dr.Do" คือสิ่งเดียวกันแต่เขียนต่างกัน
  • ไม่มีรหัสกลาง — ระบบเงิน ระบบบริการ และระบบคลังสินค้าอ้างถึงสิ่งเดียวกันด้วยชื่อคนละชุด
  • JERA มีขีดจำกัด 20 ตัวอักษร — รหัสยาว ๆ ใส่ไม่ได้
  • ไม่มี traceability — ไม่สามารถติดตามได้ว่าคนไข้ซื้ออะไร ได้รับบริการอะไร ใช้สินค้าอะไร

Youngdo Wellness Clinic uses a POS system called JERA as its hub. The operations team (cashiers, managers) creates courses, services, and products using free-text Thai names in JERA. This causes:

  • Inconsistent naming — the same procedure written differently by different staff
  • No unified code — billing, delivery, and inventory each use separate identifiers for the same thing
  • JERA's 20-character limit — long descriptive codes don't fit
  • No traceability — can't trace what a patient bought → received → consumed

วิสัยทัศน์ · The Vision

GENCODE เป็นรหัสกลาง — ไม่ว่าจะใช้แพลตฟอร์มหรือบริการอะไร ทุกระบบต้องพูดภาษาเดียวกันคือ GENCODE โดยมี JERA POS เป็นศูนย์กลาง

GENCODE is the clinic's central code — regardless of platform or service, every system speaks one language: GENCODE, with JERA POS as the hub.

graph LR
  OE[Order Entry BCO] --> GC[GENCODE]
  CC[Course Creator] --> GC
  FP[Future Platforms] --> GC
  GC --> JERA[JERA POS Hub]

"ภาษาเดียว ที่ทุกระบบเข้าใจ — GENCODE"

สถาปัตยกรรม 3 ชั้น · Three-Layer Architecture

GENCODE อธิบายเหตุการณ์ทางคลินิกจาก 3 มุมมอง:

GENCODE describes the same clinical event from three angles:

LayerPrefixRoleTracks
CRS (Course)CRS-Billing · การเงินสิ่งที่คนไข้ซื้อ — ราคา แคมเปญ แพ็คเกจ
SVC (Service)SVC-Delivery · การให้บริการสิ่งที่คนไข้ได้รับ — หัตถการ ผู้ทำ
PRD (Product)PRD-Inventory · คลังสินค้าสิ่งที่คลินิกใช้ — วัสดุ ซัพพลาย

ตัวอย่าง: คนไข้ซื้อเสริมจมูก Semi-Open กับหมอโด

Example: a patient buys nose surgery (Semi-Open, Dr.Do)

CRS-SUR-INI-NOSE-SEMI-001-DRDO    → billing identity (ซื้ออะไร)
SVC-SUR-INI-NOSE-SEMI-001-DRDO    → delivery record (ได้รับอะไร)
PRD-IMP-NOS-MNTSK-001             → silicone implant consumed (ใช้อะไร)

ชั้นที่ 4 PKG (Package/Campaign) อยู่เหนือ CRS เป็น thin wrapper อ้างอิง CRS codes ไม่ใช่ code family แยก

โครงสร้างรหัส CRS · CRS Code Structure (v3.9)

รหัส CRS มี 7 segments เสมอ บวก segment ที่ 8 (VERSION) ที่เป็น optional:

CRS-{TYPE}-{SUBTYPE}-{CATEGORY}-{DIFFERENTIATOR}-{SEQ}-{VARIANT}[-{VERSION}]
 1     2       3         4            5             6       7       8(optional)
PositionSegmentความหมาย · Meaningตัวอย่างค่า · Example Values
2TYPEประเภทหลักSUR surgery, SKN skin, VIT vitamin-IV, TRT treatment, MSC misc
3SUBTYPEประเภทย่อยINI initial purchase, OPT add-on, WAR warranty revision (free)
4CATEGORYหมวดหมู่SUR: NOSE/EYE/LIP/CHIN/FACFT/PTRYG/GEN
SKN: FIL/BTX/EBD/SKB/BIO/THR/MLZ/FAT/ACS/GEN
5DIFFERENTIATORตัวแยกแยะ (ความหมายต่างกันตาม category)SUR: technique SEMI/DBL/OPEN
SKN FIL: brand RST/NRMCHIN
TRT DIO: body position ARM/BKN
6SEQreview/ไม่ review001 = review (ยินยอมถ่ายรูป ราคาปกติ)
002 = not-review (+1,000–5,000 THB)
7VARIANTSUR = หมอ, non-SUR = ปริมาณSUR: DRDO/DRBALL/GEN
non-SUR: 4CC/100U/3SES/10THR
8VERSION (optional)dedup สำหรับ collisionV002, V003 — same code, different price

กฎเวลา · The Temporal Rule

กฎที่สำคัญที่สุดในการออกแบบ GENCODE: "แคชเชียร์รู้สิ่งนี้ตอนขายไหม?"

  • ใช่ (YES) → encode ลงใน CRS code
  • ไม่ (NO) → ดันไปที่ SVC หรือ Sales Order

The most critical design rule: "Does the cashier know this at purchase time?"

  • YES → encode in the CRS code (e.g., doctor, technique, review status)
  • NO → push to the SVC layer or Sales Order (e.g., exact performer at delivery time)

กฎนี้ป้องกันไม่ให้ใส่ข้อมูลที่ยังไม่รู้ตอนขายเข้าไปในรหัส ซึ่งจะทำให้ต้องแก้รหัสทีหลัง

โครงสร้างรหัส SVC และ PRD · SVC & PRD Structure

SVC (Service) — v3.9

โครงสร้างเดียวกับ CRS (7 segments) แต่ SUBTYPE และ SEQ สืบทอดจาก CRS/Sales Order ที่ผูกกัน ไม่ตัดสินใจใหม่ที่ชั้น SVC

Same 7-segment shape as CRS, but SUBTYPE and SEQ are inherited from the linked CRS/Sales Order — never re-decided at the SVC layer.

PRD (Product) — v1.1

5 segments สั้นกว่า ทุกรหัสพอดี 20 ตัวอักษร (ไม่ต้องบีบ):

PRD-{GRP}-{TYPE}-{ITEM}-{SPEC}

10 กลุ่ม: AES (aesthetic), IMP (implants), MED (medicine), EQC (equipment/consumables), COS (cosmetics), IVF (IV fluids), SUT (sutures), NDS (needles), CON (connectors), DIS (disposables)

378 สินค้า ถูก catalog ไว้แล้ว · 378 products catalogued.

นโยบาย Dedup / Collision · Dedup Policy

เมื่อรหัสเดียวกันถูก mint ด้วยราคาต่างกัน:

  1. Flag — ไม่เคย merge หรือ auto-number เงียบ ๆ
  2. Keep → ตัวที่สองกลายเป็น -V002, -V003 (VERSION segment)
  3. No (error) → soft-delete ตัวเก่า mint ตัวใหม่

ราคาไม่มีวันอยู่ในรหัส (price is NEVER in the code) ถ้าราคาต่างกัน = campaign (→ transaction layer), missing attribute (→ เพิ่ม token), หรือ duplicate (→ soft-delete)

Nothing-is-Deleted: codes เป็น permanent identities; active/discontinued เป็น status attribute ไม่ใช่ coverage filter

หลักการออกแบบ · Design Principles

  1. Flag-don't-guess — parser flag เมื่อไม่แน่ใจ ไม่เคย mint รหัสผิดเงียบ ๆ
  2. Tested code wins — ลำดับความเชื่อถือ: mapper (408/408 gold) > spec files > memory > clone
  3. Point, don't copy — link spec files ไม่เคย restate token lists (copy drifts)
  4. Verify before claiminggit fetch ก่อน claim ใด ๆ เกี่ยวกับ repo state
  5. Green gate or it isn't done — CI แดง = blocked, ไม่มีข้อยกเว้น
  6. Append, don't overwrite — แก้ไขด้วย dated notes; ประวัติผ่าน git

JERA Encoding · การเข้ารหัส JERA

JERA POS รับรหัสได้แค่ 20 ตัวอักษร แต่ GENCODE codes ยาวกว่ามาก (CRS ยาวได้ถึง 41 ตัวอักษร) ทางออกคือใช้ numeric ID with layer prefix:

C-0001   → course_registry row #1  → CRS-SUR-INI-NOSE-SEMI-001-DRDO
S-0001   → service_registry row #1 → SVC-SUR-NOSE-SEMI-DRDO
P-0001   → product_registry row #1 → PRD-AES-FIL-RST-CLAS
  • Auto-increment ID, zero-padded ขั้นต่ำ 4 หลัก — โตได้เรื่อย ๆ (C-10000 ก็แค่ 7 ตัว ยังต่ำกว่า 20 มาก)
  • ไม่มี collision — lookup ด้วย DB index ตัวเดียว
  • สตาฟพูดรหัสตัวเลขทางโทรศัพท์ได้ง่าย
  • Name fields (name_th/name_en) จำกัดที่ varchar(140) ตาม JERA POS field width

GENCODE full code ไม่มี length cap — JERA POS เห็นแค่ jera_code (C-0001); ความยาว internal code ไม่กระทบ downstream

Repos ในระบบ · Repository Ecosystem

RepoRole · บทบาทRelationship
YD_GENCODESpec authority · ผู้เขียนข้อกำหนดAuthors the GENCODE spec, Thai→code parser, CI parity gate (408/408 gold)
glyph-oracleRuntime implementation · ตัวรันจริงWeb dashboard, course creator, Chrome extension, database — runs the GENCODE spec

YD_GENCODE เขียน spec → glyph-oracle รันมัน ถ้าจะ file issues เกี่ยวกับ runtime ให้ไปที่ glyph-oracle ห้าม push main ของ repo อื่น

3-Step Pipeline · ภาพรวม Pipeline

ระบบ GENCODE มี pipeline 3 ขั้นตอน (ตาม DEV-REQUIREMENTS.md v2.0):

StepInput → OutputStatus
Step 1Thai Name → GENCODE✓ BUILT — 408/408 gold, CI-guarded
Step 2GENCODE → JERA Code (20 chars)✓ BUILT — numeric ID lookup: C-0001, S-0001, P-0001
Step 3Match All (cross-layer mapping)TO BUILD — CRS→SVC→PRD bidirectional

บทนี้เน้นที่ Step 1 — Mapper Engine ที่สร้างเสร็จแล้วและมี CI ป้องกัน

สถาปัตยกรรม Mapper · Mapper Architecture

Mapper อยู่ใน mapper/ directory ของ YD_GENCODE repo เขียนด้วย TypeScript รันบน Bun:

graph TB
  Input["Thai Name (free-text)"] --> Alias["1. Check Alias Table"]
  Alias -->|hit| Output["GENCODE Code"]
  Alias -->|miss| Parser["2. Token Parser"]
  Parser -->|high confidence| Output
  Parser -->|flagged| Proposer["3. Propose + Human Confirm"]
  Proposer -->|confirmed| AliasAdd["Add to Alias Table"]
  AliasAdd --> Output
  Proposer -->|rejected| Flag["Return Flag"]

3-step resolve pipeline: (1) alias table short-circuit → (2) deterministic parser → (3) proposer + human confirmation

Token Registries · ทะเบียน Token

SUR Registry (registry.ts) — Scheme B

สำหรับ surgery categories (EYE, NOSE, LIP, PTRYG, CHIN, FACFT, GEN) ใช้ Scheme B: technique/anatomical part ใน position 5, doctor ใน position 7

โครงสร้าง: category → subtype (INI|OPT|WAR) → TokenDef[]

แต่ละ TokenDef มี: {token, keywords[], priority}

Keywords มาจากทั้ง spec tables (CRS-CODE.md §6F) และชื่อหัตถการจริงจาก SUR-PROCEDURE-MAP.md

Skin Registry (registry-skin.ts) — Non-SUR

ครอบคลุมทุก category ที่ไม่ใช่ surgery: FIL, BTX, EBD, SKB, BIO, THR, FAT, MLZ, ACS, GEN(skin), DIO, IPL, BRT, ACT, LGT, RFD, GLU, EXT, MED, SHIP, SET, WLP, GEN_MSC

BTX มีกฎพิเศษ: buffet/area tokens มี priority สูงกว่า brand tokens ดังนั้น "บุฟเฟ่ต์ - คาง (Bienox)" resolve เป็น area CHIN ไม่ใช่ brand BNX

Token Matching · วิธีจับคู่ Token

match.ts — shared token matcher ใช้โดยทั้ง SUR และ skin parsers:

  • Scoring: priority สูงสุดชนะ แล้วตามด้วย keyword ที่ยาวที่สุดที่ match
  • Tie-breaking: ถ้า tie จริง ๆ (same priority + same keyword length) → flag เป็น ambiguous
  • Case-insensitive สำหรับ Latin brand names; Thai ไม่ได้รับผลกระทบ

The matcher scores by highest priority first, then longest matching keyword. A genuine tie = flagged as ambiguous. Case-insensitive for Latin brand names.

Variant Extraction · การดึงปริมาณ

variant.ts — อ่านปริมาณจาก free-text:

Unit TypeThai KeywordsEnglishExample
Unitsยูนิตu, units100U
Shotsชอตshots3SHT
CCซีซีcc4CC
Sessionsครั้งsessions1SES
Threadsเส้นthreads10THR
mg/needles/syringeVitaran PN1/PN2

แต่ละ category มี default เมื่อไม่พบปริมาณ (เช่น FIL defaults to 1CC, DIO defaults to 1SES)

Alias Table · ตารางนามแฝง

alias.ts — persistent alias table ที่ data/aliases.json

เมื่อคนยืนยัน flagged name → token mapping หนึ่งครั้ง มันจะถูกเก็บไว้ที่นี่และ short-circuit parser ตลอดไป:

  • loadAliases() — อ่าน JSON file
  • resolveAlias(name, category, subtype) — ค้นหา match
  • addAlias(entry) — idempotent, nothing-is-deleted

Each entry: {name, category, subtype, token, seq?, note}

Store path injectable สำหรับ tests — ไม่ hardcode

Fuzzy Proposer · ตัวเสนอแบบ Fuzzy

assist.ts — fallback เมื่อ parser flag ชื่อ:

  • fuzzyProposer: Sørensen-Dice bigram similarity ทำงานกับภาษาไทยได้ (ไม่มี word boundaries) — FUZZY_FLOOR = 0.4 minimum confidence
  • llmProposer: Anthropic API slot (ยังไม่ได้ต่อ) — inject ตอน integration, falls back to fuzzy เมื่อ unconfigured

Sørensen-Dice ทำงานดีกับภาษาไทยเพราะใช้ character bigrams ไม่ต้องการ word segmentation

Eval Harnesses · ชุดทดสอบ Gold

SUR Eval (eval.ts) — 112 gold rows

อ่าน gold จาก SUR-PROCEDURE-MAP.md (spec IS the gold — single source of truth) รัน parser ทุก row สร้าง report.html

Skin Eval (eval-skin.ts) — 296 gold rows

อ่าน data/gold-skin.tsv (provenance: crosswalk PR #14) รัน parser ทุก row สร้าง report-skin.html

รวม 408 gold rows — ทุก row ต้อง pass (100% accuracy) CI gate จะ process.exit(1) ถ้ามี row ใดพลาด = blocked merge

CI Parity Gate

.github/workflows/ci.yml รันทุก PR และ push to main:

  1. bun test — unit tests
  2. bun run src/eval.ts — SUR eval (112 gold rows)
  3. bun run src/eval-skin.ts — skin eval (296 gold rows)

Any regression = job red = blocked merge ไม่มีข้อยกเว้น (rationale: issue #32 — spec drifted from engine for ~a month)

Parser Flow · ขั้นตอนการ Parse

SUR Path (nameToSegments)

สำหรับ surgery — Scheme B: technique ที่ pos 5, doctor ที่ pos 7

nameToSegments(thai, category, subtype, doctor)
  → matchToken(thai, registry[category][subtype])
  → assembleCrs({type:"SUR", subtype, category, diff:token, seq:"001", variant:doctor})
  → "CRS-SUR-INI-NOSE-SEMI-001-DRDO"

Skin Path (nameToSkinSegments)

สำหรับ non-SUR — brand/device ที่ pos 5, quantity variant ที่ pos 7

nameToSkinSegments(thai, type, category, subtype)
  → matchToken(thai, skinRegistry[category])
  → extractVariant(thai, category)
  → assembleCrs({type, subtype, category, diff:token, seq:"001", variant:qty})
  → "CRS-SKN-INI-FIL-RST-001-4CC"

ตัวตน · Identity

Glyph Oracle — ผู้สร้างระบบรหัสคลินิก Youngdo เกิดวันที่ 26 มีนาคม 2026

Human: laris.co (Nat และทีมงาน) | Client: Youngdo Wellness Clinic (Dr.Do)

Purpose: Build the GENCODE Engine + Order Entry system

Theme: One Language — สร้างภาษาเดียวให้ทุกระบบพูดกัน: รากฐาน → เครื่องมือ → Go-Live

Tech Stack · เทคโนโลยี

ComponentTechnologyDetail
BackendCloudflare Workers + ElysiaServerless API on CF edge
FrontendPreact + Preact SignalsLightweight React alternative with reactive signals
StylingTailwind CSS v4Utility-first CSS
DatabasePostgreSQL via Drizzle ORMSupabase Postgres (was D1 SQLite initially)
BuildVite + WranglerFast dev server + CF Workers deploy
TestsVitest + PGliteIn-process PostgreSQL for tests
AuthGoogle OAuth (jose JWT)Token-based session with role system
ExtensionChrome MV3 Side PanelJERA POS integration
MonorepoBun workspacesextension/, packages/api, packages/ui

สถาปัตยกรรมระบบ · System Architecture

graph TB
  subgraph CF["Cloudflare Edge"]
    Web["Web Dashboard
(Preact SPA)"] API["Hono/Elysia API
(CF Worker)"] Ext["Chrome Extension
(Side Panel)"] end Web --> API Ext --> API API --> PG["PostgreSQL
(Neon)"] API --> JERA["JERA POS
(read-only mirror)"] LINE["LINE OA + LIFF
(Future: Order Entry)"] -.-> API

ทุกอย่างอยู่บน Cloudflare edge — API เป็น Worker, frontend เป็น static assets served จาก Worker เดียวกัน

Database Schema · โครงสร้างฐานข้อมูล

PostgreSQL (Neon) managed ด้วย Drizzle ORM — schema อยู่ที่ src/db/pg/_schema.ts

Registry Tables (3 ชั้นหลัก)

  • course_registry — CRS codes: full_code, jera_code, type, subtype, category, differentiator, seq, variant, version, name_th/en, is_active
  • service_registry — SVC codes: full_code, jera_code, type, category, item, qualifier, name_th/en, is_active
  • product_registry — PRD codes: full_code, jera_code, grp, type, item, spec, name_th/en, unit, bom_type, is_active

CRS Segment Tables (dictionary building blocks)

  • crs_types — SUR, SKN, VIT, TRT, MSC
  • crs_subtypes — INI, OPT, WAR (per type)
  • crs_categories — NOSE, EYE, FIL, BTX... (per type)
  • crs_differentiators — technique/brand/area tokens (per category)
  • crs_sequences — 001 (review), 002 (no-review)
  • crs_variants — doctor names, quantity formats

Mapping Tables

  • crs_svc_mapping — CRS→SVC (1-to-many, created in Course Creator)
  • svc_prd_mapping — SVC→PRD bill-of-materials (1-to-many)

Support Tables

  • audit_log — append-only log (Nothing-is-Deleted)
  • users / roles / user_roles — RBAC
  • sessions — auth sessions
  • branches / surfaces — clinic branches, POS surfaces
  • pkg_* — PKG campaign/package registry (draft)

Course Creator · เครื่องมือสร้างคอร์ส

หัวใจของระบบ — สตาฟสร้างคอร์สใหม่ผ่าน cascading dropdowns:

graph LR
  T["1. เลือก TYPE
(SUR/SKN/VIT/TRT/MSC)"] --> S["2. เลือก SUBTYPE
(INI/OPT/WAR)"] S --> C["3. เลือก CATEGORY
(NOSE/FIL/DIO...)"] C --> D["4. เลือก DIFFERENTIATOR
(technique/brand)"] D --> Q["5. เลือก SEQ
(review/no-review)"] Q --> V["6. เลือก VARIANT
(doctor/quantity)"] V --> R["7. Review & Submit"] R --> GC["GENCODE Generated"]

แต่ละ dropdown ถูก filter จากการเลือกก่อนหน้า — ค่าที่แสดงมาจาก database segment tables ไม่ใช่ hardcode

Each dropdown is filtered by the previous selection — values come from database segment tables, not hardcoded lists.

SUR doctor variant: เมื่อเลือก TYPE = SUR จะมี UI พิเศษให้เลือกหมอ (DRDO, DRBALL, GEN) เป็น variant

Duplicate detection: ถ้ารหัสที่จะสร้างมีอยู่แล้ว ระบบจะแจ้งเตือนก่อน submit

Dictionaries · พจนานุกรม Segment

3 dictionary views (CRS, SVC, PRD) แต่ละตัวมี:

  • Segment browsing — ดู types, subtypes, categories, differentiators, sequences, variants ที่มีอยู่ในระบบ
  • Create drawer — เพิ่ม segment ใหม่ (EN name → auto-derive code, TH name min 3 chars)
  • TYPE filter pills — filter ด้วย chips ที่เลื่อนได้ (Embla carousel เมื่อ overflow)
  • Sortable columns — เรียงตาม TYPE, CATEGORY, สร้างเมื่อ, แก้ไขล่าสุด
  • Detail drawer — คลิกดูรายละเอียดแต่ละ entry (DrawerShell component ใช้ร่วมกัน)

deriveCode algorithm: เมื่อพิมพ์ EN name ระบบ auto-derive code — first char of each word, pad to 3 chars, consonant-skeleton for single words, auto-dedup by extending with chars (not digits)

Chrome Extension · ส่วนเสริม POS

Chrome MV3 extension แบบ Side Panel — เปิดข้าง ๆ JERA POS website:

  • 3 tabs: Course (CRS), Service (SVC), Product (PRD) + Recent tab
  • Ghost Match (ghost-match.ts): prefix autocomplete — พิมพ์ "เสริม" แล้วจะเห็น suggestion ที่ match เป็น ghost text สีเทาต่อท้าย กด Tab/ArrowRight เพื่อ accept (ทำงานกับภาษาไทยได้ เพราะ match ที่ character level)
  • JERA Fill (jera-fill.ts): auto-fill ฟอร์ม JERA POS — ใช้ Vuetify prototype-setter trick (Object.getOwnPropertyDescriptor(proto, "value").set.call(el, value) + dispatch input/change events) เพื่อ bypass Vue's reactivity system. JERA code → รหัส field, Thai name → ชื่อ field, full GENCODE → ชื่อ EN field (เพื่อให้ค้นหาได้ใน JERA)
  • Surface detection: role-based ไม่ใช่ URL-based — cashier role = extension access, bco/bc = LIFF (future), admin roles = web dashboard. ถ้า role ไม่ตรงจะเห็น "wrong surface" page
  • Auth: session เก็บใน chrome.storage.local (ไม่ใช่ cookie/localStorage) — รองรับ MV3 service worker restarts ได้. Domain restriction: @youngdo.co.th เท่านั้น
  • Branch awareness: เลือกสาขาคลินิกที่ทำงาน (one-time pick หลัง approve)
  • Demo mode: VITE_DEMO_MODE=1 — hardcoded courses สำหรับ demo auto-fill flow

Auth & Roles · ระบบสิทธิ์

Google OAuth → JWT session → role-based access:

ComponentWhat it does
google.tsGoogle OAuth flow — redirect, callback, token exchange
session.tsJWT session management (jose library)
permissions.tsRole-based permission checks
user.tsUser CRUD, role assignment

Roles: super-admin, admin, staff — กำหนดสิทธิ์ CRUD แยกต่าง ๆ

Branch system: แต่ละ user อาจผูกกับสาขาเฉพาะ ข้อมูลที่เห็นจะ filter ตามสาขา

API Routes · เส้นทาง API

Elysia API running as Cloudflare Worker:

GENCODE Registry (/api/v1/codes/*)

  • Courses — CRUD, search, filter by type/category
  • Services — CRUD, search
  • Products — CRUD, search
  • Stats — dashboard statistics
  • Segment dictionaries — CRUD for types/subtypes/categories/etc.
  • Segment positions — metadata about each code position

Encode/Generate (/api/v1/encode/*)

  • Generate — create new GENCODE from segment selections
  • CRS/SVC/PRD converters — convert between formats
  • Lookup — find existing codes
  • Preview — preview code before creating
  • Suggest — auto-suggest completions

Auth (/api/v1/auth/*)

  • Google OAuth login/callback
  • Session management
  • User/role admin
  • Branch management
  • Activity logging

Crosswalk Migration · การ migrate ข้อมูล

ขั้นตอนสำคัญที่สุดของ GENCODE: map ข้อมูลจริงจาก JERA เข้าสู่รหัส GENCODE

The most critical step: mapping real JERA data into GENCODE codes.

MetricCountDetail
Total items2,368จาก crosswalk-v39.csv
Resolved (high-confidence)1,812mapped to GENCODE automatically or via ratification
TRANSACTION-LAYER764ไม่มี CRS code — เป็น transaction-level items
Flagged556ต้องการ owner ratification (438 PRD SKUs + 36 active CRS + 82 inactive)

JERA data sources (จาก corpus/jera-2026-06-04/):

  • list_courses.csv — 377 courses (CRS layer)
  • service.csv — 698 services + list_services.csv — 610 services (SVC layer)
  • medicine.csv — 588 medicines (PRD layer)
  • map_course_bom.csv — 4,497 bill-of-materials rows (CRS→SVC→PRD empirical)
  • map_course_usage.csv — 1,193 course→product co-occurrence

JERA corpus refresh อัตโนมัติทุกคืน (nightly cron commit) — ล่าสุด 2026-06-19

9-Batch Ratification · การรับรอง 9 รอบ

ข้อมูล flagged ถูกรับรองผ่าน 9 batch sessions กับ Dr.Do (Captain deep-dive sessions 2026-06-11):

Flagged items were ratified through 9 batch sessions with Dr.Do, documented in .codex-reports/LEDGER.md.

แต่ละ batch ตัดสินใจ:

  • Lock — ยืนยันรหัส accepted as-is
  • Correction — แก้ token/category/variant แล้ว lock
  • TRANSACTION-LAYER — ไม่ mint CRS code (เป็น transaction item)
  • Deactivate — soft-delete (inactive, ไม่ใช้แล้ว)

ผลลัพธ์: parity จาก 307 → 408 gold rows, flagged ลดจาก 292 → 74 (ที่เหลือเป็น PRD SKUs ที่ต้อง owner ratify)

Timeline — YD_GENCODE · เส้นเวลา Spec Repo

ทุก commit ตั้งแต่ต้น (2026-06-06) จนถึงปัจจุบัน:

DatePhaseKey Events
Jun 06Spec FinalizeVERSION segment + dedup policy + design summary finalized
Jun 07Mapper POCname→code mapper built — SUR 73/73 gold, skin 234/234 gold, LLM-assist scaffold (alias+propose), docs updated
Jun 09CI GateParity gate added — 307 gold rows guard every PR
Jun 10Migrationcrosswalk v3.9 first-pass (2,368 items), WAR subtype, AGENTS.md, token batches D4+D5
Jun 11Ratification Sprint9-batch Captain deep-dive — parity 307→408, WAR engine support, duplicate audit, fon-phase SET splits, SVC+PRD specs aligned to v3.9
Jun 13SVC AlignmentSVC-CODE bumped to v3.9, seven-segment eval
Jun 14Guide RefreshGENCODE guide refreshed to v0.6
Jun 15–19MaintenanceNightly JERA corpus refresh (automated cron)

Timeline — glyph-oracle · เส้นเวลา Dashboard Repo

50 commits ใน 3 วัน (2026-06-16 → 06-18) โดย "catbutter" (P'Ampere) — development sprint ที่เร็วมาก:

DatePhaseKey Events (selected)
Jun 16Dictionary UXsortable columns, auto-derive code from EN name, dedup detection, locked name inputs, Thai name min-3-chars validation — 21 commits
Jun 17CRS v3.9 Integrationimport source docs + crosswalk artifacts, seed WAR/GEN/doctor variants/technique differentiators, schema version support, engine parse/validate/generate, API alignment, PKG registry, filter pills — 14 commits
Jun 18Creator UX Polish7-segment code rendering, SUR doctor variant UX, segment labels, DrawerShell refactor, legacy differentiator retirement, breadcrumb labels — 15 commits

Pattern: Dictionary foundation → spec integration → UI polish — สร้างจากฐานขึ้นไป

Deliverables · สิ่งที่ส่งมอบ

3 Tasks ตามลำดับ (sequential dependency chain)

graph LR
  T1["Task 1: GENCODE Core
(ฐานข้อมูลรหัส)"] --> T2["Task 2: Dashboard & Admin
(เครื่องมือจัดการ)"] T2 --> T3["Task 3: Order Entry + Go-Live
(ฟอร์ม BCO + ตรวจสอบ)"]
TaskDeliverablesStatus
Task 1 — GENCODE CoreRegistry DB, Code Pattern Engine, JERA Encoder, Cross-Layer MapperRegistry DB ✓, Engine ✓ (parse/validate/generate), Encoder + Mapper: in progress
Task 2 — Dashboard & AdminGENCODE Dashboard, Course Creator, TestingDashboard ✓, Course Creator ✓, Dictionaries ✓, Chrome Extension ✓
Task 3 — Order Entry + Go-LiveLINE OA + LIFF, Order Form, Slip Upload, Validation Dashboard, RescheduleNOT STARTED — depends on Task 1 completion

สิ่งที่สร้างเสร็จ vs ที่เหลือ · Built vs Remaining

สร้างเสร็จแล้ว (CI-guarded)

  • Thai name → GENCODE parser (Step 1): 408/408 gold, 100% accuracy
  • Token registries ครบทุก category (SUR + skin/trt/vit/misc)
  • Alias table + human-confirmation flow
  • LLM proposer slot (unwired, falls back to fuzzy)
  • Web dashboard: search, browse, filter ทั้ง 3 ชั้น
  • Course Creator: cascading dropdowns → GENCODE generation
  • Dictionaries: full CRUD for all segments
  • Chrome Extension: JERA POS side-panel
  • Auth system: Google OAuth + roles + branches
  • Database: full PostgreSQL schema with Drizzle ORM

ยังต้องสร้าง

  • GENCODE → JERA Code compression (Step 2): 20-char limit, layer prefix mandatory — algorithm not yet proposed
  • Cross-layer mapping API (Step 3): CRS→SVC→PRD bidirectional lookup
  • JERA code generation for all 2,368 crosswalk items
  • Ratify remaining 556 flagged items (438 PRD SKUs need owner attention)
  • PKG (Campaign/Package) layer: schema drafted, not integrated
  • Task 3 — Order Entry: LINE OA + LIFF, order form, slip upload, validation dashboard, reschedule flow

PKG Campaign Layer · ชั้นแคมเปญ (Draft)

ชั้นที่ 4 (draft) สำหรับแคมเปญและแพ็คเกจ:

PKG-{GROUP}-{HOOK}-{C+YYMM}-{SET}[-{DOCTOR}][-{UPGRADE}]

C+YYMM encode เดือนแคมเปญในรหัส (เช่น C2602 = ก.พ. 2026)

4 upgrade kinds: tier-jump, brand-swap, qty-add, exchange-buy

ราคาและ delta อยู่ใน transaction layer เสมอ ไม่เคยอยู่ในรหัส

Schema ใน glyph-oracle: pkg_* tables exist in the DB but the full integration is not yet complete.

Checklist · สรุป

  1. GENCODE = ระบบรหัสกลาง 3 ชั้น (CRS/SVC/PRD) ของคลินิก Youngdo — ภาษาเดียวที่ทุกระบบเข้าใจ
  2. YD_GENCODE = spec authority + parser (408/408 gold, CI-guarded); glyph-oracle = runtime dashboard
  3. Mapper Engine: Thai free-text → structured code ผ่าน 3-step resolve (alias → parser → proposer)
  4. Web Dashboard (CF Workers + Preact + PostgreSQL): search, create, dictionaries, Chrome extension
  5. Migration: 2,368 JERA items mapped, 9-batch ratification with Dr.Do, nightly corpus refresh
  6. ยังเหลือ: GENCODE→JERA compression, cross-layer mapping API, PKG integration, Order Entry (Task 3)
  7. Design principles: flag-don't-guess, tested-code-wins, point-don't-copy, nothing-is-deleted