BREAKDOWN

Refactor Addition Feature

Feature Addition Plan - CloudChat Application

Rencana penambahan 10 fitur baru untuk CloudChat berdasarkan requirements yang diberikan.

Uploaded Feature Requirements


User Review Required

[!IMPORTANT] Setiap fitur memiliki complexity dan dependensi yang berbeda. Harap review prioritas implementasi.

[!WARNING] Beberapa fitur memerlukan perubahan database schema dan integrasi dengan external APIs.


Daftar Fitur yang Akan Ditambahkan

  1. Chatbot - Waktu Aktif Bot
  2. Laporan Chatbot
  3. Mode Antrian (Queue System)
  4. Mode Pilih Agen
  5. Integrasi Ongkir (Shipping Cost API)
  6. Broadcast WA Official - Template Device Filter
  7. Template Meta - CRUD & Device Filter
  8. Facebook - Connection Error Info
  9. Icon Notifikasi Inbox
  10. Pipeline (100% mirip Socialchat)

Fitur 1: Chatbot - Waktu Aktif Bot

Deskripsi

Menambahkan kemampuan untuk mengatur jadwal waktu aktif chatbot. Bot hanya akan merespons dalam rentang waktu yang ditentukan.

Use Case

Flow Diagram

flowchart TD
    A[Pesan Masuk ke Chatbot] --> B{Cek Waktu Aktif<br/>Bot Enabled?}
    B -->|Tidak| C[Proses Normal<br/>Bot Merespons]
    B -->|Ya| D{Apakah Sekarang<br/>Dalam Jadwal Aktif?}
    D -->|Ya| C
    D -->|Tidak| E[Skip Bot Response]
    E --> F{Ada Auto Reply<br/>di Luar Jam?}
    F -->|Ya| G[Kirim Pesan<br/>Luar Jam Kerja]
    F -->|Tidak| H[Tidak Ada Response]
    G --> I[Tandai Conversation<br/>Needs Human]
    H --> I
    C --> J[Bot Process Normal]

Database Schema Changes

[NEW] Table: chatbot_schedules

CREATE TABLE chatbot_schedules (
    id SERIAL PRIMARY KEY,
    bot_id INTEGER NOT NULL REFERENCES chatbots(id) ON DELETE CASCADE,
    day_of_week INTEGER NOT NULL, -- 0=Sunday, 6=Saturday
    start_time TIME NOT NULL,
    end_time TIME NOT NULL,
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_chatbot_schedules_bot_id ON chatbot_schedules(bot_id);

[MODIFY] Table: chatbots

ALTER TABLE chatbots 
ADD COLUMN schedule_enabled BOOLEAN DEFAULT false,
ADD COLUMN timezone VARCHAR(50) DEFAULT 'Asia/Jakarta',
ADD COLUMN outside_hours_message TEXT;

Implementation Details

Backend

[NEW] src/controllers/chatbotScheduleController.js
// GET /api/app/chatbot/bots/:botId/schedules
// POST /api/app/chatbot/bots/:botId/schedules
// PUT /api/app/chatbot/schedules/:id
// DELETE /api/app/chatbot/schedules/:id
[NEW] src/services/chatbotScheduleService.js

Functions:

[MODIFY] src/services/chatbotService.js

Update processMessage():


Frontend

[NEW] frontend/src/pages/Chatbot/BotScheduleSettings.js

Component untuk manage bot schedules:

UI Components:


Fitur 2: Laporan Chatbot

Deskripsi

Dashboard laporan untuk memonitor performa dan statistik chatbot.

Metrics yang Dilacak

  1. Interaction Metrics

    • Total conversations handled
    • Average response time
    • Success rate (resolved vs escalated)
  2. Knowledge Base Performance

    • Most used Q&A pairs
    • Questions that failed to match
    • Confidence score distribution
  3. User Satisfaction

    • Rating dari users (jika ada)
    • Escalation rate
    • Conversation resolution time
  4. Time-based Analytics

    • Hourly/Daily/Weekly trends
    • Peak usage times
    • Response time trends

Flow Diagram

flowchart LR
    A[Chatbot Interaction] --> B[Log ke Database]
    B --> C[chatbot_interactions<br/>table]
    C --> D[Background Job<br/>Aggregate Data]
    D --> E[chatbot_analytics<br/>table]
    E --> F[Dashboard API]
    F --> G[Frontend Charts]
    
    H[Admin Akses<br/>Laporan] --> F

Database Schema Changes

[NEW] Table: chatbot_interactions

CREATE TABLE chatbot_interactions (
    id SERIAL PRIMARY KEY,
    bot_id INTEGER NOT NULL REFERENCES chatbots(id) ON DELETE CASCADE,
    conversation_id INTEGER REFERENCES conversations(id) ON DELETE SET NULL,
    question TEXT NOT NULL,
    answer TEXT,
    confidence_score DECIMAL(5,2),
    matched_qa_id INTEGER REFERENCES chatbot_qa(id) ON DELETE SET NULL,
    response_time_ms INTEGER,
    was_escalated BOOLEAN DEFAULT false,
    user_rating INTEGER, -- 1-5 stars
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_chatbot_interactions_bot_id ON chatbot_interactions(bot_id);
CREATE INDEX idx_chatbot_interactions_created_at ON chatbot_interactions(created_at);

[NEW] Table: chatbot_analytics

CREATE TABLE chatbot_analytics (
    id SERIAL PRIMARY KEY,
    bot_id INTEGER NOT NULL REFERENCES chatbots(id) ON DELETE CASCADE,
    date DATE NOT NULL,
    hour INTEGER, -- 0-23, NULL for daily aggregates
    total_interactions INTEGER DEFAULT 0,
    successful_interactions INTEGER DEFAULT 0,
    escalated_interactions INTEGER DEFAULT 0,
    avg_response_time_ms INTEGER,
    avg_confidence_score DECIMAL(5,2),
    avg_rating DECIMAL(3,2),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(bot_id, date, hour)
);

CREATE INDEX idx_chatbot_analytics_bot_date ON chatbot_analytics(bot_id, date);

Implementation Details

Backend

[NEW] src/controllers/chatbotReportController.js

Endpoints:

[NEW] src/services/chatbotReportService.js

Functions:

[NEW] src/queues/chatbotAnalyticsWorker.js

Background worker untuk aggregate data hourly:

[MODIFY] src/services/chatbotService.js

Update processMessage():


Frontend

[NEW] frontend/src/pages/Chatbot/BotReportsPage.js

Dashboard dengan:

Libraries:


Fitur 3: Mode Antrian dengan Divisi (Division-based Queue System)

Deskripsi

Sistem antrian otomatis berdasarkan Divisi/Department (Support, Billing, Umum, dll). Customer memilih divisi yang dituju, sistem auto-routing ke agen yang online di divisi tersebut, atau masukkan ke queue jika semua agen busy.

Screenshot Referensi

Contoh Queue Response

Cara Kerja

  1. Customer mengirim pesan pertama → Sistem kirim auto-reply menu divisi

    • "Selamat datang di toko kami, silahkan pilih agen yang anda tuju"
    • "1. Billing"
    • "2. Support"
    • "3. Umum"
  2. Customer pilih divisi (ketik 1, 2, 3 atau nama divisi)

    • Sistem deteksi pilihan (1, "billing", dll)
    • Cek agen yang online di divisi tersebut
  3. Auto-routing:

    • Jika ada agen online → Assign langsung ke agen
    • Jika semua agen busy/offline → Masuk queue divisi tersebut
    • Kirim auto-reply: "Anda akan di layani oleh tim {divisi}, Tunggu dalam antrian ke {nomor}. Tekan # untuk cek antrian"
  4. Check queue: Customer ketik "#" untuk cek posisi

    • Response: "Anda masih dalam antrian ke {nomor}. mohon menunggu"
  5. Saat agen available → Auto-assign dari queue (FIFO per divisi)

Flow Diagram

flowchart TD
    A[Customer Kirim<br/>Pesan Pertama] --> B{Queue Mode<br/>Enabled?}
    B -->|Tidak| C[Proses Normal]
    B -->|Ya| D[Kirim Menu Divisi<br/>Auto-Reply]
    
    E[Customer Pilih<br/>Divisi e.g. 1] --> F[Parse Pilihan<br/>Divisi ID]
    F --> G{Divisi Valid?}
    G -->|Tidak| H[Kirim Ulang Menu]
    G -->|Ya| I[Cek Agen Online<br/>di Divisi]
    
    I --> J{Ada Agen<br/>Online?}
    J -->|Ya| K[Auto-Assign<br/>ke Agen]
    J -->|Tidak| L[Masuk Queue<br/>Divisi]
    L --> M[Generate Queue<br/>Number]
    M --> N[Kirim Auto-Reply<br/>Nomor Antrian]
    
    K --> O[Mulai Chat<br/>dengan Agen]
    
    P[Customer Ketik #] --> Q[Cek Posisi Queue]
    Q --> R[Kirim Posisi<br/>Antrian]
    
    S[Agen Online/Available] --> T[Ambil dari Queue<br/>Divisi FIFO]
    T --> U[Auto-Assign<br/>Conversation]
    U --> V[Notif Customer<br/>Agen Siap]

Database Schema Changes

[NEW] Table: divisions (Divisi/Department)

CREATE TABLE divisions (
    id SERIAL PRIMARY KEY,
    organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL, -- e.g. "Billing", "Support", "Umum"
    description TEXT,
    keyword_triggers TEXT[], -- ['billing', 'tagihan', '1']
    is_active BOOLEAN DEFAULT true,
    position INTEGER DEFAULT 0, -- For ordering in menu
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_divisions_org ON divisions(organization_id);

[NEW] Table: division_agents (Agent Assignment)

CREATE TABLE division_agents (
    id SERIAL PRIMARY KEY,
    division_id INTEGER NOT NULL REFERENCES divisions(id) ON DELETE CASCADE,
    user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(division_id, user_id)
);

CREATE INDEX idx_division_agents_division ON division_agents(division_id);
CREATE INDEX idx_division_agents_user ON division_agents(user_id);

[NEW] Table: chat_queues

CREATE TABLE chat_queues (
    id SERIAL PRIMARY KEY,
    organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
    division_id INTEGER NOT NULL REFERENCES divisions(id) ON DELETE CASCADE,
    queue_number INTEGER NOT NULL, -- Queue number per division
    status VARCHAR(20) DEFAULT 'waiting', -- waiting, assigned, cancelled
    assigned_agent_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
    assigned_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_chat_queues_org_division ON chat_queues(organization_id, division_id, status);
CREATE INDEX idx_chat_queues_created ON chat_queues(created_at);
CREATE UNIQUE INDEX idx_chat_queues_conversation ON chat_queues(conversation_id) WHERE status = 'waiting';

[NEW] Table: queue_settings

CREATE TABLE queue_settings (
    id SERIAL PRIMARY KEY,
    organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE UNIQUE,
    is_enabled BOOLEAN DEFAULT false,
    welcome_message TEXT DEFAULT 'Selamat datang di toko kami, silahkan pilih agen yang anda tuju',
    queue_message_template TEXT DEFAULT 'Anda akan di layani oleh tim {division}, Tunggu dalam antrian ke {queue_number}. Tekan # untuk cek antrian',
    check_queue_keyword VARCHAR(10) DEFAULT '#',
    queue_position_message TEXT DEFAULT 'Anda masih dalam antrian ke {queue_number}. mohon menunggu',
    no_agent_available_message TEXT DEFAULT 'Maaf, saat ini tidak ada agen yang tersedia. Anda akan dilayani secepatnya.',
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

[MODIFY] Table: conversations

ALTER TABLE conversations
ADD COLUMN division_id INTEGER REFERENCES divisions(id) ON DELETE SET NULL,
ADD COLUMN awaiting_division_selection BOOLEAN DEFAULT false;

Implementation Details

Backend

[NEW] src/controllers/divisionController.js

Division Management Endpoints:

[NEW] src/controllers/queueController.js

Queue Endpoints:

[NEW] src/services/queueService.js

Functions:

[NEW] src/services/divisionService.js

Functions:

[MODIFY] src/controllers/webhookController.js

Update handleWAWebhook():

// When new message arrives
if (queueSettings.is_enabled && !conversation.division_id) {
    // First message from customer
    await queueService.sendDivisionMenu(conversation.id);
    await pool.query(
        'UPDATE conversations SET awaiting_division_selection = true WHERE id = $1',
        [conversation.id]
    );
} else if (conversation.awaiting_division_selection) {
    // Customer memilih divisi
    await queueService.handleDivisionSelection(conversation.id, message.text);
} else if (message.text === queueSettings.check_queue_keyword) {
    // Customer cek queue position
    await queueService.handleCheckQueueCommand(conversation.id);
}
[NEW] Socket.IO Events
// To agents in specific division
io.to(`division:${divisionId}`).emit('queue:updated', queueData);
io.to(`agent:${agentId}`).emit('queue:assigned', conversationData);

// To customer when assigned
io.to(`conversation:${conversationId}`).emit('agent:assigned', agentInfo);

Frontend

[NEW] frontend/src/pages/Settings/DivisionManagement.js

Division Management Page (Settings > Queue & Divisi > Manajemen Divisi):

Features:

  1. Division List

    • Table dengan columns: Name, Keywords, Agents Count, Active Status, Actions
    • Drag-and-drop untuk reorder (position)
    • Add Division button
    • Edit/Delete actions
  2. Add/Edit Division Modal

    • Division name input
    • Description textarea
    • Keyword triggers (comma-separated): "billing, tagihan, 1"
    • Active toggle
    • Agent multi-select (assign agents to this division)
  3. Agent Assignment

    • For each division, show assigned agents
    • Add/remove agents
    • Agent can be in multiple divisions
[NEW] frontend/src/pages/Settings/QueueSettingsPage.js

Queue Settings Page (Settings > Queue & Divisi > Pengaturan Antrian):

Configuration Sections:

  1. Enable Queue System

    • Toggle: Enable/Disable
    • Info box: Penjelasan cara kerja queue
  2. Welcome Message

    • Textarea: Pesan sambutan
    • Default: "Selamat datang di toko kami, silahkan pilih agen yang anda tuju"
    • Preview: Shows how menu will look with divisions
  3. Queue Message Template

    • Template dengan variables: {division}, {queue_number}
    • Default: "Anda akan di layani oleh tim {division}, Tunggu dalam antrian ke {queue_number}. Tekan # untuk cek antrian"
  4. Check Queue Keyword

    • Input: Keyword untuk cek antrian (default: "#")
  5. Queue Position Message

    • Template dengan variable: {queue_number}
    • Default: "Anda masih dalam antrian ke {queue_number}. mohon menunggu"
  6. No Agent Available Message

    • Message saat semua agen offline
  7. Preview Section

    • Live preview conversation flow
    • Show menu dengan divisions yang sudah dibuat
    • Show contoh queue messages

Location: Settings > Queue & Divisi

[NEW] frontend/src/components/inbox/QueuePanel.js

Queue Panel di Inbox (untuk Agents):

Features:

[MODIFY] frontend/src/pages/InboxPage.js

Updates:

[NEW] frontend/src/components/settings/DivisionAgentAssignment.js

Component untuk assign agents ke divisions:


Configuration Workflow (Setup Guide)

Step-by-step untuk Admin:

  1. Enable Queue System

    • Go to Settings > Queue & Divisi > Pengaturan Antrian
    • Toggle "Enable Queue System" ON
  2. Create Divisions

    • Go to Settings > Queue & Divisi > Manajemen Divisi
    • Click "Add Division"
    • Input:
      • Name: "Billing"
      • Keywords: "billing, tagihan, 1"
    • Repeat untuk divisions lain (Support, Umum, dll)
  3. Assign Agents to Divisions

    • For each division, click "Manage Agents"
    • Select agents yang belong to divisi tersebut
    • Save
  4. Configure Messages

    • Customize welcome message
    • Customize queue message template
    • Set check queue keyword (default: #)
  5. Test

    • Send message sebagai customer
    • Verify menu divisi muncul
    • Test selection
    • Test queue assignment
    • Test "#" command

Fitur 4: Division Selection Enhancement

Deskripsi

Enhancement untuk Fitur 3 - memberikan customer lebih banyak flexibility dalam memilih divisi dan melihat informasi divisi.

Additional Features

  1. Division Description di Menu

    • Saat menampilkan menu, include deskripsi divisi
    • Example:
      Selamat datang! Pilih divisi yang ingin Anda hubungi:
      
      1. Billing - Untuk pertanyaan pembayaran dan invoice
      2. Support - Bantuan teknis dan troubleshooting
      3. Umum - Pertanyaan umum lainnya
      
  2. Estimated Wait Time

    • Show estimasi waktu tunggu per divisi
    • Based on current queue + average handling time
    • Example: "Support (3 antrian, ~15 menit)"
  3. Smart Keyword Detection

    • Detect keywords di customer message
    • Auto-suggest divisi yang relevan
    • Example: Customer ketik "saya mau bayar" → Auto-detect "Billing"
  4. Rich Menu Options

    • Support menu dengan buttons (jika platform support)
    • WhatsApp: List message atau buttons
    • Telegram: Inline keyboard
    • Messenger: Quick replies

Database Schema Addition

[MODIFY] Table: divisions

ALTER TABLE divisions
ADD COLUMN avg_handling_time_minutes INTEGER DEFAULT 10,
ADD COLUMN show_wait_time BOOLEAN DEFAULT false,
ADD COLUMN auto_detect_keywords BOOLEAN DEFAULT false;

Implementation

[MODIFY] src/services/queueService.js

Enhanced functions:

[MODIFY] frontend/src/pages/Settings/DivisionManagement.js

Additional fields:


Fitur 5: Integrasi Ongkir (BYOK System)

Deskripsi

Integrasi dengan RajaOngkir API menggunakan sistem BYOK (Bring Your Own Key) - setiap member membawa API Key sendiri. Member bisa mendaftar ke RajaOngkir dan memasukkan API Key mereka di CloudChat.

Use Cases

  1. Member daftar RajaOngkir dan dapatkan API Key
  2. Member input API Key di CloudChat Settings
  3. User tanya ongkir → Bot provide cost estimation menggunakan API Key member
  4. Integration dengan chatbot untuk auto-reply
  5. Support multiple couriers (JNE, TIKI, POS, J&T, SiCepat, dll)
  6. Calculate berdasarkan origin, destination, weight

Flow Diagram

flowchart TD
    A[User Request Ongkir] --> B[Parse Input<br/>Origin, Dest, Weight]
    B --> C{Data Lengkap?}
    C -->|Tidak| D[Request Missing Data]
    C -->|Ya| E[Call Ongkir API]
    E --> F{API Success?}
    F -->|Tidak| G[Error Message]
    F -->|Ya| H[Format Results]
    H --> I[Kirim ke User<br/>List Kurir + Harga]
    I --> J[Log Transaction]

Database Schema Changes

[NEW] Table: ongkir_settings

CREATE TABLE ongkir_settings (
    id SERIAL PRIMARY KEY,
    organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE UNIQUE,
    rajaongkir_api_key TEXT NOT NULL, -- Member's RajaOngkir API Key
    rajaongkir_account_type VARCHAR(20) DEFAULT 'starter', -- starter, basic, pro
    default_origin_city_id INTEGER,
    default_origin_city_name VARCHAR(255),
    default_origin_province VARCHAR(255),
    enabled_couriers TEXT[], -- ['jne', 'tiki', 'pos', 'jnt', 'sicepat', 'anteraja']
    is_active BOOLEAN DEFAULT false,
    last_verified_at TIMESTAMP, -- Last time API key was verified
    api_status VARCHAR(20) DEFAULT 'unverified', -- unverified, active, invalid, quota_exceeded
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

[NEW] Table: ongkir_logs

CREATE TABLE ongkir_logs (
    id SERIAL PRIMARY KEY,
    organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    conversation_id INTEGER REFERENCES conversations(id) ON DELETE SET NULL,
    origin VARCHAR(255),
    destination VARCHAR(255),
    weight INTEGER, -- in grams
    courier VARCHAR(50),
    cost INTEGER,
    api_response JSONB,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_ongkir_logs_org ON ongkir_logs(organization_id);
CREATE INDEX idx_ongkir_logs_created ON ongkir_logs(created_at);

Implementation Details

Backend

[NEW] src/controllers/ongkirController.js

Endpoints:

[NEW] src/services/ongkirService.js

Functions:

[NEW] src/services/integrations/rajaOngkirClient.js

RajaOngkir API client:

[MODIFY] src/services/chatbotService.js

Add ongkir intent detection:


Frontend

[NEW] frontend/src/pages/Settings/OngkirSettingsPage.js

Settings page (Submenu di Settings):

UI Components:

  1. Setup Guide Section

  2. API Configuration

    • Input field: RajaOngkir API Key (password type)
    • Button: "Verify API Key" (check validity)
    • Status indicator: ✅ Active / ❌ Invalid / ⚠️ Quota Exceeded
    • Account type display (Starter/Basic/Pro) - auto-detected
  3. Default Origin Settings

    • Province dropdown (fetched dari RajaOngkir)
    • City dropdown (filtered by province)
    • Display: Selected city as default origin
  4. Courier Selection

    • Checkbox list: JNE, TIKI, POS, J&T, SiCepat, AnterAja, dll
    • Select all / Deselect all buttons
  5. Usage Statistics

    • Total requests this month
    • Remaining quota (if applicable)
    • Last check: timestamp
  6. Actions

    • Save Settings button
    • Test Connection button

Location: Accessible via Settings > Integrasi > Ongkir

[NEW] frontend/src/components/tools/OngkirChecker.js

Standalone tool untuk test ongkir:


Fitur 6: Broadcast WA Official - Template Device Filter

Deskripsi

Saat pilih template untuk broadcast WA Official (Meta), otomatis tampilkan template yang sesuai dengan device yang dipilih.

Flow Diagram

flowchart LR
    A[User Pilih Device<br/>untuk Broadcast] --> B[Get Device Type<br/>& Meta Account]
    B --> C{Device Type?}
    C -->|WA Official| D[Query Meta Templates<br/>untuk WABA tersebut]
    C -->|WA Device| E[Show Custom<br/>Templates]
    D --> F[Filter Approved<br/>Templates Only]
    F --> G[Display di Dropdown]
    E --> G

Implementation Details

Backend

[MODIFY] src/controllers/broadcastController.js

Update endpoint:

Logic:

  1. Get device by ID
  2. Check device type (wa_official vs wa_device)
  3. If wa_official → fetch dari meta_templates WHERE waba_id = device.waba_id
  4. If wa_device → fetch custom templates
  5. Return filtered list
[MODIFY] src/services/metaTemplateService.js

Add function:


Frontend

[MODIFY] frontend/src/pages/Broadcast/CreateCampaign.js

Update logic:

  1. Saat user pilih device di dropdown
  2. Fetch templates untuk device tersebut
  3. Update template selector options
  4. Show device name di template selector untuk clarity
[MODIFY] frontend/src/pages/Broadcast/MessageTemplates.js

Update UI:


Fitur 7: Template Meta - CRUD & Device Filter

Deskripsi

Menambahkan kemampuan CRUD (Create, Read, Update, Delete) untuk Meta templates dan filter berdasarkan device.

Use Cases

  1. Create custom Meta template
  2. Edit existing template
  3. Delete template
  4. Filter templates by device/WABA
  5. Info box showing which device template belongs to

Flow Diagram

flowchart TD
    A[Template Management<br/>Page] --> B[List All Templates]
    B --> C{Filter by Device?}
    C -->|Ya| D[Filter Templates<br/>by WABA ID]
    C -->|Tidak| E[Show All Templates]
    
    F[Create Template] --> G[Select WABA/Device]
    G --> H[Fill Template Data]
    H --> I[Submit to Meta API]
    I --> J{Success?}
    J -->|Ya| K[Save to Database]
    J -->|Tidak| L[Show Error]
    K --> M[Show Success<br/>+ Pending Status]
    
    N[Edit Template] --> O{Status?}
    O -->|Approved| P[Cannot Edit<br/>Show Info]
    O -->|Pending/Rejected| Q[Allow Edit]
    Q --> I
    
    R[Delete Template] --> S[Soft Delete<br/>in Database]

Database Schema Changes

[MODIFY] Table: meta_templates

ALTER TABLE meta_templates
ADD COLUMN IF NOT EXISTS device_id INTEGER REFERENCES devices(id) ON DELETE SET NULL,
ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS last_synced_at TIMESTAMP;

-- Add index for better filtering
CREATE INDEX IF NOT EXISTS idx_meta_templates_device ON meta_templates(device_id);
CREATE INDEX IF NOT EXISTS idx_meta_templates_waba ON meta_templates(waba_id);

Implementation Details

Backend

[MODIFY] src/controllers/metaTemplateController.js

Add/Update endpoints:

[NEW] src/services/metaTemplateService.js (atau modify jika sudah ada)

Functions:

Integration dengan Meta Marketing API:

// POST https://graph.facebook.com/v18.0/{waba-id}/message_templates
// GET https://graph.facebook.com/v18.0/{waba-id}/message_templates
// DELETE https://graph.facebook.com/v18.0/{waba-id}/message_templates

Frontend

[NEW] frontend/src/pages/Integrations/MetaTemplateManager.js

Full CRUD interface:

List View:

Create/Edit Form:

Info Box:

[NEW] frontend/src/components/meta/TemplateBuilder.js

Visual template builder component:


Fitur 8: Facebook - Connection Error Info

Deskripsi

Jika Facebook Messenger gagal connect, tampilkan info bahwa page tersebut harus terhubung ke Business Manager (BM).

Current Issue

User tidak tahu kenapa connection gagal, tidak ada helpful error message.

Solution

Detect specific error codes dan tampilkan actionable error message.

Flow Diagram

flowchart TD
    A[User Connect<br/>FB Page] --> B[Request Permissions]
    B --> C{Success?}
    C -->|Ya| D[Save Connection]
    C -->|Tidak| E[Detect Error Type]
    E --> F{Error Code?}
    F -->|200| G[Show: Page belum<br/>linked ke BM]
    F -->|190| H[Show: Token Invalid<br/>Login Ulang]
    F -->|Other| I[Show: Generic Error<br/>+ Support Link]
    
    G --> J[Show Instructions:<br/>Cara Link ke BM]
    J --> K[Provide BM Link]

Implementation Details

Backend

[MODIFY] src/controllers/messenger/authController.js

Update handleCallback():

Add error detection:

try {
    // Request to Facebook API
} catch (error) {
    const errorCode = error.response?.data?.error?.code;
    const errorType = error.response?.data?.error?.type;
    
    let userMessage = 'Gagal menghubungkan page';
    let actionRequired = null;
    
    if (errorCode === 200 || errorType === 'OAuthException') {
        userMessage = 'Page belum terhubung ke Business Manager';
        actionRequired = 'link_to_bm';
    } else if (errorCode === 190) {
        userMessage = 'Sesi login sudah kadaluarsa';
        actionRequired = 'reauth';
    }
    
    return res.status(400).json({
        error: userMessage,
        errorCode,
        actionRequired,
        helpUrl: 'https://business.facebook.com/...'
    });
}
[NEW] src/utils/facebookErrorHandler.js

Centralized Facebook error handling:


Frontend

[MODIFY] frontend/src/pages/Integrations/MessengerIntegration.js

Update error handling:

catch (error) {
    const { error: message, actionRequired, helpUrl } = error.response.data;
    
    if (actionRequired === 'link_to_bm') {
        // Show special alert with instructions
        showBMInstructionsModal();
    } else if (actionRequired === 'reauth') {
        // Show re-login button
        showReAuthButton();
    } else {
        // Generic error
        showError(message);
    }
}
[NEW] frontend/src/components/messenger/BMInstructionsModal.js

Modal dengan instructions:

Content:

  1. Login ke business.facebook.com
  2. Pilih Business Manager
  3. Go to Business Settings → Accounts → Pages
  4. Click "Add" → "Add a Page"
  5. Enter page name dan claim
  6. Kembali connect di CloudChat

Fitur 9: Icon Notifikasi Inbox

Deskripsi

Menambahkan icon notifikasi di inbox untuk indicate unread messages atau pending actions.

Features

  1. Unread count badge - Show jumlah unread conversations
  2. Desktop notifications - Browser notifications untuk new messages
  3. Sound alerts - Optional sound untuk new messages
  4. Visual indicators - Dot/badge pada conversations yang unread

Flow Diagram

flowchart LR
    A[New Message<br/>via Socket.IO] --> B{User di Inbox?}
    B -->|Ya| C[Update Unread Badge]
    B -->|Tidak| D[Increment Global<br/>Unread Count]
    C --> E{Sound Enabled?}
    D --> E
    E -->|Ya| F[Play Sound]
    E -->|Tidak| G[Skip Sound]
    F --> H{Desktop Notif<br/>Enabled?}
    G --> H
    H -->|Ya| I[Show Browser<br/>Notification]
    H -->|Tidak| J[End]
    I --> J

Implementation Details

Backend

[MODIFY] src/controllers/inboxController.js

Update getConversations():

Add endpoint:

[MODIFY] Socket.IO Events

Update message event untuk include unread info:

io.to(`org:${orgId}`).emit('message:new', {
    conversationId,
    message,
    unreadCount: updatedCount
});

Frontend

[NEW] frontend/src/hooks/useNotifications.js

Custom hook untuk handle notifications:

[MODIFY] frontend/src/pages/InboxPage.js

Add notification features:

[NEW] frontend/src/components/inbox/NotificationBadge.js

Badge component:

[NEW] frontend/src/pages/Settings/NotificationSettings.js

Settings page:

Sound Files:


Fitur 10: Pipeline Management (Kanban CRM)

Deskripsi

Sistem pipeline untuk conversation management, 100% mirip dengan SocialChat. Pipeline memungkinkan user untuk organize conversations dalam stages/tahapan sebagai Kanban CRM.

Sidebar Menu Placement

Menu Pipeline ditambahkan di sidebar setelah menu Chatbot, sebelum menu lainnya.

📊 Dashboard
📥 Inbox
👥 Contacts
📢 Broadcast
🤖 Chatbot
🔄 Pipeline  ← NEW MENU (setelah Chatbot)
⚙️ Settings
...

Use Cases

Flow Diagram

flowchart TD
    A[Create Pipeline] --> B[Define Stages]
    B --> C[Set Stage Order]
    C --> D[Configure Automation<br/>Optional]
    
    E[New Conversation] --> F[Assign to Pipeline]
    F --> G[Set Initial Stage]
    
    H[Move Conversation] --> I[Drag to New Stage]
    I --> J[Update Stage]
    J --> K{Automation<br/>Configured?}
    K -->|Ya| L[Execute Actions<br/>Tag, Assign, etc]
    K -->|Tidak| M[Update Only]
    
    N[View Pipeline] --> O[Kanban Board View]
    O --> P[Cards Grouped<br/>by Stage]

Database Schema Changes

[NEW] Table: pipelines

CREATE TABLE pipelines (
    id SERIAL PRIMARY KEY,
    organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    icon VARCHAR(50),
    color VARCHAR(7), -- Hex color
    is_default BOOLEAN DEFAULT false,
    is_active BOOLEAN DEFAULT true,
    created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_pipelines_org ON pipelines(organization_id);

[NEW] Table: pipeline_stages

CREATE TABLE pipeline_stages (
    id SERIAL PRIMARY KEY,
    pipeline_id INTEGER NOT NULL REFERENCES pipelines(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    color VARCHAR(7),
    position INTEGER NOT NULL,
    is_closed_stage BOOLEAN DEFAULT false, -- Mark as final stage
    automation_actions JSONB, -- Auto-assign, auto-tag, etc.
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_pipeline_stages_pipeline ON pipeline_stages(pipeline_id);
CREATE INDEX idx_pipeline_stages_position ON pipeline_stages(pipeline_id, position);

[MODIFY] Table: conversations

ALTER TABLE conversations
ADD COLUMN pipeline_id INTEGER REFERENCES pipelines(id) ON DELETE SET NULL,
ADD COLUMN pipeline_stage_id INTEGER REFERENCES pipeline_stages(id) ON DELETE SET NULL,
ADD COLUMN stage_changed_at TIMESTAMP;

CREATE INDEX idx_conversations_pipeline ON conversations(pipeline_id, pipeline_stage_id);

[NEW] Table: pipeline_stage_history

CREATE TABLE pipeline_stage_history (
    id SERIAL PRIMARY KEY,
    conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
    pipeline_id INTEGER NOT NULL REFERENCES pipelines(id) ON DELETE CASCADE,
    from_stage_id INTEGER REFERENCES pipeline_stages(id) ON DELETE SET NULL,
    to_stage_id INTEGER NOT NULL REFERENCES pipeline_stages(id) ON DELETE CASCADE,
    changed_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
    duration_seconds INTEGER, -- Time spent in previous stage
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_pipeline_history_conversation ON pipeline_stage_history(conversation_id);
CREATE INDEX idx_pipeline_history_created ON pipeline_stage_history(created_at);

Implementation Details

Backend

[NEW] src/controllers/pipelineController.js

Endpoints:

Pipeline Management:

Stage Management:

Conversation Pipeline Management:

Analytics:

[NEW] src/services/pipelineService.js

Functions:

[MODIFY] src/controllers/inboxController.js

Update getConversations():

[NEW] Socket.IO Events
// Real-time pipeline updates
io.to(`org:${orgId}`).emit('pipeline:stage-changed', {
    conversationId,
    pipelineId,
    fromStageId,
    toStageId
});

Frontend

[NEW] frontend/src/pages/Pipeline/PipelineListPage.js

List semua pipelines:

[NEW] frontend/src/pages/Pipeline/PipelineBoardPage.js

Kanban board view (mirip SocialChat):

Features:

Libraries:

[NEW] frontend/src/pages/Pipeline/PipelineEditorPage.js

Pipeline editor:

[NEW] frontend/src/components/pipeline/StageCard.js

Stage column component:

[NEW] frontend/src/components/pipeline/ConversationCard.js

Conversation card untuk kanban:

[NEW] frontend/src/components/pipeline/PipelineAnalytics.js

Analytics dashboard:

[MODIFY] frontend/src/pages/InboxPage.js

Add pipeline features:

[MODIFY] frontend/src/App.jsx

Add routes:

<Route path="/app/pipelines" element={<PipelineListPage />} />
<Route path="/app/pipelines/:id/board" element={<PipelineBoardPage />} />
<Route path="/app/pipelines/:id/edit" element={<PipelineEditorPage />} />
<Route path="/app/pipelines/new" element={<PipelineEditorPage />} />

Pipeline UI Reference (SocialChat Style)

Kanban Board Layout

┌─────────────────────────────────────────────────────────────────┐
│  Pipeline: Sales Process                          [+ New] [⚙️]   │
├─────────────────────────────────────────────────────────────────┤
│  🔍 Search  │ 👤 Filter Agent  │  🏷️ Filter Label  │  📊 Analytics │
├──────────────┬──────────────┬──────────────┬────────────────────┤
│ 📥 New Lead  │ ✅ Qualified │ 📝 Proposal  │  🤝 Negotiation    │
│    (12)      │     (8)      │     (5)      │      (3)           │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐ │  ┌──────────┐      │
│ │ John Doe │ │ │ Jane S.  │ │ │ Company  │ │  │ Big Corp │      │
│ │ "Hai..."  │ │ │ "Sudah"  │ │ │ "Draft"  │ │  │ "nego"   │      │
│ │ 👤 Agent1 │ │ │ 👤 Agent2│ │ │ 👤 Agent1│ │  │ 👤 Agent3│      │
│ │ ⏱️ 2h     │ │ │ ⏱️ 1d    │ │ │ ⏱️ 3d    │ │  │ ⏱️ 5d     │      │
│ └──────────┘ │ └──────────┘ │ └──────────┘ │  └──────────┘      │
└──────────────┴──────────────┴──────────────┴────────────────────┘

Summary Implementasi Priority

High Priority (Must Have)

  1. Fitur 3: Mode Antrian - Core feature untuk customer service
  2. Fitur 9: Icon Notifikasi Inbox - UX improvement yang penting
  3. Fitur 6: Broadcast Template Filter - Bug fix/improvement

Medium Priority (Should Have)

  1. Fitur 1: Chatbot Waktu Aktif - Important untuk automation
  2. Fitur 2: Laporan Chatbot - Analytics yang berguna
  3. Fitur 10: Pipeline - Powerful feature untuk sales/support
  4. Fitur 8: Facebook Error Info - Better UX

Low Priority (Nice to Have)

  1. Fitur 4: Mode Pilih Agen - Advanced feature
  2. Fitur 5: Integrasi Ongkir - Specific use case
  3. Fitur 7: Template Meta CRUD - Advanced Meta integration

Estimasi Waktu Implementasi

Fitur Estimasi Complexity
#1 Chatbot Schedule 3-5 hari Medium
#2 Laporan Chatbot 5-7 hari High
#3 Mode Antrian 7-10 hari High
#4 Mode Pilih Agen 5-7 hari High
#5 Integrasi Ongkir 3-5 hari Medium
#6 Broadcast Template Filter 1-2 hari Low
#7 Template Meta CRUD 5-7 hari High
#8 Facebook Error Info 1-2 hari Low
#9 Icon Notifikasi 2-3 hari Low
#10 Pipeline 10-14 hari Very High

Total Estimasi: 42-62 hari kerja (8-12 minggu)


Verification Plan

Automated Tests

Untuk setiap fitur, buat:

  1. Unit tests untuk services
  2. Integration tests untuk API endpoints
  3. Component tests untuk React components
# Run tests
npm test

# Run specific test
npm test -- pipelineService.test.js

Manual Verification

Fitur 1-2: Chatbot

  1. Create bot dengan schedule
  2. Test response dalam/luar jam
  3. Verify laporan data accuracy
  4. Export laporan

Fitur 3-4: Queue & Agent Selection

  1. Enable queue mode
  2. Send messages dari multiple users
  3. Verify queue order (FIFO)
  4. Test agent assignment
  5. Test queue position check
  6. Test agent selection dengan AI assist

Fitur 5: Ongkir

  1. Configure API settings
  2. Test dengan berbagai origin/destination
  3. Verify pricing accuracy
  4. Test chatbot integration

Fitur 6-7: Templates

  1. Create WA Official device
  2. Create Meta template
  3. Verify template filtering
  4. Test template CRUD operations

Fitur 8: Facebook

  1. Try connecting Facebook page (without BM)
  2. Verify error message
  3. Test dengan page yang sudah linked

Fitur 9: Notifications

  1. Enable notifications
  2. Send test message
  3. Verify badge count
  4. Test desktop notification
  5. Test sound alert

Fitur 10: Pipeline

  1. Create pipeline dengan stages
  2. Add conversations to pipeline
  3. Drag & drop between stages
  4. Verify automation actions
  5. Check analytics accuracy
  6. Test real-time updates

User Acceptance Testing

Deploy ke staging environment dan conduct UAT dengan real users untuk setiap fitur.


Dependencies & Prerequisites

Backend Dependencies (npm packages)

{
  "node-schedule": "^2.1.1",        // For chatbot schedules
  "moment-timezone": "^0.5.43",     // Timezone handling
  "chart.js": "^4.4.0",             // Analytics (if server-side rendering)
  "exceljs": "^4.3.0",              // Excel export
  "axios": "^1.6.0"                 // Ongkir API calls
}

Frontend Dependencies

{
  "react-beautiful-dnd": "^13.1.1", // Drag & drop for pipeline
  "@dnd-kit/core": "^6.0.8",        // Alternative drag & drop
  "recharts": "^2.10.0",            // Charts for analytics
  "react-datepicker": "^4.21.0",    // Date range picker
  "react-select": "^5.8.0"          // Better selects
}

Database Migrations

Buat migration files untuk semua schema changes yang didefinisikan di atas.

External APIs


Risk Mitigation

[!CAUTION] Risk: Breaking changes pada existing features

  • Mitigation: Extensive testing, feature flags, gradual rollout

[!WARNING] Risk: Performance impact dengan banyak real-time updates

  • Mitigation: Implement throttling, debouncing, pagination

[!WARNING] Risk: External API dependencies (Meta, Facebook, Ongkir)

  • Mitigation: Implement retry logic, fallback mechanisms, proper error handling
Powered by hosted.md