From a456450cd051f448274c95fdc9874223ce3ea8da Mon Sep 17 00:00:00 2001 From: ardhikaxx Date: Wed, 25 Feb 2026 08:06:48 +0700 Subject: [PATCH] docs: tambahkan dokumentasi lengkap struktur database dengan relasi antar tabel --- database.md | 406 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 database.md diff --git a/database.md b/database.md new file mode 100644 index 0000000..690f0ca --- /dev/null +++ b/database.md @@ -0,0 +1,406 @@ +# Dokumentasi Database - Sistem Tiket & Booking Banyu Biru + +## Daftar Isi +1. [Overview](#overview) +2. [Diagram Relasi](#diagram-relasi) +3. [Tabel Users](#tabel-users) +4. [Tabel Tickets](#tabel-tickets) +5. [Tabel Ticket Orders](#tabel-ticket-orders) +6. [Tabel Ticket Order Items](#tabel-ticket-order-items) +7. [Tabel Places](#tabel-places) +8. [Tabel Bookings](#tabel-bookings) +9. [Tabel Bank Accounts](#tabel-bank-accounts) +10. [Tabel Settings](#tabel-settings) +11. [Tabel Permission (Spatie)](#tabel-permission-spatie) + +--- + +## Overview + +Database ini digunakan untuk sistem manajemen tiket masuk dan booking pendopo pada Pemandian Air Panas Banyu Biru Nganjuk. Sistem ini mendukung: +- Manajemen user dengan role (admin/user) +- Penjualan tiket masuk dengan QR code +- Booking tempat (pendopo) +- Verifikasi pembayaran +- Manajemen rekening bank + +--- + +## Diagram Relasi + +``` +users (1) ----< (N) ticket_orders +users (1) ----< (N) bookings +users (1) ----< (N) ticket_orders (confirmed_by) +users (1) ----< (N) bookings (confirmed_by) + +tickets (1) ----< (N) ticket_order_items +ticket_orders (1) ----< (N) ticket_order_items + +places (1) ----< (N) bookings +``` + +--- + +## Tabel: users + +**Deskripsi**: Menyimpan data pengguna sistem (admin dan user biasa) + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| name | VARCHAR(100) | NO | - | Nama lengkap user | +| email | VARCHAR(150) | NO | - | Email (unique) | +| phone | VARCHAR(20) | YES | NULL | Nomor telepon | +| address | TEXT | YES | NULL | Alamat lengkap | +| avatar | VARCHAR(255) | YES | NULL | Path foto profil | +| email_verified_at | TIMESTAMP | YES | NULL | Waktu verifikasi email | +| password | VARCHAR(255) | NO | - | Password (hashed) | +| remember_token | VARCHAR(100) | YES | NULL | Token remember me | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- **Has Many**: `ticket_orders` (sebagai pembeli) +- **Has Many**: `bookings` (sebagai pembooking) +- **Has Many**: `ticket_orders` (sebagai confirmer via `confirmed_by`) +- **Has Many**: `bookings` (sebagai confirmer via `confirmed_by`) +- **Has Many Through Spatie**: `roles` dan `permissions` + +### Index + +- PRIMARY KEY: `id` +- UNIQUE: `email` + +--- + +## Tabel: tickets + +**Deskripsi**: Menyimpan jenis-jenis tiket yang tersedia + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| name | VARCHAR(100) | NO | - | Nama tiket (contoh: Tiket Masuk) | +| description | TEXT | YES | NULL | Deskripsi tiket | +| price | DECIMAL(10,2) | NO | - | Harga tiket | +| quota_per_day | INT | NO | 100 | Kuota per hari | +| is_active | BOOLEAN | NO | TRUE | Status aktif/nonaktif | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- **Has Many**: `ticket_order_items` + +### Index + +- PRIMARY KEY: `id` + +--- + +## Tabel: ticket_orders + +**Deskripsi**: Menyimpan data pesanan tiket dari user + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| user_id | BIGINT UNSIGNED | NO | - | Foreign Key ke users | +| order_code | VARCHAR(20) | NO | - | Kode order unik (AT-XXXXX) | +| visit_date | DATE | NO | - | Tanggal kunjungan | +| total_qty | INT | NO | - | Total jumlah tiket | +| total_price | DECIMAL(10,2) | NO | - | Total harga | +| payment_proof | VARCHAR(255) | YES | NULL | Path bukti pembayaran | +| status | ENUM | NO | 'pending' | Status: pending/confirmed/rejected | +| confirmed_at | TIMESTAMP | YES | NULL | Waktu dikonfirmasi | +| confirmed_by | BIGINT UNSIGNED | YES | NULL | Foreign Key ke users (admin) | +| rejection_note | TEXT | YES | NULL | Catatan penolakan | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- **Belongs To**: `users` (via `user_id`) +- **Belongs To**: `users` (via `confirmed_by`) +- **Has Many**: `ticket_order_items` + +### Index + +- PRIMARY KEY: `id` +- UNIQUE: `order_code` +- FOREIGN KEY: `user_id` REFERENCES `users(id)` ON DELETE CASCADE +- FOREIGN KEY: `confirmed_by` REFERENCES `users(id)` ON DELETE SET NULL + +--- + +## Tabel: ticket_order_items + +**Deskripsi**: Menyimpan detail item tiket dalam setiap pesanan (1 item = 1 tiket fisik) + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| ticket_order_id | BIGINT UNSIGNED | NO | - | Foreign Key ke ticket_orders | +| ticket_id | BIGINT UNSIGNED | NO | - | Foreign Key ke tickets | +| ticket_code | VARCHAR(20) | NO | - | Kode tiket unik (AT-XXXXX) | +| qr_code_path | VARCHAR(255) | NO | - | Path file QR code | +| qty | INT | NO | 1 | Quantity (selalu 1) | +| price | DECIMAL(10,2) | NO | - | Harga tiket saat dibeli | +| is_used | BOOLEAN | NO | FALSE | Status sudah dipakai/belum | +| used_at | TIMESTAMP | YES | NULL | Waktu digunakan | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- **Belongs To**: `ticket_orders` (via `ticket_order_id`) +- **Belongs To**: `tickets` (via `ticket_id`) + +### Index + +- PRIMARY KEY: `id` +- UNIQUE: `ticket_code` +- FOREIGN KEY: `ticket_order_id` REFERENCES `ticket_orders(id)` ON DELETE CASCADE +- FOREIGN KEY: `ticket_id` REFERENCES `tickets(id)` ON DELETE CASCADE + +--- + +## Tabel: places + +**Deskripsi**: Menyimpan data tempat yang bisa dibooking (contoh: Pendopo) + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| name | VARCHAR(100) | NO | - | Nama tempat | +| description | TEXT | YES | NULL | Deskripsi tempat | +| capacity | INT | NO | - | Kapasitas orang | +| price_per_day | DECIMAL(10,2) | NO | - | Harga per hari | +| image | VARCHAR(255) | YES | NULL | Path gambar tempat | +| is_active | BOOLEAN | NO | TRUE | Status aktif/nonaktif | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- **Has Many**: `bookings` + +### Index + +- PRIMARY KEY: `id` + +--- + +## Tabel: bookings + +**Deskripsi**: Menyimpan data booking tempat dari user + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| user_id | BIGINT UNSIGNED | NO | - | Foreign Key ke users | +| place_id | BIGINT UNSIGNED | NO | - | Foreign Key ke places | +| booking_code | VARCHAR(20) | NO | - | Kode booking unik (AB-XXXXX) | +| booking_date | DATE | NO | - | Tanggal booking | +| visitor_name | VARCHAR(100) | NO | - | Nama pengunjung | +| visitor_phone | VARCHAR(20) | NO | - | Nomor telepon pengunjung | +| visitor_address | TEXT | NO | - | Alamat pengunjung | +| num_persons | INT | NO | - | Jumlah orang | +| total_price | DECIMAL(10,2) | NO | - | Total harga | +| payment_proof | VARCHAR(255) | YES | NULL | Path bukti pembayaran | +| status | ENUM | NO | 'pending' | Status: pending/confirmed/rejected | +| confirmed_at | TIMESTAMP | YES | NULL | Waktu dikonfirmasi | +| confirmed_by | BIGINT UNSIGNED | YES | NULL | Foreign Key ke users (admin) | +| rejection_note | TEXT | YES | NULL | Catatan penolakan | +| notes | TEXT | YES | NULL | Catatan tambahan | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- **Belongs To**: `users` (via `user_id`) +- **Belongs To**: `places` (via `place_id`) +- **Belongs To**: `users` (via `confirmed_by`) + +### Index + +- PRIMARY KEY: `id` +- UNIQUE: `booking_code` +- UNIQUE: `place_id, booking_date` (composite - 1 tempat hanya bisa dibooking 1x per hari) +- FOREIGN KEY: `user_id` REFERENCES `users(id)` ON DELETE CASCADE +- FOREIGN KEY: `place_id` REFERENCES `places(id)` ON DELETE CASCADE +- FOREIGN KEY: `confirmed_by` REFERENCES `users(id)` ON DELETE SET NULL + +--- + +## Tabel: bank_accounts + +**Deskripsi**: Menyimpan data rekening bank untuk pembayaran + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| bank_name | VARCHAR(100) | NO | - | Nama bank | +| account_number | VARCHAR(50) | NO | - | Nomor rekening | +| account_name | VARCHAR(100) | NO | - | Nama pemilik rekening | +| is_active | BOOLEAN | NO | TRUE | Status aktif/nonaktif | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- Tidak ada relasi langsung (standalone table) + +### Index + +- PRIMARY KEY: `id` + +--- + +## Tabel: settings + +**Deskripsi**: Menyimpan pengaturan sistem (key-value pairs) + +### Struktur Kolom + +| Kolom | Tipe | Nullable | Default | Keterangan | +|-------|------|----------|---------|------------| +| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | Primary Key | +| key | VARCHAR(100) | NO | - | Key pengaturan (unique) | +| value | TEXT | YES | NULL | Value pengaturan | +| created_at | TIMESTAMP | YES | NULL | Waktu dibuat | +| updated_at | TIMESTAMP | YES | NULL | Waktu diupdate | + +### Relasi + +- Tidak ada relasi langsung (standalone table) + +### Index + +- PRIMARY KEY: `id` +- UNIQUE: `key` + +--- + +## Tabel Permission (Spatie) + +**Deskripsi**: Tabel dari package Spatie Laravel Permission untuk manajemen role dan permission + +### Tabel yang Digunakan + +1. **roles** - Menyimpan role (admin, user) +2. **permissions** - Menyimpan permission +3. **model_has_roles** - Relasi many-to-many antara model (users) dan roles +4. **model_has_permissions** - Relasi many-to-many antara model dan permissions +5. **role_has_permissions** - Relasi many-to-many antara roles dan permissions + +### Relasi dengan Users + +- User dapat memiliki banyak roles (many-to-many via `model_has_roles`) +- User dapat memiliki banyak permissions langsung (many-to-many via `model_has_permissions`) +- Role dapat memiliki banyak permissions (many-to-many via `role_has_permissions`) + +--- + +## Status Enum Values + +### ticket_orders.status & bookings.status + +- `pending` - Menunggu verifikasi pembayaran +- `confirmed` - Pembayaran sudah dikonfirmasi admin +- `rejected` - Pembayaran ditolak admin + +--- + +## Kode Unik + +### Format Kode + +- **Ticket Order**: `AT-XXXXX` (AT = Admission Ticket) +- **Ticket Item**: `AT-XXXXX` (setiap item punya kode unik) +- **Booking**: `AB-XXXXX` (AB = Admission Booking) + +Kode dihasilkan menggunakan helper function `generateUniqueCode()` yang memastikan keunikan. + +--- + +## Catatan Penting + +1. **Cascade Delete**: + - Jika user dihapus, semua ticket_orders dan bookings miliknya ikut terhapus + - Jika ticket_order dihapus, semua ticket_order_items ikut terhapus + +2. **Set Null on Delete**: + - Jika admin yang mengkonfirmasi dihapus, field `confirmed_by` di-set NULL + +3. **Unique Constraints**: + - 1 tempat hanya bisa dibooking 1x per tanggal (`place_id, booking_date`) + - Setiap kode order/booking/tiket harus unik + +4. **QR Code**: + - Setiap ticket_order_item memiliki QR code unik + - QR code disimpan sebagai file SVG di folder `public/qrcodes/` + - QR code berisi `ticket_code` untuk verifikasi + +5. **Payment Proof**: + - Bukti pembayaran disimpan di folder `public/payment-proofs/` + - Format: `YYYYMMDDHHMMSS_proof_uniqid.ext` + +--- + +## Query Contoh + +### Mendapatkan semua tiket yang sudah dikonfirmasi bulan ini + +```sql +SELECT * FROM ticket_orders +WHERE status = 'confirmed' +AND YEAR(created_at) = YEAR(CURDATE()) +AND MONTH(created_at) = MONTH(CURDATE()); +``` + +### Mendapatkan total pendapatan bulan ini + +```sql +SELECT + (SELECT COALESCE(SUM(total_price), 0) FROM ticket_orders + WHERE status = 'confirmed' + AND YEAR(created_at) = YEAR(CURDATE()) + AND MONTH(created_at) = MONTH(CURDATE())) + + + (SELECT COALESCE(SUM(total_price), 0) FROM bookings + WHERE status = 'confirmed' + AND YEAR(created_at) = YEAR(CURDATE()) + AND MONTH(created_at) = MONTH(CURDATE())) +AS total_revenue; +``` + +### Cek ketersediaan booking untuk tanggal tertentu + +```sql +SELECT * FROM bookings +WHERE place_id = ? +AND booking_date = '2026-02-25'; +``` + +--- + +**Dibuat**: 25 Februari 2026 +**Versi**: 1.0 +**Sistem**: Banyu Biru Ticketing & Booking System