validated 1.1 story
This commit is contained in:
parent
05851ea86d
commit
ef3f9dfd4e
|
|
@ -1,27 +1,21 @@
|
||||||
# Story 1.1: Project Setup & Database Schema
|
# Story 1.1: Project Setup & Database Schema
|
||||||
|
|
||||||
|
## Status
|
||||||
|
Draft
|
||||||
|
|
||||||
## Epic Reference
|
## Epic Reference
|
||||||
**Epic 1:** Core Foundation & Infrastructure
|
**Epic 1:** Core Foundation & Infrastructure
|
||||||
|
|
||||||
## User Story
|
## Story
|
||||||
As a **developer**,
|
**As a** developer,
|
||||||
I want **the Laravel 12 project configured with all required packages and complete database schema**,
|
**I want** the Laravel 12 project configured with all required packages and complete database schema,
|
||||||
So that **the foundation is established for all subsequent feature development**.
|
**So that** the foundation is established for all subsequent feature development.
|
||||||
|
|
||||||
## Story Context
|
|
||||||
|
|
||||||
### Existing System Integration
|
|
||||||
- **Integrates with:** New project setup (greenfield)
|
|
||||||
- **Technology:** Laravel 12, PHP 8.4, Livewire 3, Volt, Flux UI Free, Tailwind CSS 4
|
|
||||||
- **Follows pattern:** Laravel 12 streamlined file structure
|
|
||||||
- **Touch points:** Database migrations, model factories, development environment
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
### Functional Requirements
|
1. [ ] Laravel 12 project created with Livewire 3, Volt, Flux UI
|
||||||
- [ ] Laravel 12 project created with Livewire 3, Volt, Flux UI
|
2. [ ] Tailwind CSS 4 configured with `@theme` directive
|
||||||
- [ ] Tailwind CSS 4 configured with `@theme` directive
|
3. [ ] Database migrations for all core tables:
|
||||||
- [ ] Database migrations for all core tables:
|
|
||||||
- `users` (with user_type, national_id, company fields)
|
- `users` (with user_type, national_id, company fields)
|
||||||
- `consultations`
|
- `consultations`
|
||||||
- `timelines`
|
- `timelines`
|
||||||
|
|
@ -31,112 +25,355 @@ So that **the foundation is established for all subsequent feature development**
|
||||||
- `blocked_times`
|
- `blocked_times`
|
||||||
- `notifications`
|
- `notifications`
|
||||||
- `admin_logs`
|
- `admin_logs`
|
||||||
- [ ] Model factories created for testing
|
4. [ ] Model factories created for testing
|
||||||
- [ ] Development environment working (`composer run dev`)
|
5. [ ] Development environment working (`composer run dev`)
|
||||||
|
6. [ ] SQLite configured for development database
|
||||||
|
7. [ ] All migrations run without errors
|
||||||
|
8. [ ] Factories generate valid test data
|
||||||
|
9. [ ] All database tables have proper indexes
|
||||||
|
10. [ ] Foreign key constraints properly defined
|
||||||
|
|
||||||
### Integration Requirements
|
## Tasks / Subtasks
|
||||||
- [ ] SQLite configured for development database
|
|
||||||
- [ ] All migrations run without errors
|
|
||||||
- [ ] Factories generate valid test data
|
|
||||||
- [ ] Composer and npm scripts functional
|
|
||||||
|
|
||||||
### Quality Requirements
|
- [ ] **Task 1: Create PHP Enums** (AC: 3)
|
||||||
- [ ] All database tables have proper indexes
|
- [ ] Create `app/Enums/UserType.php` enum (admin, individual, company)
|
||||||
- [ ] Foreign key constraints properly defined
|
- [ ] Create `app/Enums/UserStatus.php` enum (active, deactivated)
|
||||||
- [ ] Factories cover all required fields
|
- [ ] Create `app/Enums/ConsultationType.php` enum (free, paid)
|
||||||
- [ ] Development server starts without errors
|
- [ ] Create `app/Enums/ConsultationStatus.php` enum (pending, approved, rejected, completed, no_show, cancelled)
|
||||||
|
- [ ] Create `app/Enums/PaymentStatus.php` enum (pending, received, na)
|
||||||
|
- [ ] Create `app/Enums/TimelineStatus.php` enum (active, archived)
|
||||||
|
- [ ] Create `app/Enums/PostStatus.php` enum (draft, published)
|
||||||
|
|
||||||
## Technical Notes
|
- [ ] **Task 2: Create Database Migrations** (AC: 3, 7, 9, 10)
|
||||||
|
- [ ] Modify existing `users` migration to add: user_type, full_name, national_id, company_name, company_cert_number, contact_person_name, contact_person_id, phone, status, preferred_language, two_factor fields
|
||||||
|
- [ ] Create `consultations` migration with: user_id (FK), booking_date, booking_time, problem_summary, consultation_type, payment_amount, payment_status, status, admin_notes
|
||||||
|
- [ ] Create `timelines` migration with: user_id (FK), case_name, case_reference (unique nullable), status
|
||||||
|
- [ ] Create `timeline_updates` migration with: timeline_id (FK), admin_id (FK), update_text
|
||||||
|
- [ ] Create `posts` migration with: title (JSON), body (JSON), status, published_at
|
||||||
|
- [ ] Create `working_hours` migration with: day_of_week, start_time, end_time, is_active
|
||||||
|
- [ ] Create `blocked_times` migration with: block_date, start_time (nullable), end_time (nullable), reason
|
||||||
|
- [ ] Create `notifications` migration with: user_id (FK), type, data (JSON), read_at, sent_at
|
||||||
|
- [ ] Create `admin_logs` migration with: admin_id (FK), action, target_type, target_id, old_values (JSON), new_values (JSON), ip_address
|
||||||
|
- [ ] Add indexes: users.email (unique), consultations.booking_date, consultations.user_id, timelines.user_id, posts.status
|
||||||
|
|
||||||
- **Database:** Use SQLite for development (configurable for MariaDB in production)
|
- [ ] **Task 3: Create Eloquent Models** (AC: 3, 4)
|
||||||
- **Environment:** Set `DB_CONNECTION=sqlite` in `.env` for development
|
- [ ] Update `app/Models/User.php` with relationships, casts, scopes, and helper methods
|
||||||
- **Reference:** PRD Section 16.1 for complete schema details
|
- [ ] Create `app/Models/Consultation.php` with user relationship and enum casts
|
||||||
- **Pattern:** Follow existing Volt class-based component pattern
|
- [ ] Create `app/Models/Timeline.php` with user relationship and updates relationship
|
||||||
- **Structure:** Use Laravel 12 streamlined file structure (no app/Http/Middleware, bootstrap/app.php for config)
|
- [ ] Create `app/Models/TimelineUpdate.php` with timeline and admin relationships
|
||||||
- **Testing:** Use Pest 4 for all tests (`php artisan make:test --pest`)
|
- [ ] Create `app/Models/Post.php` with JSON casts for bilingual fields
|
||||||
- **Models:** Create with `php artisan make:model ModelName -mf` (migration + factory)
|
- [ ] Create `app/Models/WorkingHour.php`
|
||||||
- **Notifications table:** Custom implementation per PRD schema (not Laravel's built-in notifications)
|
- [ ] Create `app/Models/BlockedTime.php`
|
||||||
|
- [ ] Create `app/Models/Notification.php` with user relationship and JSON data cast
|
||||||
|
- [ ] Create `app/Models/AdminLog.php` with admin relationship and JSON casts
|
||||||
|
|
||||||
### Database Schema Reference
|
- [ ] **Task 4: Create Model Factories** (AC: 4, 8)
|
||||||
|
- [ ] Update `database/factories/UserFactory.php` with states: admin(), individual(), company(), client()
|
||||||
|
- [ ] Create `database/factories/ConsultationFactory.php`
|
||||||
|
- [ ] Create `database/factories/TimelineFactory.php`
|
||||||
|
- [ ] Create `database/factories/TimelineUpdateFactory.php`
|
||||||
|
- [ ] Create `database/factories/PostFactory.php` with bilingual fake data
|
||||||
|
- [ ] Create `database/factories/WorkingHourFactory.php` with weekdays() state
|
||||||
|
- [ ] Create `database/factories/BlockedTimeFactory.php`
|
||||||
|
- [ ] Create `database/factories/NotificationFactory.php`
|
||||||
|
- [ ] Create `database/factories/AdminLogFactory.php`
|
||||||
|
|
||||||
|
- [ ] **Task 5: Write Tests** (AC: 7, 8)
|
||||||
|
- [ ] Create `tests/Unit/Models/UserTest.php` - test enum validation, relationships
|
||||||
|
- [ ] Create `tests/Unit/Models/ConsultationTest.php` - test enum validation, relationships
|
||||||
|
- [ ] Create `tests/Unit/Models/TimelineTest.php` - test relationships
|
||||||
|
- [ ] Create `tests/Unit/Enums/` tests for all enums
|
||||||
|
- [ ] Create `tests/Feature/Database/MigrationTest.php` - test migrate:fresh and rollback
|
||||||
|
- [ ] Create `tests/Feature/Database/FactoryTest.php` - test all factories create valid models
|
||||||
|
|
||||||
|
- [ ] **Task 6: Verify Development Environment** (AC: 5, 6)
|
||||||
|
- [ ] Ensure `composer run dev` starts without errors
|
||||||
|
- [ ] Verify SQLite database is created and migrations run
|
||||||
|
- [ ] Run `php artisan migrate:fresh` successfully
|
||||||
|
- [ ] Run `vendor/bin/pint` to format code
|
||||||
|
|
||||||
|
## Dev Notes
|
||||||
|
|
||||||
|
### Relevant Source Tree
|
||||||
|
```
|
||||||
|
app/
|
||||||
|
├── Enums/ # PHP 8.1+ backed enums
|
||||||
|
│ ├── UserType.php
|
||||||
|
│ ├── UserStatus.php
|
||||||
|
│ ├── ConsultationType.php
|
||||||
|
│ ├── ConsultationStatus.php
|
||||||
|
│ ├── PaymentStatus.php
|
||||||
|
│ ├── TimelineStatus.php
|
||||||
|
│ └── PostStatus.php
|
||||||
|
├── Models/
|
||||||
|
│ ├── User.php # Existing - needs modification
|
||||||
|
│ ├── Consultation.php
|
||||||
|
│ ├── Timeline.php
|
||||||
|
│ ├── TimelineUpdate.php
|
||||||
|
│ ├── Post.php
|
||||||
|
│ ├── WorkingHour.php
|
||||||
|
│ ├── BlockedTime.php
|
||||||
|
│ ├── Notification.php
|
||||||
|
│ └── AdminLog.php
|
||||||
|
database/
|
||||||
|
├── factories/
|
||||||
|
│ ├── UserFactory.php # Existing - needs modification
|
||||||
|
│ ├── ConsultationFactory.php
|
||||||
|
│ ├── TimelineFactory.php
|
||||||
|
│ ├── TimelineUpdateFactory.php
|
||||||
|
│ ├── PostFactory.php
|
||||||
|
│ ├── WorkingHourFactory.php
|
||||||
|
│ ├── BlockedTimeFactory.php
|
||||||
|
│ ├── NotificationFactory.php
|
||||||
|
│ └── AdminLogFactory.php
|
||||||
|
├── migrations/
|
||||||
|
│ ├── 0001_01_01_000000_create_users_table.php # Existing - needs modification
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_consultations_table.php
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_timelines_table.php
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_timeline_updates_table.php
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_posts_table.php
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_working_hours_table.php
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_blocked_times_table.php
|
||||||
|
│ ├── YYYY_MM_DD_HHMMSS_create_notifications_table.php
|
||||||
|
│ └── YYYY_MM_DD_HHMMSS_create_admin_logs_table.php
|
||||||
|
tests/
|
||||||
|
├── Unit/
|
||||||
|
│ ├── Models/
|
||||||
|
│ └── Enums/
|
||||||
|
└── Feature/
|
||||||
|
└── Database/
|
||||||
```
|
```
|
||||||
users:
|
|
||||||
- id, name, email, password, user_type (enum: admin/individual/company)
|
|
||||||
- national_id (nullable), company_name (nullable), company_registration (nullable)
|
|
||||||
- phone, preferred_language (enum: ar/en), status (enum: active/deactivated)
|
|
||||||
- timestamps, email_verified_at
|
|
||||||
|
|
||||||
consultations:
|
### Database Schema (Aligned with Architecture)
|
||||||
- id, user_id, scheduled_date, scheduled_time, duration (default 45)
|
|
||||||
- status (enum: pending/approved/completed/cancelled/no_show)
|
|
||||||
- type (enum: free/paid), payment_amount (nullable), payment_status
|
|
||||||
- problem_summary, admin_notes, timestamps
|
|
||||||
|
|
||||||
timelines:
|
**users** (modify existing migration):
|
||||||
- id, user_id, case_name, case_reference (unique nullable)
|
```
|
||||||
- status (enum: active/archived), timestamps
|
- id (bigint, PK)
|
||||||
|
- user_type (enum: admin|individual|company)
|
||||||
|
- full_name (string)
|
||||||
|
- national_id (string, nullable, encrypted)
|
||||||
|
- company_name (string, nullable)
|
||||||
|
- company_cert_number (string, nullable)
|
||||||
|
- contact_person_name (string, nullable)
|
||||||
|
- contact_person_id (string, nullable)
|
||||||
|
- email (string, unique)
|
||||||
|
- phone (string)
|
||||||
|
- password (string, hashed)
|
||||||
|
- status (enum: active|deactivated, default: active)
|
||||||
|
- preferred_language (string: ar|en, default: ar)
|
||||||
|
- email_verified_at (timestamp, nullable)
|
||||||
|
- two_factor_secret (text, nullable)
|
||||||
|
- two_factor_recovery_codes (text, nullable)
|
||||||
|
- two_factor_confirmed_at (timestamp, nullable)
|
||||||
|
- remember_token (string, nullable)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
```
|
||||||
|
|
||||||
timeline_updates:
|
**consultations**:
|
||||||
- id, timeline_id, admin_id, update_text, timestamps
|
```
|
||||||
|
- id (bigint, PK)
|
||||||
|
- user_id (bigint, FK -> users.id, cascade delete)
|
||||||
|
- booking_date (date)
|
||||||
|
- booking_time (time)
|
||||||
|
- problem_summary (text)
|
||||||
|
- consultation_type (enum: free|paid)
|
||||||
|
- payment_amount (decimal 10,2, nullable)
|
||||||
|
- payment_status (enum: pending|received|na, default: na)
|
||||||
|
- status (enum: pending|approved|rejected|completed|no_show|cancelled, default: pending)
|
||||||
|
- admin_notes (text, nullable)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
INDEX: booking_date, user_id
|
||||||
|
```
|
||||||
|
|
||||||
posts:
|
**timelines**:
|
||||||
- id, title_ar, title_en, body_ar, body_en
|
```
|
||||||
- status (enum: draft/published), timestamps
|
- id (bigint, PK)
|
||||||
|
- user_id (bigint, FK -> users.id, cascade delete)
|
||||||
|
- case_name (string)
|
||||||
|
- case_reference (string, nullable, unique)
|
||||||
|
- status (enum: active|archived, default: active)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
INDEX: user_id
|
||||||
|
```
|
||||||
|
|
||||||
working_hours:
|
**timeline_updates**:
|
||||||
- id, day_of_week (0-6), start_time, end_time, is_active, timestamps
|
```
|
||||||
|
- id (bigint, PK)
|
||||||
|
- timeline_id (bigint, FK -> timelines.id, cascade delete)
|
||||||
|
- admin_id (bigint, FK -> users.id, cascade delete)
|
||||||
|
- update_text (text)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
```
|
||||||
|
|
||||||
blocked_times:
|
**posts**:
|
||||||
- id, block_date, start_time (nullable), end_time (nullable)
|
```
|
||||||
- reason, timestamps
|
- id (bigint, PK)
|
||||||
|
- title (json) - {"ar": "...", "en": "..."}
|
||||||
|
- body (json) - {"ar": "...", "en": "..."}
|
||||||
|
- status (enum: draft|published, default: draft)
|
||||||
|
- published_at (timestamp, nullable)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
INDEX: status
|
||||||
|
```
|
||||||
|
|
||||||
admin_logs:
|
**working_hours**:
|
||||||
- id, admin_id, action_type, target_type, target_id
|
```
|
||||||
- old_values (json), new_values (json), ip_address, timestamps
|
- id (bigint, PK)
|
||||||
|
- day_of_week (tinyint, 0-6, Sunday=0)
|
||||||
|
- start_time (time)
|
||||||
|
- end_time (time)
|
||||||
|
- is_active (boolean, default: true)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
```
|
||||||
|
|
||||||
|
**blocked_times**:
|
||||||
|
```
|
||||||
|
- id (bigint, PK)
|
||||||
|
- block_date (date)
|
||||||
|
- start_time (time, nullable) - null means full day
|
||||||
|
- end_time (time, nullable) - null means full day
|
||||||
|
- reason (string, nullable)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
```
|
||||||
|
|
||||||
|
**notifications** (custom, NOT Laravel's built-in):
|
||||||
|
```
|
||||||
|
- id (bigint, PK)
|
||||||
|
- user_id (bigint, FK -> users.id, cascade delete)
|
||||||
|
- type (string)
|
||||||
|
- data (json)
|
||||||
|
- read_at (timestamp, nullable)
|
||||||
|
- sent_at (timestamp, nullable)
|
||||||
|
- created_at, updated_at (timestamps)
|
||||||
|
```
|
||||||
|
|
||||||
|
**admin_logs**:
|
||||||
|
```
|
||||||
|
- id (bigint, PK)
|
||||||
|
- admin_id (bigint, FK -> users.id, cascade delete)
|
||||||
|
- action (string)
|
||||||
|
- target_type (string)
|
||||||
|
- target_id (bigint, nullable)
|
||||||
|
- old_values (json, nullable)
|
||||||
|
- new_values (json, nullable)
|
||||||
|
- ip_address (string)
|
||||||
|
- created_at (timestamp)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Foreign Key Constraints
|
||||||
|
| Column | References | On Delete |
|
||||||
|
|--------|------------|-----------|
|
||||||
|
| consultations.user_id | users.id | CASCADE |
|
||||||
|
| timelines.user_id | users.id | CASCADE |
|
||||||
|
| timeline_updates.timeline_id | timelines.id | CASCADE |
|
||||||
|
| timeline_updates.admin_id | users.id | CASCADE |
|
||||||
|
| notifications.user_id | users.id | CASCADE |
|
||||||
|
| admin_logs.admin_id | users.id | CASCADE |
|
||||||
|
|
||||||
|
### Enum Definitions (from Architecture Section 4)
|
||||||
|
|
||||||
|
```php
|
||||||
|
// app/Enums/UserType.php
|
||||||
|
enum UserType: string {
|
||||||
|
case Admin = 'admin';
|
||||||
|
case Individual = 'individual';
|
||||||
|
case Company = 'company';
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/Enums/UserStatus.php
|
||||||
|
enum UserStatus: string {
|
||||||
|
case Active = 'active';
|
||||||
|
case Deactivated = 'deactivated';
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/Enums/ConsultationType.php
|
||||||
|
enum ConsultationType: string {
|
||||||
|
case Free = 'free';
|
||||||
|
case Paid = 'paid';
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/Enums/ConsultationStatus.php
|
||||||
|
enum ConsultationStatus: string {
|
||||||
|
case Pending = 'pending';
|
||||||
|
case Approved = 'approved';
|
||||||
|
case Rejected = 'rejected';
|
||||||
|
case Completed = 'completed';
|
||||||
|
case NoShow = 'no_show';
|
||||||
|
case Cancelled = 'cancelled';
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/Enums/PaymentStatus.php
|
||||||
|
enum PaymentStatus: string {
|
||||||
|
case Pending = 'pending';
|
||||||
|
case Received = 'received';
|
||||||
|
case NotApplicable = 'na';
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/Enums/TimelineStatus.php
|
||||||
|
enum TimelineStatus: string {
|
||||||
|
case Active = 'active';
|
||||||
|
case Archived = 'archived';
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/Enums/PostStatus.php
|
||||||
|
enum PostStatus: string {
|
||||||
|
case Draft = 'draft';
|
||||||
|
case Published = 'published';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Technical Standards
|
||||||
|
- **Database:** SQLite for development (`DB_CONNECTION=sqlite`)
|
||||||
|
- **Pattern:** Class-based Volt components
|
||||||
|
- **Structure:** Laravel 12 streamlined (no app/Http/Middleware, use bootstrap/app.php)
|
||||||
|
- **Models:** Create with `php artisan make:model ModelName -mf`
|
||||||
|
- **Enums:** Use PHP 8.1+ backed enums with string values
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
**Test Location:** `tests/Unit/` and `tests/Feature/Database/`
|
||||||
|
|
||||||
|
**Testing Framework:** Pest 4
|
||||||
|
- Create tests with: `php artisan make:test TestName --pest`
|
||||||
|
- Run tests with: `php artisan test`
|
||||||
|
|
||||||
|
**Required Tests:**
|
||||||
|
1. Migration tests - verify `migrate:fresh` and `migrate:rollback` work
|
||||||
|
2. Factory tests - verify each factory creates valid models
|
||||||
|
3. Enum validation tests - verify models reject invalid enum values
|
||||||
|
4. Relationship tests - verify foreign keys and Eloquent relationships work
|
||||||
|
5. JSON field tests - verify JSON columns store/retrieve correctly
|
||||||
|
|
||||||
|
**Test Patterns:**
|
||||||
|
```php
|
||||||
|
// Example factory test
|
||||||
|
test('consultation factory creates valid consultation', function () {
|
||||||
|
$consultation = Consultation::factory()->create();
|
||||||
|
|
||||||
|
expect($consultation)->toBeInstanceOf(Consultation::class)
|
||||||
|
->and($consultation->user)->toBeInstanceOf(User::class)
|
||||||
|
->and($consultation->status)->toBeInstanceOf(ConsultationStatus::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Example enum test
|
||||||
|
test('user type only accepts valid values', function () {
|
||||||
|
expect(UserType::cases())->toHaveCount(3)
|
||||||
|
->and(UserType::Admin->value)->toBe('admin')
|
||||||
|
->and(UserType::Individual->value)->toBe('individual')
|
||||||
|
->and(UserType::Company->value)->toBe('company');
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## Definition of Done
|
## Definition of Done
|
||||||
|
|
||||||
- [ ] All database migrations created and tested
|
- [ ] All database migrations created and run without errors
|
||||||
- [ ] All model factories functional
|
- [ ] All model factories functional and generate valid data
|
||||||
|
- [ ] All Eloquent models have proper relationships and casts
|
||||||
|
- [ ] All PHP enums created with correct values
|
||||||
- [ ] Development environment runs with `composer run dev`
|
- [ ] Development environment runs with `composer run dev`
|
||||||
- [ ] Tests pass for model creation using factories
|
- [ ] Tests pass for all models, factories, and enums
|
||||||
- [ ] Code formatted with Pint
|
- [ ] Code formatted with `vendor/bin/pint`
|
||||||
- [ ] No errors on fresh install
|
- [ ] No errors on fresh install (`php artisan migrate:fresh`)
|
||||||
|
|
||||||
## Test Scenarios
|
|
||||||
|
|
||||||
All tests should use Pest 4 (`php artisan make:test --pest`).
|
|
||||||
|
|
||||||
### Migration Tests
|
|
||||||
- [ ] All migrations run successfully: `php artisan migrate:fresh`
|
|
||||||
- [ ] Migrations can rollback without errors: `php artisan migrate:rollback`
|
|
||||||
- [ ] Foreign key constraints are properly created (timeline_updates.timeline_id, timeline_updates.admin_id, consultations.user_id, timelines.user_id, admin_logs.admin_id)
|
|
||||||
|
|
||||||
### Factory Tests
|
|
||||||
- [ ] UserFactory creates valid User with all user_type enum values (admin, individual, company)
|
|
||||||
- [ ] ConsultationFactory creates valid Consultation with proper user relationship
|
|
||||||
- [ ] TimelineFactory creates valid Timeline with proper user relationship
|
|
||||||
- [ ] TimelineUpdateFactory creates valid TimelineUpdate with timeline and admin relationships
|
|
||||||
- [ ] PostFactory creates valid Post with bilingual fields
|
|
||||||
- [ ] WorkingHoursFactory creates valid WorkingHours for each day_of_week (0-6)
|
|
||||||
- [ ] BlockedTimeFactory creates valid BlockedTime entries
|
|
||||||
- [ ] NotificationFactory creates valid Notification entries
|
|
||||||
- [ ] AdminLogFactory creates valid AdminLog with JSON fields
|
|
||||||
|
|
||||||
### Enum Validation Tests
|
|
||||||
- [ ] User.user_type only accepts: admin, individual, company
|
|
||||||
- [ ] User.status only accepts: active, deactivated
|
|
||||||
- [ ] User.preferred_language only accepts: ar, en
|
|
||||||
- [ ] Consultation.status only accepts: pending, approved, completed, cancelled, no_show
|
|
||||||
- [ ] Consultation.type only accepts: free, paid
|
|
||||||
- [ ] Timeline.status only accepts: active, archived
|
|
||||||
- [ ] Post.status only accepts: draft, published
|
|
||||||
|
|
||||||
### Edge Case Tests
|
|
||||||
- [ ] Nullable fields accept null values (national_id, company_name, case_reference, etc.)
|
|
||||||
- [ ] JSON fields (old_values, new_values) store and retrieve correctly
|
|
||||||
- [ ] Unique constraint on case_reference allows multiple nulls but no duplicate values
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
|
@ -144,17 +381,22 @@ All tests should use Pest 4 (`php artisan make:test --pest`).
|
||||||
|
|
||||||
## Risk Assessment
|
## Risk Assessment
|
||||||
|
|
||||||
- **Primary Risk:** Schema design changes required later
|
| Risk | Impact | Likelihood | Mitigation |
|
||||||
- **Mitigation:** Follow PRD specifications closely, validate with stakeholder
|
|------|--------|------------|------------|
|
||||||
- **Rollback:** Fresh migration reset possible in development
|
| Schema design changes required later | Medium | Low | Follow architecture document closely |
|
||||||
|
| Migration order issues (FK constraints) | Low | Medium | Create migrations in dependency order |
|
||||||
|
| Enum value mismatches | Low | Low | Use architecture document as source of truth |
|
||||||
|
|
||||||
### Error Handling
|
### Error Handling
|
||||||
|
|
||||||
- **Migration failures:** Run `php artisan migrate:status` to identify failed migrations, fix the issue, then `php artisan migrate` to continue
|
- **Migration failures:** Run `php artisan migrate:status` to identify failed migrations
|
||||||
- **Foreign key errors:** Ensure referenced tables are created before dependent tables (migrations run in filename order)
|
- **Foreign key errors:** Ensure referenced tables are created before dependent tables (users before consultations, timelines before timeline_updates)
|
||||||
- **Factory errors:** Ensure factories define all required (non-nullable) fields and use valid enum values
|
- **Factory errors:** Ensure factories define all required (non-nullable) fields and use valid enum values
|
||||||
|
- **Rollback:** Use `php artisan migrate:fresh` to reset in development
|
||||||
|
|
||||||
## Estimation
|
## Change Log
|
||||||
|
|
||||||
**Complexity:** Medium
|
| Date | Version | Description | Author |
|
||||||
**Estimated Effort:** 4-6 hours
|
|------|---------|-------------|--------|
|
||||||
|
| Dec 21, 2025 | 1.0 | Initial story draft | SM Agent |
|
||||||
|
| Dec 21, 2025 | 1.1 | Fixed schema alignment with architecture (booking_date/time), added Tasks/Subtasks, added Dev Notes with source tree and enums, added Change Log | Validation Task |
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue