Files
L-Ami-Fiduciaire/database/seeders/DatabaseSeeder.php
Saad Ibn-Ezzoubayr 35545c2a8f feat: L'Ami Fiduciaire V1.0.0 — full codebase with Story 0.1 complete
Initial commit of the L'Ami Fiduciaire SaaS platform built on Laravel 12,
Vue 3, Inertia.js 2, and Tailwind CSS 4.

Story 0.1 (rename folders to declarations in database) is implemented and
code-reviewed: migration, rollback, and 6 Pest tests all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:33:10 +00:00

201 lines
13 KiB
PHP

<?php
namespace Database\Seeders;
use App\Enums\ClientStatus;
use App\Enums\FolderPriority;
use App\Enums\FolderStatus;
use App\Enums\FolderType;
use App\Enums\LegalForm;
use App\Enums\UserGroup;
use App\Enums\WorkspaceUserRole;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Folder;
use App\Models\User;
use App\Models\Workspace;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database with realistic Moroccan data.
*/
public function run(): void
{
// --- Users (firm employees) ---
$admin = User::factory()->create([
'name' => 'Saad El Amrani',
'email' => 'saad@amifiduciaire.ma',
'password' => bcrypt('password'),
'group' => UserGroup::Superadmin,
]);
$fatima = User::factory()->create([
'name' => 'Fatima Bennis',
'email' => 'fatima@amifiduciaire.ma',
'password' => bcrypt('password'),
'group' => UserGroup::Admin,
]);
$youssef = User::factory()->create([
'name' => 'Youssef Tazi',
'email' => 'youssef@amifiduciaire.ma',
'password' => bcrypt('password'),
'group' => UserGroup::User,
]);
$khadija = User::factory()->create([
'name' => 'Khadija Alaoui',
'email' => 'khadija@amifiduciaire.ma',
'password' => bcrypt('password'),
'group' => UserGroup::User,
]);
$omar = User::factory()->create([
'name' => 'Omar Benjelloun',
'email' => 'omar@amifiduciaire.ma',
'password' => bcrypt('password'),
'group' => UserGroup::User,
]);
$users = [$admin, $fatima, $youssef, $khadija, $omar];
// --- Workspaces ---
$wsCasa = Workspace::create(['name' => "L'Ami Fiduciaire — Casablanca", 'slug' => 'ami-casa']);
$wsRabat = Workspace::create(['name' => "L'Ami Fiduciaire — Rabat", 'slug' => 'ami-rabat']);
// Attach users to workspaces
$wsCasa->users()->attach($admin->id, ['role' => WorkspaceUserRole::Owner]);
$wsCasa->users()->attach($fatima->id, ['role' => WorkspaceUserRole::Manager]);
$wsCasa->users()->attach($youssef->id, ['role' => WorkspaceUserRole::Member]);
$wsCasa->users()->attach($khadija->id, ['role' => WorkspaceUserRole::Member]);
$wsRabat->users()->attach($admin->id, ['role' => WorkspaceUserRole::Owner]);
$wsRabat->users()->attach($omar->id, ['role' => WorkspaceUserRole::Manager]);
// --- Moroccan clients for Casablanca ---
$casaClients = [
['company_name' => 'Atlas Import-Export SARL', 'legal_form' => LegalForm::SARL, 'ice' => '001234567000012', 'fiscal_id' => '12345678', 'rc' => '123456', 'cnss' => '1234567890', 'patente' => '12345678', 'contact_last_name' => 'Bennani', 'contact_first_name' => 'Ahmed', 'contact_job_title' => 'Gérant', 'contact_email' => 'a.bennani@atlasimport.ma', 'contact_phone' => '+212 522 123456'],
['company_name' => 'Maghreb Textile SA', 'legal_form' => LegalForm::SA, 'ice' => '001234567000028', 'fiscal_id' => '23456789', 'rc' => '234567', 'cnss' => '2345678901', 'patente' => '23456789', 'contact_last_name' => 'Chraibi', 'contact_first_name' => 'Nadia', 'contact_job_title' => 'Directrice Générale', 'contact_email' => 'n.chraibi@maghrebtextile.ma', 'contact_phone' => '+212 522 234567'],
['company_name' => 'Dar Al Maalem Construction', 'legal_form' => LegalForm::SARL, 'ice' => '001234567000034', 'fiscal_id' => '34567890', 'rc' => '345678', 'cnss' => '3456789012', 'patente' => '34567890', 'contact_last_name' => 'Fassi Fihri', 'contact_first_name' => 'Karim', 'contact_job_title' => 'Directeur Technique', 'contact_email' => 'k.fassifihri@daralmaalem.ma', 'contact_phone' => '+212 522 345678'],
['company_name' => 'Souss Agro-Alimentaire', 'legal_form' => LegalForm::SA, 'ice' => '001234567000040', 'fiscal_id' => '45678901', 'rc' => '456789', 'cnss' => '4567890123', 'patente' => '45678901', 'contact_last_name' => 'Ouazzani', 'contact_first_name' => 'Rachid', 'contact_job_title' => 'PDG', 'contact_email' => 'r.ouazzani@soussagro.ma', 'contact_phone' => '+212 528 456789'],
['company_name' => 'Marrakech Digital Solutions', 'legal_form' => LegalForm::SARL, 'ice' => '001234567000056', 'fiscal_id' => '56789012', 'rc' => '567890', 'cnss' => '5678901234', 'patente' => '56789012', 'contact_last_name' => 'El Idrissi', 'contact_first_name' => 'Salma', 'contact_job_title' => 'Gérante', 'contact_email' => 's.elidrissi@mkdigital.ma', 'contact_phone' => '+212 524 567890'],
['company_name' => 'Boulangerie Fès El Bali', 'legal_form' => LegalForm::AutoEntrepreneur, 'ice' => '001234567000062', 'fiscal_id' => '67890123', 'rc' => '678901', 'cnss' => '6789012345', 'patente' => '67890123', 'contact_last_name' => 'Amrani', 'contact_first_name' => 'Hassan', 'contact_job_title' => 'Propriétaire', 'contact_email' => 'h.amrani@boulangeriefes.ma', 'contact_phone' => '+212 535 678901'],
['company_name' => 'Pharmacie Anfa', 'legal_form' => LegalForm::SEL, 'ice' => '001234567000078', 'fiscal_id' => '78901234', 'rc' => '789012', 'cnss' => '7890123456', 'patente' => '78901234', 'contact_last_name' => 'Berrada', 'contact_first_name' => 'Laila', 'contact_job_title' => 'Pharmacienne', 'contact_email' => 'l.berrada@pharmacieanfa.ma', 'contact_phone' => '+212 522 789012'],
['company_name' => 'Transport Rif Express', 'legal_form' => LegalForm::SARL, 'ice' => '001234567000084', 'fiscal_id' => '89012345', 'rc' => '890123', 'cnss' => '8901234567', 'patente' => '89012345', 'contact_last_name' => 'Kettani', 'contact_first_name' => 'Mehdi', 'contact_job_title' => 'Gérant', 'contact_email' => 'm.kettani@rifexpress.ma', 'contact_phone' => '+212 539 890123'],
['company_name' => 'Cabinet Juridique El Mansour', 'legal_form' => LegalForm::SNC, 'ice' => '001234567000090', 'fiscal_id' => '90123456', 'rc' => '901234', 'cnss' => '9012345678', 'patente' => '90123456', 'contact_last_name' => 'El Mansouri', 'contact_first_name' => 'Zineb', 'contact_job_title' => 'Avocate Associée', 'contact_email' => 'z.elmansouri@cabinetmansour.ma', 'contact_phone' => '+212 522 901234'],
['company_name' => 'Hôtel Riad Zitoun', 'legal_form' => LegalForm::SARL, 'ice' => '001234567000103', 'fiscal_id' => '01234567', 'rc' => '012345', 'cnss' => '0123456789', 'patente' => '01234567', 'contact_last_name' => 'Skalli', 'contact_first_name' => 'Younes', 'contact_job_title' => 'Directeur', 'contact_email' => 'y.skalli@riadzitoun.ma', 'contact_phone' => '+212 524 012345'],
];
$responsibles = [$youssef, $khadija, $fatima];
$createdCasaClients = [];
foreach ($casaClients as $i => $data) {
$data['workspace_id'] = $wsCasa->id;
$data['internal_responsible_id'] = $responsibles[$i % count($responsibles)]->id;
$data['status'] = $i < 8 ? ClientStatus::Active : ClientStatus::Inactive;
$client = Client::create($data);
ClientContact::create([
'client_id' => $client->id,
'full_name' => $data['contact_first_name'] . ' ' . $data['contact_last_name'],
'job_title' => $data['contact_job_title'],
'email' => $data['contact_email'],
'phone' => $data['contact_phone'],
'is_principal' => true,
]);
$createdCasaClients[] = $client;
}
// --- Moroccan clients for Rabat ---
$rabatClients = [
['company_name' => 'Bureau d\'Études Oualili', 'legal_form' => LegalForm::SARL, 'ice' => '002345678000011', 'fiscal_id' => '11223344', 'rc' => '112233', 'cnss' => '1122334455', 'patente' => '11223344', 'contact_last_name' => 'Meknassi', 'contact_first_name' => 'Amine', 'contact_job_title' => 'Ingénieur Principal', 'contact_email' => 'a.meknassi@oualili.ma', 'contact_phone' => '+212 537 112233'],
['company_name' => 'Imprimerie Chellah', 'legal_form' => LegalForm::EURL, 'ice' => '002345678000027', 'fiscal_id' => '22334455', 'rc' => '223344', 'cnss' => '2233445566', 'patente' => '22334455', 'contact_last_name' => 'Zniber', 'contact_first_name' => 'Samira', 'contact_job_title' => 'Directrice', 'contact_email' => 's.zniber@imprimeriechellah.ma', 'contact_phone' => '+212 537 223344'],
['company_name' => 'Café Oudaya SARL', 'legal_form' => LegalForm::SARL, 'ice' => '002345678000033', 'fiscal_id' => '33445566', 'rc' => '334455', 'cnss' => '3344556677', 'patente' => '33445566', 'contact_last_name' => 'Belhaj', 'contact_first_name' => 'Mouad', 'contact_job_title' => 'Gérant', 'contact_email' => 'm.belhaj@cafeoudaya.ma', 'contact_phone' => '+212 537 334455'],
['company_name' => 'Clinique Agdal Santé', 'legal_form' => LegalForm::SA, 'ice' => '002345678000049', 'fiscal_id' => '44556677', 'rc' => '445566', 'cnss' => '4455667788', 'patente' => '44556677', 'contact_last_name' => 'Guessous', 'contact_first_name' => 'Hind', 'contact_job_title' => 'Administratrice', 'contact_email' => 'h.guessous@cliniqueagdal.ma', 'contact_phone' => '+212 537 445566'],
['company_name' => 'Pâtisserie Yasmina', 'legal_form' => LegalForm::EntrepriseIndividuelle, 'ice' => '002345678000055', 'fiscal_id' => '55667788', 'rc' => '556677', 'cnss' => '5566778899', 'patente' => '55667788', 'contact_last_name' => 'Tahiri', 'contact_first_name' => 'Yasmina', 'contact_job_title' => 'Propriétaire', 'contact_email' => 'y.tahiri@patisserieyasmina.ma', 'contact_phone' => '+212 537 556677'],
];
foreach ($rabatClients as $data) {
$data['workspace_id'] = $wsRabat->id;
$data['internal_responsible_id'] = $omar->id;
$data['status'] = ClientStatus::Active;
$client = Client::create($data);
ClientContact::create([
'client_id' => $client->id,
'full_name' => $data['contact_first_name'] . ' ' . $data['contact_last_name'],
'job_title' => $data['contact_job_title'],
'email' => $data['contact_email'],
'phone' => $data['contact_phone'],
'is_principal' => true,
]);
}
// --- Folders (dossiers) for Casablanca clients ---
$folderTypes = [
['type' => FolderType::VatMonthly, 'label' => 'TVA mensuelle'],
['type' => FolderType::VatQuarterly, 'label' => 'TVA trimestrielle'],
['type' => FolderType::CorporateTax, 'label' => 'IS'],
['type' => FolderType::IncomeTax, 'label' => 'IR'],
['type' => FolderType::CNSS, 'label' => 'CNSS'],
['type' => FolderType::AnnualBalance, 'label' => 'Bilan annuel'],
];
$statuses = [
FolderStatus::Draft,
FolderStatus::WaitingDocuments,
FolderStatus::DocumentsReceived,
FolderStatus::Processing,
FolderStatus::WaitingClientValidation,
FolderStatus::Validated,
FolderStatus::Closed,
];
$priorities = [FolderPriority::Low, FolderPriority::Medium, FolderPriority::High];
$folderIndex = 0;
foreach ($createdCasaClients as $client) {
// Each client gets 2-4 folders
$numFolders = fake()->numberBetween(2, 4);
$selectedTypes = fake()->randomElements($folderTypes, $numFolders);
foreach ($selectedTypes as $ft) {
$year = fake()->randomElement([2025, 2026]);
$status = $statuses[$folderIndex % count($statuses)];
$isVatMonthly = $ft['type'] === FolderType::VatMonthly;
$isVatQuarterly = $ft['type'] === FolderType::VatQuarterly;
$month = $isVatMonthly ? fake()->numberBetween(1, 3) : null;
$quarter = $isVatQuarterly ? fake()->numberBetween(1, 4) : null;
$periodSuffix = $isVatMonthly ? " — Mois $month" : ($isVatQuarterly ? " — T$quarter" : '');
Folder::create([
'workspace_id' => $wsCasa->id,
'client_id' => $client->id,
'created_by' => $responsibles[$folderIndex % count($responsibles)]->id,
'title' => "Déclaration {$ft['label']} $year{$periodSuffix}",
'type' => $ft['type'],
'period_year' => $year,
'period_month' => $month,
'period_quarter' => $quarter,
'due_date' => fake()->dateTimeBetween('2026-01-01', '2026-06-30'),
'status' => $status,
'priority' => $priorities[$folderIndex % count($priorities)],
'assigned_to' => $responsibles[$folderIndex % count($responsibles)]->id,
'notes_internal' => fake()->optional(0.4)->randomElement([
'En attente des relevés bancaires.',
'Client à relancer pour les factures manquantes.',
'Dossier prioritaire — échéance proche.',
'Documents reçus partiellement.',
'Vérification en cours avec la DGI.',
]),
]);
$folderIndex++;
}
}
}
}