Commit 2717165c authored by Mahmoud Aglan's avatar Mahmoud Aglan

Pre-reset backup: seeder, .claude docs, arabic data file

parent e891ce11
# July Import Issues — OC Sport
Imported: 2026-07-17
---
# Live Data Snapshot — oc-sport.caprover.al-arcade.com
Captured: 2026-07-17
## Products (2)
| ID | الاسم | billing_cycle | is_essential | selling_price | member_price | non_member_price |
|----|-------|---------------|--------------|---------------|--------------|-----------------|
| 1 | شنطة ملابس كرة القدم | one_time | yes | 1,200 ج.م | — | — |
| 2 | قيد اشتراك فريق اتحاد الكرة | annual | yes | 8,000 ج.م | 6,000 ج.م | 8,000 ج.م |
## Installment Plans (2) — both on product_id=2
| ID | label_ar | membership_tier | installments | frequency | installment_amounts (ج.م) |
|----|----------|-----------------|--------------|-----------|--------------------------|
| 1 | تقسيط ثلاث اشهر للاعضاء | member | 3 | monthly | 2,000 + 2,000 + 2,000 |
| 2 | تقسيط ثلاث اشهر غير الاعضاء | non_member | 3 | monthly | 2,500 + 2,500 + 3,000 |
## Training Programs (22) — all active
| ID | name_ar |
|----|---------|
| 1 | اكاديمية (2011-2008) |
| 2 | اكاديمية 2014 |
| 3 | اكاديمية 2008-2011 |
| 4 | اكاديمية 2012-2013 |
| 5 | اكاديمية اطفال 2021-2022 |
| 6 | اكاديمية تجهيزي 2019 |
| 7 | اكاديمية اطفال 2020 |
| 8 | اكاديمية 2017-2018 |
| 9 | اكاديمية 2015 |
| 10 | اكاديمية 2016 |
| 11 | الرديف من 2007 إلى 2009 |
| 12 | فريق اول قسم رابع |
| 13 | فريق 2010 |
| 14 | فريق 2011/2012 |
| 15 | فريق 2013 |
| 16 | فريق 2014 |
| 17 | فريق 2015 |
| 18 | فريق 2016 |
| 19 | فريق 2017 |
| 20 | فريق 2018 |
| 21 | فريق 2019 |
| 24 | فريق 2020 |
## Training Groups (21) — all active
| ID | training_program_id | name_ar |
|----|---------------------|---------|
| 1 | 2 | مجموعة اكاديمية 2014 1 |
| 2 | 3 | مجموعة اكاديمية 2008-2011 1 |
| 3 | 4 | مجموعة اكاديمية 2012-2013 1 |
| 4 | 5 | مجموعة اكاديمية اطفال 2021-2022 1 |
| 5 | 6 | مجموعة اكاديمية تجهيزي 2019 1 |
| 6 | 7 | مجموعة اكاديمية اطفال 2020 1 |
| 7 | 8 | مجموعة اكاديمية 2017-2018 1 |
| 8 | 9 | مجموعة اكاديمية 2015 1 |
| 9 | 10 | مجموعة اكاديمية 2016 1 |
| 10 | 11 | مجموعة فريق2014 1 |
| 11 | 12 | مجموعة فريق 2008-2011 1 |
| 12 | 13 | مجموعة فريق 2010 1 |
| 13 | 14 | مجموعة فريق 2011/2012 1 |
| 14 | 15 | مجموعة فريق 2013 1 |
| 15 | 16 | مجموعة فريق 2014 1 |
| 16 | 17 | مجموعة فريق 2015 1 |
| 17 | 18 | مجموعة فريق 2016 1 |
| 18 | 19 | مجموعة فريق 2017 1 |
| 19 | 20 | مجموعة فريق 2018 1 |
| 20 | 21 | مجموعة فريق 2019 1 |
| 21 | 24 | مجموعة فريق 2020 1 |
## Notes
- Program ID=1 (اكاديمية 2011-2008) has NO group yet
- Program IDs are not sequential (gap at 22, 23 — deleted or skipped)
- Both products are essential and appear as quick-buttons in the registration wizard
- Product #2 (annual) has 2 installment plans with explicit per-slot amounts stored in piasters
<?php
namespace Database\Seeders;
use App\Domain\Attendance\Enums\AttendanceStatus;
use App\Domain\Attendance\Models\AttendanceRecord;
use App\Domain\Identity\Models\Branch;
use App\Domain\Identity\Models\Person;
use App\Domain\Identity\Models\Role;
use App\Domain\Participant\Models\Participant;
use App\Domain\Scheduling\Models\Assignment;
use App\Domain\Shared\Models\Academy;
use App\Domain\Training\Models\Activity;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use App\Domain\Training\Models\TrainingSession;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
/**
* Seeds a complete trainer + groups + today's sessions + participants + attendance records.
*
* Trainer login: trainer@demo.com / Demo1234#
*
* Idempotent — safe to re-run.
*/
class TrainerAttendanceDemoSeeder extends Seeder
{
public function run(): void
{
$academy = Academy::first();
if (!$academy) {
$this->command->error('No academy found — run DatabaseSeeder first.');
return;
}
app()->instance('current_academy', $academy);
$admin = User::where('academy_id', $academy->id)
->where('is_super_admin', true)
->first()
?? User::where('academy_id', $academy->id)->first();
if (!$admin) {
$this->command->error('No admin user found — run DatabaseSeeder first.');
return;
}
$branch = $this->ensureBranch($academy, $admin);
$activity = $this->ensureActivity($academy, $admin);
$program = $this->ensureProgram($academy, $branch, $activity, $admin);
$trainer = $this->ensureTrainerUser($academy, $branch, $admin);
[$youth, $junior] = $this->ensureGroups($academy, $branch, $program, $trainer, $admin);
$this->ensureAssignment($academy, $trainer, $youth, $admin);
$this->ensureAssignment($academy, $trainer, $junior, $admin);
$this->ensureParticipants($academy, $branch, $activity, $admin, $youth, $junior);
$this->ensureTodaysSessions($academy, $trainer, $youth, $junior);
$this->command->info('');
$this->command->info('╔═══════════════════════════════════════════════════╗');
$this->command->info('║ Trainer Demo Seed — DONE ║');
$this->command->info('╠═══════════════════════════════════════════════════╣');
$this->command->info('║ Login : trainer@demo.com ║');
$this->command->info('║ Pass : Demo1234# ║');
$this->command->info('║ Branch : ' . str_pad($branch->name, 41) . '║');
$this->command->info('║ Groups : شباب المدرسين + ناشئين المدرسين ║');
$this->command->info('║ Go to : /trainer then click a session ║');
$this->command->info('╚═══════════════════════════════════════════════════╝');
}
// ─── Branch ───────────────────────────────────────────────────────────────
private function ensureBranch(Academy $academy, User $admin): Branch
{
return Branch::where('academy_id', $academy->id)->first()
?? Branch::create([
'academy_id' => $academy->id,
'name' => 'Main Branch',
'name_ar' => 'الفرع الرئيسي',
'code' => 'MAIN',
'is_main' => true,
'is_active' => true,
]);
}
// ─── Activity ─────────────────────────────────────────────────────────────
private function ensureActivity(Academy $academy, User $admin): Activity
{
return Activity::firstOrCreate(
['academy_id' => $academy->id, 'slug' => 'football'],
[
'academy_id' => $academy->id,
'name' => 'Football',
'name_ar' => 'كرة القدم',
'slug' => 'football',
'is_active' => true,
'sort_order' => 1,
]
);
}
// ─── Program ──────────────────────────────────────────────────────────────
private function ensureProgram(Academy $academy, Branch $branch, Activity $activity, User $admin): TrainingProgram
{
return TrainingProgram::firstOrCreate(
['academy_id' => $academy->id, 'slug' => 'football-youth-demo'],
[
'academy_id' => $academy->id,
'activity_id' => $activity->id,
'branch_id' => $branch->id,
'name' => 'Football Youth Program',
'name_ar' => 'برنامج كرة القدم للشباب',
'slug' => 'football-youth-demo',
'sessions_per_week' => 3,
'session_duration_minutes' => 90,
'total_sessions' => 48,
'program_duration_weeks' => 16,
'min_participants' => 5,
'max_participants' => 20,
'allow_waitlist' => true,
'registration_open' => true,
'status' => 'active',
'created_by' => $admin->id,
]
);
}
// ─── Trainer User ─────────────────────────────────────────────────────────
private function ensureTrainerUser(Academy $academy, Branch $branch, User $admin): User
{
$trainerRole = Role::where('academy_id', $academy->id)
->where('slug', 'trainer')
->first();
$trainer = User::firstOrCreate(
['email' => 'trainer@demo.com'],
[
'academy_id' => $academy->id,
'name' => 'Ahmed Demo Trainer',
'name_ar' => 'أحمد المدرب التجريبي',
'email' => 'trainer@demo.com',
'password' => Hash::make('Demo1234#'),
'status' => 'active',
'role_id' => $trainerRole?->id,
]
);
if (!$trainer->person_id) {
$person = Person::firstOrCreate(
['academy_id' => $academy->id, 'phone' => '01000000001'],
[
'academy_id' => $academy->id,
'name' => 'Ahmed Demo Trainer',
'name_ar' => 'أحمد المدرب التجريبي',
'email' => 'trainer@demo.com',
'phone' => '01000000001',
'gender' => 'male',
'created_by' => $admin->id,
]
);
$trainer->update(['person_id' => $person->id]);
}
if ($trainerRole) {
$linked = DB::table('role_user')
->where('user_id', $trainer->id)
->where('role_id', $trainerRole->id)
->exists();
if (!$linked) {
DB::table('role_user')->insert([
'user_id' => $trainer->id,
'role_id' => $trainerRole->id,
'branch_id' => $branch->id,
'created_at' => now(),
]);
}
}
return $trainer;
}
// ─── Groups ───────────────────────────────────────────────────────────────
private function ensureGroups(Academy $academy, Branch $branch, TrainingProgram $program, User $trainer, User $admin): array
{
$shared = [
'academy_id' => $academy->id,
'training_program_id' => $program->id,
'branch_id' => $branch->id,
'head_trainer_id' => $trainer->id,
'max_capacity' => 15,
'current_count' => 4,
'waitlist_count' => 0,
'season' => '2025-2026',
'start_date' => now()->startOfMonth()->toDateString(),
'end_date' => now()->addMonths(4)->toDateString(),
'status' => 'active',
'created_by' => $admin->id,
];
$youth = TrainingGroup::firstOrCreate(
['academy_id' => $academy->id, 'code' => 'DEMO-YOUTH'],
$shared + ['name' => 'Youth Demo Group', 'name_ar' => 'شباب المدرسين', 'code' => 'DEMO-YOUTH']
);
$junior = TrainingGroup::firstOrCreate(
['academy_id' => $academy->id, 'code' => 'DEMO-JNR'],
$shared + ['name' => 'Junior Demo Group', 'name_ar' => 'ناشئين المدرسين', 'code' => 'DEMO-JNR']
);
return [$youth, $junior];
}
// ─── Assignment ───────────────────────────────────────────────────────────
private function ensureAssignment(Academy $academy, User $trainer, TrainingGroup $group, User $admin): void
{
$exists = Assignment::where('academy_id', $academy->id)
->where('user_id', $trainer->id)
->where('assignable_type', TrainingGroup::class)
->where('assignable_id', $group->id)
->where('status', 'active')
->exists();
if ($exists) {
return;
}
Assignment::create([
'academy_id' => $academy->id,
'user_id' => $trainer->id,
'assignable_type' => TrainingGroup::class,
'assignable_id' => $group->id,
'role_label' => 'head trainer',
'scope' => 'full',
'status' => 'active',
'is_primary' => true,
'start_date' => now()->startOfMonth()->toDateString(),
'created_by' => $admin->id,
]);
}
// ─── Participants ─────────────────────────────────────────────────────────
private function ensureParticipants(Academy $academy, Branch $branch, Activity $activity, User $admin, TrainingGroup ...$groups): void
{
$byGroup = [
[
['name' => 'Mohamed Sayed', 'name_ar' => 'محمد سيد', 'phone' => '01011111101', 'dob' => '2008-03-15'],
['name' => 'Omar Hassan', 'name_ar' => 'عمر حسن', 'phone' => '01011111102', 'dob' => '2007-07-22'],
['name' => 'Karim Ali', 'name_ar' => 'كريم علي', 'phone' => '01011111103', 'dob' => '2008-11-01'],
['name' => 'Youssef Ibrahim', 'name_ar' => 'يوسف إبراهيم', 'phone' => '01011111104', 'dob' => '2009-01-30'],
],
[
['name' => 'Ahmed Ramadan', 'name_ar' => 'أحمد رمضان', 'phone' => '01011111105', 'dob' => '2011-05-10'],
['name' => 'Hassan Mostafa', 'name_ar' => 'حسن مصطفى', 'phone' => '01011111106', 'dob' => '2010-09-18'],
['name' => 'Amr Khaled', 'name_ar' => 'عمرو خالد', 'phone' => '01011111107', 'dob' => '2011-12-25'],
['name' => 'Ziad Nasser', 'name_ar' => 'زياد ناصر', 'phone' => '01011111108', 'dob' => '2012-02-14'],
],
];
foreach ($groups as $idx => $group) {
$pNum = 1001 + ($idx * 100);
foreach ($byGroup[$idx] as $data) {
$person = Person::firstOrCreate(
['academy_id' => $academy->id, 'phone' => $data['phone']],
[
'academy_id' => $academy->id,
'name' => $data['name'],
'name_ar' => $data['name_ar'],
'phone' => $data['phone'],
'date_of_birth' => $data['dob'],
'gender' => 'male',
'created_by' => $admin->id,
]
);
$participant = Participant::firstOrCreate(
['academy_id' => $academy->id, 'person_id' => $person->id],
[
'academy_id' => $academy->id,
'branch_id' => $branch->id,
'person_id' => $person->id,
'participant_number' => 'P-' . $pNum++,
'registration_date' => now()->subMonths(2)->toDateString(),
'primary_activity_id' => $activity->id,
'status' => 'active',
'created_by' => $admin->id,
]
);
Enrollment::firstOrCreate(
[
'academy_id' => $academy->id,
'participant_id' => $participant->id,
'training_group_id' => $group->id,
],
[
'academy_id' => $academy->id,
'participant_id' => $participant->id,
'training_group_id' => $group->id,
'training_program_id' => $group->training_program_id,
'enrollment_date' => now()->subMonths(2)->toDateString(),
'start_date' => now()->subMonths(2)->toDateString(),
'status' => 'active',
'enrolled_by' => $admin->id,
]
);
}
}
}
// ─── Today's Sessions + Attendance Records ────────────────────────────────
private function ensureTodaysSessions(Academy $academy, User $trainer, TrainingGroup $youth, TrainingGroup $junior): void
{
$today = now()->toDateString();
$configs = [
['group' => $youth, 'start' => '09:00:00', 'end' => '10:30:00'],
['group' => $junior, 'start' => '11:00:00', 'end' => '12:30:00'],
];
foreach ($configs as $cfg) {
/** @var TrainingGroup $group */
$group = $cfg['group'];
$session = TrainingSession::firstOrCreate(
[
'academy_id' => $academy->id,
'training_group_id' => $group->id,
'session_date' => $today,
'start_time' => $cfg['start'],
],
[
'academy_id' => $academy->id,
'training_group_id' => $group->id,
'trainer_id' => $trainer->id,
'session_date' => $today,
'start_time' => $cfg['start'],
'end_time' => $cfg['end'],
'session_number' => 1,
'status' => 'scheduled',
'expected_participants' => 4,
]
);
$enrollments = Enrollment::where('academy_id', $academy->id)
->where('training_group_id', $group->id)
->where('status', 'active')
->with('participant')
->get();
foreach ($enrollments as $enrollment) {
$participant = $enrollment->participant;
if (!$participant) {
continue;
}
AttendanceRecord::firstOrCreate(
[
'academy_id' => $academy->id,
'training_session_id' => $session->id,
'subject_type' => Participant::class,
'subject_id' => $participant->id,
],
[
'academy_id' => $academy->id,
'training_session_id' => $session->id,
'subject_type' => Participant::class,
'subject_id' => $participant->id,
'status' => AttendanceStatus::Expected,
'is_auto_generated' => true,
'is_flagged' => false,
]
);
}
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment