# Travelin QA Report

วันที่ตรวจล่าสุด: 6 สิงหาคม 2569  
สภาพแวดล้อม: Flutter Web, Pixel 6 Android Emulator, XAMPP MariaDB/MySQL,
Travelin API ที่ `127.0.0.1:8787`

## ผลสรุป

- Flutter analyzer: ผ่าน (`No issues found`)
- Automated tests: ผ่าน 31/31 รายการ
- Web release build: ผ่าน
- Android debug APK build: ผ่าน
- Android release APK build: ผ่านหลังแก้ XML comment ใน release manifest
- Android release App Bundle build: ผ่าน
- Android runtime log: ไม่พบ `FATAL EXCEPTION`, `Unhandled Exception`,
  `RenderFlex overflow` หรือ `E/flutter` หลังทดสอบ
- API และ MySQL แบบ end-to-end: ผ่านสำหรับสมัคร/ล็อกอิน โปรไฟล์ ค้นหาทริป
  เข้าร่วมกลุ่ม อ่านสถานะสมาชิก แชต และออกจากกลุ่ม
- การป้องกันสิทธิ์: API กลุ่มที่ไม่มี token ตอบ 401, โหวต bid ที่ไม่มีจริงตอบ
  404 และชำระเงิน bid ที่ยังไม่ผ่านเงื่อนไขตอบ 403
- ข้อความล็อกอินผิดใช้ข้อความเดียวกันทั้งกรณีไม่มีบัญชีและรหัสผ่านผิด
  เพื่อลดการเดาบัญชีผู้ใช้
- MySQL grants ถูกจำกัดระดับตาราง/คอลัมน์ และไม่มีสิทธิ์ `DELETE`
- ติดตั้ง APK รุ่นล่าสุดบน Pixel 6 Emulator สำเร็จ และ API ใหม่ตอบสถานะพร้อมใช้งาน
- ทดสอบสิทธิ์ `SELECT/INSERT/UPDATE` ของตารางนัดหมายและรีวิวภายใน
  transaction แล้ว `ROLLBACK` สำเร็จ โดยไม่ทิ้งข้อมูลทดสอบ

## เส้นทางที่ทดสอบบน Pixel 6

1. เปิดหน้าแรกในฐานะผู้เยี่ยมชม
2. กดเข้าสู่ระบบและล็อกอินด้วยบัญชี QA จาก MySQL
3. เปิดหน้าค้นหา AI
4. เลือกข้อความ “ญี่ปุ่น งบ 20,000 ชอบกินและถ่ายรูป”
5. Gemini แยกประเทศญี่ปุ่น หมวดอาหารและคาเฟ่/ถ่ายรูป และงบ 20,000 บาท
6. ระบบอ่าน MySQL และแสดงเฉพาะกลุ่มประเทศญี่ปุ่น 8 กลุ่ม
7. เปิด “ฮิโรชิมาและเกาะมิยาจิมะ”
8. ตรวจชื่อ ประเทศ ราคา ระยะเวลา รูป และไฮไลต์ของสถานที่
9. เข้าร่วมกลุ่มสำเร็จ สมาชิกเปลี่ยนจาก 0/13 เป็น 1/13
10. ระบบแสดงสมาชิก QA จาก MySQL
11. ส่งข้อความจากหน้าจอมือถือและอ่านกลับได้
12. เปิดหน้าโหวตและเห็น empty state ที่ถูกต้อง เพราะฐานข้อมูลยังไม่มีข้อเสนอ

หลักฐานหน้าจออยู่ในโฟลเดอร์ `audit/screenshots/`

## ชุดทดสอบอัตโนมัติ

- แยกประเทศ งบประมาณ และความสนใจจากภาษาธรรมชาติ
- กรองเฉพาะประเทศและงบที่ผู้ใช้ระบุ
- จัดอันดับทริปทะเลในไทย
- ทำงานร่วมกันระหว่างข้อความกับ filter chips
- ส่ง token และอ่านข้อมูลกลุ่มจาก API
- อ่านข้อเสนอและสถานะการโหวตจาก API
- แสดงข้อความเมื่อ API ปฏิเสธสิทธิ์
- ไม่สร้างข้อมูลชำระเงินจำลองเมื่อยังไม่มีรายการจริง
- ปุ่มค้นหากลางหน้าแรกเปิดหน้า AI Search
- แสดงสถานะสมาชิกบนหน้าแรก
- แก้ข้อมูลโปรไฟล์และความสนใจบนมือถือ
- รายละเอียดเชียงใหม่ตรงกับรายการที่เลือก
- ผู้เยี่ยมชมถูกพาไปล็อกอินก่อนเปิดโปรไฟล์
- ผู้ไม่มี session เปิดหน้าโหวตไม่ได้
- ไม่รับข้อเสนอที่ยังไม่ถูกเลือกในหน้าชำระเงิน
- หน้าผลค้นหามือถือไม่เกิด RenderFlex overflow
- หลักฐานสถานะรอตรวจสอบเปลี่ยนเป็นชำระเงินสำเร็จหลัง 3 วินาที
- หน้าชำระเงินสำเร็จกลับไปยังห้องแชตของกลุ่มได้
- ห้องแชตแสดงสถานะชำระเงิน วันเวลา จุดนัด และผู้ประสานงาน
- หลังจำลองว่าทริปสิ้นสุด สามารถให้คะแนนทริปและบริษัทนำเที่ยวแยกกันได้
- อ่านและแปลงข้อมูลนัดหมาย/รีวิวจาก API ได้ถูกต้อง

## ข้อมูลทดสอบที่เกิดขึ้น

- ใช้บัญชี QA หมายเลขผู้ใช้ 7
- มีข้อความ QA ใน `group_messages` เพื่อยืนยันการเขียน/อ่านแชตจริง
- ไม่มีการสร้างข้อเสนอ การโหวต หรือการชำระเงินปลอม
- ไม่มีการลบข้อมูลเดิม

## รายการที่ยังบล็อกการปล่อยใช้งานจริง

1. เว็บไซต์บริษัททัวร์และขั้นตอนสร้างข้อเสนอจริงยังไม่ได้พัฒนา ข้อเสนอปัจจุบันเป็น
   ข้อมูลสำหรับการทดสอบใน MySQL
2. Backend ยังเป็นบริการภายในเครื่องและไม่มี HTTPS/domain สำหรับ production
3. Android release ยังต้องมี release signing key และค่าคอนฟิก production
4. Session ฝั่ง server อยู่ในหน่วยความจำ เมื่อ server restart ผู้ใช้ต้องล็อกอินใหม่
5. Session ฝั่งแอปยังไม่เก็บแบบ secure persistence เมื่อปิดแอปอาจต้องล็อกอินใหม่
6. ลืมรหัสผ่าน/OTP/email reset ยังไม่ได้พัฒนา
7. ต้องมี Privacy Policy, Terms, consent, backup, monitoring และ incident logging
8. ควรย้ายไฟล์รูปผู้ใช้/หลักฐานชำระเงินไป object storage ที่เข้ารหัสและจำกัดสิทธิ์
9. ต้องทดสอบกับอุปกรณ์จริงหลายขนาด, เครือข่ายช้า/หลุด, Android เวอร์ชันต่าง ๆ
   และทดสอบการเข้าถึงสำหรับผู้พิการก่อนเผยแพร่
10. Universal release APK มีขนาดประมาณ 135 MB และ AAB ประมาณ 127 MB โดย assets
    รูปทริปใช้ประมาณ 88 MB ควรปรับรูปเป็น WebP/โหลดจาก CDN เพื่อลดขนาดดาวน์โหลด
11. QR Code การรอ 3 วินาที และการตรวจสลิปเป็นโหมดสาธิต ยังไม่ได้เชื่อมระบบ
    PromptPay/ธนาคารหรือ API ตรวจสลิปจริง จึงห้ามใช้รับเงินจริง

## สถานะสิทธิ์ฐานข้อมูล

ฟังก์ชันกลุ่มและแชตทำงานแล้วโดยไม่มีสิทธิ์ `DELETE` สำหรับบัญชีแอป
สิทธิ์อ่านทั้งฐานข้อมูลและสิทธิ์เขียนทั้งตาราง `users` จากรุ่นพัฒนาเดิมถูกถอนแล้ว
บัญชี `travelin_app` อ่านเฉพาะตารางที่ backend ใช้ และเขียนได้เฉพาะตาราง/คอลัมน์
สำหรับสมาชิก กลุ่ม แชต โหวต และชำระเงิน
