1. 30 Aug, 2026 2 commits
    • Mahmoud Aglan's avatar
      Replace emoji with icons; scope schedule builder by branch and sport · 9454aa03
      Mahmoud Aglan authored
      Icons
      - No emoji anywhere in the UI. Extracted the sidebar's inline SVG map into
        a single <x-ui.icon name="..."> component and added the icons the pricing
        work needed, so there is one source instead of a per-view copy. Discount
        recipes now carry icon NAMES, not glyphs.
      
      Schedule builder
      - Facilities are scoped to the selected branch. The screen listed every
        branch's facilities, which is how someone books the wrong building. A
        ?facility_id= carried over from another branch (bookmark, back button) is
        now dropped instead of silently overriding the branch scope.
      - Groups are scoped to the facility's branch AND to the sports that facility
        hosts, so a football court no longer offers swimming groups. That link did
        not exist, so this adds a facility_activities pivot. A facility that
        declares no activities still hosts anything, so nothing breaks for academies
        that have not filled it in.
      
      Facility grid
      - Removed the arbitrary ceilings (rows/columns capped at 10, lanes at 20).
        Physical space is not limited to a number we picked.
      - New facilities never got a layout, which is why the grid silently failed to
        appear on them. FacilityService::create now seeds one, the migration
        backfills every existing facility that has none, and the default is a 1x1
        grid — "one whole space, not subdivided yet" — rather than inventing a
        subdivision nobody asked for.
      - Grid size is editable straight from facility settings, with a live preview
        of the cells being described. Shrinking onto a segment that holds a
        confirmed future reservation is refused rather than silently dropping
        someone's booking.
      - Sports and starting grid are both settable at creation time too.
      Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
      9454aa03
    • Mahmoud Aglan's avatar
      Fix pricing engine and rebuild discounts around recipes and a picker · b3f127c8
      Mahmoud Aglan authored
      Two bugs meant no pricing rule has ever applied correctly:
      
      1. Condition keys never matched. The engine reads min/max/values;
         the wizard wrote min_age/min_children/target_gender and the form
         blade wrote a third set. Ranges saw null bounds and list rules saw
         an empty allow-list, both of which passed, so every rule applied to
         every participant.
      2. Percentages were 100x too small. applyAdjustment divides by 10000
         (basis points) but both screens stored a plain percent, so "20%"
         discounted 0.2%.
      
      They masked each other, which is why the symptom looked like a broken
      engine rather than two bugs — and why everyone moved to the untyped
      super-admin price override instead.
      
      Engine
      - ConditionSchema is now the single owner of the conditions vocabulary;
        builder, engine, simulator and migration all read keys from it.
      - Percent handles all basis-point conversion; nothing else touches the
        raw column.
      - evaluateInList fails closed instead of treating an empty allow-list
        as "match everyone".
      - custom rules no longer auto-apply; they are picker-only.
      - enrollment_timing honours days_before_start (fails closed without a
        program start date instead of silently passing).
      - Global discount cap reads system_settings rather than a hardcoded
        constant with a TODO.
      - New: explain(), audience(), wouldApply(), and role-capped manual
        discounts.
      
      Per-branch
      - pricing_rule_branches pivot so one rule targets many branches,
        instead of one near-identical row per branch that drifts apart.
      
      Stacking
      - is_stackable now defaults to false; best-of-one is the normal case
        and stacking is an explicit opt-in.
      
      Authoring
      - The five-step column editor becomes a recipe gallery plus an Arabic
        sentence, with a live simulator on a real participant and an audience
        count that warns when a rule would hit everyone. Saving a
        conditionless rule is refused.
      
      Checkout
      - ManagesDiscounts trait plus <x-pricing.discount-picker>: branch-scoped,
        searchable, pinned favourites, replace-vs-stack inline, blocked rows
        show why. Wired into CollectPaymentWizard renewals; discount names are
        frozen onto invoice.metadata so receipts survive later rule changes.
      - NewRegistrationWizard now prices through the engine using a
        provisional context built from the form, since the participant row
        does not exist yet. The step-4 guard still checks the base price, so a
        100% discount is not mistaken for an unpriced program.
      
      Migration
      - Rewrites conditions onto the canonical keys and scales percentages to
        basis points. Rules whose conditions cannot be mapped confidently are
        deactivated rather than guessed, with the old JSON kept in
        metadata.legacy_conditions.
      
      Also fixes list and coupon views that rendered the raw column (a 20%
      rule would have displayed as 2000%), and adds the [x-cloak] CSS rule
      that was missing app-wide.
      Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
      b3f127c8
  2. 27 Aug, 2026 2 commits
  3. 24 Aug, 2026 1 commit
  4. 23 Aug, 2026 7 commits
  5. 22 Aug, 2026 3 commits
  6. 20 Aug, 2026 1 commit
    • Mahmoud Aglan's avatar
      Add group payment/product stats + fix WithSorting trait conflict · 521f6d7b
      Mahmoud Aglan authored
      - Group view: added KPI cards for paid/unpaid/free player counts
      - Group view: added essential product purchase stats with progress bars
      - Group view: added installment info column per player in enrollments tab
      - Fixed PHP 8.2+ trait property conflict: removed $sortBy/$sortDir
        redeclarations from 13 Livewire components that use WithSorting trait,
        moved custom defaults to mount() instead
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      521f6d7b
  7. 19 Aug, 2026 3 commits
  8. 16 Aug, 2026 2 commits
  9. 15 Aug, 2026 1 commit
  10. 13 Aug, 2026 6 commits
    • Mahmoud Aglan's avatar
      Add file attachment to expenses (proof/receipt upload) · e891ce11
      Mahmoud Aglan authored
      - New migration: attachment_path + attachment_name columns on expenses
      - ExpenseForm uses WithFileUploads trait, accepts jpg/png/webp/pdf up to 5MB
      - Drag-drop upload zone in the form with preview of attached file name
      - Files stored in storage/app/public/expenses/
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      e891ce11
    • Mahmoud Aglan's avatar
      Auto-regenerate attendance records when participant reactivated · af0946b7
      Mahmoud Aglan authored
      When a participant goes from suspended/frozen/inactive → active,
      the listener now regenerates expected attendance records for all
      their active enrollments' future sessions.
      
      Previously, reactivated participants were invisible in attendance
      because records were only generated at session creation time.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      af0946b7
    • Mahmoud Aglan's avatar
      Fix POS payment collection + retroactive wizard reliability · 86da35b4
      Mahmoud Aglan authored
      Payment Collection (CollectPaymentWizard):
      - Remove branch filter from participant search (POS sells cross-branch)
      - Include Draft status in outstanding invoice query
      - Add invoice search mode (search by invoice number/contact name)
      - Allow walk-in invoices to be found and paid directly
      - Accept inactive/frozen/registered participants (not just active)
      
      Retroactive Enrollment Wizard:
      - Fix "paid outside system" to use PaymentService (creates proper Payment
        + Transaction records for financial reports)
      - Add server-side validation in confirm() before DB transaction
      - Add national_id duplicate check to prevent duplicate participants
      - Add price=0 guard (show error if no base price and no override)
      - Fix rounding loss: remainder goes to last month's invoice
      - Pass skip_auto_invoice to prevent double invoice creation
      
      POS Partial Payment:
      - Enable allows_partial_payment on all existing products (migration)
        so the deposit/partial payment UI appears at checkout
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      86da35b4
    • Mahmoud Aglan's avatar
      Add financial quick-links: invoices, POS history, expenses list · f1f30cc6
      Mahmoud Aglan authored
      All financial-related pages are now reachable from the Financial Overview
      via quick-action buttons with proper permission gates.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      f1f30cc6
    • Mahmoud Aglan's avatar
      Add sales receipts tab to product detail page · eb96c326
      Mahmoud Aglan authored
      Shows all POS receipts (RCP-*) containing this product with: receipt
      number, customer, total, payment status, method, cashier, date.
      Each receipt has a print link and invoice link for further actions.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      eb96c326
    • Mahmoud Aglan's avatar
      Redesign branch switcher: bold dropdown with pin/lock feature · e3750618
      Mahmoud Aglan authored
      - Prominent button with colored border (amber pulse when unpinned, green when pinned)
      - Dropdown with branch list, selected indicator, and pin status
      - Pin icon shows when branch is locked
      - Selecting a branch auto-pins it (persists across logout/login)
      - Unpin button available to release the lock
      - Visual hint text explains pin behavior
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      e3750618
  11. 10 Aug, 2026 2 commits
  12. 09 Aug, 2026 10 commits