# Data Model: WordPress Plugin para Controlo Seguro de Agendamentos KiviCare **Feature**: WordPress Plugin para Controlo Seguro de Agendamentos KiviCare **Date**: 2025-09-10 **Phase**: Data Model Design ## Core Entities ### 1. Restriction Entity **Table**: `wp_care_booking_restrictions` | Field | Type | Constraints | Description | |-------|------|-------------|-------------| | `id` | BIGINT(20) UNSIGNED | AUTO_INCREMENT, PRIMARY KEY | Unique restriction identifier | | `restriction_type` | ENUM('doctor', 'service') | NOT NULL | Type of restriction being applied | | `target_id` | BIGINT(20) UNSIGNED | NOT NULL | ID of the doctor or service being restricted | | `doctor_id` | BIGINT(20) UNSIGNED | NULL | For service restrictions, which doctor it applies to | | `is_blocked` | BOOLEAN | DEFAULT FALSE | Whether the item is blocked from public view | | `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | When restriction was created | | `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | When restriction was last modified | **Indexes**: - `PRIMARY KEY (id)` - `INDEX idx_type_target (restriction_type, target_id)` - `INDEX idx_doctor_service (doctor_id, target_id)` - For service restrictions by doctor - `INDEX idx_blocked (is_blocked)` - For filtering active restrictions ### 2. WordPress Integration Entities **Cache Keys** (WordPress Transients): - `care_booking_doctors_blocked` - List of blocked doctor IDs - `care_booking_services_blocked_{doctor_id}` - Blocked services for specific doctor - `care_booking_restrictions_hash` - Hash of current restrictions for cache validation **WordPress Options**: - `care_booking_plugin_version` - Plugin version for migration handling - `care_booking_cache_timeout` - Cache timeout in seconds (default: 3600) ## Entity Relationships ### Doctor Restrictions ``` Restriction (restriction_type = 'doctor') ├── target_id → KiviCare Doctor ID ├── doctor_id → NULL (not applicable) └── is_blocked → TRUE/FALSE ``` ### Service Restrictions ``` Restriction (restriction_type = 'service') ├── target_id → KiviCare Service ID ├── doctor_id → KiviCare Doctor ID (which doctor this applies to) └── is_blocked → TRUE/FALSE ``` ## Data Validation Rules ### Restriction Entity Validation 1. **restriction_type**: Must be either 'doctor' or 'service' 2. **target_id**: Must be positive integer, must exist in KiviCare 3. **doctor_id**: - Must be NULL for doctor restrictions - Must be positive integer for service restrictions - Must exist in KiviCare doctors table 4. **is_blocked**: Boolean only (0 or 1) ### Business Logic Validation 1. **Doctor Restriction**: - target_id must exist in KiviCare doctors - Only one restriction per doctor (unique constraint on target_id for doctor type) 2. **Service Restriction**: - target_id must exist in KiviCare services - doctor_id must exist in KiviCare doctors - Service must be assignable to the specified doctor - Only one restriction per service-doctor combination ### Data Integrity Rules 1. **Orphan Prevention**: Before creating restriction, verify target exists in KiviCare 2. **Cascade Cleanup**: When KiviCare entity is deleted, cleanup related restrictions 3. **Cache Invalidation**: When any restriction changes, invalidate related cache keys ## State Transitions ### Restriction Lifecycle ``` [Non-existent] → [Created (is_blocked=false)] → [Blocked (is_blocked=true)] → [Unblocked (is_blocked=false)] → [Deleted] ↗ ↙ [Blocked (is_blocked=true)] ←→ [Unblocked (is_blocked=false)] ``` ### Admin Interface States 1. **New Restriction**: Create with is_blocked=true (default blocked) 2. **Toggle Restriction**: Update is_blocked value 3. **Remove Restriction**: DELETE from database (not soft delete) ## Query Patterns ### Common Queries ```sql -- Get all blocked doctors SELECT target_id FROM wp_care_booking_restrictions WHERE restriction_type = 'doctor' AND is_blocked = 1; -- Get blocked services for specific doctor SELECT target_id FROM wp_care_booking_restrictions WHERE restriction_type = 'service' AND doctor_id = ? AND is_blocked = 1; -- Check if specific doctor is blocked SELECT 1 FROM wp_care_booking_restrictions WHERE restriction_type = 'doctor' AND target_id = ? AND is_blocked = 1 LIMIT 1; -- Get all restrictions for admin interface SELECT * FROM wp_care_booking_restrictions ORDER BY restriction_type, target_id; ``` ### Performance Considerations - Use prepared statements for all queries - Leverage indexes for common query patterns - Cache frequently accessed data using WordPress transients - Batch operations for bulk updates ## Database Schema Migration ### Version 1.0.0 Initial Schema ```sql CREATE TABLE IF NOT EXISTS {$wpdb->prefix}care_booking_restrictions ( id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY, restriction_type ENUM('doctor', 'service') NOT NULL, target_id BIGINT(20) UNSIGNED NOT NULL, doctor_id BIGINT(20) UNSIGNED NULL, is_blocked BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_type_target (restriction_type, target_id), INDEX idx_doctor_service (doctor_id, target_id), INDEX idx_blocked (is_blocked) ); ``` ### Migration Strategy 1. **Plugin Activation**: Check if table exists, create if needed 2. **Version Updates**: Compare plugin version, run migrations if needed 3. **Plugin Deactivation**: Keep data (user might reactivate) 4. **Plugin Uninstall**: Drop table and clean up options (permanent removal) ## WordPress Integration Data Flow ### Admin Interface Data Flow ``` WordPress Admin Panel ↓ (User Action) AJAX Request with Nonce ↓ (Validation) Database Update (wp_care_booking_restrictions) ↓ (Cache Invalidation) WordPress Transients Cleared ↓ (Response) JSON Response to Admin Interface ``` ### Frontend Filtering Data Flow ``` KiviCare Hook Triggered ↓ (Check Cache) WordPress Transients (if exists) ↓ (If cache miss) Database Query (wp_care_booking_restrictions) ↓ (Filter Data) Modified Doctor/Service List ↓ (CSS Injection) Hidden Elements via CSS ``` This data model provides a robust foundation for the WordPress plugin while maintaining simplicity and performance through appropriate indexing and caching strategies.