# Story 15.1: Database Schema & Model Setup ## Story **As an** admin **I want to** have a database structure for potential clients **So that** I can store and manage prospective client information ## Acceptance Criteria ### AC1: Database Migration **Given** the system needs to store potential clients **When** the migration runs **Then** a `potential_clients` table is created with: - `id` - bigint, primary key, auto-increment - `type` - varchar, stores potential client type (individual, company, agency) - `name` - varchar(255), nullable - `phone` - varchar(50), nullable - `email` - varchar(255), nullable - `address` - text, nullable - `social_media` - varchar(255), nullable - `website` - varchar(255), nullable - `notes` - text, nullable - `created_at` - timestamp - `updated_at` - timestamp ### AC2: PotentialClientType Enum **Given** potential clients have different types **When** the enum is created **Then** `App\Enums\PotentialClientType` contains: - `Individual` = 'individual' - `Company` = 'company' - `Agency` = 'agency' And includes a `label()` method returning translated labels. ### AC3: PotentialClient Model **Given** the migration exists **When** the model is created **Then** `App\Models\PotentialClient` includes: - Proper `$fillable` array for all fields - Cast `type` to `PotentialClientType` enum - No relationships required (standalone model) ### AC4: Model Factory **Given** tests need potential client data **When** the factory is created **Then** `Database\Factories\PotentialClientFactory` generates: - Random type from enum values - Realistic fake data for all fields - State methods: `individual()`, `company()`, `agency()` ### AC5: Translation Keys **Given** the system is bilingual **When** translations are added **Then** create keys in `lang/en/potential-clients.php` and `lang/ar/potential-clients.php`: - Model name (singular/plural) - Enum type labels - All field labels ## Technical Notes ### Files to Create | File | Purpose | |------|---------| | `database/migrations/xxxx_create_potential_clients_table.php` | Database schema | | `app/Enums/PotentialClientType.php` | Type enum | | `app/Models/PotentialClient.php` | Eloquent model | | `database/factories/PotentialClientFactory.php` | Test factory | | `lang/en/potential-clients.php` | English translations | | `lang/ar/potential-clients.php` | Arabic translations | ### Migration Schema ```php Schema::create('potential_clients', function (Blueprint $table) { $table->id(); $table->string('type'); $table->string('name')->nullable(); $table->string('phone', 50)->nullable(); $table->string('email')->nullable(); $table->text('address')->nullable(); $table->string('social_media')->nullable(); $table->string('website')->nullable(); $table->text('notes')->nullable(); $table->timestamps(); }); ``` ### Enum Implementation ```php __('potential-clients.types.individual'), self::Company => __('potential-clients.types.company'), self::Agency => __('potential-clients.types.agency'), }; } } ``` ### Model Implementation ```php PotentialClientType::class, ]; } } ``` ### Factory Implementation ```php fake()->randomElement(PotentialClientType::cases()), 'name' => fake()->name(), 'phone' => fake()->phoneNumber(), 'email' => fake()->safeEmail(), 'address' => fake()->address(), 'social_media' => fake()->url(), 'website' => fake()->url(), 'notes' => fake()->optional()->sentence(), ]; } public function individual(): static { return $this->state(['type' => PotentialClientType::Individual]); } public function company(): static { return $this->state(['type' => PotentialClientType::Company]); } public function agency(): static { return $this->state(['type' => PotentialClientType::Agency]); } } ``` ### Translation Files ```php // lang/en/potential-clients.php return [ 'title' => 'Potential Clients', 'singular' => 'Potential Client', 'types' => [ 'individual' => 'Individual', 'company' => 'Company', 'agency' => 'Agency', ], 'fields' => [ 'type' => 'Type', 'name' => 'Name', 'phone' => 'Phone', 'email' => 'Email', 'address' => 'Address', 'social_media' => 'Social Media', 'website' => 'Website', 'notes' => 'Notes', ], ]; // lang/ar/potential-clients.php return [ 'title' => 'العملاء المحتملون', 'singular' => 'عميل محتمل', 'types' => [ 'individual' => 'فرد', 'company' => 'شركة', 'agency' => 'وكالة', ], 'fields' => [ 'type' => 'النوع', 'name' => 'الاسم', 'phone' => 'الهاتف', 'email' => 'البريد الإلكتروني', 'address' => 'العنوان', 'social_media' => 'وسائل التواصل', 'website' => 'الموقع الإلكتروني', 'notes' => 'ملاحظات', ], ]; ``` ## Dev Checklist - [x] Create migration file with proper schema - [x] Run migration successfully - [x] Create `PotentialClientType` enum with `label()` method - [x] Create `PotentialClient` model with fillable and casts - [x] Create factory with all state methods - [x] Create English translations - [x] Create Arabic translations - [x] Write model unit tests - [x] Verify factory generates valid data ## Estimation **Complexity:** Low **Risk:** Low - Standard model/migration setup ## Dependencies - None (foundation for other stories in this epic) --- ## Dev Agent Record ### Status Ready for Review ### Agent Model Used Claude Opus 4.5 (claude-opus-4-5-20251101) ### Completion Notes All acceptance criteria met: - AC1: Migration created with all specified fields and proper schema - AC2: PotentialClientType enum with Individual, Company, Agency cases and label() method - AC3: PotentialClient model with fillable array and type casting to enum - AC4: Factory with definition() and state methods (individual(), company(), agency()) - AC5: English and Arabic translation files with all required keys ### File List | File | Action | |------|--------| | `database/migrations/2026_01_09_163956_create_potential_clients_table.php` | Created | | `app/Enums/PotentialClientType.php` | Created | | `app/Models/PotentialClient.php` | Created | | `database/factories/PotentialClientFactory.php` | Created | | `lang/en/potential-clients.php` | Created | | `lang/ar/potential-clients.php` | Created | | `tests/Unit/Models/PotentialClientTest.php` | Created | | `tests/Unit/Enums/PotentialClientTypeTest.php` | Created | ### Change Log - 2026-01-09: Initial implementation of Story 15.1 - Created potential_clients table migration with all specified columns - Created PotentialClientType enum with label() method for bilingual support - Created PotentialClient model with proper fillable and casts - Created factory with realistic data and state methods - Added English and Arabic translations - Added comprehensive unit tests for model and enum (13 tests, 32 assertions)