# 🗄️ Database Schema - Sistem Manajemen Anggota PKS

## 📋 Overview

Dokumentasi ini menjelaskan struktur database untuk **Sistem Manajemen Anggota PKS**. Database menggunakan MySQL dengan optimasi performa tinggi dan enkripsi data sensitif.

## 🏗️ Database Architecture

### Technology Stack
- **Database**: MySQL 8.0+
- **ORM**: Laravel Eloquent
- **Migrations**: Laravel Database Migrations
- **Indexes**: 16+ performance indexes
- **Encryption**: Laravel Encryption untuk data sensitif

## 📊 Core Tables

### 1. 👥 tbl_anggota (Anggota)

Tabel utama untuk menyimpan data anggota PKS.

```sql
CREATE TABLE tbl_anggota (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nomor_identitas_anggota VARCHAR(255) UNIQUE NOT NULL,
    nama_lengkap VARCHAR(255) NOT NULL,
    tempat_lahir VARCHAR(255) NOT NULL,
    tanggal_lahir DATE NOT NULL,
    jenis_kelamin ENUM('L', 'P') NOT NULL,
    
    -- Alamat
    alamat_jalan TEXT NOT NULL,
    rt VARCHAR(5) NOT NULL,
    rw VARCHAR(5) NOT NULL,
    kelurahan VARCHAR(255) NOT NULL,
    kecamatan VARCHAR(255) NOT NULL,
    kota VARCHAR(255) NOT NULL,
    provinsi VARCHAR(255) NOT NULL,
    kode_pos VARCHAR(10),
    
    -- Kontak
    no_telepon VARCHAR(15),
    email VARCHAR(255),
    
    -- Organisasi
    ref_jenjang_id BIGINT,
    ref_grup_upa_id BIGINT,
    upa_id BIGINT,
    dpc_id BIGINT,
    dpd_id BIGINT,
    
    -- Status
    tanggal_bergabung DATE NOT NULL,
    status_keanggotaan ENUM('Aktif', 'Tidak Aktif', 'Diberhentikan', 'Pindah') DEFAULT 'Aktif',
    
    -- Data Tambahan
    penghasilan_per_bulan DECIMAL(12,2),
    muzaki_mustahiq ENUM('Muzaki', 'Mustahiq'),
    nomor_identitas_pasangan VARCHAR(255),
    catatan_profil TEXT,
    keahlian_lainnya TEXT,
    foto VARCHAR(255),
    
    -- Encrypted Fields
    nomor_identitas_anggota_encrypted TEXT,
    alamat_jalan_encrypted TEXT,
    rt_encrypted TEXT,
    rw_encrypted TEXT,
    kelurahan_encrypted TEXT,
    no_telepon_encrypted TEXT,
    email_encrypted TEXT,
    penghasilan_per_bulan_encrypted TEXT,
    nomor_identitas_pasangan_encrypted TEXT,
    
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (ref_jenjang_id) REFERENCES tbl_ref_jenjang(ref_jenjang_id),
    FOREIGN KEY (ref_grup_upa_id) REFERENCES tbl_ref_grup_upa(ref_grup_upa_id),
    FOREIGN KEY (upa_id) REFERENCES tbl_upa(upa_id),
    FOREIGN KEY (dpc_id) REFERENCES tbl_dpc(dpc_id),
    FOREIGN KEY (dpd_id) REFERENCES tbl_dpd(dpd_id),
    
    -- Indexes
    INDEX idx_nomor_identitas (nomor_identitas_anggota),
    INDEX idx_status_keanggotaan (status_keanggotaan),
    INDEX idx_jenjang_anggota (ref_jenjang_id),
    INDEX idx_dpc_id (dpc_id),
    INDEX idx_dpd_id (dpd_id),
    INDEX idx_status_jenjang (status_keanggotaan, ref_jenjang_id),
    INDEX idx_status_dpc (status_keanggotaan, dpc_id),
    INDEX idx_status_dpd (status_keanggotaan, dpd_id),
    INDEX idx_status_grup_upa (status_keanggotaan, ref_grup_upa_id),
    INDEX idx_tanggal_bergabung (tanggal_bergabung),
    INDEX idx_created_at (created_at),
    INDEX idx_nama_lengkap (nama_lengkap),
    INDEX idx_dashboard_dpc (status_keanggotaan, ref_jenjang_id, dpc_id),
    INDEX idx_dashboard_dpd (status_keanggotaan, ref_jenjang_id, dpd_id)
);
```

### 2. 🔄 tbl_mutasi (Mutasi)

Tabel untuk mengelola mutasi anggota antar struktur organisasi.

```sql
CREATE TABLE tbl_mutasi (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    anggota_id BIGINT NOT NULL,
    jenis_mutasi ENUM('Masuk', 'Pindah', 'Keluar', 'Promosi', 'Demosi', 'Pencupatan', 'Reaktivasi') NOT NULL,
    struktur_dari BIGINT,
    struktur_ke BIGINT,
    jenjang_dari VARCHAR(255),
    jenjang_ke VARCHAR(255),
    tanggal_mutasi DATE NOT NULL,
    alasan_mutasi TEXT NOT NULL,
    nomor_sk VARCHAR(255),
    tanggal_sk DATE,
    disetujui_oleh VARCHAR(255),
    catatan TEXT,
    status_mutasi ENUM('Pending', 'Disetujui', 'Ditolak') DEFAULT 'Pending',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (anggota_id) REFERENCES tbl_anggota(id) ON DELETE CASCADE,
    FOREIGN KEY (struktur_dari) REFERENCES tbl_struktur_organisasi(id) ON DELETE SET NULL,
    FOREIGN KEY (struktur_ke) REFERENCES tbl_struktur_organisasi(id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_anggota_id (anggota_id),
    INDEX idx_tanggal_mutasi (tanggal_mutasi),
    INDEX idx_jenis_mutasi (jenis_mutasi),
    INDEX idx_status_mutasi (status_mutasi)
);
```

### 3. 📅 tbl_kegiatan (Kegiatan)

Tabel untuk mengelola kegiatan organisasi.

```sql
CREATE TABLE tbl_kegiatan (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    kode_kegiatan VARCHAR(255) UNIQUE NOT NULL,
    nama_kegiatan VARCHAR(255) NOT NULL,
    jenis_kegiatan ENUM('Mabit', 'Rapat', 'Takwim', 'Lainnya') NOT NULL,
    jenis_kegiatan_lainnya VARCHAR(255),
    uraian_kegiatan TEXT,
    tanggal_mulai DATETIME NOT NULL,
    tanggal_selesai DATETIME NOT NULL,
    tempat VARCHAR(255) NOT NULL,
    alamat_tempat TEXT,
    struktur_penyelenggara_id BIGINT,
    pic_kegiatan VARCHAR(255) NOT NULL,
    penyelenggara_anggota_id BIGINT,
    koordinator_anggota_id BIGINT,
    catatan TEXT,
    status_kegiatan ENUM('Planned', 'Ongoing', 'Completed', 'Cancelled') DEFAULT 'Planned',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (struktur_penyelenggara_id) REFERENCES tbl_struktur_organisasi(id) ON DELETE SET NULL,
    FOREIGN KEY (penyelenggara_anggota_id) REFERENCES tbl_anggota(id) ON DELETE SET NULL,
    FOREIGN KEY (koordinator_anggota_id) REFERENCES tbl_anggota(id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_kode_kegiatan (kode_kegiatan),
    INDEX idx_jenis_kegiatan (jenis_kegiatan),
    INDEX idx_tanggal_mulai (tanggal_mulai),
    INDEX idx_status_kegiatan (status_kegiatan)
);
```

### 4. 📊 tbl_takwim (Takwim)

Tabel untuk mengelola program takwim berkelanjutan.

```sql
CREATE TABLE tbl_takwim (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_takwim VARCHAR(255) NOT NULL,
    deskripsi TEXT,
    tanggal_mulai DATE NOT NULL,
    tanggal_selesai DATE,
    struktur_penyelenggara_id BIGINT,
    koordinator VARCHAR(255) NOT NULL,
    penyelenggara_anggota_id BIGINT,
    koordinator_anggota_id BIGINT,
    evaluasi TEXT,
    catatan_berkelanjutan TEXT,
    status_takwim ENUM('Aktif', 'Selesai', 'Ditunda') DEFAULT 'Aktif',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (struktur_penyelenggara_id) REFERENCES tbl_struktur_organisasi(id) ON DELETE SET NULL,
    FOREIGN KEY (penyelenggara_anggota_id) REFERENCES tbl_anggota(id) ON DELETE SET NULL,
    FOREIGN KEY (koordinator_anggota_id) REFERENCES tbl_anggota(id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_tanggal_mulai (tanggal_mulai),
    INDEX idx_status_takwim (status_takwim)
);
```

### 5. ✅ tbl_absensi_kegiatan (Absensi Kegiatan)

Tabel untuk mengelola absensi kegiatan.

```sql
CREATE TABLE tbl_absensi_kegiatan (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    kegiatan_id BIGINT NOT NULL,
    anggota_id BIGINT NOT NULL,
    waktu_checkin DATETIME NOT NULL,
    status ENUM('hadir', 'tidak_hadir', 'izin') DEFAULT 'hadir',
    keterangan TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (kegiatan_id) REFERENCES tbl_kegiatan(id) ON DELETE CASCADE,
    FOREIGN KEY (anggota_id) REFERENCES tbl_anggota(id) ON DELETE CASCADE,
    
    -- Indexes
    INDEX idx_kegiatan_anggota (kegiatan_id, anggota_id),
    INDEX idx_waktu_checkin (waktu_checkin),
    INDEX idx_status (status)
);
```

## 🏢 Reference Tables

### 6. 🏛️ tbl_struktur_organisasi (Struktur Organisasi)

```sql
CREATE TABLE tbl_struktur_organisasi (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_struktur VARCHAR(255) NOT NULL,
    jenis_struktur ENUM('DPD', 'DPC', 'UPA') NOT NULL,
    parent_id BIGINT,
    level_struktur INT,
    alamat TEXT,
    no_telepon VARCHAR(15),
    email VARCHAR(255),
    ketua VARCHAR(255),
    sekretaris VARCHAR(255),
    bendahara VARCHAR(255),
    status ENUM('Aktif', 'Tidak Aktif') DEFAULT 'Aktif',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (parent_id) REFERENCES tbl_struktur_organisasi(id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_jenis_struktur (jenis_struktur),
    INDEX idx_parent_id (parent_id),
    INDEX idx_status (status)
);
```

### 7. 📚 tbl_ref_jenjang (Referensi Jenjang)

```sql
CREATE TABLE tbl_ref_jenjang (
    ref_jenjang_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_jenjang VARCHAR(255) NOT NULL,
    kode_jenjang VARCHAR(10) UNIQUE NOT NULL,
    level_jenjang INT NOT NULL,
    deskripsi TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Indexes
    INDEX idx_kode_jenjang (kode_jenjang),
    INDEX idx_level_jenjang (level_jenjang),
    INDEX idx_is_active (is_active)
);
```

### 8. 👥 tbl_ref_grup_upa (Referensi Grup UPA)

```sql
CREATE TABLE tbl_ref_grup_upa (
    ref_grup_upa_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_grup_upa VARCHAR(255) NOT NULL,
    kode_grup_upa VARCHAR(10) UNIQUE NOT NULL,
    deskripsi TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Indexes
    INDEX idx_kode_grup_upa (kode_grup_upa),
    INDEX idx_is_active (is_active)
);
```

### 9. 🏢 tbl_upa (UPA)

```sql
CREATE TABLE tbl_upa (
    upa_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_upa VARCHAR(255) NOT NULL,
    alamat TEXT,
    provinsi_id BIGINT,
    kota_id BIGINT,
    kecamatan_id BIGINT,
    kelurahan_id BIGINT,
    kode_pos VARCHAR(10),
    no_telepon VARCHAR(15),
    email VARCHAR(255),
    ketua VARCHAR(255),
    sekretaris VARCHAR(255),
    bendahara VARCHAR(255),
    dpc_id BIGINT,
    status ENUM('Aktif', 'Tidak Aktif') DEFAULT 'Aktif',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (provinsi_id) REFERENCES ref_provinsi(id) ON DELETE SET NULL,
    FOREIGN KEY (kota_id) REFERENCES ref_kota(id) ON DELETE SET NULL,
    FOREIGN KEY (kecamatan_id) REFERENCES ref_kecamatan(id) ON DELETE SET NULL,
    FOREIGN KEY (kelurahan_id) REFERENCES ref_kelurahan(id) ON DELETE SET NULL,
    FOREIGN KEY (dpc_id) REFERENCES tbl_dpc(dpc_id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_dpc_id (dpc_id),
    INDEX idx_status (status),
    INDEX idx_provinsi_id (provinsi_id),
    INDEX idx_kota_id (kota_id)
);
```

### 10. 🏛️ tbl_dpc (DPC)

```sql
CREATE TABLE tbl_dpc (
    dpc_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_dpc VARCHAR(255) NOT NULL,
    alamat TEXT,
    no_telepon VARCHAR(15),
    email VARCHAR(255),
    ketua VARCHAR(255),
    sekretaris VARCHAR(255),
    bendahara VARCHAR(255),
    dpd_id BIGINT,
    status ENUM('Aktif', 'Tidak Aktif') DEFAULT 'Aktif',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (dpd_id) REFERENCES tbl_dpd(dpd_id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_dpd_id (dpd_id),
    INDEX idx_status (status)
);
```

### 11. 🏛️ tbl_dpd (DPD)

```sql
CREATE TABLE tbl_dpd (
    dpd_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    nama_dpd VARCHAR(255) NOT NULL,
    alamat TEXT,
    no_telepon VARCHAR(15),
    email VARCHAR(255),
    ketua VARCHAR(255),
    sekretaris VARCHAR(255),
    bendahara VARCHAR(255),
    status ENUM('Aktif', 'Tidak Aktif') DEFAULT 'Aktif',
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Indexes
    INDEX idx_status (status)
);
```

## 📍 Address Reference Tables

### 12. 🗺️ ref_provinsi (Referensi Provinsi)

```sql
CREATE TABLE ref_provinsi (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    kode_provinsi VARCHAR(10) UNIQUE NOT NULL,
    nama_provinsi VARCHAR(100) NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Indexes
    INDEX idx_kode_provinsi (kode_provinsi),
    INDEX idx_is_active (is_active)
);
```

### 13. 🏙️ ref_kota (Referensi Kota/Kabupaten)

```sql
CREATE TABLE ref_kota (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    kode_kota VARCHAR(10) UNIQUE NOT NULL,
    nama_kota VARCHAR(100) NOT NULL,
    provinsi_id BIGINT NOT NULL,
    tipe ENUM('Kota', 'Kabupaten') NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (provinsi_id) REFERENCES ref_provinsi(id) ON DELETE CASCADE,
    
    -- Indexes
    INDEX idx_kode_kota (kode_kota),
    INDEX idx_provinsi_id (provinsi_id),
    INDEX idx_is_active (is_active)
);
```

### 14. 🏘️ ref_kecamatan (Referensi Kecamatan)

```sql
CREATE TABLE ref_kecamatan (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    kode_kecamatan VARCHAR(10) UNIQUE NOT NULL,
    nama_kecamatan VARCHAR(100) NOT NULL,
    kota_id BIGINT NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (kota_id) REFERENCES ref_kota(id) ON DELETE CASCADE,
    
    -- Indexes
    INDEX idx_kode_kecamatan (kode_kecamatan),
    INDEX idx_kota_id (kota_id),
    INDEX idx_is_active (is_active)
);
```

### 15. 🏠 ref_kelurahan (Referensi Kelurahan/Desa)

```sql
CREATE TABLE ref_kelurahan (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    kode_kelurahan VARCHAR(10) UNIQUE NOT NULL,
    nama_kelurahan VARCHAR(100) NOT NULL,
    kecamatan_id BIGINT NOT NULL,
    kode_pos VARCHAR(10),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (kecamatan_id) REFERENCES ref_kecamatan(id) ON DELETE CASCADE,
    
    -- Indexes
    INDEX idx_kode_kelurahan (kode_kelurahan),
    INDEX idx_kecamatan_id (kecamatan_id),
    INDEX idx_kode_pos (kode_pos),
    INDEX idx_is_active (is_active)
);
```

## 🔗 Relationship Tables

### 16. 👥 tbl_anggota_keahlian (Anggota - Keahlian)

```sql
CREATE TABLE tbl_anggota_keahlian (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    anggota_id BIGINT NOT NULL,
    ref_keahlian_id BIGINT NOT NULL,
    level_keahlian ENUM('Pemula', 'Menengah', 'Mahir', 'Expert') DEFAULT 'Pemula',
    sertifikat VARCHAR(255),
    tanggal_sertifikat DATE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (anggota_id) REFERENCES tbl_anggota(id) ON DELETE CASCADE,
    FOREIGN KEY (ref_keahlian_id) REFERENCES tbl_ref_keahlian(ref_keahlian_id) ON DELETE CASCADE,
    
    -- Unique constraint
    UNIQUE KEY unique_anggota_keahlian (anggota_id, ref_keahlian_id),
    
    -- Indexes
    INDEX idx_anggota_id (anggota_id),
    INDEX idx_ref_keahlian_id (ref_keahlian_id)
);
```

### 17. 📊 tbl_peserta_takwim (Peserta Takwim)

```sql
CREATE TABLE tbl_peserta_takwim (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    takwim_id BIGINT NOT NULL,
    anggota_id BIGINT NOT NULL,
    tanggal_daftar DATE NOT NULL,
    status_peserta ENUM('Aktif', 'Tidak Aktif', 'Lulus', 'Tidak Lulus') DEFAULT 'Aktif',
    catatan TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (takwim_id) REFERENCES tbl_takwim(id) ON DELETE CASCADE,
    FOREIGN KEY (anggota_id) REFERENCES tbl_anggota(id) ON DELETE CASCADE,
    
    -- Unique constraint
    UNIQUE KEY unique_takwim_anggota (takwim_id, anggota_id),
    
    -- Indexes
    INDEX idx_takwim_id (takwim_id),
    INDEX idx_anggota_id (anggota_id),
    INDEX idx_status_peserta (status_peserta)
);
```

### 18. 📝 tbl_penilaian_peserta_takwim (Penilaian Peserta)

```sql
CREATE TABLE tbl_penilaian_peserta_takwim (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    peserta_takwim_id BIGINT NOT NULL,
    indikator_takwim_id BIGINT NOT NULL,
    nilai DECIMAL(5,2) NOT NULL,
    catatan TEXT,
    penilai_id BIGINT,
    tanggal_penilaian DATE NOT NULL,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (peserta_takwim_id) REFERENCES tbl_peserta_takwim(id) ON DELETE CASCADE,
    FOREIGN KEY (indikator_takwim_id) REFERENCES tbl_indikator_takwim(id) ON DELETE CASCADE,
    FOREIGN KEY (penilai_id) REFERENCES tbl_anggota(id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_peserta_takwim_id (peserta_takwim_id),
    INDEX idx_indikator_takwim_id (indikator_takwim_id),
    INDEX idx_penilai_id (penilai_id),
    INDEX idx_tanggal_penilaian (tanggal_penilaian)
);
```

## 🔐 Security Features

### Data Encryption
- **Encrypted Fields**: Data sensitif dienkripsi menggunakan Laravel Encryption
- **Encryption Key**: Menggunakan APP_KEY dari environment
- **Automatic Encryption**: Enkripsi otomatis saat save data
- **Automatic Decryption**: Dekripsi otomatis saat retrieve data

### Encrypted Fields in tbl_anggota:
- `nomor_identitas_anggota_encrypted`
- `alamat_jalan_encrypted`
- `rt_encrypted`, `rw_encrypted`
- `kelurahan_encrypted`
- `no_telepon_encrypted`
- `email_encrypted`
- `penghasilan_per_bulan_encrypted`
- `nomor_identitas_pasangan_encrypted`

## ⚡ Performance Optimization

### Database Indexes
Aplikasi memiliki **16+ database indexes** untuk performa optimal:

1. **Primary Indexes**: Semua primary key
2. **Foreign Key Indexes**: Semua foreign key
3. **Search Indexes**: Untuk pencarian cepat
4. **Composite Indexes**: Untuk query kompleks
5. **Status Indexes**: Untuk filter status
6. **Date Indexes**: Untuk query berdasarkan tanggal

### Query Optimization
- **Lazy Loading**: Relasi dimuat sesuai kebutuhan
- **Eager Loading**: Relasi dimuat sekaligus untuk efisiensi
- **Query Caching**: Cache untuk query yang sering digunakan
- **Database Connection Pooling**: Pool koneksi database

## 📊 Data Relationships

### Entity Relationship Diagram (ERD)

```
tbl_anggota (1) -----> (N) tbl_mutasi
tbl_anggota (1) -----> (N) tbl_absensi_kegiatan
tbl_anggota (N) <-----> (N) tbl_ref_keahlian [via tbl_anggota_keahlian]
tbl_anggota (N) <-----> (N) tbl_takwim [via tbl_peserta_takwim]

tbl_kegiatan (1) -----> (N) tbl_absensi_kegiatan
tbl_takwim (1) -----> (N) tbl_peserta_takwim
tbl_peserta_takwim (1) -----> (N) tbl_penilaian_peserta_takwim

tbl_struktur_organisasi (1) -----> (N) tbl_mutasi [struktur_dari]
tbl_struktur_organisasi (1) -----> (N) tbl_mutasi [struktur_ke]

ref_provinsi (1) -----> (N) ref_kota
ref_kota (1) -----> (N) ref_kecamatan
ref_kecamatan (1) -----> (N) ref_kelurahan

tbl_dpd (1) -----> (N) tbl_dpc
tbl_dpc (1) -----> (N) tbl_upa
tbl_upa (1) -----> (N) tbl_anggota
```

## 🚀 Migration Commands

### Run Migrations
```bash
# Run all migrations
php artisan migrate

# Run specific migration
php artisan migrate --path=database/migrations/2025_09_12_214319_create_tbl_anggota_table.php

# Rollback migrations
php artisan migrate:rollback

# Reset database
php artisan migrate:reset
```

### Seed Database
```bash
# Run all seeders
php artisan db:seed

# Run specific seeder
php artisan db:seed --class=AnggotaDemoSeeder

# Fresh migration with seed
php artisan migrate:fresh --seed
```

## 📈 Database Monitoring

### Performance Monitoring
```sql
-- Check slow queries
SHOW PROCESSLIST;

-- Check table sizes
SELECT 
    table_name,
    ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Size in MB'
FROM information_schema.tables
WHERE table_schema = 'bkdpd'
ORDER BY (data_length + index_length) DESC;

-- Check index usage
SHOW INDEX FROM tbl_anggota;
```

### Backup Commands
```bash
# MySQL backup
mysqldump -u username -p bkdpd > backup_$(date +%Y%m%d_%H%M%S).sql

# Laravel backup
php artisan backup:run
```

---

**Database schema ini dirancang untuk performa tinggi, keamanan data, dan skalabilitas! 🚀**
