Lewati ke isi

Sentra Service — Database Design

Database dirancang dengan fokus utama pada pemetaan jadwal kerja staf, durasi layanan, pencatatan antrean, serta komisi jasa.

4.1 Entity Relationship Diagram (ERD)

erDiagram
    BRANCHES ||--o{ STAFF_SCHEDULES : "has"
    BRANCHES ||--o{ APPOINTMENTS : "hosts"
    USERS ||--o{ STAFF_SCHEDULES : "works"
    CUSTOMERS ||--o{ APPOINTMENTS : "books"
    SERVICES ||--o{ APPOINTMENT_ITEMS : "included_in"
    APPOINTMENTS ||--o{ APPOINTMENT_ITEMS : "contains"
    USERS ||--o{ APPOINTMENT_ITEMS : "assigned_to"
    APPOINTMENTS ||--o{ TRANSACTIONS : "billed_by"
    TRANSACTIONS ||--o{ RETAIL_SALES : "includes"
    RETAIL_PRODUCTS ||--o{ RETAIL_SALES : "sold"
    USERS ||--o{ STAFF_COMMISSIONS : "earns"
    TRANSACTIONS ||--o{ STAFF_COMMISSIONS : "generates"

4.2 Skema Tabel DDL (PostgreSQL Dialect)

-- 1. Tabel Branches (Cabang Outlet)
CREATE TABLE branches (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    address TEXT,
    phone VARCHAR(20),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 2. Tabel Users (Mencakup Staf Jasa seperti Kapster/Mekanik/Terapis)
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(50) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(100) NOT NULL,
    role VARCHAR(30) CHECK (role IN ('OWNER', 'SYSTEM_ADMIN', 'BRANCH_MANAGER', 'RECEPTIONIST_CASHIER', 'SERVICE_STAFF')),
    specialty_skills VARCHAR(255)[], -- Kumpulan keahlian, e.g. {'Haircut', 'Coloring'}
    base_salary DECIMAL(15,2) DEFAULT 0.00,
    commission_percentage DECIMAL(5,2) DEFAULT 0.00, -- Persentase komisi umum staf
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 3. Tabel Customers
CREATE TABLE customers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    phone VARCHAR(20) UNIQUE NOT NULL,
    full_name VARCHAR(100) NOT NULL,
    email VARCHAR(100),
    membership_tier VARCHAR(20) CHECK (membership_tier IN ('BRONZE', 'SILVER', 'GOLD', 'PLATINUM')) DEFAULT 'BRONZE',
    loyalty_points INT DEFAULT 0,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 4. Tabel Services (Daftar Layanan Jasa)
CREATE TABLE services (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(150) NOT NULL,
    category VARCHAR(50) NOT NULL, -- Hair, Massage, Engine, dll.
    duration_minutes INT NOT NULL DEFAULT 30, -- Estimasi durasi dasar
    price DECIMAL(15,2) NOT NULL,
    commission_type VARCHAR(10) CHECK (commission_type IN ('FIXED', 'PERCENTAGE')) DEFAULT 'PERCENTAGE',
    commission_value DECIMAL(15,2) NOT NULL, -- Nilai komisi staf per jasa ini
    is_active BOOLEAN DEFAULT TRUE
);

-- 5. Tabel Staff Schedules (Jadwal Roster Shift Kerja Staf)
CREATE TABLE staff_schedules (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    branch_id UUID REFERENCES branches(id) ON DELETE CASCADE,
    work_date DATE NOT NULL,
    shift_start TIME NOT NULL,
    shift_end TIME NOT NULL,
    break_start TIME,
    break_end TIME,
    is_off_day BOOLEAN DEFAULT FALSE,
    UNIQUE(user_id, work_date)
);

-- 6. Tabel Appointments (Pemesanan Slot Waktu Jasa)
CREATE TABLE appointments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    branch_id UUID REFERENCES branches(id),
    customer_id UUID REFERENCES customers(id),
    booking_number VARCHAR(100) UNIQUE NOT NULL,
    appointment_date DATE NOT NULL,
    scheduled_start TIMESTAMP WITH TIME ZONE NOT NULL,
    scheduled_end TIMESTAMP WITH TIME ZONE NOT NULL, -- Start + Total Duration
    deposit_amount DECIMAL(15,2) DEFAULT 0.00,
    source VARCHAR(20) CHECK (source IN ('ONLINE_WIDGET', 'WALK_IN', 'WHATSAPP_BOT')),
    status VARCHAR(30) CHECK (status IN ('PENDING_PAYMENT', 'CONFIRMED', 'CHECKED_IN', 'IN_SERVICE', 'COMPLETED', 'NO_SHOW', 'CANCELLED')) DEFAULT 'CONFIRMED',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 7. Tabel Appointment Items (Detail Jasa Terpesan & Staff Assignment)
CREATE TABLE appointment_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    appointment_id UUID REFERENCES appointments(id) ON DELETE CASCADE,
    service_id UUID REFERENCES services(id),
    assigned_staff_id UUID REFERENCES users(id), -- Staf pelaksana jasa
    price_charged DECIMAL(15,2) NOT NULL,
    sequence_order INT NOT NULL DEFAULT 1 -- Urutan pengerjaan jika multi-jasa
);

-- 8. Tabel Transactions
CREATE TABLE transactions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    appointment_id UUID REFERENCES appointments(id) ON DELETE SET NULL,
    branch_id UUID REFERENCES branches(id),
    cashier_id UUID REFERENCES users(id),
    invoice_number VARCHAR(100) UNIQUE NOT NULL,
    subtotal_services DECIMAL(15,2) NOT NULL DEFAULT 0.00,
    subtotal_retail DECIMAL(15,2) NOT NULL DEFAULT 0.00,
    discount_amount DECIMAL(15,2) DEFAULT 0.00,
    tax_amount DECIMAL(15,2) DEFAULT 0.00, -- PPN 11%
    grand_total DECIMAL(15,2) NOT NULL,
    payment_method VARCHAR(30) CHECK (payment_method IN ('CASH', 'QRIS', 'DEBIT_CARD', 'CREDIT_CARD', 'SPLIT')),
    rounding_amount DECIMAL(15,2) DEFAULT 0.00,
    tips_amount DECIMAL(15,2) DEFAULT 0.00, -- Tip sukarela pelanggan
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 9. Tabel Staff Commissions (Audit Trail Hak Insentif Staf)
CREATE TABLE staff_commissions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    transaction_id UUID REFERENCES transactions(id) ON DELETE CASCADE,
    staff_id UUID REFERENCES users(id),
    source_type VARCHAR(20) CHECK (source_type IN ('SERVICE', 'RETAIL_PRODUCT')),
    commission_amount DECIMAL(15,2) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);