feat(products): implement JSON import with auto-provisioning, UI modal, and documentation schema
This commit is contained in:
1 parent
63e3a2895d
commit
101143f26a
5 files changed
+768
-187
No files matched your search
@@ -0,0 +1,134 @@
|
||||
# คู่มือโครงสร้าง JSON สำหรับนำเข้าสินค้า (Product JSON Import Specification)
|
||||
|
||||
ระบบนำเข้าสินค้าของ HomAroma รองรับการ Import ผ่านไฟล์ `.json` หรือวาง Payload JSON Array ได้โดยตรงผ่าน:
|
||||
1. **หน้าจอ Admin:** เมนู `/products` -> กดปุ่ม **"Import JSON"**
|
||||
2. **API Endpoint:** `POST /api/products/bulk` หรือ `POST /api/products`
|
||||
|
||||
---
|
||||
|
||||
## 1. รูปแบบโครงสร้าง JSON (JSON Schema)
|
||||
|
||||
Payload หลักจะต้องเป็น **JSON Array** ของสินค้า โดยรองรับสินค้า 2 รูปแบบหลัก:
|
||||
|
||||
### แบบที่ 1: สินค้าเดี่ยว (Simple Product - ไม่มีตัวเลือกย่อย)
|
||||
เหมาะสำหรับสินค้าที่มีขนาดเดียว ราคาเดียว ไม่ต้องแตก Variant:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "ก้านไม้หอมปรับอากาศ กลิ่นมะลิไทย (Reed Diffuser Jasmine)",
|
||||
"categoryName": "Reed Diffuser",
|
||||
"brandName": "HomAroma",
|
||||
"price": 490,
|
||||
"stock": 100,
|
||||
"sku": "HA-RD-JAS-100",
|
||||
"barcode": "8859123456801",
|
||||
"description": "ก้านไม้กระจายความหอมกลิ่นดอกมะลิธรรมชาติ หอมละมุน 4-6 สัปดาห์",
|
||||
"details": "ปริมาตร: 100ml\nรวมก้านไม้ไฟเบอร์ 6 ก้าน",
|
||||
"images": [
|
||||
"https://example.com/uploads/diffuser-1.jpg",
|
||||
"https://example.com/uploads/diffuser-2.jpg"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> **ระบบ Auto-Handling:** เมื่อใส่ `price`, `stock`, `sku`, `barcode` ไว้ที่ระดับบนสุด ระบบจะสร้าง Default Base Variant ให้โดยอัตโนมัติ
|
||||
|
||||
---
|
||||
|
||||
### แบบที่ 2: สินค้าที่มีหลายตัวเลือกย่อย (Variable Product)
|
||||
เหมาะสำหรับสินค้าที่มี ขนาด, กลิ่น, หรือสี ให้เลือก:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "น้ำมันหอมระเหย ลาเวนเดอร์ 100% Pure Essential Oil",
|
||||
"categoryName": "Aroma Oil",
|
||||
"brandName": "HomAroma",
|
||||
"description": "น้ำมันหอมระเหยบริสุทธิ์แท้ 100% สกัดจากดอกลาเวนเดอร์ประเทศฝรั่งเศส",
|
||||
"details": "วิธีใช้: หยด 3-5 หยดลงในเตาอโรมา\nขนาด: 10ml, 30ml",
|
||||
"options": [
|
||||
{
|
||||
"name": "ขนาด",
|
||||
"values": ["10ml", "30ml"]
|
||||
}
|
||||
],
|
||||
"variants": [
|
||||
{
|
||||
"option1": "10ml",
|
||||
"price": 390,
|
||||
"stock": 50,
|
||||
"sku": "HA-LAV-10ML",
|
||||
"barcode": "8859123456701"
|
||||
},
|
||||
{
|
||||
"option1": "30ml",
|
||||
"price": 890,
|
||||
"stock": 30,
|
||||
"sku": "HA-LAV-30ML",
|
||||
"barcode": "8859123456702"
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
"https://example.com/uploads/lav-1.jpg"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### แบบที่ 3: รองรับหลายภาษา (Multilingual)
|
||||
สามารถใส่ข้อความหลายภาษาใน `translations` หรือใส่เป็น Object ที่ฟิลด์ `name`, `description`, `details` ได้โดยตรง:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "น้ำมันหอมระเหย ยูคาลิปตัส",
|
||||
"categoryName": "Aroma Oil",
|
||||
"brandName": "HomAroma",
|
||||
"price": 320,
|
||||
"stock": 60,
|
||||
"sku": "HA-EUC-10ML",
|
||||
"translations": {
|
||||
"th": {
|
||||
"name": "น้ำมันหอมระเหย ยูคาลิปตัส 100%",
|
||||
"description": "ช่วยให้หายใจโล่ง สดชื่น ปลอดโปร่ง",
|
||||
"details": "ขนาด: 10ml"
|
||||
},
|
||||
"en": {
|
||||
"name": "Eucalyptus Pure Essential Oil 100%",
|
||||
"description": "Refreshes breathing and clarifies the mind.",
|
||||
"details": "Size: 10ml"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. พจนานุกรมฟิลด์ (Data Dictionary)
|
||||
|
||||
| ฟิลด์ | ชนิดข้อมูล | จำเป็น? | คำอธิบายและข้อกำหนด |
|
||||
| :--- | :--- | :---: | :--- |
|
||||
| `name` | `string` \| `object` | **ใช่** | ชื่อสินค้า (เช่น `"Aroma Oil"` หรือ `{"th": "...", "en": "..."}`) |
|
||||
| `categoryName` | `string` | ทางเลือก | ชื่อหมวดหมู่ (หากยังไม่มีในระบบ ระบบจะ **Auto-Create** ให้ทันที) |
|
||||
| `categoryId` | `number` | ทางเลือก | รหัสหมวดหมู่เดิมในระบบ (ใช้แทน `categoryName` ได้) |
|
||||
| `brandName` | `string` | ทางเลือก | ชื่อแบรนด์ (หากยังไม่มีในระบบ ระบบจะ **Auto-Create** ให้ทันที) |
|
||||
| `brandId` | `number` | ทางเลือก | รหัสแบรนด์เดิมในระบบ (ใช้แทน `brandName` ได้) |
|
||||
| `description` | `string` \| `object` | ไม่ | คำอธิบายสินค้าโดยย่อ |
|
||||
| `details` | `string` \| `object` | ไม่ | รายละเอียดสินค้า วิธีการใช้งาน คุณสมบัติ |
|
||||
| `price` | `number` | ไม่* | ราคาจำหน่าย (กรณีสินค้าเดี่ยวไม่มี Variants) |
|
||||
| `stock` | `number` | ไม่* | จำนวนสต็อกคงเหลือ (กรณีสินค้าเดี่ยวไม่มี Variants) |
|
||||
| `sku` | `string` | ไม่ | รหัสสินค้า SKU |
|
||||
| `barcode` | `string` | ไม่ | รหัสบาร์โค้ดสินค้า (สำหรับยิงขายที่ POS) |
|
||||
| `images` | `array` | ไม่ | รายการรูปภาพ (รองรับทั้ง Array URL `["https://..."]` หรือ `[{"url": "...", "order": 0}]`) |
|
||||
| `options` | `array` | ไม่* | รายการตัวเลือก สูงสุด 3 ตัวเลือก เช่น `[{"name": "ขนาด", "values": ["10ml", "30ml"]}]` |
|
||||
| `variants` | `array` | ไม่* | รายการสินค้าย่อย โดย `option1`, `option2`, `option3` จะแมปตามลำดับของ `options` |
|
||||
| `translations` | `object` | ไม่ | แผนที่ภาษา เช่น `{"th": {...}, "en": {...}, "ja": {...}}` |
|
||||
|
||||
---
|
||||
|
||||
## 3. กลไกอัตโนมัติของ Backend (Auto-Provisioning Engine)
|
||||
|
||||
เมื่อส่ง JSON เข้าสู่ `POST /api/products/bulk`:
|
||||
1. **Auto-Category & Auto-Brand:** หากส่ง `categoryName` หรือ `brandName` ที่ยังไม่มีในระบบ ระบบจะสร้าง Category/Brand ใหม่ให้โดยอัตโนมัติ ไม่เกิด Error
|
||||
2. **Auto-Default Base Variant:** หากไม่ส่ง `variants` มา แต่ระบุ `price` หรือ `stock` หรือ `sku` ที่ระดับบนสุด ระบบจะแปลงเป็น Single Base Variant ให้อัตโนมัติ ทำให้สินค้าพร้อมขายและตัดสต็อกใน POS ได้ทันที
|
||||
3. **Auto-Normalize Images:** แปลงทั้ง String URLs และ Image Objects ให้อยู่ในฟอร์แมตฐานข้อมูลพร้อมกำหนด Order ให้อัตโนมัติ
|
||||
4. **Auto-Seed CMS Detail Sections:** ระบบจะสร้าง Section มาตรฐานสำหรับหน้าเว็บ Next.js SSR (Product Main Card, Description, Specifications, Reviews, Related Products) ให้ทันที ทำให้หน้าบ้านแสดงผลได้สมบูรณ์แบบโดยไม่ต้องเข้าไปตั้งค่าทีละชิ้น
|
||||
Reference in new issue
Block a user