Lewati ke isi

Sentra F&B — Database Design

Database dirancang untuk mengelola struktur data F&B yang kompleks, seperti variasi resep bahan baku, komposisi modifier menu, pengaturan meja makan (table layout), serta transaksi split bill.

4.1 Entity Relationship Diagram (ERD)

erDiagram
    OUTLETS ||--o{ TABLES : "contains"
    TABLES ||--o{ SEATING_SESSIONS : "holds"
    SEATING_SESSIONS ||--o{ ORDERS : "places"
    MENUS ||--o{ MENU_VARIANTS : "has"
    MENU_VARIANTS ||--o{ RECIPES : "composed_of"
    INGREDIENTS ||--o{ RECIPES : "used_in"
    ORDERS ||--o{ ORDER_ITEMS : "contains"
    MENU_VARIANTS ||--o{ ORDER_ITEMS : "sold"
    ORDER_ITEMS ||--o{ ORDER_ITEM_MODIFIERS : "customized"
    MENU_MODIFIERS ||--o{ ORDER_ITEM_MODIFIERS : "applies"
    ORDERS ||--o{ TRANSACTIONS : "settled_by"
    OUTLETS ||--o{ INGREDIENT_STOCKS : "manages"
    INGREDIENTS ||--o{ INGREDIENT_STOCKS : "stores"

4.2 Skema Tabel DDL (PostgreSQL Dialect)

-- 1. Tabel Outlets
CREATE TABLE outlets (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    address TEXT,
    phone VARCHAR(20),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 2. Tabel Tables (Pengaturan Meja Restoran)
CREATE TABLE tables (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    outlet_id UUID REFERENCES outlets(id) ON DELETE CASCADE,
    table_number VARCHAR(10) NOT NULL,
    seating_capacity INT DEFAULT 4,
    status VARCHAR(20) CHECK (status IN ('AVAILABLE', 'OCCUPIED', 'RESERVED')) DEFAULT 'AVAILABLE',
    section VARCHAR(30) DEFAULT 'MAIN_HALL', -- Ruangan: AC, Smoking Area, VIP, dll.
    UNIQUE(outlet_id, table_number)
);

-- 3. Tabel Seating Sessions (Sesi Pelanggan di Meja)
CREATE TABLE seating_sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    table_id UUID REFERENCES tables(id),
    customer_count INT DEFAULT 1,
    opened_by UUID NOT NULL, -- User ID pelayan yang membuka meja
    opened_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    closed_at TIMESTAMP WITH TIME ZONE,
    status VARCHAR(20) CHECK (status IN ('ACTIVE', 'CLOSED')) DEFAULT 'ACTIVE'
);

-- 4. Tabel Menus (Daftar Menu Utama)
CREATE TABLE menus (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(150) NOT NULL,
    category VARCHAR(50) CHECK (category IN ('FOOD', 'BEVERAGE', 'DESSERT', 'OTHER')),
    base_price DECIMAL(15,2) NOT NULL, -- Harga Dasar Sebelum PPN/Service
    is_available BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 5. Tabel Menu Variants (Varian Ukuran / Tipe Menu)
CREATE TABLE menu_variants (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    menu_id UUID REFERENCES menus(id) ON DELETE CASCADE,
    name VARCHAR(100) NOT NULL, -- Regular, Large, Hot, Iced
    additional_price DECIMAL(15,2) DEFAULT 0.00
);

-- 6. Tabel Menu Modifiers (Kustomisasi Menu, e.g. Add Shot, Oatmilk)
CREATE TABLE menu_modifiers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    outlet_id UUID REFERENCES outlets(id),
    name VARCHAR(100) NOT NULL,
    price DECIMAL(15,2) DEFAULT 0.00,
    is_active BOOLEAN DEFAULT TRUE
);

-- 7. Tabel Ingredients (Bahan Baku Dasar, e.g. Biji Kopi, Susu, Gula)
CREATE TABLE ingredients (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(150) NOT NULL,
    unit VARCHAR(20) NOT NULL, -- gram, ml, pcs, bag
    avg_cost_price DECIMAL(15,2) NOT NULL DEFAULT 0.00 -- HPP rata-rata per unit
);

-- 8. Tabel Recipes (Matriks Komposisi Menu dan Bahan Baku)
CREATE TABLE recipes (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    menu_variant_id UUID REFERENCES menu_variants(id) ON DELETE CASCADE,
    ingredient_id UUID REFERENCES ingredients(id),
    quantity_required DECIMAL(12,4) NOT NULL, -- Jumlah pemakaian bahan baku
    yield_percentage DECIMAL(5,2) DEFAULT 100.00 -- Konversi susut bahan baku
);

-- 9. Tabel Ingredient Stocks (Pelacakan Stok Bahan per Outlet)
CREATE TABLE ingredient_stocks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    outlet_id UUID REFERENCES outlets(id) ON DELETE CASCADE,
    ingredient_id UUID REFERENCES ingredients(id) ON DELETE CASCADE,
    qty_actual DECIMAL(12,4) NOT NULL DEFAULT 0.0000,
    minimum_alert DECIMAL(12,4) NOT NULL DEFAULT 100.0000,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(outlet_id, ingredient_id)
);

-- 10. Tabel Orders
CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    seating_session_id UUID REFERENCES seating_sessions(id),
    outlet_id UUID REFERENCES outlets(id),
    order_number VARCHAR(100) UNIQUE NOT NULL,
    status VARCHAR(30) CHECK (status IN ('PENDING', 'KITCHEN_PREP', 'READY_TO_SERVE', 'SERVED', 'CANCELLED', 'PAID')) DEFAULT 'PENDING',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 11. Tabel Order Items (Daftar Menu Terpesan)
CREATE TABLE order_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
    menu_variant_id UUID REFERENCES menu_variants(id),
    qty INT NOT NULL,
    selling_price DECIMAL(15,2) NOT NULL,
    customer_notes TEXT,
    kds_status VARCHAR(20) CHECK (kds_status IN ('WAITING', 'COOKING', 'READY', 'SERVED')) DEFAULT 'WAITING',
    kitchen_station VARCHAR(30) DEFAULT 'KITCHEN' -- BAR, KITCHEN, DESSERT
);

-- 12. Tabel Order Item Modifiers (Kustomisasi Item Terpesan)
CREATE TABLE order_item_modifiers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_item_id UUID REFERENCES order_items(id) ON DELETE CASCADE,
    menu_modifier_id UUID REFERENCES menu_modifiers(id),
    qty INT NOT NULL DEFAULT 1
);