README.md

21.81 KB
12/09/2025 06:16
MD
# Budget Tracker - ระบบบันทึกรายรับรายจ่ายพร้อม AI

ระบบจัดการการเงินส่วนบุคคลแบบ web application ที่ช่วยให้ผู้ใช้สามารถบันทึกรายรับรายจ่าย และใช้ AI ช่วยจัดหมวดหมู่รายการอัตโนมัติ

## 📋 สารบัญ

1. [ภาพรวมโปรเจ็ค](#ภาพรวมโปรเจ็ค)
2. [แนวคิดการออกแบบ](#แนวคิดการออกแบบ)
3. [สถาปัตยกรรมระบบ](#สถาปัตยกรรมระบบ)
4. [ระบบ AI Categorization](#ระบบ-ai-categorization)
5. [Prompt Engineering](#prompt-engineering)
6. [การติดตั้งและใช้งาน](#การติดตั้งและใช้งาน)
7. [โครงสร้างไฟล์](#โครงสร้างไฟล์)
8. [API Documentation](#api-documentation)

## ภาพรวมโปรเจ็ค

Budget Tracker เป็นเว็บแอปพลิเคชันสำหรับจัดการการเงินส่วนบุคคล ที่มีจุดเด่นหลักคือการใช้ AI ช่วยจัดหมวดหมู่รายการรายรับรายจ่ายอัตโนมัติ

### ฟีเจอร์หลัก
- 📝 บันทึกรายรับรายจ่ายแบบ real-time
- 🤖 AI จัดหมวดหมู่อัตโนมัติ (รองรับทั้งรายรับและรายจ่าย)
- 📊 สรุปยอดรวม และแสดงยอดคงเหลือ
- 🔍 กรองรายการตามวันที่
- 💾 เก็บข้อมูลใน IndexedDB (ทำงานแบบ offline)
- 🌐 Responsive design รองรับมือถือ

### เทคโนโลยีที่ใช้
- **Frontend**: HTML5, CSS3, Vanilla JavaScript
- **Backend**: PHP 8+
- **Database**: IndexedDB (client-side)
- **AI Service**: Google Generative AI (Gemini)
- **Web Server**: Apache/Nginx

## แนวคิดการออกแบบ

### 1. User Experience (UX) Design
- **Simple First**: ออกแบบให้ใช้งานง่าย โดยไม่ต้องสมัครสมาชิก
- **Progressive Enhancement**: เริ่มจากฟีเจอร์พื้นฐาน แล้วค่อยเพิ่ม AI
- **Offline-First**: ใช้ IndexedDB เพื่อให้ทำงานได้แม้ไม่มีอินเทอร์เน็ต
- **Mobile-Friendly**: ออกแบบ responsive สำหรับการใช้งานบนมือถือ

### 2. Data Flow Design
```
[User Input] → [Form Validation] → [IndexedDB] → [UI Update]
                                       ↓
[AI Categorization] ← [Normalize] ← [Filter "อื่นๆ"]
```

### 3. AI Integration Philosophy
- **Human-AI Collaboration**: AI เป็นเครื่องมือช่วย ไม่ใช่ทดแทนการตัดสินใจของมนุษย์
- **Transparency**: แสดง prompt ที่ส่งให้ AI เพื่อให้ผู้ใช้เข้าใจกระบวนการ
- **Privacy-Aware**: ส่งเฉพาะคำอธิบายรายการ ไม่ส่งข้อมูลยอดเงินหรือข้อมูลส่วนตัว
- **Graceful Degradation**: หาก AI ไม่ทำงาน ระบบยังใช้งานได้ปกติ

### 4. Error Handling Strategy
- **Client-Side Validation**: ตรวจสอบข้อมูลก่อนส่ง
- **Progressive Error Display**: แสดงข้อผิดพลาดแบบไม่รบกวนผู้ใช้
- **Fallback Mechanisms**: มีทางเลือกเมื่อ AI service ไม่ทำงาน

## สถาปัตยกรรมระบบ

### Frontend Architecture
```
index.html (UI Structure)
├── styles.css (Styling)
└── app.js (Business Logic)
    ├── BudgetTracker Class
    ├── IndexedDB Management
    ├── UI Event Handlers
    └── AI Integration
```

### Backend Architecture
```
ai_categorize.php
├── Input Validation
├── Google AI API Integration
├── Error Handling
└── JSON Response
```

### Data Architecture
```
IndexedDB: BudgetTrackerDB
└── transactions (Object Store)
    ├── id (auto-increment)
    ├── type (income/expense)
    ├── category (หมวดหมู่)
    ├── description (รายละเอียด)
    ├── amount (จำนวนเงิน)
    ├── date (วันที่)
    └── timestamp (เวลาที่บันทึก)
```

## ระบบ AI Categorization

### การทำงานของ AI System

#### 1. Detection Phase (การตรวจจับรายการที่ต้องจัดหมวด)
```javascript
// ตรวจหารายการที่ยังไม่ได้จัดหมวด
const uncategorizedIncome = transactions.filter(t =>
  t.type === 'income' && (t.category === 'อื่นๆ' || !t.category)
);
const uncategorizedExpenses = transactions.filter(t =>
  t.type === 'expense' && (t.category === 'อื่นๆ' || !t.category)
);
```

#### 2. Normalization Phase (การทำให้ข้อมูลเป็นมาตรฐาน)
```javascript
normalizeDescription(desc) {
  return desc.trim().toLowerCase()
    .replace(/[^\u0E00-\u0E7Fa-zA-Z0-9\s]/g, '') // เก็บแต่ไทย อังกฤษ ตัวเลข ช่องว่าง
    .replace(/\s+/g, ' '); // normalize whitespace
}
```

**เหตุผลของการ Normalize:**
- **ความถูกต้องในการจับคู่**: AI อาจส่งคำตอบที่ normalize แล้ว
- **ลดความผิดพลาดจาก case sensitivity**: "ข้าวกล่อง" vs "ข้าวกล่อง "
- **กำจัดเครื่องหมายพิเศษ**: ลบ emoji, เครื่องหมายวรรคตอนที่อาจรบกวน

#### 3. Categorization Phase (การจัดหมวดหมู่)

**แยกการประมวลผลตาม Type:**
- ส่งคำขอแยกกันสำหรับ `income` และ `expense`
- ใช้ prompt และ category set ที่เฉพาะเจาะจงสำหรับแต่ละประเภท

**ข้อดีของการแยกส่ง:**
1. **ความแม่นยำสูงขึ้น**: prompt เฉพาะทางทำให้ AI เข้าใจบริบทดีขึ้น
2. **ความปลอดภัย**: ลดข้อมูลที่ส่งในแต่ละครั้ง
3. **Error Isolation**: หาก expense ล้มเหลว income ยังทำงานได้
4. **Progress Tracking**: แสดงความคืบหน้าได้ชัดเจน

#### 4. Mapping Phase (การแมปผลลัพธ์)
```javascript
// สำหรับรายจ่าย
const expenseCategoryMap = {
  'Food': 'อาหาร',
  'Transport': 'เดินทาง',
  'Entertainment': 'บันเทิง'
};

// สำหรับรายรับ
const incomeCategoryMap = {
  'Salary': 'เงินเดือน',
  'Bonus': 'โบนัส',
  'SideIncome': 'รายได้เสริม',
  'Gift': 'ของขวัญ'
};
```

## Prompt Engineering

### หลักการออกแบบ Prompt

#### 1. Clear Task Definition
- ระบุงานที่ต้องการให้ AI ทำอย่างชัดเจน
- กำหนด input format และ output format ที่ต้องการ
- ใช้ภาษาที่เข้าใจง่ายและไม่คลุมเครือ

#### 2. Constraint Specification
- จำกัด category ที่ AI สามารถเลือกได้
- ระบุ output format ที่ต้องการ (JSON)
- ป้องกันการสร้าง category ใหม่โดยไม่ได้รับอนุญาต

#### 3. Context Provision
- บอกว่าข้อมูลเป็นภาษาไทย
- ระบุประเภทของรายการ (รายรับ/รายจ่าย)

### Prompt Templates

#### สำหรับรายจ่าย (Expense)
```
Categorize these Thai expenses into Food, Transport, Entertainment: {expense_list}.
Return only a JSON object with format: {"item1": "category", "item2": "category"}.
Use only these categories: Food, Transport, Entertainment.
```

**การวิเคราะห์ Prompt:**
- **"Thai expenses"**: บอกภาษาและประเภทข้อมูล
- **"into Food, Transport, Entertainment"**: จำกัดทางเลือก
- **"Return only a JSON object"**: กำหนด output format
- **"Use only these categories"**: เน้นย้ำข้อจำกัด

#### สำหรับรายรับ (Income)
```
Categorize these Thai income sources into Salary, Bonus, SideIncome, Gift: {income_list}.
Return only a JSON object with format: {"item1": "category", "item2": "category"}.
Use only these categories: Salary, Bonus, SideIncome, Gift.
```

**เหตุผลการเลือก Categories:**

**รายจ่าย:**
- **Food**: ครอบคลุมอาหาร เครื่องดื่ม (รวมถึงเหล้า)
- **Transport**: รถ แท็กซี่ รถเมล์ น้ำมัน
- **Entertainment**: ความบันเทิง โรงหนัง เกม

**รายรับ:**
- **Salary**: เงินเดือน ค่าจ้างประจำ
- **Bonus**: โบนัส เงินรางวัล
- **SideIncome**: รายได้เสริม ขายของ งานพิเศษ
- **Gift**: ของขวัญ เงินให้

### Prompt Optimization Techniques

#### 1. Response Format Control
```
"Return only a JSON object with format: {...}"
```
- ป้องกัน AI ส่งข้อความอธิบายเพิ่มเติม
- ทำให้ parsing ง่ายขึ้น

#### 2. Category Restriction
```
"Use only these categories: ..."
```
- ป้องกันการสร้าง category ใหม่
- รับประกันความสอดคล้องกับระบบ

#### 3. Language Specification
```
"Categorize these Thai..."
```
- ช่วยให้ AI เข้าใจบริบทภาษา
- ปรับปรุงความแม่นยำสำหรับข้อความภาษาไทย

#### 4. Input Validation
```javascript
// ตรวจสอบผลลัพธ์จาก AI
if (expenseResult.success && expenseResult.categories) {
  // ตรวจสอบว่า category ที่ได้เป็น valid category
  if (aiCategory && expenseCategoryMap[aiCategory]) {
    // อัปเดตเฉพาะเมื่อ valid เท่านั้น
  }
}
```

### Error Handling in Prompts

#### 1. Malformed Response
- ใช้ regex ดึง JSON object จาก response ที่อาจมี markdown
- มี fallback parsing เมื่อ JSON.parse() ล้มเหลว

#### 2. Invalid Categories
- ตรวจสอบว่า category ที่ AI ส่งมาอยู่ใน mapping table
- ข้ามรายการที่ไม่สามารถแมปได้

#### 3. Partial Success
- รายงานจำนวนรายการที่จัดสำเร็จ เทียบกับรายการทั้งหมด
- ไม่ถือว่าล้มเหลวทั้งหมดเมื่อจัดได้เพียงบางรายการ
- กรอก "จำนวนเงิน"
- เลือก "วันที่"
- คลิก "เพิ่มรายการ"

### 2. ดูสรุปการเงิน
- รายรับรวม
- รายจ่ายรวม
- ยอดคงเหลือ

### 3. จัดหมวดหมู่ด้วย AI
- เพิ่มรายการโดยเลือกหมวดหมู่เป็น "อื่นๆ"
- คลิกปุ่ม "จัดหมวดหมู่รายการที่ยังไม่ได้จัด"
- AI จะจัดหมวดหมู่รายการอัตโนมัติเป็น:
  - อาหาร (Food)
  - เดินทาง (Transport)
  - บันเทิง (Entertainment)

### 4. กรองรายการตามวันที่
- ใช้ช่อง "กรองตามวันที่" ในส่วนรายการ
- เลือกวันที่ที่ต้องการดู

## คุณสมบัติ

### ✅ ฟีเจอร์หลัก
- เพิ่ม/ลบ/แก้ไขรายการรายรับ-รายจ่าย
- จัดหมวดหมู่อัตโนมัติด้วย Google AI
- สรุปการเงินแบบเรียลไทม์
- เก็บข้อมูลใน IndexedDB (ไม่ต้องใช้ฐานข้อมูล)
- Responsive Design ใช้งานได้บนมือถือ
- กรองรายการตามวันที่

### 📱 การรองรับอุปกรณ์
- Desktop (Chrome, Firefox, Safari, Edge)
- Mobile (iOS Safari, Chrome Mobile, Firefox Mobile)
- Tablet

### 🔐 ความปลอดภัย
- ข้อมูลเก็บใน IndexedDB ในเครื่องผู้ใช้
- API Key ถูกซ่อนไว้ใน Server-side PHP
- ไม่มีการส่งข้อมูลส่วนตัวไปยัง AI (ส่งเฉพาะชื่อรายการ)

## การแก้ไขปัญหา

### ปัญหา: AI ไม่ทำงาน
```
เหตุผลที่เป็นไปได้:
1. API Key ไม่ถูกต้อง
2. ไฟล์ PHP ไม่สามารถเข้าถึงอินเทอร์เน็ต
3. cURL extension ไม่ได้ติดตั้ง
4. Google AI API มีปัญหา

การแก้ไข:
1. ตรวจสอบ API Key
2. ตรวจสอบ Network connectivity
3. ติดตั้ง php-curl extension
4. ดู Error Log ของเว็บเซิร์ฟเวอร์
```

### ปัญหา: ข้อมูลหาย
```
เหตุผล: Browser cache ถูกล้าง
การแก้ไข: ข้อมูลจะสูญหายถาวร เพราะเก็บใน IndexedDB
แนะนำ: Export ข้อมูลก่อนล้าง cache (ฟีเจอร์นี้จะเพิ่มในอนาคต)
```

### ปัญหา: หน้าเว็บไม่แสดง
```
เหตุผล: ไฟล์ HTML ไม่ถูกต้อง
การแก้ไข: ตรวจสอบไฟล์ index.html และ path ของไฟล์
```

## การพัฒนาเพิ่มเติม

### เพิ่มหมวดหมู่ใหม่
แก้ไขใน JavaScript ส่วน `categories`:
```javascript
this.categories = {
    income: ['เงินเดือน', 'โบนัส', 'รายได้เสริม', 'หมวดหมู่ใหม่'],
    expense: ['อาหาร', 'เดินทาง', 'บันเทิง', 'หมวดหมู่ใหม่']
};
```

### เปลี่ยนภาษา AI Prompt
แก้ไขใน `categorizeWithAI()` function:
```javascript
prompt: `Categorize this list of expenses into หมวดใหม่1, หมวดใหม่2: ${expenseList}`
```

## ข้อจำกัด

### Google AI Studio API
- ฟรี: 15 requests/minute, 1,500 requests/day
- ต้องการอินเทอร์เน็ตในการจัดหมวดหมู่
- รองรับเฉพาะภาษาอังกฤษในการจัดหมวดหมู่

### IndexedDB
- ข้อมูลเก็บในเครื่องผู้ใช้เท่านั้น
- ข้อมูลจะหายถ้าล้าง Browser cache
- ไม่สามารถ Sync ข้ามอุปกรณ์

## การอัปเกรดในอนาคต
- [ ] Export/Import ข้อมูลเป็น CSV
- [ ] รายงานแบบกราฟ
- [ ] การตั้งงบประมาณ
- [ ] แจ้งเตือนเมื่อใกล้เกินงบ
- [ ] Multi-currency support
- [ ] Cloud sync

---

**หมายเหตุ:** แอปนี้ใช้ API ฟรีของ Google AI Studio ซึ่งมีขีดจำกัดการใช้งาน หากต้องการใช้งานจริงในระดับ Production ควรพิจารณาอัปเกรดแพลน

## การติดตั้งและการกำหนดค่า GOOGLE_AI_API_KEY (Installation & Configuration)

ด้านล่างเป็นคำอธิบายการติดตั้งเว็บเซิร์ฟเวอร์ และการกำหนดค่า `GOOGLE_AI_API_KEY` อย่างปลอดภัย

### 1) ติดตั้งเว็บเซิร์ฟเวอร์และ PHP

- ติดตั้ง Apache หรือ Nginx และ PHP 8+ พร้อม extension ที่จำเป็น (เช่น curl)
- ตัวอย่างบน Ubuntu/Debian:

```
sudo apt update
sudo apt install -y apache2 php php-curl php-xml
```

ปรับแต่งให้ DocumentRoot ชี้ไปที่โฟลเดอร์โปรเจ็ค (`/var/www/html` หรือ path ที่คุณใช้)

### 2) รับ GOOGLE_AI_API_KEY จาก Google Cloud

1. เข้าไปที่ Google Cloud Console: https://console.cloud.google.com/
2. เลือกหรือสร้างโปรเจ็คใหม่
3. เปิดใช้งานบริการ Generative AI (หรือ API ที่เกี่ยวข้อง) ตามเอกสารของ Google Cloud
4. ไปที่เมนู "APIs & Services" → "Credentials"
5. คลิก "Create credentials" → "API key"
6. คัดลอก API key และเก็บไว้ในที่ปลอดภัย

> หมายเหตุ: ชื่อเมนูหรือขั้นตอนใน Console อาจเปลี่ยนแปลงได้ตาม UI ของ Google Cloud ให้ดูเอกสารอย่างเป็นทางการกรณีสงสัย

### 3) กำหนดค่าคีย์อย่างปลอดภัย (แนะนำ)

ไม่ควรเก็บ API Key ไว้ในซอร์สโค้ดโดยตรง ให้ใช้วิธีเก็บใน Environment Variables หรือไฟล์คอนฟิกที่ไม่ถูกรวมใน git (เช่น `.env` ที่ใส่ใน `.gitignore`)

ตัวอย่างการตั้งค่า environment variable (ชั่วคราว ใน shell session):

```
export GOOGLE_AI_API_KEY="YOUR_REAL_API_KEY"
```

สำหรับ Apache (ใส่ใน VirtualHost หรือไฟล์ conf ของไซต์):

```
SetEnv GOOGLE_AI_API_KEY "YOUR_REAL_API_KEY"
```

สำหรับ systemd service ที่รัน PHP backend ให้เพิ่มในไฟล์ unit:

```
Environment=GOOGLE_AI_API_KEY=YOUR_REAL_API_KEY
```

### 4) วิธีที่ `ai_categorize.php` อ่านค่า (ตัวอย่าง)

ไฟล์ `ai_categorize.php` ถูกปรับให้ตรวจสอบตัวแปรสภาพแวดล้อมก่อนใช้ค่าเริ่มต้น ตัวอย่างที่ใช้ในโค้ด:

```php
$GOOGLE_AI_API_KEY = getenv('GOOGLE_AI_API_KEY') ?: 'GOOGLE_AI_API_KEY';
```

หากไม่ได้ตั้งค่า environment variable ไว้ โค้ดจะยังคงใช้ค่า placeholder `GOOGLE_AI_API_KEY` ซึ่งจะไม่สามารถเรียกใช้งานจริงได้

### 5) การทดสอบหลังตั้งค่า

1. ตั้งค่าตัวแปรสภาพแวดล้อม (หรือ Restart Apache ถ้าใช้ SetEnv)
2. เรียก endpoint `ai_categorize.php` ด้วย POST JSON:

```json
{
  "prompt": "ทดสอบการจัดหมวดหมู่ รายการอาหาร แท็กค่า"
}
```

3. ตรวจสอบว่าตอบกลับ JSON มี `success: true` หรือมี error รายละเอียด

### 6) คำแนะนำด้านความปลอดภัย

- อย่า commit API Key ลงใน git
- จำกัดการใช้งานของ API Key หากเป็นไปได้ (จำกัดเฉพาะ IP หรือบริการ)
- เก็บ log ที่มีข้อมูลสำคัญอย่างระมัดระวัง