# DATABASE DESIGN

Dokumen ini menjelaskan rancangan database logis untuk platform E-Voting.
Struktur ini adalah baseline desain dan tidak boleh diubah tanpa persetujuan.

## Tables

### organizations

- id
- name
- slug
- status
- description
- created_by
- created_at
- updated_at
- deleted_at

### users

- id
- organization_id
- name
- email
- password
- role
- email_verified_at
- last_login_at
- remember_token
- created_at
- updated_at
- deleted_at

### events

- id
- organization_id
- name
- slug
- description
- starts_at
- ends_at
- status
- created_by
- created_at
- updated_at
- deleted_at

### candidates

- id
- event_id
- name
- photo_path
- vision_mission
- sort_order
- is_active
- created_at
- updated_at
- deleted_at

### voters

- id
- event_id
- email
- name
- otp_verified_at
- has_voted
- voted_at
- status
- created_at
- updated_at
- deleted_at

### votes

- id
- event_id
- candidate_id
- created_at
- updated_at

### otp_codes

- id
- voter_id
- email
- otp_hash
- sent_at
- expires_at
- verified_at
- consumed_at
- attempts
- status
- created_at
- updated_at

### audit_logs

- id
- organization_id
- user_id
- event_id
- actor_type
- action
- subject_type
- subject_id
- metadata
- ip_address
- user_agent
- created_at

## Relations

Organization
|
+-- Events
    |
    +-- Candidates
    |
    +-- Voters
    |
    +-- Votes

## Relationship Notes

- `organizations` memiliki banyak `users`, `events`, dan `audit_logs`.
- `events` memiliki banyak `candidates`, `voters`, dan `votes`.
- `voters` dipakai untuk verifikasi OTP dan status voting.
- `votes` hanya menyimpan `event_id` dan `candidate_id` supaya vote tetap anonim.
- `otp_codes` boleh terhubung ke `voters` karena hanya dipakai untuk verifikasi, bukan untuk menyimpan pilihan suara.
- `audit_logs` tidak boleh menyimpan data pilihan kandidat yang dipilih voter.

## Index and Constraint Guidelines

- `organizations.slug` unique.
- `users.email` unique.
- `events.organization_id` indexed.
- `events.slug` unique per organisasi bila diperlukan.
- `candidates.event_id` indexed.
- `voters.event_id` plus `email` unique per event.
- `votes.event_id` indexed.
- `votes.candidate_id` indexed.
- `otp_codes.voter_id` indexed.
- `otp_codes.expires_at` indexed untuk cleanup job.
- `audit_logs.created_at` indexed untuk reporting.

## Anonymity Rules

- Tidak ada `voter_id` pada tabel `votes`.
- Tidak ada email voter pada tabel `votes`.
- Tidak ada referensi langsung dari suara ke identitas voter.
- Hasil vote hanya dapat dihitung secara agregat per event dan kandidat.

## Data Safety Notes

- Gunakan soft delete untuk entity yang butuh jejak historis.
- Simpan hash untuk OTP, bukan OTP plain text.
- Simpan metadata audit secukupnya, tanpa data sensitif yang tidak perlu.

