libra/docs/stories/story-15.1-database-model.md

6.6 KiB

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

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

namespace App\Enums;

enum PotentialClientType: string
{
    case Individual = 'individual';
    case Company = 'company';
    case Agency = 'agency';

    public function label(): string
    {
        return match($this) {
            self::Individual => __('potential-clients.types.individual'),
            self::Company => __('potential-clients.types.company'),
            self::Agency => __('potential-clients.types.agency'),
        };
    }
}

Model Implementation

<?php

namespace App\Models;

use App\Enums\PotentialClientType;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PotentialClient extends Model
{
    use HasFactory;

    protected $fillable = [
        'type',
        'name',
        'phone',
        'email',
        'address',
        'social_media',
        'website',
        'notes',
    ];

    protected function casts(): array
    {
        return [
            'type' => PotentialClientType::class,
        ];
    }
}

Factory Implementation

<?php

namespace Database\Factories;

use App\Enums\PotentialClientType;
use App\Models\PotentialClient;
use Illuminate\Database\Eloquent\Factories\Factory;

class PotentialClientFactory extends Factory
{
    protected $model = PotentialClient::class;

    public function definition(): array
    {
        return [
            'type' => 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

// 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

  • Create migration file with proper schema
  • Run migration successfully
  • Create PotentialClientType enum with label() method
  • Create PotentialClient model with fillable and casts
  • Create factory with all state methods
  • Create English translations
  • Create Arabic translations
  • Write model unit tests
  • Verify factory generates valid data

Estimation

Complexity: Low Risk: Low - Standard model/migration setup

Dependencies

  • None (foundation for other stories in this epic)