Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions connectors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ core sạch và không phụ thuộc vào bất kỳ nền tảng cụ thể nà
```
connectors/
├── zalo/ # Zalo OA Connector — nhận/gửi tin nhắn qua Zalo Official Account
├── google_sheet/ # (sắp có) đọc/ghi đơn hàng, khách hàng qua Google Sheet
├── google_sheet/ # Google Sheet Connector — đọc/ghi đơn hàng, khách hàng
├── nhanh/ # (sắp có) tích hợp Nhanh.vn
└── base/ # (sắp có) tích hợp Base.vn
```
Expand All @@ -37,5 +37,6 @@ connectors/
```bash
pip install -e sdk/python[connectors,dev]
pip install -r connectors/zalo/requirements.txt
pytest connectors/zalo/tests
pip install -r connectors/google_sheet/requirements.txt
pytest connectors/zalo/tests connectors/google_sheet/tests
```
89 changes: 89 additions & 0 deletions connectors/google_sheet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Google Sheet Connector

Đọc/ghi dữ liệu đơn hàng (`Order`) và khách hàng (`Customer`) từ Google Sheet —
phù hợp cho shop nhỏ chưa dùng phần mềm quản lý bán hàng riêng.

## 1. Chuẩn bị

1. Tạo project trên [Google Cloud Console](https://console.cloud.google.com), bật **Google Sheets API**.
2. Tạo **Service Account** → tải file JSON key.
3. Mở Google Sheet cần dùng → **Share** với email của Service Account
(dạng `xxx@project-id.iam.gserviceaccount.com`), quyền **Editor**.
4. Copy `config.example.yaml` → `config.yaml`, điền `spreadsheet_id` (lấy từ URL sheet)
và nội dung JSON key.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

> ⚠️ **`config.yaml` và file JSON key chứa secret** (private key của service account).
> Không commit hai file này vào git (đã có trong `.gitignore` mẫu — kiểm tra lại trước khi
> push). Ở production, ưu tiên `service_account_file` trỏ tới key nằm ngoài repo, hoặc
> nạp key từ secret manager (Vault, AWS Secrets Manager...) thay vì nhúng thẳng vào YAML.

## 2. Cài đặt

Chạy từ thư mục gốc repo (`magic/`):

```bash
pip install -e 'sdk/python[connectors]'
pip install -r connectors/google_sheet/requirements.txt
```

## 3. Sử dụng

Sheet cần có dòng header ở hàng đầu tiên khớp với tên field, ví dụ tab `Customers`:

| id | name | phone | email | address |
|----|------|-------|-------|---------|
| C001 | Nguyễn Văn A | 0901234567 | a@example.com | 12 Lê Lợi, Q1 |
Comment thread
coderabbitai[bot] marked this conversation as resolved.

> **Quan trọng:** `map_from_common_schema` luôn ghi giá trị theo **thứ tự cột cố định**
> (đúng thứ tự field trong ví dụ trên với Customer, và
> `id, customer_id, status, total_amount, shipping_fee, created_at, items_json` với Order).
> Nếu bạn đổi thứ tự cột trong sheet thật, giá trị sẽ bị ghi lệch cột — giữ đúng thứ tự
> này, hoặc tự viết lại `map_from_common_schema` để ghi theo header thực tế của sheet.

```python
import asyncio
import yaml
from connectors.google_sheet.connector import GoogleSheetConnector

async def main():
config = yaml.safe_load(open("connectors/google_sheet/config.yaml"))
async with GoogleSheetConnector(config) as conn:
# Đọc toàn bộ khách hàng
data = await conn.execute("read_range", {"range": "Customers!A1:E100"})
header, *rows = data.get("values", [])
customers = [conn.map_to_common_schema({"header": header, "row": r}, "customer") for r in rows]
print(customers)

# Thêm khách hàng mới — thứ tự cột phải khớp header (xem lưu ý ở trên)
row = conn.map_from_common_schema(
{"id": "C002", "name": "Trần Thị B", "phone": "0909999999"}, "customer"
)
await conn.execute("append_row", {"range": "Customers!A1:E1", "values": [row]})

asyncio.run(main())
```

## 4. Các operation hỗ trợ (`execute(operation, params)`)

| operation | params | Mô tả |
|-----------|--------|-------|
| `read_range` | `range` (A1 notation, vd `"Orders!A1:H100"`) | Đọc dữ liệu thô |
| `update_range` | `range`, `values` (list of rows) | Ghi đè một vùng |
| `append_row` | `range`, `values` | Thêm dòng mới vào cuối bảng |
| `batch_update` | `updates: [{range, values}, ...]` | Ghi nhiều vùng trong 1 lần gọi API |

## 5. Giới hạn hiện tại

- Mapping Common Schema dựa vào tên cột trong header khi **đọc**; khi **ghi**,
`map_from_common_schema` xuất theo thứ tự cột cố định (xem mục 3) — chưa hỗ trợ
mapping tùy biến theo header thực tế qua config.
- `Order.items` lưu dưới dạng JSON string trong cột `items_json` (Sheet không có kiểu
dữ liệu lồng nhau).
- Google Sheets API có giới hạn quota (mặc định 60 request ghi/phút/user) —
connector sẽ raise `RateLimitError` khi bị giới hạn, cần tự xử lý backoff ở tầng gọi.

## 6. Chạy test

```bash
pytest connectors/google_sheet/tests
```
5 changes: 5 additions & 0 deletions connectors/google_sheet/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Google Sheet connector for MagiC."""

from .connector import GoogleSheetConnector

__all__ = ["GoogleSheetConnector"]
22 changes: 22 additions & 0 deletions connectors/google_sheet/config.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copy to config.yaml (gitignored) and fill in real values.
#
# 1. Tạo Service Account trên Google Cloud Console, bật Google Sheets API.
# 2. Tải file JSON key của Service Account.
# 3. Share Google Sheet với email của Service Account (vd:
# xxx@my-project.iam.gserviceaccount.com), quyền Editor.
# 4. Copy nội dung file JSON key vào service_account_info bên dưới, hoặc
# dùng service_account_file trỏ tới đường dẫn file JSON.

spreadsheet_id: "YOUR_SPREADSHEET_ID" # lấy từ URL: /spreadsheets/d/<ID>/edit

# Cách 1: nhúng trực tiếp nội dung JSON key
service_account_info:
type: service_account
project_id: "your-project-id"
private_key_id: "..."
private_key: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
client_email: "xxx@your-project.iam.gserviceaccount.com"
token_uri: "https://oauth2.googleapis.com/token"

# Cách 2 (thay cho service_account_info): trỏ tới file JSON key
# service_account_file: "/path/to/service-account-key.json"
Loading
Loading