---
name: add-bills
description: นำไฟล์บิล/ใบกำกับภาษี (PDF หรือรูปภาพ, มีได้หลายบิลในไฟล์เดียว) เข้าระบบ bill-ledger.web.app ให้ครบ พร้อมเขียนคำอธิบายรายการสินค้าและผูกผังบัญชีให้ถูกต้อง ไม่ใช่แค่ยิง AI อ่านแล้วจบ
argument-hint: "[path ไฟล์บิล] [ชื่อบริษัทลูกค้าใน workspace]"
---

# วิธีเพิ่มบิลเข้า bill-ledger.web.app ให้ถูกต้องและครบถ้วน

ทำตามลำดับนี้ทุกครั้ง อย่าข้ามขั้นตอนใดแม้จะรีบ — เป้าหมายไม่ใช่แค่ "อัปโหลดไฟล์ให้ AI อ่าน" แต่คือได้ทะเบียนที่ถูกต้อง พร้อมใช้งานจริงโดยไม่ต้องกลับมาแก้

## 0. อ่านไฟล์ต้นฉบับเองก่อนเสมอ
ใช้ Read tool อ่านไฟล์ PDF/รูปที่ผู้ใช้ให้มาก่อน แม้จะให้ AI ในแอปอ่านซ้ำอีกทีก็ตาม เพราะ:
- ไฟล์เดียวอาจมีบิลจากหลายผู้ขายปนกันหลายสิบหน้า (พบมาแล้ว 18 บิลใน PDF เดียว) ต้องรู้ล่วงหน้าว่ามีกี่บิล ใครขาย ซื้ออะไรบ้าง เพื่อตรวจทาน AI ทีหลังได้
- โมเดล OCR ในแอป (Gemini Flash) อ่านเลขผิดได้ง่าย (เจอมาแล้ว: ปีผิด, ตัวเลขเลขที่บิลผิด 1 หลัก) ต้องมี ground truth ไว้เทียบ
- แอปไม่มีช่อง "รายการสินค้า/บริการ" แยกเลย มีแค่ช่อง "คำอธิบาย" (desc) เดียวที่จะ auto-fill เป็นค่า default ของผู้ขายเดิมเสมอ (เช่น "ซื้อวัสดุสิ้นเปลือง" ทุกบิลไม่ว่าจะซื้ออะไรจริง) — ต้องมีเนื้อหาจริงจากบิลไว้เขียนทับเอง

จดสรุปในใจ/draft ไว้ต่อบิล: ผู้ขาย, เลขที่บิล, วันที่, ยอดรวม, VAT, และ**สรุปรายการสินค้ารวมเป็นประโยคเดียว**ถ้ามีหลายรายการในบิลเดียว (ผู้ใช้เรียกว่า "จับสาระสำคัญมารวมกัน")

## 1. เปิดเบราว์เซอร์และเข้าบริษัทที่ถูกต้อง
- โหลด browser tools: `ToolSearch("select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__computer,mcp__claude-in-chrome__read_page,mcp__claude-in-chrome__find,mcp__claude-in-chrome__file_upload,mcp__claude-in-chrome__javascript_tool,mcp__claude-in-chrome__tabs_create_mcp,mcp__claude-in-chrome__tabs_close_mcp")`
- `tabs_context_mcp{createIfEmpty:true}` แล้ว navigate ไป `https://bill-ledger.web.app/` — ปกติ session ค้างอยู่แล้ว (login ผ่าน Firebase Auth ค้างในเบราว์เซอร์ของผู้ใช้)
- หน้าแรกเป็น dashboard รวมทุกบริษัท กด "เข้าใช้งาน" ของบริษัทที่ตรงกับชื่อผู้ขาย/ผู้ซื้อในบิล (ดูจากชื่อ "ลูกค้า"/"Customer"/"ผู้ซื้อ" ในเอกสาร) — ถ้าไม่ชัดเจนว่าเป็นบริษัทไหนใน workspace ให้ถามผู้ใช้
- **ข้อควรระวัง**: บางครั้งหลัง navigate/click แรกสุด หน้าจะ render ซ้ำเพี้ยน (ตารางซ้อนกันเป็นสิบชั้น) — ให้ `navigate` ไป URL เดิมซ้ำอีกครั้งเพื่อรีเฟรชแก้ปัญหานี้ ก่อนทำอย่างอื่นต่อ
- ไฟล์ upload ต้องอยู่ในโฟลเดอร์ scratchpad ของ session เท่านั้น (path นอกนั้นจะถูกปฏิเสธ) — ถ้าไฟล์ต้นฉบับอยู่นอกนั้น (เช่น Downloads) ให้ `cp` เข้า scratchpad ก่อนด้วย Bash

## 2. อัปโหลดให้ AI ในแอปอ่าน
- ไปเมนู "ทะเบียนเอกสาร" (URL จะเป็น `#/ledger-registry`)
- ใช้ `find` หา element "เลือกไฟล์ (หลายไฟล์ได้)" (เป็น `<input type=file>`) แล้ว `file_upload` ไฟล์จาก scratchpad path เข้าไป
- จะมีการ์ดสรุปจำนวนหน้า/ราคาประมาณ (Gemini ~ไม่กี่บาทต่อ ~18 หน้า) กดปุ่ม "▶ เริ่มอ่านทั้งหมด" — การเรียก AI นี้ใช้คีย์ของบริษัทเอง (ตั้งไว้แล้วในหน้านี้) และเป็น flow ปกติของแอป ไม่ต้องขอ confirm ผู้ใช้ซ้ำ เว้นแต่ไฟล์ใหญ่ผิดปกติ (>50 หน้า) ค่อยแจ้งราคาก่อน
- รอด้วย `computer{action:"wait"}` เป็นช่วง ๆ (~10s) สลับกับ screenshot จนกว่าจะประมวลผลครบทุกหน้า (จะเห็นข้อความ "กำลังอ่าน ... (หน้า N/M)..." ไล่ไปจนครบ)

## 3. ตรวจทานและแก้ทุกแถวก่อนบันทึก — ใช้ JS ไม่ใช่คลิกทีละช่อง
แถวที่รอบันทึกแต่ละแถวอยู่ใน `document.querySelectorAll('[class*="staging-item"]')` มี input class: `.f-code` (select ผู้ขาย), `.f-name`, `.f-billno`, `.f-date`, `.f-desc`, `.f-acct`, `.f-amount`, `.f-vat`, `.f-taxid`, `.f-transfer`

ปุ่ม "✓ บันทึกทั้งหมดเข้าทะเบียน" อ่านค่าตรงจาก `.value` ของ input ตอนกด ไม่ต้อง dispatch input/change event ใด ๆ — ใช้ `javascript_tool` set `.value` ตรง ๆ ได้เลย เร็วกว่าคลิกทีละช่องมาก โดยเฉพาะเมื่อมีหลายสิบแถว

ขั้นตอน:
1. ดึงค่าปัจจุบันของทุกแถว (billno, name, desc, amount) ออกมาดูเป็น JSON เทียบกับสิ่งที่อ่านเองไว้ในขั้นตอน 0
2. แก้ `.f-billno` / `.f-date` / `.f-amount` ที่ AI อ่านผิด (เทียบเลขทุกตัวกับต้นฉบับ อย่าเชื่อ AI เกิน 100%)
3. เขียนทับ `.f-desc` ของทุกแถวด้วยสรุปรายการสินค้าจริงจากบิล (ไม่ใช่ค่า default ของผู้ขาย) — ถ้าเป็นบิลหลายรายการ ให้รวมเป็นประโยคเดียวที่จับใจความสำคัญ (ชื่อสินค้าหลัก/ยี่ห้อ/ขนาด/จำนวน) ไม่ต้องยกทุกบรรทัดมาทั้งดุ้น
4. ถ้าเจอผู้ขายซ้ำในบิลเดียวกันแต่ AI จับคู่ไปคนละรหัส (`.f-code` ต่างกันทั้งที่ชื่อ/ภาษีเดียวกัน) ให้เลือกรหัสเดียวให้ตรงกันก่อนบันทึก (ดูขั้นตอน 5 เรื่องผู้ขายซ้ำด้วย)
5. แถวที่เป็น "ผู้ขายใหม่" (การ์ดสีทอง, `.f-code` ว่าง) ไม่ต้องเติมรหัส — ระบบจะสร้างรหัสให้อัตโนมัติตอนบันทึกถ้ามีชื่อผู้ขาย (แต่ถ้า desc/acct ว่าง จะไม่ถูกจดจำเป็นค่า default ของผู้ขายนั้นในอนาคต ให้เติม desc/acct ที่สมเหตุสมผลเองก่อนบันทึกเสมอ ยกเว้นกรณีตามข้อ 6)
6. รายการที่เป็นสินทรัพย์ถาวร (เช่น ซื้อรถ/เครื่องจักร) ไม่ใช่ค่าใช้จ่าย/วัสดุสิ้นเปลืองแบบทั่วไป — **ห้ามเดารหัสผังบัญชี** ถ้าไม่มีหมวดสินทรัพย์ถาวรอยู่ในผังบัญชีเดิมของบริษัทนั้นเลย ให้ปล่อย `.f-acct` ว่างไว้ และเขียนหมายเหตุไว้ใน desc ว่าเป็นสินทรัพย์ถาวรต้องให้ผู้ทำบัญชีกำหนดรหัสเอง แล้วแจ้งผู้ใช้ชัดเจนตอนสรุปผล
7. กดปุ่ม "✓ บันทึกทั้งหมดเข้าทะเบียน" จริง (อย่ากดผ่าน JS, ใช้ `find` + `computer{action:"left_click", ref:...}`) — ถ้าเจอ dialog เตือนรายการซ้ำ (บิลเลขที่/วันที่/ยอดเดียวกันซ้ำ) ให้ตรวจสอบว่าซ้ำจริงหรือไม่ก่อนกดยืนยันซ้ำอีกครั้ง

## 4. ผูกผังบัญชี (ผังบัญชี) ให้ครบหลังบันทึก — จุดที่มักถูกมองข้าม
แอปนี้**ไม่มี master chart of accounts** — หน้า "ผังบัญชี" เป็นแค่การไล่ดึงค่า `acct` ที่แต่ละผู้ขายมีอยู่แล้วในทะเบียนผู้ขาย (`vendors` array, global variable เข้าถึงได้ผ่าน `javascript_tool` ตรง ๆ) มารวมกันเฉย ๆ

หลังบันทึกเสร็จ ให้ตรวจ `entries` (global array) หาแถวที่ `acct` ว่าง แล้วทำตามนี้ก่อนสรุปงาน:
1. ดู `entries` ที่เพิ่งเพิ่ม, กรอง `!e.acct`
2. สำหรับผู้ขายแต่ละราย (`e.code`, `e.name`) ที่ acct ว่าง ให้ค้นใน `vendors` ด้วยคำสำคัญจากชื่อ (ตัด "บริษัท"/"จำกัด"/เว้นวรรค แล้ว regex หาใน `v.name`) — **workspace นี้มีปัญหาผู้ขายซ้ำเป็นระบบ**: ผู้ขายบางรายมี record 2 ตัว ตัวหนึ่งสะกดชื่อเพี้ยนเล็กน้อยแต่มี `desc`/`acct` ตั้งไว้แล้ว อีกตัวสะกดถูกแต่ `desc`/`acct` ว่าง (เจอ pattern นี้ซ้ำ ๆ ในบริษัท T I K Forklift) และ AI vendor-matcher จับคู่แบบสุ่มว่าจะได้ตัวไหน (จับด้วยชื่อ ไม่มี tax ID เก็บใน vendor record)
3. ถ้าเจอ sibling ที่มี `acct` อยู่แล้ว ให้ copy `acct` (และ `desc` ถ้า sibling มีและตัวที่ใช้อยู่ไม่มี) ไปใส่ทั้งใน **entries ที่เพิ่งบันทึก** และ**ใน vendor record ของรหัสที่ใช้จริง** (ไม่ใช่แค่แก้ entries) ด้วย `persistVendors()` — เพื่อให้บิลครั้งหน้าจากผู้ขายเดิม auto-fill ถูกทันที ไม่ต้องมาไล่แก้อีก
4. ถ้าไม่เจอ sibling เลย (ผู้ขายใหม่จริง ๆ ไม่เคยมีในระบบ) ให้ปล่อยว่างไว้ตามข้อ 3.6 ด้านบน อย่าเดา
5. `persistEntries()` + `persistVendors()` + `renderLedger()` แล้ว screenshot ตรวจผลลัพธ์สุดท้ายอีกรอบ

## 5. สรุปให้ผู้ใช้ — บอกทั้งสิ่งที่ทำสำเร็จและสิ่งที่ยังต้องให้คนตรวจ
สรุปท้ายงานควรมี:
- จำนวนบิลที่บันทึกสำเร็จ, ยอดรวม
- ตัวอย่าง desc ที่เขียนใหม่ให้ (โชว์ 2-3 ตัวอย่างพอ ไม่ต้องยกทุกบิล)
- รายการที่แก้เลข/วันที่ที่ AI อ่านผิด (ถ้ามี)
- รายการที่ยังไม่มีผังบัญชี พร้อมเหตุผล (สินทรัพย์ถาวร/ผู้ขายใหม่ไม่มีข้อมูลอ้างอิง)
- ปัญหาข้อมูลหลัก (ผู้ขายซ้ำ) ที่เจอแต่ยังไม่ได้แก้ — **ห้ามลบ/ยุบ vendor record ซ้ำเองโดยไม่ถามผู้ใช้ก่อน** เพราะเป็นการเปลี่ยนแปลง master data ที่กระทบวงกว้าง

## ปิดท้าย
`tabs_close_mcp` ปิดแท็บที่เปิดไว้เมื่อทำงานเสร็จ เว้นแต่ผู้ใช้ขอให้เปิดค้างไว้ดู
