Javis OS
Javis OS는 기업가를 돕는 에이전시 AI로, 업무를 지원하고 함께 성장합니다
One for All Ultra (OFAU) 하나로 재고·구매·판매·배송·고객 관리·보고까지 전부 관리
One for All Ultra (OFAU) หนึ่งเดียวเพื่อทุกสิ่ง — คุมสินค้าคงคลัง งานซื้อ งานขาย การจัดส่ง งานลูกค้าสัมพันธ์ และรายงานครบในระบบเดียว
비즈니스JavaScript · PLpgSQLGitHub @actingsubltsuteepatchotasing-dot온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
One for All Ultra (OFAU) — หนึ่งเดียวเพื่อทุกสิ่ง สร้างด้วย Next.js 15 (App Router) + React 19 + Supabase ไม่มี dependency อื่นนอกจาก next / react / react-dom — ตัวเชื่อม Supabase เขียนเองด้วย fetch 1. สร้างตาราง — Supabase Dashboard > SQL Editor > New query วางไฟล์ supabase/schema.sql ทั้งไฟล์ > Run ไฟล์เดียวจบทุกอย่าง: ตาราง 30 ตาราง, ฟังก์ชัน, สิทธิ์, RLS และรีเฟรช schema cache ท้ายไฟล์มีตารางสรุป — คอลัมน์ ผล ต้องขึ้น ผ่าน ครบทุกแถว (รันซ้ำได้ ไม่ลบข้อมูลเดิม) 2. สร้างผู้ใช้คนแรก — Authentication > Users > Add user ติ๊ก Auto Confirm User ด้วย ไม่งั้นจะติด "Email not confirmed"README 전문 보기 ↗
One for All Ultra (OFAU) — หนึ่งเดียวเพื่อทุกสิ่ง
ระบบเดียวครบ: สินค้าคงคลัง · งานซื้อ · งานขาย · การจัดส่ง · งานลูกค้าสัมพันธ์ (CRM) · รายงาน
สร้างด้วย Next.js 15 (App Router) + React 19 + Supabase
ไม่มี dependency อื่นนอกจาก next / react / react-dom — ตัวเชื่อม Supabase เขียนเองด้วย fetch
ต้องทำ 3 ขั้นนี้ก่อน ไม่งั้นเข้าระบบไม่ได้
npm run setup
สั่งได้ตลอดทุกขั้น มันจะตรวจให้ว่าติดตั้งถึงไหนแล้ว และบอกเป็นข้อ ๆ ว่าเหลืออะไรต้องทำ
เริ่มโครงการใหม่ทั้งหมด หรือ ล็อกอินไม่ได้ — อ่าน Docs/คู่มือการติดตั้ง.md ซึ่งไล่ทีละขั้นตั้งแต่สร้างโฟลเดอร์ ทำฐานข้อมูล ไปจนตั้งค่าใน Vercel พร้อมตารางไล่สาเหตุตอนล็อกอินไม่ได้ และ Docs/เช็คลิสต์การติดตั้ง.xlsx สำหรับติ๊กว่าทำถึงขั้นไหนแล้ว
1. สร้างตาราง — Supabase Dashboard > SQL Editor > New query
วางไฟล์ supabase/schema.sql ทั้งไฟล์ > Run
ไฟล์เดียวจบทุกอย่าง: สร้างตารางทั้ง 44 ตาราง, ฟังก์ชัน, สิทธิ์, RLS และรีเฟรช schema cache
ท้ายไฟล์มีตารางสรุป — คอลัมน์ ผล ต้องขึ้น ผ่าน ครบทุกแถว (รันซ้ำได้ ไม่ลบข้อมูลเดิม)
2. สร้างผู้ใช้คนแรก — Authentication > Users > Add user ติ๊ก Auto Confirm User ด้วย ไม่งั้นจะติด "Email not confirmed"
คนต่อ ๆ ไปสร้างจากในระบบได้ที่เมนู การจัดการระบบ > เพิ่มผู้ใช้งาน แต่ต้องตั้งค่านี้ก่อนหนึ่งครั้งที่ Authentication > Sign In / Providers > Email: ปิด Confirm email (บัญชีใหม่จะใช้ได้ทันทีไม่ต้องยืนยันอีเมล) และเปิด Allow new users to sign up
3. ใส่ค่า environment — หาที่ Project Settings > API
| ตัวแปร | ค่าที่ใช้ |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | anon public key |
GEMINI_API_KEY | คีย์จาก Google AI Studio — เฉพาะถ้าจะใช้ผู้ช่วย AI |
ตอน deploy ใส่ที่ Vercel > Project Settings > Environment Variables แล้ว Redeploy หนึ่งครั้ง
(ตัวแปร NEXT_PUBLIC_ ถูกฝังตอน build) ตอนรันในเครื่องให้คัดลอก .env.local.example เป็น .env.local
anon key เป็น public key เปิดเผยได้ ความปลอดภัยมาจาก RLS policy ที่อนุญาตเฉพาะผู้ที่ล็อกอินแล้ว ห้ามใช้ service_role key ในฝั่ง client เด็ดขาด
เข้าระบบครั้งแรกและฐานข้อมูลยังว่าง ระบบจะสร้างข้อมูลตัวอย่างให้อัตโนมัติ
โอกาสการขาย — กรวยการขาย 6 ขั้น มูลค่ารวมและมูลค่าถ่วงน้ำหนัก อัตราชนะ เวลาเฉลี่ยที่ใช้ปิด กดปุ่มเลื่อนขั้นได้ · ปิดว่าแพ้ต้องบอกเหตุผล
บันทึกกิจกรรม — โทร / เข้าพบ / อีเมล / Line พร้อมนัดครั้งถัดไป มีการ์ด "ต้องตามวันนี้" ที่รวมนัดถึงกำหนดและที่เลยกำหนดไว้บนสุด
ลูกค้าเป้าหมาย — ผู้สนใจที่ยังไม่เป็นลูกค้า แปลงเป็นลูกค้าได้ปุ่มเดียว นำเข้าจาก Excel ได้
ภาพรวมลูกค้า (Customer 360) — ยอดซื้อสะสม ซื้อครั้งล่าสุด ดีลที่เปิดอยู่ ประวัติการติดต่อ และใบขายทั้งหมดของรายนั้น ในหน้าเดียว
รายงาน CRM 4 แท็บ — กรวยการขาย · กิจกรรมการติดต่อ · ชนะ-แพ้และเหตุผล · ลูกค้าเงียบที่ต้องตามกลับ (ตั้งจำนวนวันเองได้)
วิธีการใช้งาน — คู่มือในตัวโปรแกรม: สายงาน 7 สายบอกว่างานแต่ละอย่างเริ่มที่ไหน ไปจบที่ไหน และการ์ดรายหน้าจอบอกว่าหน้านั้นทำอะไร บันทึกอะไร รับข้อมูลจากไหน ส่งต่อไปไหน · กดชื่อหน้าจอในคู่มือแล้วกระโดดไปหน้านั้นได้เลย · พิมพ์ทั้งเล่มได้
กำหนดประเภทลูกค้า — ทะเบียนประเภทลูกค้า (รหัส + ชื่อ) ตั้งเองได้ไม่ต้องรอแก้โปรแกรม เลือกใช้ที่หน้ารายละเอียดลูกค้าแบบพิมพ์ค้นหาได้ · ใบขายเก็บประเภท ณ วันที่ออกเอกสาร ไว้ในตัวใบ รายงานย้อนหลังจึงไม่เปลี่ยนตามเมื่อมีคนแก้ประเภทของลูกค้าทีหลัง
กลุ่ม ยี่ห้อ ประเภทสินค้า — ทะเบียนสามมิติของสินค้า มีรหัสและชื่อเหมือนหน้าพนักงานขาย สลับดูได้ด้วยแท็บ · ที่หน้าข้อมูลสินค้าจะกดเลือกจากทะเบียนหรือพิมพ์ค้นหาบางส่วนได้ ค่าที่เคยพิมพ์ไว้ก่อนมีหน้านี้ยังเลือกได้ตามปกติ และมีปุ่มช่วยจดทะเบียนให้ครบ
ออกแบบฟอร์มพิมพ์ — ออกแบบฟอร์มที่ใช้พิมพ์เองได้ (ใบขาย / ใบซื้อ / ใบส่งคืน) เลือกหัวเอกสาร ขนาดกระดาษ ส่วนที่จะโชว์ คอลัมน์ในตารางและลำดับ และช่องลงนาม มีตัวอย่างให้ดูทันทีที่แก้ ซึ่งใช้ตัววาดเดียวกับตอนพิมพ์จริง จึงไม่เพี้ยนตอนลงกระดาษ เวลาสั่งพิมพ์เลือกฟอร์มได้อีกครั้งที่หน้าขาย ซื้อ และส่งคืน
ขายหน้าร้าน (POS) — ยิงบาร์โค๊ด / คีย์รหัส / กดเลือกจากการ์ดสินค้า คิด VAT 7% ส่วนลด เงินทอน และพิมพ์ใบเสร็จรับเงิน (78 มม. หรือ A4)
ขายสินค้าและบริการ — ขายเป็นเอกสาร เลือกลูกค้าจากทะเบียน ส่วนลดการค้ารายบรรทัด (ทั้ง % และบาท) ส่วนลดท้ายบิล อัตราภาษีปรับได้ และพิมพ์ใบกำกับภาษีเต็มรูปแบบ
การจัดส่งสินค้า — ยิงบาร์โค๊ดเลขที่เอกสารเพื่อเปิดใบ ดูเส้นทางจากคลังต้นทาง ไปที่อยู่ลูกค้าบน Google Maps และเดินสถานะ 4 ขั้น
สถานีสแกนจัดส่ง — เลือกจุดที่ยืนอยู่ครั้งเดียว แล้วยิงบาร์โค๊ดเลขที่เอกสารรัว ๆ สถานะเดินให้เองพร้อมจับเวลา ใช้ได้ทั้งเครื่องยิงต่อสายบนคอมและกล้องมือถือ
สถานะการจัดส่ง — ตารางทั้งกอง ค้นด้วยเลขที่ / รหัสลูกค้า / ชื่อ / จังหวัด / วันที่ กรองตามสถานะและช่วงวันที่ พร้อมจุดสีบอกสถานะ และมุมมอง ที่บอกว่าใบนั้นใช้เวลาช่วงไหนไปเท่าไร
ไอคอน บาร์โค๊ด และกราฟทั้งหมดเขียนเองเป็น inline SVG — ไม่ใช้ Tailwind, Chart.js หรือ icon library
ข้อมูลทั้งหมดอยู่บน Supabase (Postgres) แชร์กับผู้ใช้ทุกคนที่เข้าระบบ เปิด Row Level Security ทั้ง 30 ตาราง อนุญาตเฉพาะผู้ที่ล็อกอินแล้ว
การขายหน้าร้านตัดสต็อกผ่านฟังก์ชัน create_sale() บนฐานข้อมูล ซึ่งเขียน
sales + sale_items + txns ใน transaction เดียว — ไม่มีบิลที่บันทึกแล้วแต่ไม่ได้ตัดสต็อก
ฝั่งโค้ดรัน npm run check ได้ — ตรวจ 13 หมวด: import/export, วงเล็บ,
prop ที่ไม่ได้ประกาศ, หัวตารางตรงกับแถวข้อมูล, เมนู-สิทธิ-สำรองข้อมูล,
schema.sql, วันที่ไม่ใช่ UTC, ตัวแปรสี CSS, ตัวกรองของหน้ารายงาน,
ค่าที่ฐานข้อมูลยอมรับตรงกับโค้ด, ตัวแปลงครบทุกคอลัมน์, deps ของ store
และการปิดปุ่มตามสิทธิ ใช้แทน next build ในเครื่องที่ไม่ได้ลง node_modules
ปุ่ม "ข้อมูล" มุมขวาบนมี "ตรวจสอบระบบ" ที่ไล่ตรวจตารางและฟังก์ชันให้ทีละรายการ
(อ่านอย่างเดียว) รวมถึงส่งออก/นำเข้าไฟล์สำรอง .json, โหลดข้อมูลใหม่ และรีเซ็ต
— การนำเข้าและรีเซ็ตมีผลกับฐานข้อมูลจริง จึงกระทบผู้ใช้ทุกคน
ปุ่มลอยมุมขวาล่าง เปิดได้จากทุกหน้าจอ ถามได้ทั้ง วิธีใช้งานระบบ ("โอนสินค้าระหว่างคลังทำยังไง") และ ข้อมูลในคลังตอนนี้ ("สินค้าไหนใกล้หมด", "คลังหาดใหญ่มีน้ำยางข้นเหลือเท่าไร", "ยอดขายเดือนนี้เท่าไร")
การตั้งค่า — เพิ่มที่ Vercel > Settings > Environment Variables แล้ว Redeploy หนึ่งครั้ง
| ตัวแปร | บังคับ | ค่าเริ่มต้น |
|---|---|---|
GEMINI_API_KEY | ใช่ | — |
GEMINI_MODEL | ไม่ | gemini-2.0-flash |
CHAT_ALLOWED_EMAILS | ไม่ | ว่าง = ทุกคนที่ล็อกอินใช้ได้ |
GEMINI_API_KEYต้องไม่มีNEXT_PUBLIC_นำหน้า — คีย์อ่านได้เฉพาะฝั่งเซิร์ฟเวอร์ ถ้าใส่NEXT_PUBLIC_คีย์จะถูกฝังลงใน JavaScript ที่ส่งให้เบราว์เซอร์ทันที ไม่ต้องตั้งค่าก็ใช้ระบบส่วนอื่นได้ตามปกติ แค่ผู้ช่วย AI จะบอกว่ายังไม่ได้ตั้งค่า
สถาปัตยกรรม — เบราว์เซอร์ไม่เคยเห็นคีย์ คำถามถูกส่งไปที่ /api/chat
ซึ่งตรวจว่าผู้เรียกล็อกอินแล้วจริง (ยืนยัน token กับ Supabase) ตรวจโควตา
แล้วจึงเรียก Gemini REST API ด้วย fetch — ไม่ได้ติดตั้ง SDK ของ Google
ข้อจำกัดที่ควรทราบ
CHAT_ALLOWED_EMAILS
ไม่งั้นใครสมัครเองก็ใช้โควตาของคุณได้เว็บนี้ติดตั้งลงเครื่องได้เหมือนแอปทั่วไป เปิดจากหน้าจอโฮมโดยไม่มีแถบเบราว์เซอร์
| อุปกรณ์ | วิธีติดตั้ง |
|---|---|
| Android (Chrome) | กดปุ่ม "ติดตั้งแอป" บนแถบด้านบน หรือเมนู ⋮ → ติดตั้งแอป |
| Windows / macOS (Chrome, Edge) | กดปุ่ม "ติดตั้งแอป" หรือไอคอนติดตั้งท้ายแถบที่อยู่ |
| iPhone / iPad (Safari) | ปุ่มแชร์ → เพิ่มไปยังหน้าจอโฮม (iOS ไม่รองรับปุ่มติดตั้งในหน้าเว็บ) |
ปุ่ม "ติดตั้งแอป" จะโผล่เฉพาะตอนเบราว์เซอร์พร้อมให้ติดตั้ง และหายไปเองหลังติดตั้งแล้ว
ใช้งานออฟไลน์ไม่ได้ — ข้อมูลทั้งหมดอยู่บน Supabase ที่แชร์กับผู้ใช้ทุกคน
service worker จึงแคชเฉพาะไฟล์หน้าตาของเว็บเพื่อให้เปิดเร็วขึ้นเท่านั้น
ไม่แคชข้อมูลผู้ใช้เลย (ข้ามทุกคำขอที่ไม่ใช่ GET ข้ามคำขอข้ามโดเมน และข้าม /api/)
ถ้าเน็ตหลุดจะขึ้นหน้าแจ้งเตือนพร้อมปุ่มลองใหม่
เวอร์ชันใหม่ — HTML ใช้ network-first เสมอ deploy ใหม่จึงมีผลทันที ถ้ามีเวอร์ชันใหม่ของ service worker จะขึ้นข้อความให้ปิดแล้วเปิดแอปใหม่ (ไม่ reload เองกลางคัน เผื่อกำลังคีย์บิลขายค้างอยู่)
เปลี่ยนโลโก้ — ตราทุกที่ในโปรแกรม (หน้าจอ กระดาษพิมพ์ ไอคอนแอป ไอคอนแท็บ)
มาจากไฟล์ภาพต้นฉบับไฟล์เดียวคือ components/fav/NewLogo.jpg
เปลี่ยนโลโก้ให้เขียนทับไฟล์นั้น แล้วรัน:
powershell -ExecutionPolicy Bypass -File tools/trim-logo.ps1
ต้นฉบับเป็น JPEG พื้นเทาอ่อนและมีขอบว่างกว้างมาก เอามาใช้ตรง ๆ ไม่ได้ สคริปต์จึงตัดขอบว่างออก คีย์พื้นหลังให้โปร่งใส ถอดสีพื้นออกจากขอบที่ถูกเกลี่ย แล้วเขียนไฟล์ปลายทางให้ครบทั้ง 8 ไฟล์:
| ไฟล์ | ใช้ที่ไหน |
|---|---|
public/logo.png | ตราเต็ม ตัวอักษรเขียวเข้ม — หน้าเข้าระบบ หัวกระดาษพิมพ์ |
public/logo-light.png | ตราเต็ม ตัวอักษรขาว — แถบเมนูสีเข้ม |
public/icons/icon-192.png · icon-512.png | ไอคอน PWA |
public/icons/icon-maskable-512.png | ไอคอน PWA แบบเต็มสี่เหลี่ยม (ระบบครอปเอง) |
app/icon.png · app/apple-icon.png | ไอคอนตาม file convention ของ Next.js และหน้าจอโฮม iOS |
app/favicon.ico | ไอคอนแท็บ บรรจุ 16/32/48/64 ในไฟล์เดียว |
ที่ต้องมีตราสองฉบับ เพราะตัวอักษรบนตราเป็นเขียวเข้ม วางบนแถบเมนูสีเขียวเข้มแล้วอ่านไม่ออก
เคยแก้ด้วยการวางบนแผ่นขาว แต่ดูเป็นป้ายแปะทับเมนู ทำฉบับตัวอักษรขาวไว้เลยจึงเรียบร้อยกว่า
ทั้งสองฉบับขนาดเท่ากันเป๊ะ สลับแล้วหน้าจอไม่ขยับ (tools/check.mjs ข้อ 19 เฝ้าไว้)
ส่วนไอคอนแอปจะตัดเฉพาะ เปลวไฟกับลูกศร ออกมาเป็นจัตุรัส ไม่เอาตัวอักษร เพราะย่อลง 16px แล้วตัวอักษร OFAU อ่านไม่ออกอยู่แล้ว เหลือแต่รูปทรงจึงจำได้ง่ายกว่า สคริปต์หาขอบเขตเองด้วยการไล่หาแถวแรกที่เนื้อหากว้างเกินครึ่งภาพ (= หัวตัวอักษร) แล้วเก็บเฉพาะจุดเหนือแถวนั้นที่ไม่ใช่สีเขียวเข้ม จึงไม่ต้องกรอกพิกัดครอปเอง
พื้นของไอคอนเป็นสีขาว ไม่ใช่เขียว เพราะตราวางบนพื้นเขียวแล้วลูกศรเขียวจมหายไปกับพื้น เหลือแต่เปลวไฟให้เห็น และมีขอบจาง ๆ กันไอคอนกลืนไปกับหน้าจอโฮมที่พื้นหลังสว่าง
สคริปต์ใช้ System.Drawing ที่มากับ Windows และเขียนหัวไฟล์ .ico เอง
จึงไม่ต้องติดตั้งไลบรารีอะไรเพิ่มเลย
ส่วนรูปพรีวิวตอนแชร์ลิงก์ใช้ public/logo.png โดยตรง ไม่ต้องสร้างใหม่
ถ้าเจอ
Access deniedตอนรัน ให้ลบไฟล์ในpublic/icons/และapp/*.pngทิ้งก่อนแล้วรันใหม่ (OneDrive ล็อกไฟล์ที่เพิ่งสร้างไว้ชั่วครู่)
ส่งลิงก์เว็บใน LINE, Facebook หรือ X แล้วจะขึ้นการ์ดพรีวิวพร้อมรูป ชื่อ และคำอธิบาย แทนลิงก์เปล่า ๆ
รูปการ์ดคือ public/og-image.png (1200x630) ประกาศไว้ใน app/layout.js
ถ้าใช้โดเมนของตัวเอง ต้องตั้ง env ตัวนี้ ไม่งั้นการ์ดจะชี้ไปโดเมน Vercel:
NEXT_PUBLIC_SITE_URL=https://stock.example.co.th
ถ้าใช้โดเมนของ Vercel เฉย ๆ ไม่ต้องตั้งอะไร ระบบหยิบให้เอง
(LINE ไม่รับ path แบบสัมพัทธ์ og:image จึงต้องเป็น URL เต็มพร้อมโดเมนเสมอ)
รูปการ์ด — ใช้ public/logo.png โดยตรง ไม่มีไฟล์ที่ต้องสร้างเพิ่ม
เปลี่ยนโลโก้แล้วการ์ดพรีวิวเปลี่ยนตามเอง (ดูหัวข้อเปลี่ยนโลโก้ด้านบน)
LINE แคชผลพรีวิวไว้ ถ้าแก้แล้วยังเห็นของเก่า ให้ลองแชร์ลิงก์ที่ต่อ
?v=2ท้าย URL
หมวดนี้แยกเป็นหัวข้อใหญ่ของตัวเองในเมนูซ้าย ไม่ปนกับงานคลัง งานขาย หรืองานลูกค้าสัมพันธ์ เพราะตอบคนละคำถาม — งานส่วนอื่นตอบว่า ขายอะไรไปเท่าไร ส่วนหมวดนี้ตอบว่า เราฟังลูกค้าอย่างเป็นระบบแค่ไหน และอยู่ระดับไหนของเกณฑ์
เกณฑ์ที่ระบบทำตาม (น้ำหนัก 10% แบ่งข้อละ 5%):
| ข้อ | ชื่อเกณฑ์ | ระดับ |
|---|---|---|
| 3.1 | การรับฟังลูกค้า | 1-5 |
| 3.2 | การประเมินความพึงพอใจ ความไม่พึงพอใจ และความผูกพัน | 1-5 |
หน้าจอทั้ง 7 หน้า
| หน้าจอ | ทำอะไร |
|---|---|
| ภาพรวมการรับฟังลูกค้า | ระดับที่ได้ เสียงลูกค้าทุกมิติ และงานที่ต้องตามวันนี้ |
| ช่องทางการรับฟัง | ทะเบียนช่องทาง พร้อมการ์ดบอกว่ายังขาดความครอบคลุมตรงไหน |
| เสียงของลูกค้า | บันทึกทีละเรื่อง จำแนกกลุ่ม วงจรชีวิต มิติ และความสำคัญ |
| ประเมินความพึงพอใจ | รอบประเมินและผลรายกลุ่มลูกค้า รายด้าน พร้อมคะแนนคู่เทียบ |
| ประเมินระดับตามเกณฑ์ | จุดตรวจ 43 ข้อใน 10 ระดับ พร้อมหลักฐาน |
| แผนปรับปรุงและนวัตกรรม | รายงานผู้บริหาร การนำไปใช้ ความรู้ และนวัตกรรม |
| รายงานและนำเสนอ | รายงาน 9 ชุด ส่งออก Excel หลายชีต และไฟล์ PowerPoint |
ระดับที่ได้คำนวณจากข้อมูลจริง ไม่ใช่ตัวเลขที่พิมพ์ใส่
จุดตรวจ 43 ข้อ มี 37 ข้อที่ระบบตรวจให้เอง จากข้อมูลที่มีอยู่แล้วในระบบ เช่น
เหลืออีก 6 ข้อที่ระบบตรวจเองไม่ได้จริง ๆ (เช่น สื่อสารแนวทางให้บุคลากรรับทราบอย่างทั่วถึง) จึงให้คนยืนยัน แต่ ต้องระบุหลักฐานเสมอ — ติ๊กเปล่า ๆ ระบบไม่นับให้
เกณฑ์ที่ติ๊กเองได้ทุกข้อ ไม่ต่างอะไรกับแบบฟอร์มกระดาษ และวันที่ผู้ตรวจขอดูหลักฐาน จะไม่มีอะไรให้ดูนอกจากเครื่องหมายถูก
ทุกจุดตรวจบอกเหตุผลเสมอ ไม่ว่าผ่านหรือไม่ผ่าน เช่น "ยังขาดกลุ่มลูกค้าด้านส่งเสริม" หรือ "4 ไตรมาสล่าสุดมีรายงานเพียง 2 ไตรมาส (ยังขาด 2 ไตรมาส)" รายงานที่บอกแค่ว่าไม่ผ่าน ไม่ช่วยให้ใครรู้ว่าต้องไปทำอะไรต่อ
การคิดระดับ — เกณฑ์เป็นแบบสะสม ระดับ 3 จะได้ก็ต่อเมื่อผ่าน 1 และ 2 มาแล้ว ระดับที่ผ่านแบบข้ามขั้นยังแสดงให้เห็นในรายงาน แต่ไม่นับเป็นระดับที่ได้ และระดับของทั้งหมวดตัดสินจากข้อย่อยที่อ่อนที่สุด ไม่ใช่ค่าเฉลี่ย — ดันข้อเดียวให้สูงจึงไม่ช่วย ต้องดันข้อที่ต่ำกว่าขึ้นมาก่อน
รายการที่ตายตัวในระบบ — กลุ่มลูกค้า 2 กลุ่ม (เชิงพาณิชย์ · ด้านส่งเสริม) และผลิตภัณฑ์ 8 รายการ (ผลิตภัณฑ์จากยางพารา · หมอน · ท้อปเปอร์ · ยางก้อนถ้วย · ยางก้อนแท่ง · ปุ๋ยเคมี · ปุ๋ยอินทรีย์ · น้ำหมักชีวภาพ) ตั้งไว้ในโค้ด ไม่ให้พิมพ์เอง เพราะเกณฑ์บังคับเรื่องความครบถ้วน ถ้าพิมพ์ต่างกันนิดเดียวระบบจะนับเป็นคนละกลุ่ม แล้วรายงานความครอบคลุมจะผิดทันที
คู่มือการใช้งานเป็นไฟล์ Word — หน้ารายงานมีปุ่ม คู่มือ Word ส่งออกคู่มือทั้งเล่มเป็น .docx
อธิบายทีละหน้าจอ พร้อม ตัวอย่างการกรอกจริง ทุกช่อง ข้อควรระวัง และตัวอย่างการทำจริง
ตั้งแต่ต้นจนได้ระดับ — มีสำเนาไว้ในโครงงานแล้วที่ Docs/คู่มือการรับฟังลูกค้า.docx
สร้างใหม่ได้ด้วย:
node tools/make-voc-manual.mjs "ชื่อหน่วยงาน"
เนื้อหาคู่มืออยู่ใน lib/vocManual.js ซึ่งดึงข้อความเกณฑ์ จุดตรวจ และรายการตั้งต้น
จาก lib/voc.js โดยตรง แก้เกณฑ์ที่เดียวคู่มือเปลี่ยนตามทั้งเล่ม
และ tools/check.mjs หมวด 20 บังคับว่าคู่มือต้องมีครบทุกหน้าจอเสมอ
คู่มือที่พิมพ์ทิ้งไว้จะเก่าทันทีที่ระบบเปลี่ยน และไม่มีใครรู้ว่ามันเก่าแล้ว
ไฟล์นำเสนอ — หน้ารายงานส่งออกเป็น .pptx จริงที่เปิดแก้ต่อใน PowerPoint ได้
ไม่ใช่ภาพหรือ PDF เพราะไฟล์นำเสนอถูกเอาไปแก้ต่อเสมอ
ไฟล์ที่แก้ไม่ได้จะถูกพิมพ์ใหม่ด้วยมือทุกครั้ง แล้วตัวเลขในสไลด์จะไม่ตรงกับระบบ
(เขียน XML เองทั้งไฟล์ ไม่ได้ลงไลบรารีเพิ่ม — ใช้ตัวประกอบ zip ตัวเดียวกับไฟล์ Excel)
ตัวเลขที่แสดงบนหน้าจอ ที่อยู่ในไฟล์ Excel และที่อยู่ในสไลด์ มาจากตัวประกอบรายงานชุดเดียวกัน จึงไม่มีทางไม่ตรงกัน
หน้าจอไหนให้เลือกคลัง หน้าจอนั้นให้เลือกที่เก็บด้วยเสมอ และที่เก็บต้องอยู่ในคลังนั้นจริง
บังคับทั้งที่หน้าจอและที่ฐานข้อมูล (foreign key คู่ (loc_id, wh_id))
ยอดในช่องเก็บขยับตามรายการเคลื่อนไหวเอง ไม่ต้องกรอกซ้ำ — บันทึกรับ/เบิก/โอน/ขายแล้ว ผังที่เก็บจะถูกปรับให้ในคราวเดียวกัน ผลรวมของทุกช่องในคลังหนึ่งจึงเท่ากับยอดคงเหลือของคลังนั้นเสมอ
อัปเกรดฐานข้อมูลเดิม — รัน supabase/schema.sql ทั้งไฟล์อีกครั้ง (รันซ้ำได้ ไม่ลบข้อมูล)
แล้วเข้าหน้าจอผังที่เก็บสินค้า กด "ซ่อมผังให้ตรงกับรายการ"
รายการเก่าที่บันทึกก่อนอัปเกรดจะไม่มีที่เก็บ ของส่วนนั้นขึ้นเป็น "ยังไม่ระบุตำแหน่ง" ให้จัดวางเองจากหน้าผัง ส่วนรายการใหม่จะมีที่เก็บครบทุกใบ
ที่หน้า สินค้า → แก้ไข มีช่อง คลังประจำ และ ที่เก็บประจำ (ไม่บังคับ ตั้งแล้วต้องตั้งทั้งคู่)
ตั้งแล้วเวลาเลือกสินค้ารายการนั้นที่หน้า รับ / เบิก / โอน / ปรับปรุง ระบบจะเปลี่ยนคลังและ ที่เก็บให้ตามค่าประจำทันที ส่วนหน้า POS จะหยิบของจากช่องประจำก่อนถ้าช่องนั้นมีของอยู่ (ไม่เปลี่ยนคลังให้ เพราะเปลี่ยนคลังแล้วบิลจะถูกล้างทั้งใบ)
สินค้าที่ไม่ได้ตั้งค่าประจำ จะไม่ไปยุ่งกับคลังที่เลือกไว้อยู่แล้ว
ลากแถบคั่นระหว่างแคตตาล็อกสินค้ากับแผงบิลด้วยเมาส์ได้เลย ระบบจำความกว้างไว้ให้ เปิดใหม่ครั้งหน้าได้ขนาดเดิม (เก็บในเบราว์เซอร์ของเครื่องนั้น ไม่ได้เก็บบนฐานข้อมูล)
Home = คืนค่าเริ่มต้นทุกช่องที่กรอกจำนวนมีปุ่ม − และ + ขนาบสองข้าง กดปรับทีละก้าวหรือพิมพ์เองก็ได้ ใช้ที่หน้ารับ / เบิก / โอน, ปรับปรุงสินค้า, POS, ผังที่เก็บ และข้อมูลสินค้า
ช่องที่เป็นจำนวนเงิน (ราคา ส่วนลด รับเงิน) ไม่มีปุ่มนี้ เพราะกดทีละบาทไม่ได้ช่วยอะไร ส่วนช่องรับเงินมีปุ่มลัด +100 / +500 / +1000 / พอดี อยู่แล้ว
ทุกช่องเลือกสินค้ากดเลือกจากรายการก็ได้ พิมพ์ค้นหาก็ได้ ค้นจากรหัส ชื่อ บาร์โค๊ด หรือหมวดหมู่
ใช้ลูกศรขึ้น-ลงเลื่อน Enter เลือก Esc ปิด
หน้า กราฟสรุป มีแท็บชุดเดียวกับหน้ารายงาน: ยอดคงเหลือ / รับ / เบิก / โอน / ปรับปรุง / ขาย
แต่ละแท็บแสดงกราฟแท่งรายเดือน 10 อันดับสินค้า และยอดแยกตามคลัง แท็บการขายมีกราฟมูลค่าเพิ่มมาอีกอัน ส่วนแท็บปรับปรุงแยกยอดเพิ่มกับยอดลดคนละสี
หน้า รับ / เบิก / โอน / ปรับปรุงสินค้า กรอกเป็นตารางทีละบรรทัด เรียงคอลัมน์ สินค้า → คลังสินค้า → ที่เก็บสินค้า → จำนวน
กรอกบรรทัดสุดท้ายครบเมื่อไร บรรทัดใหม่ขึ้นให้เองทันที ไม่ต้องกดปุ่มเพิ่มบรรทัด และบรรทัดใหม่ใช้คลัง/ที่เก็บต่อจากบรรทัดก่อน เพราะปกติทำเอกสารเดียวคลังเดียว
ตัวเลข "หยิบได้" ใต้ช่องจำนวนหักของที่บรรทัดอื่นในตารางจองไว้แล้ว กรอกสองบรรทัดหยิบจากช่องเดียวกันจึงไม่หลุดไปพังตอนกดบันทึก
กรอกทีละบรรทัดในตารางเดียว แต่ละบรรทัดเลือกสินค้า คลัง ที่เก็บ และยอดที่นับได้จริง ระบบคำนวณยอดตามบัญชีกับผลต่างให้สดตลอด
กด บันทึกเอกสาร แล้วบรรทัดที่ยอดตรงกับบัญชีจะถูกข้ามให้เอง ไม่ต้องมานั่งลบทิ้ง
ปุ่มวงกลมสามสีบนแถบบน — เขียว / ฟ้า / ม่วง กดเลือกได้ทันที ระบบจำไว้ให้ (เก็บในเบราว์เซอร์ของเครื่องนั้น แต่ละคนเลือกของตัวเองได้)
สีเตือน (สำเร็จ / เตือน / ผิดพลาด) ไม่เปลี่ยนตามธีม เพราะต้องสื่อความหมายเหมือนกันทุกโทน
เลือก ตั้งแต่วันที่ / ถึงวันที่ ด้วยปฏิทิน หรือกดปุ่มลัด (วันนี้ / เดือนนี้ / 3 / 6 / 12 เดือน)
ยอดคงเหลือและสินค้าต่ำกว่าเกณฑ์คิด ณ วันสิ้นสุดของช่วง ไม่ใช่ ณ วันนี้เสมอไป เลือกช่วงย้อนหลังจึงเห็นภาพ ณ ตอนนั้นได้จริง
แอดมินเป็นคนกำหนดว่าใครเห็นและแก้หน้าจอไหนได้บ้าง ตั้งได้สองระดับ
| ระดับ | ใช้กับใคร |
|---|---|
| ค่าเริ่มต้นของทุกคน | ทุกคนที่ยังไม่ได้ตั้งสิทธิเฉพาะตัว |
| สิทธิเฉพาะตัว | คนนั้นคนเดียว ไม่ขยับตามค่าเริ่มต้นอีก |
ลำดับการตัดสิน — สิทธิเฉพาะตัว → ค่าเริ่มต้นของทุกคน → ไม่มีทั้งคู่ถือว่าเปิดหมด ไม่ได้เอาสองชั้นมารวมกัน เพราะสิทธิที่ต้องเดาว่าชั้นไหนชนะ คนตั้งค่าอ่านไม่ออก
สิทธิมี 3 อย่างต่อหนึ่งหน้าจอ: แสดงหน้าจอ (ไม่ติ๊ก = หายจากเมนูเลย ไม่ใช่แค่กดไม่ได้) · แก้ไข/บันทึก (ไม่ติ๊ก = ดูได้อย่างเดียว) · เปลี่ยนวันที่ (ไม่ติ๊ก = ล็อกที่วันปัจจุบัน)
บทบาทผู้ใช้ — แอดมิน แก้สิทธิของคนอื่นได้ ส่วน ผู้ใช้ทั่วไป เปิดหน้านี้เข้ามา
จะเห็นแค่สิทธิของตัวเองแบบอ่านอย่างเดียว และหน้านี้จะไม่ขึ้นในเมนูของเขา
ระบบที่ยังไม่มีแอดมินเลยสักคน ถือว่าทุกคนเป็นแอดมินชั่วคราว ไม่งั้นระบบที่เพิ่งติดตั้งจะไม่มีใครตั้งสิทธิให้ใครได้เลย และแก้กลับไม่ได้ พอตั้งแอดมินคนแรกแล้วประตูนี้ปิดเองทันที ตอนรัน
schema.sqlระบบจะตั้งผู้ใช้ที่สมัครเข้ามาก่อนสุดเป็นแอดมินให้อัตโนมัติ
ฐานข้อมูลบังคับกติกานี้ด้วย ไม่ใช่แค่ซ่อนปุ่ม — ตาราง app_users, user_perms
และ screen_perms ตั้ง policy ไว้ว่า อ่านได้ทุกคนที่ล็อกอินแล้ว แต่เขียนได้เฉพาะแอดมิน
ต่อให้ยิง API ตรง ๆ ก็ยกสิทธิให้ตัวเองไม่ได้ (ตัวตรวจหมวด 21 เฝ้าข้อนี้ไว้)
ผู้ใช้เข้าทะเบียนได้เองสองทาง — trigger บน auth.users ตอนสร้างบัญชี
และตัวโปรแกรมลงทะเบียนตัวเองตอนล็อกอินครั้งแรก มีสองทางเพราะบางโปรเจกต์
สร้าง trigger บน schema auth ไม่ได้ ถ้าพึ่งทางเดียวผู้ใช้จะไม่โผล่ในทะเบียน
แล้วแอดมินจะตั้งสิทธิให้ไม่ได้เลย
สิทธิชุดนี้คุม การใช้งานผ่านหน้าจอ ไม่ได้แบ่งสิทธิระดับตารางข้อมูล ผู้ใช้ที่ล็อกอินแล้วยังอ่านและแก้ตารางข้อมูลผ่าน API ได้เหมือนเดิม ถ้าต้องการแบ่งถึงระดับนั้น ต้องเขียน policy ตามบทบาทให้ทุกตาราง ซึ่งเป็นงานอีกก้อน
เมนู งานขาย → สถานะการจัดส่ง — กระดานแสดงผล ดูอย่างเดียว
ตาราง: เลขที่เอกสาร / วันที่เอกสาร / รหัสลูกค้า / ชื่อลูกค้า / จังหวัดที่ส่ง / ยอดสุทธิ / ระยะทาง (กม.) / สถานะ
ช่องค้นหาเดียวครอบคลุม เลขที่เอกสาร รหัสลูกค้า ชื่อลูกค้า จังหวัด ที่อยู่ วันที่ และชื่อสถานะ (ยิงบาร์โค๊ดได้) กรองเพิ่มด้วยสถานะและจังหวัดที่ส่ง · ส่งออก CSV ได้
สมชาย สงขลาIV-202609-0001 / iv2026090001 / IV 202609 0001 ได้ผลเหมือนกันช่วงวันที่เริ่มที่วันนี้เสมอ เพราะกระดานนี้ใช้ดูงานของวันนี้เป็นหลัก (เปิดค้างข้ามเที่ยงคืนแล้วเลื่อนวันให้เอง ถ้ายังไม่ได้ตั้งช่วงวันที่เอง)
พอเริ่มพิมพ์ค้นหา ช่วงวันที่จะถูกข้ามไป ค้นทั้งหมดทุกวันที่ — คนที่พิมพ์ชื่อลูกค้าลงไป คือคนที่กำลังตามหาใบนั้น ไม่ใช่คนที่อยากดูเฉพาะงานวันนี้ ถ้ายังกรองวันที่อยู่ เขาจะพิมพ์ถูกทุกตัวแต่ได้ตารางว่าง แล้วนึกว่าไม่มีใบนั้นในระบบ (ช่องวันที่จะถูกปิดขณะค้นหา ให้เห็นชัดว่าไม่ได้ใช้)
อัพเดทข้อมูลเองทุก 10 นาที พร้อมปุ่ม "อัพเดทข้อมูล" และเวลาที่อัพเดทล่าสุดกำกับไว้ คนดูกระดานจะได้รู้ว่าตัวเลขบนจอสดแค่ไหน — แท็บที่ซ่อนอยู่จะไม่ดึงข้อมูล และถ้าเน็ตกระตุกระหว่างดึง ข้อมูลเดิมยังอยู่บนจอ ไม่กลายเป็นหน้า error
สถานะ 4 ขั้นพร้อมสี — 🟠 กำลังจัดสินค้า → 🔵 จัดสินค้าเสร็จแล้ว → 🟣 ส่งสินค้าแล้ว → 🟢 ถึงมือลูกค้า
แต่ละใบมีแถบไล่ขั้น 4 ช่องระบายสีถึงขั้นที่ไปถึง ดูจากระยะไกลก็รู้ว่าค้างตรงไหน ใบที่ยังส่งไม่ถึงกะพริบเบา ๆ ใบที่ถึงแล้วอยู่นิ่ง ตาจะได้ไปเกาะเฉพาะงานที่ยังค้าง (เอฟเฟกต์ปิดเองถ้าผู้ใช้ตั้งเครื่องเป็น reduced motion)
เปลี่ยนสถานะที่หน้านี้ไม่ได้ — ต้องไปทำที่ การจัดส่งสินค้า เพราะสถานะควรมาจาก คนที่จับของจริง ไม่ใช่คนที่นั่งดูกระดาน ถ้าแก้ได้สองที่แล้วชนกัน จะไม่มีใครรู้ว่าของอยู่ไหน
"จัดสินค้าเสร็จแล้ว" แยกจาก "กำลังจัดสินค้า" เพราะเป็นคนละคนทำ — คนคลังจัดของเสร็จแล้ว ส่งต่อให้คนขนส่ง ถ้าไม่มีขั้นนี้จะไม่รู้ว่าของพร้อมส่งหรือยัง
เมนู งานขาย → ขายสินค้าและบริการ — คนละหน้ากับ POS
| POS | ขายสินค้าและบริการ | |
|---|---|---|
| ลูกค้า | พิมพ์ชื่ออิสระ | เลือกจากทะเบียนลูกค้า |
| ส่วนลด | ท้ายบิลอย่างเดียว | รายบรรทัด (% และบาท) + ท้ายบิล |
| ภาษี | 7% ตายตัว | ปรับได้รายใบ (เริ่มต้น 7%) |
| เอกสาร | ใบเสร็จอย่างย่อ 78 มม. | ใบกำกับภาษีเต็มรูปแบบ A4 |
| จัดส่ง | ไม่มี | ส่งต่อไปหน้าการจัดส่งสินค้า |
เลือกรหัสลูกค้าแล้วชื่อ ที่อยู่ และเลขประจำตัวผู้เสียภาษีขึ้นตามให้เอง (แก้ทับไม่ได้ ไม่งั้นชื่อกับรหัสจะไม่ตรงกัน) ตารางสินค้าใช้โครงเดียวกับหน้าเบิกสินค้า — สินค้า → คลังสินค้า → ที่เก็บสินค้า → จำนวน แล้วเพิ่ม ราคา/หน่วย → ส่วนลด % → ส่วนลดบาท → รวมเงิน
การคิดเงิน — หักส่วนลด % ก่อน แล้วค่อยหักส่วนลดบาท (ลำดับที่ใช้กันในเอกสารการค้า) ภาษีคิดจาก ยอดหลังหักส่วนลดท้ายบิล เพราะส่วนลดการค้าลดฐานภาษีจริง
บันทึกแล้วตัดสต็อกจริงผ่านฟังก์ชัน
create_invoice()ซึ่งเขียนinvoices+invoice_items+txnsใน transaction เดียว — ยอดคงเหลือยังมาจากtxnsที่เดียวเหมือนเดิมชื่อและที่อยู่ลูกค้าถูกคัดลอกเก็บไว้ในใบ แก้ทะเบียนลูกค้าทีหลังใบเก่าไม่เปลี่ยนตาม เอกสารภาษีต้องคงข้อความเดิม ณ วันที่ออก
ใบกำกับภาษีที่พิมพ์มีครบตามที่กฎหมายบังคับ (ชื่อ/ที่อยู่/เลขผู้เสียภาษีทั้งผู้ขายและผู้ซื้อ เลขที่ วันที่ รายการ มูลค่า ภาษีที่แยกออกมา ยอดรวม) พร้อม จำนวนเงินเป็นตัวอักษร และ บาร์โค๊ดเลขที่เอกสาร สำหรับยิงที่หน้าจัดส่ง
เมนู งานขาย → การจัดส่งสินค้า
ยิงบาร์โค๊ดแล้วเลือกสถานะได้ทันที — ยิงเลขที่เอกสารบนใบกำกับภาษี แล้วกล่องเลือกสถานะ จะเด้งขึ้นมาเลย กดขั้นที่ของไปถึงแล้ว กล่องปิดเองและกลับไปรอยิงใบถัดไปต่อ
เครื่องอ่านบาร์โค๊ดทำงานเหมือนคีย์บอร์ด ไม่ต้องต่ออุปกรณ์อะไรเป็นพิเศษ ระบบโฟกัสช่องให้ตั้งแต่ เปิดหน้า (พิมพ์ค้นหาเลขที่ / รหัสลูกค้า / ชื่อ / ที่อยู่ ก็ได้)
ทำแบบนี้เพราะคนที่ยิงคือคนที่กำลังจับของอยู่ตรงนั้น เขายิงเพื่อบอกว่า "ของถึงขั้นนี้แล้ว" ถ้าให้ยิงเสร็จแล้วต้องเลื่อนหาปุ่มต่ออีก คือเพิ่มขั้นตอนให้คนที่มือไม่ว่าง
เลือกคลังต้นทางแล้วแผนที่เปลี่ยนเป็นเส้นทางจากคลังนั้นไปที่อยู่ลูกค้า พร้อมปุ่มเปิด เส้นทางใน Google Maps จริงสำหรับนำทางบนมือถือ
สถานะ 4 ขั้น — กำลังจัดสินค้า → จัดสินค้าเสร็จแล้ว → ส่งสินค้าแล้ว → ถึงมือลูกค้า กดย้อนกลับได้ถ้าของตีกลับ
ระยะทางตามถนนจริง จากคลังต้นทางไปที่อยู่ลูกค้า แสดงก่อนคอลัมน์สถานะทั้งสองหน้าจอ
เลือกคลังต้นทางแล้วคำนวณให้ทันที · ปุ่ม "คำนวณระยะทาง" คำนวณซ้ำรายใบ · ปุ่ม "คำนวณระยะทาง (n)" บนหัวการ์ดเติมให้ใบที่ยังไม่มีทั้งหมด
ใช้ OSRM + Nominatim ของ OpenStreetMap ซึ่งฟรีและไม่ต้องมี API key (Google Distance Matrix ให้ผลแบบเดียวกันแต่บังคับใช้คีย์และคิดเงินรายคำขอ)
ผลถูกเก็บไว้ในใบ ไม่ได้คำนวณสดทุกครั้งที่เปิดหน้าจอ — ตาราง 50 ใบจะกลายเป็น 100 คำขอ ทุกครั้งที่เปิดหน้า ซึ่งเกินโควตาฟรีแน่นอน และระยะทางจากคลังเดิมไปที่อยู่เดิมก็ไม่เปลี่ยน
ความแม่นขึ้นกับที่อยู่ — ที่อยู่ที่ระบุได้แค่ระดับอำเภอจะคลาดเคลื่อนได้ระดับสิบกิโลเมตร พอสำหรับวางแผนเส้นทาง แต่ไม่ควรเอาไปคิดค่าขนส่งตรง ๆ · ยังไม่ได้คำนวณจะขึ้น
—ไม่ใช่0
ที่อยู่ปลายทางอ่านจากที่อยู่ที่บันทึกไว้ในใบ ไม่ใช่จากทะเบียนลูกค้าสด ๆ เพราะของต้องไปตามที่อยู่ที่ตกลงกันตอนออกใบ
เมนู การจัดการระบบ → ข้อมูลกิจการ — ชื่อ ที่อยู่ และเลขประจำตัวผู้เสียภาษีที่พิมพ์เป็น หัวใบกำกับภาษี ต้องแก้ให้ตรงกับที่จดทะเบียนจริงก่อนออกเอกสาร ไม่งั้นใบที่พิมพ์ออกไปใช้ไม่ได้
เก็บในฐานข้อมูล ไม่ได้ฝังในโค้ด — วันที่กิจการย้ายที่อยู่จะได้แก้เองได้ทันทีโดยไม่ต้อง deploy ใหม่
ที่หน้า สินค้าตามจังหวัด กดปุ่ม "ปักหมุดตำแหน่ง" บนการ์ดแผนที่
ช่องค้นหารับสองอย่างในช่องเดียว:
13.7563, 100.5018 (จาก Google Maps) หมุดย้ายทันที ไม่ต้องยิงเน็ตบนแผนที่: คลิก = วางหมุด · ลาก = เลื่อนภาพ · ปุ่ม + / − = ซูม · ปุ่มหมุด = กลับไปที่หมุด คลิกที่แผนที่แล้วกดลูกศรขยับหมุดทีละน้อย (Shift ค้าง = เร็วขึ้น) ใช้ด้วยคีย์บอร์ดล้วนได้
แผนที่ปักหมุดเขียนเองด้วยภาพ tile ของ OpenStreetMap ไม่ใช้ไลบรารีแผนที่และไม่ต้องมี API key — แผนที่ Google Maps Embed ที่ใช้แสดงผลเป็น iframe ข้ามโดเมน จึงรู้ไม่ได้ว่าผู้ใช้คลิกตรงไหน
การค้นหาใช้ Nominatim ซึ่งจำกัด 1 คำขอต่อวินาที ระบบจึงค้นเมื่อกดปุ่มหรือกด Enter เท่านั้น
เมนู ข้อมูลหลัก → รายละเอียดลูกค้า เก็บทะเบียนลูกค้า: รหัส (ออกให้อัตโนมัติแบบ C0001)
ชื่อ ที่อยู่ ตำบล อำเภอ จังหวัด รหัสไปรษณีย์ เบอร์โทร และประเภทลูกค้า
ที่อยู่แยกเป็นคนละช่อง ไม่ได้เก็บรวมเป็นก้อนเดียว เพราะต้องเอาไปกรองและออกรายงานรายจังหวัด ค้นหาได้จากทุกช่องพร้อมกัน (รหัส ชื่อ เบอร์โทร ที่อยู่) และกรองตามประเภทได้
จังหวัด / อำเภอ / ตำบล เลือกเอา ไม่ต้องพิมพ์ — เลือกจังหวัดแล้วเห็นเฉพาะอำเภอของจังหวัดนั้น เลือกอำเภอแล้วเห็นเฉพาะตำบลของอำเภอนั้น พอเลือกตำบลแล้ว รหัสไปรษณีย์เติมให้เองและแก้ไม่ได้ (รหัสที่ไม่ตรงกับตำบลคือที่อยู่ที่ส่งของไม่ถึง) กรุงเทพฯ ป้ายเปลี่ยนเป็น เขต/แขวง ให้เอง
ข้อมูล 77 จังหวัด · 930 อำเภอ/เขต · 7,452 ตำบล/แขวง ฝังไว้ในโปรเจกต์ที่ lib/thaiAddress.js
ไม่ได้ยิง API ตอนใช้งาน — ที่อยู่ต้องกรอกได้ตลอด ถ้าไปพึ่งเว็บนอกแล้ววันไหนเขาปิด
หน้าจอนี้จะกรอกไม่ได้ทันที ไฟล์นี้โหลดแบบ dynamic เฉพาะตอนเปิดหน้าลูกค้า ไม่ติดไปกับหน้าอื่น
อัปเดตข้อมูลเมื่อมีการเปลี่ยนเขตปกครอง (ต้องต่อเน็ต):
node tools/make-thai-address.mjs
ที่มาข้อมูล: kongvut/thai-province-data (MIT) อ้างอิงกรมการปกครอง
ช่อง "ชื่อลูกค้า" ที่หน้า POS ยังเป็นข้อความอิสระเหมือนเดิม ยังไม่ได้ผูกกับทะเบียนนี้
เมนู การจัดการระบบ → กำหนดคลังและที่เก็บ เลือกคลังทางซ้าย จัดการช่องเก็บของคลังนั้นทางขวา (ต่างจาก ผังที่เก็บสินค้า ที่เน้นดูเป็นภาพและจัดวางสินค้าลงช่อง)
ลบไม่ได้ถ้าของยังอยู่ — คลังที่ยังมีสินค้าคงเหลือหรือเคยมีรายการเคลื่อนไหวลบไม่ได้ (ประวัติต้องเก็บไว้ตรวจสอบย้อนหลัง) ช่องเก็บที่ยังมีของก็ลบไม่ได้ ต้องย้ายของออกก่อน ไม่งั้นผลรวมของทุกช่องจะไม่เท่ากับยอดคงเหลือของคลัง ซึ่งเป็นกติกาที่ทั้งระบบยึดไว้
เมนู การจัดการระบบ → การกำหนดกลุ่มเอกสาร ตั้งรูปแบบเลขที่เอกสารของแต่ละหน้าจอทำรายการ (รับ / เบิก / โอน / ปรับปรุง / ขาย) ได้ 3 อย่าง:
| ตั้งได้ | ค่าเริ่มต้น | หมายเหตุ |
|---|---|---|
| อักษรนำหน้า | RC IS TF AD SL | A-Z และ 0-9 ไม่เกิน 6 ตัว |
| การขึ้นเลขใหม่ | ขึ้นใหม่ทุกเดือน | ต่อเนื่องตลอด / ทุกปี / ทุกเดือน |
| จำนวนหลัก | 4 | 2 ถึง 8 |
เลขถัดไปนับจากเอกสารที่บันทึกไว้จริง ไม่ได้เก็บตัวนับไว้ที่ไหน เพราะฐานข้อมูลใช้ร่วมกัน หลายเครื่อง ถ้าเก็บตัวนับแล้วสองเครื่องอ่านพร้อมกันจะได้เลขซ้ำ
เปลี่ยนรูปแบบแล้วเลขเริ่มนับหนึ่งใหม่ — เป็นผลโดยตรงจากวิธีนับ เพราะเลขถัดไปดูจาก เอกสารที่ขึ้นต้นด้วยอักษรนำหน้าชุดเดียวกันเท่านั้น เอกสารเดิมไม่ถูกแก้ไข ยังค้นหาได้ตามปกติ ระบบจะถามยืนยันให้ก่อนถ้ากลุ่มนั้นมีเอกสารอยู่แล้ว
กดที่หัวข้อกลุ่ม (ภาพรวม / ทำรายการ / ขายหน้าร้าน / ข้อมูลหลัก / การจัดการระบบ / รายงาน) เพื่อหุบกลุ่มนั้น ระบบจำไว้ให้ในเบราว์เซอร์ของเครื่องนั้น
ถ้ากดทางลัดไปหน้าที่อยู่ในกลุ่มที่หุบไว้ กลุ่มนั้นจะกางออกให้เอง จะได้เห็นว่าตัวเองอยู่ตรงไหน
Deploy บน Vercel — ไม่ต้องตั้งค่าอะไรเพิ่ม Vercel ตรวจจับ Next.js จาก package.json
แล้วรัน npm install + next build ให้เองบนคลาวด์
npm install
npm run dev # เปิด http://localhost:3000
รายละเอียดสเปก โครงสร้างไฟล์ ผลการทดสอบ และบันทึกการแก้ไข อยู่ที่ Docs/ProjectPlan.txt
Docs/ProjectProcess.xlsx — กระบวนการสร้างโครงงานนี้แบบละเอียด 9 ชีต:
ภาพรวมโครงงาน · ขั้นตอนการทำงานมาตรฐาน 18 ขั้น · ขั้นตอนการสร้างจริง 69 รอบ
(พร้อมเหตุผลของแต่ละการตัดสินใจ) · ประวัติการส่งงานจาก git · หน้าจอทั้งหมด ·
ตารางฐานข้อมูลและคอลัมน์ · ตรรกะกลางที่เขียนเอง · ตัวตรวจอัตโนมัติทุกหมวด ·
กฎที่ยึดตลอดโครงงาน
สร้างใหม่ให้ตรงกับโค้ดปัจจุบันได้ทุกเมื่อ:
node tools/make-process-xlsx.mjs
ไฟล์นี้อ่านข้อมูลจากของจริง (แผนงาน · เมนู · schema.sql · ตัวตรวจ · ประวัติ git) จึงไม่มีตัวเลขที่พิมพ์ค้างไว้ให้เก่าโดยไม่มีใครรู้
การดึงบิลอัตโนมัติ — ดึงบิลจากไฟล์ Excel (.xlsx) หรือ CSV เข้ามาติดตามการจัดส่ง หน้าจอบอกรูปแบบไฟล์ที่ต้องใช้ครบ พร้อมปุ่มโหลดแบบฟอร์มที่มีหัวคอลัมน์ให้แล้ว (เลขที่เอกสาร · วันที่เอกสาร · รหัสลูกค้า · ชื่อลูกค้า · ที่อยู่จัดส่ง · จังหวัด · ยอดเงิน) จับคู่คอลัมน์ให้อัตโนมัติ ดูข้อมูลในไฟล์ก่อนได้ และถามยืนยันก่อนอัพโหลดทุกครั้ง
เพิ่มผู้ใช้งาน — สร้างบัญชีเข้าระบบด้วยอีเมลและรหัสผ่าน ใช้ได้ทันทีไม่ต้องยืนยันอีเมล
เชื่อมต่อฐานข้อมูลภายนอก — SQL Server / MySQL-MariaDB / Microsoft Access เก็บค่าการเชื่อมต่อ (Server / ฐานข้อมูล / ผู้ใช้ / รหัสผ่าน หรือที่อยู่ไฟล์สำหรับ Access) ไว้ได้หลายชุด ตั้งค่าเริ่มต้นได้ คัดลอก connection string ไปใช้ที่อื่นได้ และทดสอบการเชื่อมต่อผ่าน "ตัวเชื่อม" ที่รันไว้ในวงเดียวกับเซิร์ฟเวอร์ (เบราว์เซอร์ต่อฐานข้อมูลพวกนี้ตรง ๆ ไม่ได้ เพราะเป็น TCP ดิบ ส่วน Access เป็นไฟล์)
นำเข้าข้อมูลจาก Excel — เลือกหน้าจอที่จะนำเข้า (สินค้า / ลูกค้า / เจ้าหนี้ / คลัง / บิล) ดูตัวอย่างรูปแบบไฟล์ กดสร้างแบบฟอร์มไปกรอก แล้วโหลดกลับเข้ามา เห็นข้อมูลในไฟล์ก่อน ตรวจรายแถว บอกชัดว่าซ้ำเลขที่/รหัสไหน และถามยืนยันก่อนอัพโหลด
เปลี่ยนรหัสผ่าน — ใส่รหัสเดิมแล้วตั้งรหัสใหม่สองครั้งให้ตรงกัน
รายละเอียดเจ้าหนี้ — ทะเบียนเจ้าหนี้ โครงเดียวกับทะเบียนลูกค้าทุกอย่าง
ซื้อสินค้าและบริการ — รับของเข้าคลังพร้อมบันทึกภาษีซื้อและเลขที่ใบของเจ้าหนี้
ส่งคืนสินค้าและบริการ — คืนของให้เจ้าหนี้ อ้างใบซื้อเสมอ คืนเกินที่ซื้อมาไม่ได้
เตรียมใบตรวจนับ — เลือกคลัง ขอบเขต (เฉพาะที่มีของ / ทั้งหมด) และผู้ตรวจนับ 2 คน ระบบเก็บยอด ณ ตอนสร้างใบไว้เป็นตัวเทียบ ปิดใบแล้วออกเอกสารปรับปรุงเฉพาะบรรทัดที่ต่างให้เอง
นับสินค้า (มือถือ) — ถือมือถือเดินนับ เปิดกล้องส่องบาร์โค๊ดที่ตัวสินค้า เด้งรหัสและชื่อขึ้นมาให้กรอกจำนวน กดตกลงแล้วกล้องเปิดใหม่รอชิ้นต่อไปทันที แสดงรายการทั้งใบพร้อมสถานะ (ยังไม่ได้นับ = ขอบกะพริบ / ตรวจนับแล้ว / มีผลต่าง) กดที่บรรทัดเพื่อนับเองได้ และพิมพ์หรือส่งออกเป็นรายงานผลการตรวจนับได้จากหน้านี้
สร้างรายงาน — ตารางสรุปแบบ pivot เลือกแถว/คอลัมน์/ค่าที่จะรวมเองได้เหมือนใน Excel
สำรองและกู้คืนข้อมูล — สำรองทุกตารางลงไฟล์เดียว เลือกโฟลเดอร์ปลายทางในเครื่องได้
กำหนดสิทธิการใช้งาน — ติ๊กเลือกว่าหน้าจอไหนแสดง แก้ไขได้ และเปลี่ยนวันที่ได้
รายงาน 18 แท็บ — ครบทุกหน้าจอที่มีการบันทึกข้อมูล แบ่งกลุ่มตามงาน: ภาพรวม (ยอดคงเหลือ, บัตรสินค้า) · ทำรายการ (รับ/เบิก/โอน/ปรับปรุง, ใบตรวจนับ) · งานซื้อ (ใบซื้อ, ใบส่งคืน) · งานขาย (รายการขาย, บิล/ใบเสร็จ, ใบขาย) · งานจัดส่ง (เวลาแต่ละขั้น) · ข้อมูลหลัก (ทะเบียนสินค้า/ลูกค้า/เจ้าหนี้, คลังและช่องเก็บ) ทุกแท็บพิมพ์ ส่งออก CSV/Excel และค้นหาได้ — ช่องค้นหาพิมพ์แค่ส่วนใดส่วนหนึ่งก็เจอ ช่องเลือกลูกค้า/เจ้าหนี้/สินค้า กดเลือกหรือพิมพ์ค้นก็ได้ แถบตัวกรองเปลี่ยนตามแท็บ แสดงเฉพาะช่องที่มีผลกับข้อมูลในแท็บนั้นจริง
กราฟสรุป — แนวโน้มยอดคงเหลือ, รับเข้าเทียบจ่ายออก, แยกหมวดหมู่, 10 อันดับสูงสุด
Quick View (มือถือ) — ดูยอดขายเทียบเป้าเร็ว ๆ เลือกช่วงเวลา พนักงานขาย ยี่ห้อสินค้า มีทั้งตัวเลข กราฟ (แท่ง / แท่งนอน / โดนัท) และยอดขายรายลูกค้าเรียงมากไปน้อย
กำหนดเป้าขาย — ตั้งเป้ารายงวด แยกรายพนักงานขาย กลุ่ม ยี่ห้อ ประเภทสินค้า เทียบกับยอดขายจริงให้อัตโนมัติ · โหลดจาก Excel ได้
กำหนดพนักงานขาย — รหัส (ไม่เกิน 50 ตัว) และชื่อ (ไม่เกิน 200 ตัว) เลือกได้ที่หน้าขายและตั้งเป็นคนประจำของลูกค้าได้
แดชบอร์ดที่เลือกได้ — ดรอปดาวน์เลือกหน้าจอที่จะดูข้อมูล (ภาพรวมคลัง / ขาย / POS / ซื้อ / จัดส่ง / ทำรายการ) แล้วติ๊กเลือกว่าจะเอาการ์ดหรือกราฟใบไหนมาแสดง ระบบจัดตำแหน่งให้เอง เลือกรูปแบบกราฟได้ (แท่ง / เส้น / แท่งนอน / โดนัท) และจำสิ่งที่เลือกไว้ในเครื่องนั้น
ผู้ช่วย AI — ปุ่มลอยมุมขวาล่าง ถามได้ทั้งวิธีใช้งานระบบและข้อมูลในคลังตอนนี้
ติดตั้งเป็นแอปได้ (PWA) — เปิดจากหน้าจอโฮมเหมือนแอปทั่วไป ไม่มีแถบเบราว์เซอร์