1. 28 Jul, 2026 16 commits
    • Mahmoud Aglan's avatar
      feat(hr): implement إدارة→قسم→موظف two-level department hierarchy · fc229f20
      Mahmoud Aglan authored
      Adds department_type column (idara/qism) to hr_departments. Idaras are
      top-level administrations; aqsam (sections) belong to an idara via
      parent_id. Employees are assigned to a qism.
      
      Cascading changes across 14 files:
      - Migration adds department_type with CHECK constraint
      - Model: allIdaras(), allAqsam(), getAqsamByIdara() helpers
      - Controller: type-aware CRUD, validation (qism requires parent)
      - Views: cascading إدارة→قسم dropdowns in employee form, type badges
        in department list, grouped optgroups in employee filters
      - Reports: headcount groups by idara
      - Routes: new /hr/departments/{id}/aqsam-json endpoint
      - Bootstrap: updated Arabic labels
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      fc229f20
    • Mahmoud Aglan's avatar
      fix(hr): use correct column references in getComprehensiveSalary query · 982aa243
      Mahmoud Aglan authored
      calculation_type lives on hr_salary_components (sc), not hr_employee_salary_details (sd).
      Also fixed sc.component_type → sc.type to match actual DB schema.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      982aa243
    • Fares's avatar
      fix(migration): use 'float' instead of 'decimal' for system_config config_type · 919975e2
      Fares authored
      The config_type column only accepts: string, integer, float, json.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      919975e2
    • Fares's avatar
      feat(hr): comprehensive 30-point HR module overhaul · 39b96a83
      Fares authored
      - Employee profile: workforce type, fingerprint code, education fields,
        expanded military status (6 values), comprehensive salary display
      - Department staffing: authorized positions per job title, capacity tracking
      - Payroll: martyrs fund, stamp duties, external loan deductions (configurable)
      - Leave: configurable annual days from system_config, unlimited unpaid,
        breastfeeding hour tolerance integrated into attendance tardiness
      - Biometric: device management, punch reception API, attendance integration
      - Insurance Form S2 (wage adjustment notification), contract work receipt
      - Overtime fix: employee_id → employee_profile_id throughout
      - Disciplinary: investigation_result field
      - Loans: financing_company/bank_loan types with external entity fields
      - Documents: validity_status tracking, new types (work_stub, insurance_cert)
      - Label changes: الأجر التأميني, الرقم التأميني, الراتب الشامل
      - All HR permissions seeded to super_admin role
      - Architecture Map and Dependency Graph updated
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      39b96a83
    • Fares's avatar
      fix(payments): split inherited vs own payments in member history · 016b6717
      Fares authored
      For members who received membership via waiver or death transfer, the
      payment history now shows two separate sections:
      - "مدفوعات العضوية الحالية" (current membership payments)
      - "مدفوعات العضوية السابقة (موروثة)" (inherited from previous owner)
      
      The split uses ownership_transfer_date (or activated_at as fallback).
      Also added missing Arabic labels for hourly_booking and early_settlement.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      016b6717
    • Fares's avatar
      fix: comprehensive subscription, transfer, and archive fixes (10 issues) · cfa6456e
      Fares authored
      1. Subscription sync: add refreshForMember() and markCurrentYearPaid()
         to handle post-transfer subscription creation and payment marking.
      2. Event listeners: transfer.completed and death.completed now trigger
         subscription sync for new members and cleanup for source members.
      3. Waiver: stop transferring ALL payments/subscriptions/fines to target.
         Only pending subscriptions, active installments, and unpaid fines move.
         Paid history stays with the archived source member.
      4. Death: createNewSubscriptions() now marks all rows as 'paid' since
         the annual fee is collected as part of the death transfer fee.
      5. Death dependent: remove pending subscription rows when a spouse/child
         dies (not the primary member).
      6. Members: add ownership_transfer_date column (migration + display)
         to record when membership ownership was transferred.
      7. Archive: group subscriptions by financial year with summary totals.
      8. Arabize: archive views (entity_type, snapshot_reason, NULL→فارغ),
         subscription statuses, and payment type labels.
      9. Seasonal: fix duplicate national_id error by checking all members
         (including archived) during validation.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      cfa6456e
    • Fares's avatar
      fix(migration): use correct system_config column names in Phase_100_002 · 8b87f1ea
      Fares authored
      The INSERT was using non-existent columns (config_group, label_ar, field_type).
      The actual table has config_type, group_name, description_ar, is_editable.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      8b87f1ea
    • Fares's avatar
      fix(seasonal): skip 505 EGP form fee for seasonal memberships · 47e980f5
      Fares authored
      Seasonal members don't need the استمارة fee. Set form_fee_paid=true
      in getSeasonalBill() so the member show page skips the form fee
      step entirely and goes straight to seasonal fee payment.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      47e980f5
    • Fares's avatar
      feat(seasonal): require manual seasonal membership number on creation · 5da85db1
      Fares authored
      Seasonal memberships now require a manually entered temporary
      membership number (رقم العضوية الموسمية) instead of using the
      shared auto-increment sequence. The number is validated for
      uniqueness and assigned to the member record immediately, so
      the payment guard won't override it with an auto-generated one.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      5da85db1
    • Fares's avatar
      feat(transfers): manual form_number input for child separation · 76ca34c3
      Fares authored
      Instead of auto-generating form_number at execution time, require
      the user to enter it when creating the separation request. Stored
      in transfer_requests.form_number and used during TransferProcessor
      execution. Falls back to auto-generation if empty.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      76ca34c3
    • Fares's avatar
      fix(sa): fix group auto-creation and old() array conversion errors · 772a86ba
      Fares authored
      - Remove non-existent facility_unit_id from sa_groups insert in
        enrollByCoach, add required code column with auto-generated value
      - Guard schedule copy when no source group exists
      - Fix old() helper usage for array fields (additional_coaches) by
        reading directly from session _old_input instead of old() which
        only returns strings
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      772a86ba
    • Fares's avatar
      feat(sa): redesign player assignment with trainer flow and add game pricing type · 140ee3da
      Fares authored
      Redesign the player assignment page with a 3-step guided workflow
      (Sport → Program → Trainer) supporting both trainer-based and
      program-based assignments. Add multi-coach support for groups via
      sa_group_coaches pivot table. Add per-hour/per-game pricing type
      to recreational games.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      140ee3da
    • Fares's avatar
      fix(migration): make Phase_100_002 idempotent to handle pre-existing columns · 46f03bbf
      Fares authored
      The medical_grace_deadline column already exists in the live DB from a
      prior partial run. Converted to a closure-based migration that checks
      information_schema before altering.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      46f03bbf
    • Fares's avatar
      feat(sa): add player assignment page and recreational games module · 641ec646
      Fares authored
      Player Assignment Page (/sa/assignments):
      - General-purpose assignment flow for all disciplines (not just swimming)
      - Filter by discipline and unassigned status
      - Shows player medical status, type, current groups
      - Assign with capacity check, age validation, force-enroll option
      - Registered in sidebar menu with sa.player.assign permission
      
      Recreational Games (/sa/games):
      - Full CRUD for games with type/fee/duration/facility config
      - Game sessions with open/full/in_progress/completed lifecycle
      - Ticket issuance per session with player name, type, fee tracking
      - Session detail view with ticket list and payment status
      - Migration creates sa_games, sa_game_sessions, sa_game_tickets tables
      - Registered in sidebar with sa.game.view/manage permissions
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      641ec646
    • Fares's avatar
      feat(sa): implement medical level, grace period, booking postponement, and mirror recurrence · 2e5488e5
      Fares authored
      - Medical Level (1-3): added to approval flow, saved to players/sa_players/medical_records,
        displayed on player detail page with color-coded badge
      - Medical Grace Period: configurable days (system_config), set on enrollment when
        medical cert is missing, shown in attendance view, cron auto-suspends expired grace
      - Booking Postponement: new postpone method with max 3 attempts, change history table,
        availability check for new slot, UI form on booking detail page
      - Mirror Recurrence: templates now support daily/weekly/biweekly/monthly/custom patterns,
        expandTemplate respects recurrence_type, wizard UI updated with pattern selector
      - Attendance view: grace period deadline shown instead of generic medical warning
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2e5488e5
    • Fares's avatar
      fix(sa): fix mirror connection error with better error handling · 05172c6e
      Fares authored
      - CSRF token now uses \App\Core\CSRF::token() to ensure it's always
        generated, not raw $_SESSION which could be empty
      - apiPost and loadState now check response.ok before parsing JSON,
        preventing silent failures when server returns 419/500/HTML
      - Error messages now include status code or exception details
      - Added guard for empty SLOTS array (missing operating hours)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      05172c6e
  2. 27 Jul, 2026 5 commits
    • Fares's avatar
      feat(sa): extend facility grid system to all facility types · 26eb4204
      Fares authored
      The zone grid was previously restricted to pool-type facilities only.
      Now any facility can have a grid configured (rows × cols, max 25 each)
      via the create/edit forms. Facilities with grid dimensions get the
      visual grid manager; those without keep the unit-based mirror view.
      
      Changes:
      - Remove facility_type='pool' filter from PoolGridService::getFacility
      - MirrorController routes by grid dimensions instead of facility type
      - Facility create/edit forms now include grid rows/cols fields
      - FacilityController store/update save grid dimensions
      - Facility model fillable updated with grid columns
      - Grid size limit increased from 20 to 25
      - Facility show page adds "الشبكة" button when grid is configured
      - MirrorStateService and SlotAvailabilityService check grid dims
        instead of facility_type for zone booking cross-checks
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      26eb4204
    • Fares's avatar
      fix(sa): improve group player search with status info and treasury button · 858cd3f6
      Fares authored
      - Player search now shows type (member/non-member), medical status, and
        serial number in dropdown results for accurate identification
      - Group player table adds columns for player type and medical status
      - Pending payment players now show a "الخزينة" button linking to cashier
      - Enrollment form stays visible when group is full (uses force-enroll)
      - SearchableSelect prioritizes label field for richer display text
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      858cd3f6
    • Fares's avatar
      fix(swimming): show accurate member/non-member pricing on assignment page · 8d0f495b
      Fares authored
      Display both fee tiers on each group card with the applicable one highlighted
      based on the player's registration type, preventing pricing confusion.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      8d0f495b
    • Fares's avatar
      feat(swimming): add discipline dropdown filter to player assignment page · 2b19960d
      Fares authored
      The assignment page now shows a dropdown to select which sport's programs/groups
      to display. Defaults to Swimming but allows switching to any active discipline.
      Groups are filtered by the selected discipline and show their program names.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2b19960d
    • Fares's avatar
      fix(sa): fix coach dropdown click bug and auto-create group on program creation · 60d769cf
      Fares authored
      1. searchable-select.js: mouseover was calling renderList() which replaced
         innerHTML and destroyed the click target DOM node, making options unclickable.
         Now mouseover only toggles inline styles without re-rendering.
      
      2. ProgramController: auto-creates a default group (code-G1) when a new program
         is created, using the first available coach for that discipline.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      60d769cf
  3. 26 Jul, 2026 5 commits
  4. 23 Jul, 2026 3 commits
  5. 22 Jul, 2026 11 commits