# Perancangan Basis Data - Pangkalan LPG

Dokumen ini berisi rancangan basis data pangkalan LPG yang telah direvisi sesuai kebutuhan panjang data aktual (tanpa spare berlebihan), penggunaan tipe data `VARCHAR` untuk ID non-auto-increment pada tabel terkait, serta penamaan primary key dan foreign key yang deskriptif (`id_transaksi`, `id_user`, dll).

---

## Legenda Kunci (Keys) & Hubungan Relasi
Untuk mempermudah membaca rancangan tabel di bawah, berikut arti singkatan kolom **Key**:
* **`PRI` (Primary Key)**: Kunci Utama unik yang digunakan untuk mengidentifikasi setiap baris data secara tunggal di tabel tersebut. Nilainya tidak boleh duplikat dan tidak boleh kosong (`NOT NULL`).
* **`MUL` (Multiple / Foreign Key)**: Kunci Tamu (Foreign Key) yang menghubungkan tabel tersebut dengan Kunci Utama (`PRI`) dari tabel lain untuk membentuk hubungan relasi (relational link).
* **`UNI` (Unique Key)**: Kolom yang nilainya dipastikan tidak boleh sama/kembar di dalam satu tabel (misal: alamat email), tetapi bukan kunci utama.

### Diagram Hubungan Entitas (Entity-Relationship Diagram / ERD)
Berikut visualisasi relasi antar-tabel dalam database saat ini:

```mermaid
erDiagram
    users {
        VARCHAR(7) id_user PK
        VARCHAR(30) name
        VARCHAR(40) email UK
        VARCHAR(60) password
        VARCHAR(9) role
        VARCHAR(13) phone
        TEXT address
        DECIMAL gaji_pokok
        DECIMAL insentif_3kg
        DECIMAL insentif_12kg
        VARCHAR(100) remember_token
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    customers {
        VARCHAR(10) customers_id PK
        VARCHAR(35) name
        VARCHAR(6) product_name
        VARCHAR(13) phone
        TEXT address
        VARCHAR(20) kecamatan
        VARCHAR(20) kabupaten
        VARCHAR(10) id_zones FK
        VARCHAR(40) titik_koordinat
        DECIMAL price_category
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    zones {
        VARCHAR(10) id_zones PK
        VARCHAR(13) name
        VARCHAR(19) kabupaten
        ENUM zone_type
        INT shipping_cost
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    stok_akhir {
        VARCHAR(5) id_produk PK
        VARCHAR(50) nama_produk
        VARCHAR(15) jenis_barang
        INT stok_isi
        INT stok_kosong
        INT total_aset
        TIMESTAMP waktu_update
    }
    transaksi {
        VARCHAR(15) id_transaksi PK
        VARCHAR(10) customers_id FK
        VARCHAR(5) id_produk
        INT qty_beli_isi
        INT qty_tukar_kosong
        DECIMAL harga_satuan
        DECIMAL ongkir
        DECIMAL total_harga
        VARCHAR(10) metode_bayar
        VARCHAR(50) bukti_bayar
        VARCHAR(35) nama_pengirim
        DATE tanggal_transaksi
        ENUM status
        VARCHAR(7) id_kurir FK
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    belanja {
        VARCHAR(5) id_produk PK
        VARCHAR(50) nama_produk
        INT jumlah
        DECIMAL harga_beli
        DECIMAL total_biaya
        DATE tanggal_beli
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    pengeluaran {
        VARCHAR(15) id_pengeluaran PK
        DATE tanggal
        VARCHAR(50) keterangan
        BIGINT jumlah
        VARCHAR(15) kategori
        VARCHAR(35) nama_pengirim
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    price_settings {
        VARCHAR(15) id_price_setting PK
        VARCHAR(50) name
        INT price
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    notifications {
        VARCHAR(15) id_notification PK
        VARCHAR(7) id_user FK
        VARCHAR(15) id_transaksi FK
        VARCHAR(30) judul
        TEXT pesan
        VARCHAR(10) tipe
        TINYINT is_read
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    pengumuman {
        VARCHAR(15) id_pengumuman PK
        VARCHAR(40) judul
        TEXT konten
        VARCHAR(10) tipe
        TINYINT is_aktif
        VARCHAR(50) foto
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    slips_gaji {
        VARCHAR(20) id_slip_gaji PK
        VARCHAR(7) id_user FK
        VARCHAR(7) periode
        DATE tanggal_bayar
        INT total_qty_3kg
        INT total_qty_12kg
        INT total_hari_kerja
        DECIMAL gaji_pokok_nominal
        DECIMAL insentif_nominal
        DECIMAL uang_makan_nominal
        DECIMAL potongan
        DECIMAL total_diterima
        ENUM status
        VARCHAR(255) bukti_transfer
        TEXT catatan
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }

    zones ||--o{ customers : "has"
    customers ||--o{ transaksi : "places"
    users ||--o{ transaksi : "delivers (as courier)"
    users ||--o{ notifications : "receives"
    transaksi ||--o{ notifications : "triggers"
    users ||--o{ slips_gaji : "has"
```

---

## 1. Tabel `users`
Tabel ini digunakan untuk mengelola data akun pengguna sistem (Admin, Kurir, Pelanggan).

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_user` | VARCHAR | 7 | NO | PRI | NULL | ID unik pengguna (Primary Key, misal: 'USR0001') |
| `name` | VARCHAR | 30 | NO | - | NULL | Nama lengkap pengguna |
| `email` | VARCHAR | 40 | NO | UNI | NULL | Alamat email unik |
| `password` | VARCHAR | 60 | NO | - | NULL | Password terenkripsi (hash bcrypt) |
| `role` | VARCHAR | 9 | NO | - | 'admin' | Peran pengguna ('admin', 'kurir', 'pelanggan') |
| `phone` | VARCHAR | 13 | YES | - | NULL | Nomor telepon genggam (Indonesian format) |
| `address` | TEXT | - | YES | - | NULL | Alamat lengkap rumah |
| `gaji_pokok` | DECIMAL | 12,2 | NO | - | 0.00 | Gaji pokok kurir |
| `insentif_3kg` | DECIMAL | 12,2 | NO | - | 500.00 | Insentif per tabung 3kg |
| `insentif_12kg` | DECIMAL | 12,2 | NO | - | 5000.00 | Insentif per tabung 12kg |
| `remember_token` | VARCHAR | 100 | YES | - | NULL | Token sesi login ("remember me") |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE users (
    id_user VARCHAR(7) NOT NULL,
    name VARCHAR(30) NOT NULL,
    email VARCHAR(40) NOT NULL UNIQUE,
    password VARCHAR(60) NOT NULL,
    role VARCHAR(9) NOT NULL DEFAULT 'admin',
    phone VARCHAR(13) NULL,
    address TEXT NULL,
    gaji_pokok DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    insentif_3kg DECIMAL(12,2) NOT NULL DEFAULT 500.00,
    insentif_12kg DECIMAL(12,2) NOT NULL DEFAULT 5000.00,
    remember_token VARCHAR(100) NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_user)
);
```

---

## 2. Tabel `customers`
Tabel ini menyimpan data profil lengkap dari pelanggan terdaftar.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `customers_id` | VARCHAR | 10 | NO | PRI | NULL | ID unik pelanggan (Primary Key, format 'PELxxxxxxx') |
| `name` | VARCHAR | 35 | NO | - | NULL | Nama lengkap pelanggan |
| `product_name` | VARCHAR | 6 | YES | - | NULL | Ukuran tabung pilihan utama (e.g. '3KG') |
| `phone` | VARCHAR | 13 | YES | - | NULL | Nomor telepon genggam |
| `address` | TEXT | - | YES | - | NULL | Alamat pengiriman |
| `kecamatan` | VARCHAR | 20 | YES | - | NULL | Nama kecamatan (fit to Sepatan Timur) |
| `kabupaten` | VARCHAR | 20 | YES | - | NULL | Nama kabupaten (fit to Kabupaten Tangerang) |
| `id_zones` | VARCHAR | 10 | YES | MUL | NULL | ID Zona pengiriman (Foreign Key ke tabel zones) |
| `titik_koordinat` | VARCHAR | 40 | YES | - | NULL | Koordinat GPS (latitude, longitude) |
| `price_category` | DECIMAL | 8,2 | NO | - | 0.00 | Kategori/potongan harga khusus |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE customers (
    customers_id VARCHAR(10) NOT NULL,
    name VARCHAR(35) NOT NULL,
    product_name VARCHAR(6) NULL,
    phone VARCHAR(13) NULL,
    address TEXT NULL,
    kecamatan VARCHAR(20) NULL,
    kabupaten VARCHAR(20) NULL,
    id_zones VARCHAR(10) NULL,
    titik_koordinat VARCHAR(25) NULL,
    price_category DECIMAL(8,2) NOT NULL DEFAULT 0.00,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (customers_id),
    FOREIGN KEY (id_zones) REFERENCES zones(id_zones) ON DELETE SET NULL
);
```

---

## 3. Tabel `stok_akhir`
Tabel ini digunakan untuk memantau sediaan stok gas (tabung berisi, tabung kosong, dan total aset).

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_produk` | VARCHAR | 5 | NO | PRI | NULL | Kode ukuran tabung (Primary Key, e.g., '3KG') |
| `nama_produk` | VARCHAR | 50 | YES | - | NULL | Nama produk lengkap |
| `jenis_barang` | VARCHAR | 15 | YES | - | NULL | Jenis/kategori barang |
| `stok_isi` | INT | - | NO | - | 0 | Jumlah tabung berisi |
| `stok_kosong` | INT | - | NO | - | 0 | Jumlah tabung kosong |
| `total_aset` | INT | - | NO | - | 0 | Total aset fisik (`stok_isi` + `stok_kosong`) |
| `waktu_update` | TIMESTAMP | - | NO | - | CURRENT_TIMESTAMP | Pembaruan terakhir (otomatis) |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE stok_akhir (
    id_produk VARCHAR(5) NOT NULL,
    nama_produk VARCHAR(50) NULL,
    jenis_barang VARCHAR(15) NULL,
    stok_isi INT NOT NULL DEFAULT 0,
    stok_kosong INT NOT NULL DEFAULT 0,
    total_aset INT NOT NULL DEFAULT 0,
    waktu_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id_produk)
);
```

---

## 4. Tabel `transaksi`
Tabel ini mencatat pesanan pembelian, penukaran tabung kosong, pembayaran, kurir pengirim, dan ongkos kirim. Menggunakan ID bertipe VARCHAR (format 'TX202606281001') tanpa auto-increment.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_transaksi` | VARCHAR | 15 | NO | PRI | NULL | ID transaksi unik (Primary Key, VARCHAR, Non Auto Increment) |
| `customers_id` | VARCHAR | 10 | NO | MUL | NULL | Pelanggan pemesan (Foreign Key ke tabel customers) |
| `id_produk` | VARCHAR | 5 | NO | - | NULL | Kode produk tabung yang dibeli |
| `qty_beli_isi` | INT | - | NO | - | NULL | Jumlah pembelian tabung berisi |
| `qty_tukar_kosong`| INT | - | NO | - | NULL | Jumlah tabung kosong yang dikembalikan |
| `harga_satuan` | DECIMAL | 12,2 | NO | - | NULL | Harga per unit gas |
| `ongkir` | DECIMAL | 12,2 | NO | - | 0.00 | Tarif pengiriman kurir |
| `total_harga` | DECIMAL | 15,2 | NO | - | NULL | Total tagihan (`harga_satuan` * qty + `ongkir`) |
| `metode_bayar` | VARCHAR | 10 | YES | - | NULL | Metode bayar ('Transfer' / 'Tunai') |
| `bukti_bayar` | VARCHAR | 50 | YES | - | NULL | File bukti pembayaran transfer |
| `nama_pengirim` | VARCHAR | 35 | YES | - | NULL | Nama rekening pengirim transfer |
| `tanggal_transaksi`| DATE | - | YES | - | NULL | Tanggal transaksi |
| `status` | ENUM | 'menunggu', 'diproses', 'dikirim', 'selesai', 'dibatalkan' | NO | - | 'selesai' | Status siklus transaksi |
| `id_kurir` | VARCHAR | 7 | YES | - | NULL | ID Kurir pengantar (Foreign Key ke tabel users, VARCHAR) |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE transaksi (
    id_transaksi VARCHAR(15) NOT NULL,
    customers_id VARCHAR(10) NOT NULL,
    id_produk VARCHAR(5) NOT NULL,
    qty_beli_isi INT NOT NULL,
    qty_tukar_kosong INT NOT NULL,
    harga_satuan DECIMAL(12,2) NOT NULL,
    ongkir DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    total_harga DECIMAL(15,2) NOT NULL,
    metode_bayar VARCHAR(10) NULL,
    bukti_bayar VARCHAR(50) NULL,
    nama_pengirim VARCHAR(35) NULL,
    tanggal_transaksi DATE NULL,
    status ENUM('menunggu', 'diproses', 'dikirim', 'selesai', 'dibatalkan') NOT NULL DEFAULT 'selesai',
    id_kurir VARCHAR(7) NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_transaksi),
    FOREIGN KEY (customers_id) REFERENCES customers(customers_id) ON DELETE CASCADE,
    FOREIGN KEY (id_kurir) REFERENCES users(id_user) ON DELETE SET NULL
);
```

---

## 5. Tabel `belanja`
Tabel ini digunakan untuk mencatat restock gas yang dipasok kembali ke pangkalan dari agen.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_produk` | VARCHAR | 5 | NO | PRI | NULL | Kode produk gas (Primary Key) |
| `nama_produk` | VARCHAR | 50 | NO | - | NULL | Nama ukuran produk gas |
| `jumlah` | INT | - | NO | - | NULL | Jumlah tabung restock |
| `harga_beli` | DECIMAL | 12,2 | NO | - | NULL | Harga beli per unit dari agen |
| `total_biaya` | DECIMAL | 12,2 | NO | - | NULL | Total pengeluaran restock |
| `tanggal_beli` | DATE | - | NO | - | NULL | Tanggal belanja stok gas |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE belanja (
    id_produk VARCHAR(5) NOT NULL,
    nama_produk VARCHAR(50) NOT NULL,
    jumlah INT NOT NULL,
    harga_beli DECIMAL(12,2) NOT NULL,
    total_biaya DECIMAL(12,2) NOT NULL,
    tanggal_beli DATE NOT NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_produk)
);
```

---

## 6. Tabel `pengeluaran`
Tabel ini mendata pengeluaran operasional di luar pengisian ulang stok gas. Menggunakan ID bertipe VARCHAR (format 'EXP202606281001') tanpa auto-increment.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_pengeluaran` | VARCHAR | 15 | NO | PRI | NULL | ID pengeluaran unik (Primary Key, VARCHAR, Non Auto Increment) |
| `tanggal` | DATE | - | NO | - | NULL | Tanggal pencatatan pengeluaran |
| `keterangan` | VARCHAR | 50 | NO | - | NULL | Penjelasan operasional pengeluaran |
| `jumlah` | BIGINT UNSIGNED | - | NO | - | NULL | Nominal nominal pengeluaran |
| `kategori` | VARCHAR | 15 | NO | - | 'Lain-lain' | Kategori (e.g. 'Gaji', 'Operasional') |
| `nama_pengirim` | VARCHAR | 35 | YES | - | NULL | Nama penanggung jawab pengeluaran |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE pengeluaran (
    id_pengeluaran VARCHAR(15) NOT NULL,
    tanggal DATE NOT NULL,
    keterangan VARCHAR(50) NOT NULL,
    jumlah BIGINT UNSIGNED NOT NULL,
    kategori VARCHAR(15) NOT NULL DEFAULT 'Lain-lain',
    nama_pengirim VARCHAR(35) NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_pengeluaran)
);
```

---

## 7. Tabel `zones`
Tabel ini menyimpan data wilayah pengantaran dan biaya ongkir standar yang bersangkutan. Menggunakan ID bertipe VARCHAR (misal: 'ZN001') tanpa auto-increment.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_zones` | VARCHAR | 10 | NO | PRI | NULL | ID zona unik (Primary Key, VARCHAR, Non Auto Increment) |
| `name` | VARCHAR | 13 | NO | - | NULL | Nama wilayah / kelurahan |
| `kabupaten` | VARCHAR | 19 | NO | - | NULL | Nama kabupaten / kota |
| `zone_type` | ENUM | 'local', 'nearby', 'far' | NO | - | 'nearby' | Kategori jarak zona |
| `shipping_cost` | INT UNSIGNED | - | NO | - | 2000 | Tarif ongkir standar |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE zones (
    id_zones VARCHAR(10) NOT NULL,
    name VARCHAR(13) NOT NULL,
    kabupaten VARCHAR(19) NOT NULL,
    zone_type ENUM('local', 'nearby', 'far') NOT NULL DEFAULT 'nearby',
    shipping_cost INT UNSIGNED NOT NULL DEFAULT 2000,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_zones)
);
```

---

## 8. Tabel `price_settings`
Tabel ini berisi tingkat harga harga satuan produk gas.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_price_setting` | VARCHAR | 15 | NO | PRI | NULL | ID kategori harga (Primary Key) |
| `name` | VARCHAR | 50 | NO | - | NULL | Nama kategori harga/tabung |
| `price` | INT | - | NO | - | NULL | Tarif harga rupiah |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE price_settings (
    id_price_setting VARCHAR(15) NOT NULL,
    name VARCHAR(50) NOT NULL,
    price INT NOT NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_price_setting)
);
```

---

## 9. Tabel `notifications`
Tabel ini menyimpan data notifikasi status transaksi bagi Admin, Kurir, maupun Pelanggan. Menggunakan ID bertipe VARCHAR (misal: 'NTF202606281001') tanpa auto-increment.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_notification` | VARCHAR | 15 | NO | PRI | NULL | ID notifikasi unik (Primary Key, VARCHAR, Non Auto Increment) |
| `id_user` | VARCHAR | 7 | NO | MUL | NULL | Penerima notifikasi (Foreign Key ke tabel users, VARCHAR) |
| `id_transaksi` | VARCHAR | 15 | YES | - | NULL | Transaksi pemicu (Foreign Key ke tabel transaksi, VARCHAR) |
| `judul` | VARCHAR | 30 | NO | - | NULL | Judul singkat notifikasi |
| `pesan` | TEXT | - | NO | - | NULL | Isi pesan detail notifikasi |
| `tipe` | VARCHAR | 10 | NO | - | 'info' | Jenis notifikasi ('info', 'success', etc) |
| `is_read` | TINYINT | 1 | NO | MUL | 0 | Status dibaca (0 = belum, 1 = sudah) |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu notifikasi dikirim |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu notifikasi diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE notifications (
    id_notification VARCHAR(15) NOT NULL,
    id_user VARCHAR(7) NOT NULL,
    id_transaksi VARCHAR(15) NULL,
    judul VARCHAR(30) NOT NULL,
    pesan TEXT NOT NULL,
    tipe VARCHAR(10) NOT NULL DEFAULT 'info',
    is_read TINYINT(1) NOT NULL DEFAULT 0,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_notification),
    FOREIGN KEY (id_user) REFERENCES users(id_user) ON DELETE CASCADE,
    FOREIGN KEY (id_transaksi) REFERENCES transaksi(id_transaksi) ON DELETE SET NULL
);
```

---

## 10. Tabel `pengumuman`
Tabel ini digunakan oleh Admin untuk menyiarkan berita atau informasi promo di halaman dasbor pelanggan. Menggunakan ID bertipe VARCHAR (misal: 'PM202606281001') tanpa auto-increment.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_pengumuman` | VARCHAR | 15 | NO | PRI | NULL | ID pengumuman unik (Primary Key, VARCHAR, Non Auto Increment) |
| `judul` | VARCHAR | 40 | NO | - | NULL | Judul pengumuman |
| `konten` | TEXT | - | NO | - | NULL | Konten pengumuman |
| `tipe` | VARCHAR | 10 | NO | - | 'info' | Tipe info pengumuman |
| `is_aktif` | TINYINT | 1 | NO | - | 1 | Apakah aktif ditampilkan (0/1) |
| `foto` | VARCHAR | 50 | YES | - | NULL | File gambar pendukung pengumuman |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu pengumuman dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu pengumuman diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE pengumuman (
    id_pengumuman VARCHAR(15) NOT NULL,
    judul VARCHAR(40) NOT NULL,
    konten TEXT NOT NULL,
    tipe VARCHAR(10) NOT NULL DEFAULT 'info',
    is_aktif TINYINT(1) NOT NULL DEFAULT 1,
    foto VARCHAR(50) NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_pengumuman)
);

---

## 11. Tabel `slips_gaji`
Tabel ini digunakan untuk mencatat rincian slip gaji kurir per periode bulan. Menggunakan ID bertipe VARCHAR (format 'SG-YYYYMM-XXXX') tanpa auto-increment.

### Kamus Data
| Nama Kolom | Tipe Data | Panjang / Nilai | Null | Key | Default | Keterangan |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `id_slip_gaji` | VARCHAR | 20 | NO | PRI | NULL | ID unik slip gaji (Primary Key, VARCHAR, Non Auto Increment) |
| `id_user` | VARCHAR | 7 | NO | MUL | NULL | ID Penerima gaji (Foreign Key ke tabel users) |
| `periode` | VARCHAR | 7 | NO | - | NULL | Periode gaji (format 'YYYY-MM') |
| `tanggal_bayar` | DATE | - | YES | - | NULL | Tanggal pembayaran dilakukan |
| `total_qty_3kg` | INT | - | NO | - | 0 | Total volume pengiriman tabung 3kg |
| `total_qty_12kg` | INT | - | NO | - | 0 | Total volume pengiriman tabung 12kg |
| `total_hari_kerja` | INT | - | NO | - | 0 | Jumlah hari kerja kurir dalam sebulan |
| `gaji_pokok_nominal` | DECIMAL | 12,2 | NO | - | NULL | Nominal gaji pokok yang dibayarkan |
| `insentif_nominal` | DECIMAL | 12,2 | NO | - | NULL | Total nominal insentif pengiriman |
| `potongan` | DECIMAL | 12,2 | NO | - | 0.00 | Potongan gaji jika ada |
| `total_diterima` | DECIMAL | 12,2 | NO | - | NULL | Total gaji bersih yang diterima |
| `status` | ENUM | 'draft', 'dibayar' | NO | - | 'draft' | Status pembayaran slip gaji |
| `bukti_transfer` | VARCHAR | 255 | YES | - | NULL | Path file bukti transfer pembayaran |
| `catatan` | TEXT | - | YES | - | NULL | Catatan tambahan |
| `created_at` | TIMESTAMP | - | YES | - | NULL | Waktu data dibuat |
| `updated_at` | TIMESTAMP | - | YES | - | NULL | Waktu data diperbarui |

### Query Pembuatan Tabel (DDL)
```sql
CREATE TABLE slips_gaji (
    id_slip_gaji VARCHAR(20) NOT NULL,
    id_user VARCHAR(7) NOT NULL,
    periode VARCHAR(7) NOT NULL,
    tanggal_bayar DATE NULL,
    total_qty_3kg INT NOT NULL DEFAULT 0,
    total_qty_12kg INT NOT NULL DEFAULT 0,
    total_hari_kerja INT NOT NULL DEFAULT 0,
    gaji_pokok_nominal DECIMAL(12,2) NOT NULL,
    insentif_nominal DECIMAL(12,2) NOT NULL,
    potongan DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    total_diterima DECIMAL(12,2) NOT NULL,
    status ENUM('draft', 'dibayar') NOT NULL DEFAULT 'draft',
    bukti_transfer VARCHAR(255) NULL,
    catatan TEXT NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    PRIMARY KEY (id_slip_gaji),
    FOREIGN KEY (id_user) REFERENCES users(id_user) ON DELETE CASCADE,
    UNIQUE KEY unique_user_periode (id_user, periode)
);
```
```
