- 16 Jul, 2026 4 commits
-
-
Mahmoud Aglan authored
- EnrollmentSettingsSeeder: fix Organization → Academy class name - ReceiptTemplate: add defaultInvoiceFields/Settings + defaultPaymentFields/Settings - ReceiptSettings: rewritten with pos/invoice/payment tabs; each tab loads its own ReceiptTemplate (type='invoice'|'payment') and saves independently - receipt-settings.blade.php: 3-tab UI with field toggles + appearance settings per document type; link to branding page for logo/colors - print/invoice.blade.php: all 15 fields now gated by invoice template flags (logo, academy name, branch, tax number, client details, items table, subtotal, discount, tax, service fee, paid amount, payments history, signature, terms & conditions, footer text) - print/payment-receipt.blade.php: all 11 fields gated by payment template; footer text pulled from template settings instead of hardcoded string Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
CapRover volume remounts can override build-time chown, leaving storage/logs owned by root. Explicitly touch + chown the log file at container start before php-fpm runs. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- AuthService: accepts email or phone for login (identifier-based lookup) - Login UI: updated to text input with Arabic labels - EgyptianNidDecoder: decodes 14-digit NID → birth date, gender, governorate - ProrationResult DTO + ProrationService: mid-month enrollment fee proration (x/30 of remaining days based on configurable renewal day) - EnrollmentSettingsSeeder: seeds enrollment.allow_proration and enrollment.renewal_day per academy - NewRegistrationWizard: rewritten — player-first flow, NID auto-decode locks birth/gender/governorate, foreign player toggle, guardian name deduced from player name, phone-only guardian, super admin price override, proration display - EnrollmentService: applies proration to invoice creation - EnrollExistingWizard: adds proratedProgramFee computed property, review step shows original vs prorated fee - Migration: adds governorate column to people table Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
- 11 Jul, 2026 6 commits
-
-
Mahmoud Aglan authored
Every entity list now has clickable rows that navigate to rich detail pages with KPIs, tabbed content, and related data. New show pages: - TrainerShow: groups, schedule, attendance, financial, qualifications - EmployeeShow: personal info, team hierarchy, documents, timeline - GroupShow: enrollments, schedule, sessions, attendance stats - ProgramShow: groups, enrollments, settings, requirements - FacilityShow: layouts, segments, reservations, schedule - ProductShow: stock levels, movements, analytics Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The old 'inventory.adjustments.wizard' route was removed — now just 'inventory.adjustments'. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The wizard was overengineered for this flow. Programs are created via the existing ProgramForm. Updated dashboard and program-list links. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Stock Count fix: dispatch StockCountCompleted event after completing a count so the ProcessCountAdjustments listener creates inventory movements. Made listener synchronous for immediate feedback. 2. Stock Adjustment: route now points to the existing wizard component instead of the plain form. 3. Purchase Orders: new CreatePurchaseOrderWizard with 4-step flow (supplier → warehouse/dates → items → review & confirm). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The PaymentMethod and PaymentStatus enums were passed directly to __() which expects a string, causing "Cannot access offset of type enum on array". Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Production had no trainers/employees and only 1 branch. Rewrote seeder to be fully self-contained: creates 2 new branches, 19 people, 11 employees, 12 trainers, then populates all HR tables. Cleans up prior data on re-run. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 10 Jul, 2026 10 commits
-
-
Mahmoud Aglan authored
Covers: 11 employees (6 staff + 4 trainer-employees + 1 resigned), all 12 trainers with bios/sports/qualifications/availability, 3 months of compensation history, 2 closed payroll periods with payslips, advances in all states, rate history. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- SKU is NOT NULL in the database but was nullable in wizard validation, causing a crash when submitted without a SKU value - Auto-generate SKU (PRD-0001, SRV-0001, DIG-0001) when not provided - Catch QueryException in both product forms to show friendly error instead of crashing on unique constraint violations Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add explicit $table = 'trainer_compensations' to TrainerCompensation model (Laravel resolved singular 'trainer_compensation' by default) - Wrap TrainerDuesWidget query in try/catch so dashboard loads even if the compensation migration hasn't been run yet Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- InvoiceService::create() now auto-generates number if not provided - Invoice list/show views fall back to billable.person.name_ar when contact_name is null (matches print view behavior) - Fix participant link to use model route binding (uuid) not raw ID - CSV export no longer restricts to current month by default — exports all invoices matching the active filters (status, search) - CreateInvoiceWizard falls back to participantName for contact_name Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
InvoiceService::create() was not setting issue_date or due_date, causing a NOT NULL violation on the invoices table when the POS checkout flow creates an invoice without explicitly passing dates. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-
Mahmoud Aglan authored
- Add cascading filters across all list pages (activity→program→group, program→trainer, direction→movement type) - Make sidebar sections collapsible with auto-expand on active page - Route all "Create" buttons to wizards instead of plain forms - Fix low stock count mismatch between dashboard and product list Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-
Mahmoud Aglan authored
Instances no longer hold WhatsApp API credentials. They send messages via the el-captain-manager messaging hub API using MESSAGING_HUB_URL and MESSAGING_HUB_KEY env vars. The hub handles Meta Graph API calls, rate limiting, and delivery tracking centrally. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Root cause: format_money() was used in 20+ views but never defined, causing silent fatal errors on every print attempt. Also simplified ReceiptController to render standalone HTML pages instead of depending on ReceiptTemplate records that may not exist in the DB. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 09 Jul, 2026 13 commits
-
-
Mahmoud Aglan authored
Cast config values to string with null-coalescing fallback, and add empty-string defaults to env() calls so instances without WhatsApp configured still boot without TypeError. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The demo_academy DB doesn't have organizations/users tables with those exact names. Use plain indexed columns instead. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- WhatsAppService: send text, template, image, document messages - Bulk send to groups/status/custom selections - Message log with status tracking (sent/delivered/read/failed) - Three Livewire pages: Send Message, Send Template, Message Log - Migration for whatsapp_messages table - Added 'whatsapp' channel to NotificationChannel enum - Wired into NotificationService for automated notifications - Sidebar section "واتساب" with 3 items - Config via WHATSAPP_PHONE_NUMBER_ID + WHATSAPP_ACCESS_TOKEN env vars Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Auto-seed default sections on first visit when none exist - Every section now shows skeleton placeholders when empty (branches, partners, pricing, trainers, stats, schedule) - Converted remaining dark sections to light theme (branches, trainers, pricing, contact, schedule) for consistency - Stats band keeps dark bg for visual contrast - Fresh deploy = beautiful skeleton website ready for client to imagine Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Fixes Route [inventory.purchase-orders.create] not defined error by adding the missing routes and creating PurchaseOrderForm + PurchaseOrderShow Livewire components with full Arabic UI. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Default background: white, text: dark gray, accent: blue - Hero/navbar/footer stay dark (branded primary color) - All sections show skeleton placeholder cards when no data exists - Removed all hard-coded oklch dark values from section views - Cards, testimonials, FAQ items now use white bg + subtle borders - Empty states show shimmer animation + "لم تُضف ... بعد" message Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Use null-coalescing for age_from/age_to/duration_months (columns don't exist yet) - Handle __PHP_Incomplete_Class from stale cache by re-fetching on type mismatch - Add cache:clear to deploy entrypoint to prevent stale cache after rebuilds Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Livewire's ExtendedCompilerEngine misparses @if inside <script> tags. Replaced inline Blade conditionals with @php block + json_encode. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Route / now serves academy public website (no auth required) - Dashboard moved to /dashboard - Login/Dashboard button added to website navbar (desktop + mobile) - Added "الموقع الإلكتروني" section to sidebar with all 9 CMS pages - Added missing inventory items (POs, Kits, Stock Counts) to sidebar - Configured explicit middleware redirects for guest/auth flows Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add branch_id accessor to User model (resolves from role_user pivot) - Create AppliesRoleScope trait for one-liner scope enforcement - Enhance PermissionService: include head_trainer_id in group lookup, add training_programs and invoices table support for own_groups scope - Apply AppliesRoleScope to 16 list components: ParticipantList, GroupList, EnrollmentList, AttendanceList, InvoiceList, ProgramList, EvaluationList, CashSessionList, WalletList, AssignmentList, PersonList, FacilityList, ProductList, PurchaseOrderList, KitList, StockCountList Now trainers only see their assigned groups/participants, branch managers only see their branch data, parents only see their children, and receptionists are branch-scoped. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Detect on mount if user already has Trainer/Employee/Guardian records - Show green notice when record exists, amber warning when role implies record but none exists (orphan state) - Allow entity creation on save even without role change when entities are missing (repair orphaned users from before the redesign) - Disable create toggles when record already exists to prevent duplicates Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- CreateTrainerWizard: 9-step flow with activities, user account creation, and initial group assignment (was 6 disconnected steps) - CreateProgramWizard: 7-step flow with head trainer, schedule template, initial group, BasePrice record, facility (was 4 steps, no group/trainer) - NewRegistrationWizard: add parent account creation step so guardians can log in to the Parent Portal immediately - UserForm: role-aware prompts — assigning trainer role creates Trainer+Employee records, parent role links Guardian, staff creates Employee - EnrollmentForm: 3-panel guided experience with group cards, capacity bars, live price preview from PricingService, and schedule conflict detection - TrainerCredentialsGenerated event for async email delivery Closes the "isolated CRUD screens" problem — every entity creation now handles the full business workflow in a single transaction. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 07 Jul, 2026 3 commits
-
-
Mahmoud Aglan authored
- PurchaseOrderList: status filter, receive/cancel actions - KitList + KitForm: CRUD with dynamic components, assemble/disassemble - StockCountList + StockCountForm: warehouse picker, variance display - Register routes for all new inventory components - config/mail.php: add SSL stream options for self-signed cert bypass - Update gap-analysis.md to mark completed items Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Multi-tenant public website system: each academy gets a data-driven advertising site at /site/{slug} with 16 customizable sections, theme editor, gallery, testimonials, FAQ, news, partners, and contact form management. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
4 tiers in EGP: نسبة فقط (Free/12%), المبتدئ (1000/7.5%), المؤسسي (3500/5%), الاحترافي (10000/3.5%). Interactive slider shows total cost based on monthly collections volume, highlights the best-value plan dynamically. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 06 Jul, 2026 1 commit
-
-
Mahmoud Aglan authored
1. User form: add hint that email is used as login username 2. Dashboard low stock widget: only show products below min_stock_level (was showing all) 3. Dashboard attendance widget: link to filtered view showing only sessions without attendance 4. Trainer form: require at least one activity selected (validation + UI) 5. Cross-reference: show activities on trainer list, show trainers on activity cards Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 05 Jul, 2026 3 commits
-
-
Mahmoud Aglan authored
Laravel 13 base Controller has no AuthorizesRequests trait. Use Gate::authorize() facade instead. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Without branch filtering, the collection rate showed global stats even when viewing a specific branch. Now filters invoices by branch via their associated payments. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The revenue query filtered by invoice_items.branch_id which doesn't exist, causing 0 results when a branch is selected. Use payments.branch_id directly since payments already track their branch. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-