1. 24 Jul, 2026 2 commits
    • Mahmoud Aglan's avatar
      Fix website builder audit issues — missing $sections + forbidden href=# · a26be026
      Mahmoud Aglan authored
      - PublicEventController: pass $sections to views (navbar/footer crash without it)
      - Navbar: replace href="#" with href="#section-hero" (forbidden pattern)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a26be026
    • Mahmoud Aglan's avatar
      Add Events/Tournaments system — full vertical slice · 44c8d8aa
      Mahmoud Aglan authored
      Complete events module with admin CRUD, public registration, and management:
      - Migrations: events, event_registrations, media collections, permissions
      - Domain: Event/Enums (5), Models (2), Services (EventService, EventRegistrationService)
      - Admin: EventList, CreateEventWizard (4-step with form builder), EventShow, EventRegistrationList
      - Public: event listing + detail pages under /site/{slug}/events with Livewire registration form
      - Form builder: button-based add/remove/reorder fields stored as JSONB
      - Registration: dynamic validation from form_fields, person matching, registration numbers
      - Admin registrations: dynamic columns, bulk confirm/cancel, CSV export
      - Livewire scripts added to website layout for public forms
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      44c8d8aa
  2. 22 Jul, 2026 11 commits
  3. 20 Jul, 2026 3 commits
    • Mahmoud Aglan's avatar
      Fix schedule builder grid — support grid/lanes/zones layout types · 1b16cf85
      Mahmoud Aglan authored
      The grid was blank because lanes and zones segments have null row_index/col_index.
      The old code assumed all layouts were grid-type and collapsed to 0×0.
      
      - Grid layouts: keep the spreadsheet-style row/col selector view
      - Lanes layouts: render as horizontal strips (label + cell side by side)
      - Zones/custom layouts: responsive card grid (no row/col concept)
      
      Layout type is now read from Facility::activeLayout (new HasOne relationship)
      with a null-safe fallback to row_index detection. Segment cell HTML extracted
      to _segment-cell.blade.php partial to avoid triplication.
      Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
      1b16cf85
    • Mahmoud Aglan's avatar
      Fix facilities route ordering — static segments must precede {facility} wildcard · abd15a9b
      Mahmoud Aglan authored
      /facilities/space-assignment and /facilities/schedule-builder were registered
      after /facilities/{facility}, so Laravel matched the wildcard first and tried
      to resolve the literal slugs as UUIDs, crashing with invalid uuid syntax.
      Static routes are now declared before the wildcard.
      Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
      abd15a9b
    • Mahmoud Aglan's avatar
      Add installment collection breakdown to product analytics · 8bf5451e
      Mahmoud Aglan authored
      Adds محصّل vs إجمالي الإيرادات with a progress bar and remaining balance.
      Collection is computed as a pro-rata share of invoice.paid_amount based on
      the product line's fraction of the invoice total — so mixed invoices
      (product + program) correctly attribute only the product's share of each
      payment. Price overrides are excluded from the product's line because they
      always land on the program item, leaving the product total_amount intact.
      Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
      8bf5451e
  4. 19 Jul, 2026 3 commits
  5. 17 Jul, 2026 4 commits
  6. 16 Jul, 2026 15 commits
    • Mahmoud Aglan's avatar
      Remove client-specific import seeder from repo · 97d3b159
      Mahmoud Aglan authored
      This file contained OC Sport-specific data and does not belong in the
      shared multi-tenant codebase.
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      97d3b159
    • Mahmoud Aglan's avatar
      Add JulyPlayersImportSeeder for OC-Sport legacy player data · 069533c5
      Mahmoud Aglan authored
      Imports Team (99) and Academy (93) players from HTML sheet one at a time
      using existing services (InvoiceService, PaymentService). Creates Person →
      Participant → Enrollment → Invoice → Payment per player, with installment
      plan attachment for partial القيد payments. Cross-sheet duplicates are
      written to storage/app/july_import_duplicates.json. Idempotent by name.
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      069533c5
    • Mahmoud Aglan's avatar
      Fix varchar(10) overflow on training_groups.code column · 41b7657c
      Mahmoud Aglan authored
      Generated codes like TEAM2001-10 exceed 10 chars when there are 10+ duplicate
      program names within an academy. Widen to varchar(20).
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      41b7657c
    • Mahmoud Aglan's avatar
      Add per-slot explicit installment amounts to product plans · fe016b49
      Mahmoud Aglan authored
      - Migration: add installment_amounts JSONB (nullable) to product_installment_plans
      - ProductInstallmentPlan: new buildSchedule() method — uses explicit piaster amounts per slot where set, auto-calculates remainder evenly for blank slots; downPaymentAmount/regularInstallmentAmount respect slot[0] override
      - ProductForm: syncInstallmentSlots() keeps slot array in sync when count changes; plan rows load/save installment_amounts (stored as piasters, shown as pounds); slot inputs appear under collapsible "تحديد مبلغ كل قسط" toggle per plan row
      - Wizard confirm(): uses buildSchedule() so each Installment row gets its correct explicit or auto-calculated amount
      - Wizard blade breakdown preview: renders individual amounts when slots differ, uniform "N × amount" when all regular slots match
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      fe016b49
    • Mahmoud Aglan's avatar
      Add annual products with dual pricing and installment plans · 7f4dbddd
      Mahmoud Aglan authored
      - New migration: billing_cycle (one_time/annual), member_price, non_member_price on products; product_installment_plans table (per-product, per-tier plan templates)
      - ProductInstallmentPlan model with scopeActive/forTier, downPaymentAmount/regularInstallmentAmount helpers
      - Product model: priceForTier(), isAnnual(), installmentPlans() relationship
      - ProductForm: annual billing section with member/non-member dual prices and installment plan builder (add/remove rows, upsert on save)
      - Registration wizard: essentialProducts() and hotbuyResults() now return billing_cycle and plans[]; addHotbuyItem() carries plans into cart; setHotbuyPlan() selects a plan per cart item; confirm() generates PaymentPlan + Installment rows for annual items with a selected plan
      - Wizard blade: annual cart items show purple "سنوي" badge, plan pills (full payment + per-plan buttons), and installment breakdown preview on selection
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      7f4dbddd
    • Mahmoud Aglan's avatar
      Fix proration settings never saving or taking effect · b9239f68
      Mahmoud Aglan authored
      Two bugs:
      1. save() wrote bare key "allow_proration" but ProrationService reads
         dotted "enrollment.allow_proration" — now always writes "{group}.{key}"
      2. loadAllSettings() tried to read bare keys but DB had dotted keys from
         seeder — now strips group prefix on read so UI always sees bare keys
      
      Result: toggle saves correctly, ProrationService reads the live value,
      mid-month enrollment now shows prorated fee (e.g. day 16 = 15/30 × fee).
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      b9239f68
    • Mahmoud Aglan's avatar
      Fix null metadata crash on invoice_items insert · 160e9785
      Mahmoud Aglan authored
      JSONB column has NOT NULL constraint — pass empty array instead of null
      when no price override metadata exists.
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      160e9785
    • Mahmoud Aglan's avatar
      Add guardian profession and workplace to registration wizard and participant view · a979f30b
      Mahmoud Aglan authored
      Fields already existed on the guardians table (occupation, workplace) but
      had no UI. Now:
      - Registration wizard step 2 shows المهنة + جهة العمل fields (optional)
      - Saved to Guardian on create; updates existing guardian if already found
      - Pre-populated when selecting an existing guardian via search
      - Participant show → أولياء الأمور tab adds المهنة / جهة العمل column
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      a979f30b
    • Mahmoud Aglan's avatar
      Expose proration settings in /settings/system → التسجيل tab · 85319db6
      Mahmoud Aglan authored
      Add allow_proration (boolean) and renewal_day (number, 1-28) to the
      enrollment settings schema with descriptive hints so admins can find and
      toggle partial monthly payment from the UI.
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      85319db6
    • Mahmoud Aglan's avatar
      Add essential products: quick-buttons in wizard, delivery tracking, admin price override on invoice · 9df1341d
      Mahmoud Aglan authored
      - Add is_essential boolean to products (migration + model + form toggle)
      - Essential products appear as quick-add buttons in registration wizard step 5 (no search needed), highlighted when added to cart
      - New EssentialDeliveries page (/inventory/essential-deliveries): lists all players who bought essential products, mark استلم/لم يستلم per item with who delivered and when
      - Delivery tracking: add is_delivered, delivered_at, delivered_by to invoice_items; hotbuy cart items now store itemable_type/id for proper morph link
      - Admin price override now stored in invoice item metadata (original_price, overridden_price, override_reason) and displayed on invoice print with crossed-out original price
      - "أساسي" badge on product list; "تسليم الأساسيات" button on product list header and sidebar
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      9df1341d
    • Mahmoud Aglan's avatar
      Expand wizard payment step: all 7 methods, partial, split, transaction refs · c6327cf7
      Mahmoud Aglan authored
      Payment modes:
      - Full (default): pays entire invoice amount
      - Partial: enter amount paid now, remainder stays as balance due on invoice
      - Split: two methods, amount1 + calculated remainder, both recorded as payments
      
      All 7 PaymentMethod values now available:
      - cash: no extra fields
      - card: transaction_reference (required)
      - bank_transfer: transaction_reference (required), bank_name (optional)
      - online (Instapay/digital wallets): transaction_reference (required)
      - wallet (club wallet): deducts from member balance
      - cheque: cheque_number (required), bank_name (optional)
      - other: notes field
      
      Each payment recorded with gateway_data JSON (ref, cheque_number, bank_name)
      Enrollment payment_status only set to 'paid' when full amount covered
      Validation rules built dynamically from active mode + method combination
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      c6327cf7
    • Mahmoud Aglan's avatar
      Unify receipt/invoice settings: 3-tab template system + fix seeder · 2be39175
      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: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      2be39175
    • Mahmoud Aglan's avatar
      Fix log permission: touch and chown laravel.log in entrypoint · 20284ee2
      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: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      20284ee2
    • Mahmoud Aglan's avatar
    • Mahmoud Aglan's avatar
      Add phone-or-email login, Egyptian NID decoder, proration engine, and receptionist wizard overhaul · 0504e7d1
      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: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      0504e7d1
  7. 11 Jul, 2026 2 commits