# Schema Cơ Sở Dữ Liệu - MKT Zalo Service

Thiết kế và tài liệu database schema.

## Tổng Quan Tables

9 tables với relationships:
- `ZaloCustomers` - Hồ sơ khách hàng
- `CustomerTags` - Tags khách hàng (many-to-many)
- `Conversations` - Phiên chat
- `Messages` - Tất cả tin nhắn
- `ChatbotRules` - Quy tắc tự động
- `RuleConditions` - Điều kiện quy tắc
- `RuleActions` - Hành động quy tắc
- `MessageTemplates` - ZNS templates
- `TemplateParameters` - Parameters template

---

## Tables Chính

### ZaloCustomers

```sql
CREATE TABLE "ZaloCustomers" (
    "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    "ZaloUserId" VARCHAR(50) NOT NULL UNIQUE,
    "DisplayName" VARCHAR(255) NOT NULL,
    "AvatarUrl" VARCHAR(500),
    "PhoneNumber" VARCHAR(20),
    "Email" VARCHAR(255),
    "Segment" INT NOT NULL DEFAULT 0,
    "FirstInteractionAt" TIMESTAMPTZ NOT NULL,
    "LastInteractionAt" TIMESTAMPTZ NOT NULL,
    "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX "IX_ZaloCustomers_ZaloUserId" ON "ZaloCustomers" ("ZaloUserId");
CREATE INDEX "IX_ZaloCustomers_Segment" ON "ZaloCustomers" ("Segment");
```

### Conversations

```sql
CREATE TABLE "Conversations" (
    "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    "CustomerId" UUID NOT NULL REFERENCES "ZaloCustomers"("Id") ON DELETE CASCADE,
    "ZaloUserId" VARCHAR(50) NOT NULL,
    "Status" INT NOT NULL DEFAULT 0,
    "StartedAt" TIMESTAMPTZ NOT NULL,
    "EndedAt" TIMESTAMPTZ,
    "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX "IX_Conversations_CustomerId" ON "Conversations" ("CustomerId");
CREATE INDEX "IX_Conversations_Status_StartedAt" ON "Conversations" ("Status", "StartedAt" DESC);
```

### Messages

```sql
CREATE TABLE "Messages" (
    "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    "ConversationId" UUID NOT NULL REFERENCES "Conversations"("Id") ON DELETE CASCADE,
    "Type" INT NOT NULL,
    "Content" TEXT NOT NULL,
    "Direction" INT NOT NULL,
    "IsFromBot" BOOLEAN NOT NULL DEFAULT FALSE,
    "SentAt" TIMESTAMPTZ NOT NULL,
    "ZaloMessageId" VARCHAR(100),
    "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX "IX_Messages_ConversationId_SentAt" ON "Messages" ("ConversationId", "SentAt" DESC);
CREATE INDEX "IX_Messages_Content_FullText" ON "Messages" USING GIN (to_tsvector('english', "Content"));
```

---

## Tables Automation

### ChatbotRules

```sql
CREATE TABLE "ChatbotRules" (
    "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    "Name" VARCHAR(255) NOT NULL,
    "Type" INT NOT NULL,
    "Priority" INT NOT NULL DEFAULT 50,
    "IsActive" BOOLEAN NOT NULL DEFAULT TRUE,
    "MatchCount" INT NOT NULL DEFAULT 0,
    "LastMatchedAt" TIMESTAMPTZ,
    "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX "IX_ChatbotRules_IsActive_Priority" ON "ChatbotRules" ("IsActive", "Priority" DESC);
```

### RuleConditions

```sql
CREATE TABLE "RuleConditions" (
    "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    "RuleId" UUID NOT NULL REFERENCES "ChatbotRules"("Id") ON DELETE CASCADE,
    "Field" VARCHAR(50) NOT NULL,
    "Operator" VARCHAR(50) NOT NULL,
    "Value" TEXT NOT NULL,
    "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX "IX_RuleConditions_RuleId" ON "RuleConditions" ("RuleId");
```

---

## Tables Template

### MessageTemplates

```sql
CREATE TABLE "MessageTemplates" (
    "Id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    "ZaloTemplateId" VARCHAR(50) NOT NULL UNIQUE,
    "Name" VARCHAR(255) NOT NULL,
    "Content" TEXT NOT NULL,
    "Status" INT NOT NULL DEFAULT 0,
    "CreatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    "UpdatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX "IX_MessageTemplates_ZaloTemplateId" ON "MessageTemplates" ("ZaloTemplateId");
```

---

## Relationships

```
ZaloCustomers (1) ──── (M) Conversations
Conversations (1) ──── (M) Messages
ZaloCustomers (1) ──── (M) CustomerTags
ChatbotRules (1) ──── (M) RuleConditions
ChatbotRules (1) ──── (1) RuleActions
MessageTemplates (1) ──── (M) TemplateParameters
```

---

## Indexes

### Indexes Quan Trọng Về Hiệu Năng

| Table | Index | Mục Đích |
|-------|-------|----------|
| ZaloCustomers | IX_ZaloCustomers_ZaloUserId | Tra cứu nhanh theo Zalo user ID |
| Conversations | IX_Conversations_Status_StartedAt | List hội thoại active/gần đây |
| Messages | IX_Messages_ConversationId_SentAt | Lấy lịch sử hội thoại |
| Messages | IX_Messages_Content_FullText | Tìm kiếm full-text |
| ChatbotRules | IX_ChatbotRules_IsActive_Priority | Đánh giá quy tắc nhanh |

---

## Migrations

### Migration Ban Đầu

```bash
dotnet ef migrations add InitialSchema \
  --project src/MktZaloService.Infrastructure
  
dotnet ef database update \
  --project src/MktZaloService.Infrastructure
```

### Seed Data

```sql
INSERT INTO "ChatbotRules" ("Id", "Name", "Type", "Priority", "IsActive")
VALUES 
  (gen_random_uuid(), 'Quy tắc chào hỏi', 0, 100, TRUE),
  (gen_random_uuid(), 'Hỏi giá', 0, 90, TRUE),
  (gen_random_uuid(), 'Giờ mở cửa', 0, 90, TRUE);
```

---

## Ước Tính Dung Lượng Dữ Liệu

| Table | 6 Tháng | Tốc Độ Tăng |
|-------|---------|-------------|
| ZaloCustomers | 10,000 | +500/ngày |
| Conversations | 50,000 | +2,000/ngày |
| Messages | 750,000 | +30,000/ngày |

**Tổng Dung Lượng DB**: ~2GB (6 tháng)

---

## Chiến Lược Backup

```bash
# Backup tự động hàng ngày
- Full backup: Hàng ngày lúc 02:00 UTC
- Retention: 30 ngày
- Point-in-time recovery: 7 ngày gần nhất
```

---

**Phiên Bản Tài Liệu**: 1.0  
**Cập Nhật Lần Cuối**: 2026-01-18
