1. 26 Jun, 2026 1 commit
    • Mahmoud Aglan's avatar
      feat(waiver): Round 2 UX — comprehensive debt check, children details, payment in target's name · 83f24d7a
      Mahmoud Aglan authored
      - checkDebtsComprehensive() returns per-person breakdown (name, type, debt_type, period, amount)
      - getDependentDetails() calculates age, DOB, age category for children
      - New sendToCashier route creates payment request in TARGET member's name (buyer pays)
      - Detailed receipt breakdown with both member names and per-category fees
      - show.php: per-person debt table, children comparison, status indicators, go-to-payment button
      - create.php: detailed debt display with person labels, children age table
      - Status flow: requested → approved → send to cashier → fee_paid → complete
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      83f24d7a
  2. 23 Jun, 2026 1 commit
  3. 22 Jun, 2026 5 commits
  4. 21 Jun, 2026 3 commits
  5. 19 Jun, 2026 1 commit
    • Mahmoud Aglan's avatar
      Fix waiver duplicate key error + wrong fee calculation + member search name mismatch · 6c3db858
      Mahmoud Aglan authored
      TKT-71: Fixed duplicate entry for membership_number by reversing operation
      order in WaiverProcessor — source member's number is now NULLed BEFORE
      assigning it to target member, preventing unique constraint violation.
      
      TKT-71: Waiver fee now calculated from current pricing_configs value instead
      of the member's stored membership_value (old/historical price).
      
      TKT-69: Member search duplicate check now shows the entity type (spouse/child)
      and the parent member's number, clarifying which person is being shown.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      6c3db858
  6. 17 Jun, 2026 3 commits
    • Mahmoud Aglan's avatar
      Remove child fees from divorce transfer — fees only on new additions post-separation · 42f0ccc6
      Mahmoud Aglan authored
      Per bylaws clarification: children transferred during divorce separation move
      without fees. Age-based fees (15%/20%/25%/30%) apply only when the new
      independent member adds NEW children after the separation is complete.
      
      - Removed child fee calculation from boardApprove flow
      - Children selection is now transfer-only (no fee columns)
      - Updated fee preview JS to exclude child fees
      - Fee breakdown shows "transferred without fees" for moved children
      - Total = percentage_fee + form_fee (570) + annual_subscription only
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      42f0ccc6
    • Mahmoud Aglan's avatar
      Use current membership value from pricing_configs for divorce fee calculation · 94e1f426
      Mahmoud Aglan authored
      Instead of using the stored member.membership_value (which may be outdated),
      the divorce module now fetches the current active price from pricing_configs
      based on the member's branch and qualification at the time of the request.
      
      - Added DivorceFeeCalculator::getCurrentMembershipValue() method
      - Updated boardApprove, show, and create to use current pricing
      - Views now display "قيمة العضوية الحالية" with source indicator
      - Payment breakdown shows which source was used for the calculation
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      94e1f426
    • Mahmoud Aglan's avatar
      Fix divorce fee calculation: add both_working case, restore child <12 to 15%, unify 50% · e64c8865
      Mahmoud Aglan authored
      - Added 'both_working' case type detection via spouse.classification field
        (annual subscription only, 0% separation fee per bylaws)
      - Restored DIVORCE_CHILD_UNDER_12 percentage from 5% back to 15% per bylaws
      - Unified joined_after suggested percentage to 50% regardless of spouse order
      - Updated show.php to display both_working scenario in board panel
      - Updated architecture map with corrected business rules
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      e64c8865
  7. 13 Jun, 2026 9 commits
  8. 12 Jun, 2026 7 commits
    • Mahmoud Aglan's avatar
      Separate dev fee from subscription total: single 35 EGP added at invoice level · e381d4e9
      Mahmoud Aglan authored
      Business rule: مصاريف تنمية is a single flat 35 EGP fee per family per year,
      NOT per person, NOT included in discountable base, added AFTER all calculations.
      
      Changes:
      - Generator: total_amount = base - discount (dev fee stored separately, not in total)
      - Migration: subtracts dev_fee from total_amount for existing unpaid rows
      - payYear(): adds single dev fee on top of subscription+fine totals at payment
      - View: dev fee shown as separate line below the subscription subtotal, before
        the invoice grand total. Table columns simplified (no per-row dev fee column)
      
      Calculation order:
      1. Sum all family subscription bases
      2. Apply year discount (e.g. 50% for 2023/2024) to subscription amounts
      3. Add single 35 EGP dev fee as standalone charge at the end
      4. Add fines (on subscription only, not dev fee)
      = Final invoice total
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      e381d4e9
    • Mahmoud Aglan's avatar
      Implement unified family payment: single button pays entire year · 2d63c655
      Mahmoud Aglan authored
      - New payYear() controller action: processes all unpaid subscriptions for a
        member's financial year in one transaction with a single receipt
      - Route: POST /members/{memberId}/subscriptions/{year}/pay
      - View: replaced per-row pay buttons with a single "سداد اشتراك بالكامل" button
        at the bottom of each year section showing total due
      - Itemized table remains for transparency (shows each person's breakdown)
      - Added discount_amount column to the table display
      - FIFO still enforced: only oldest unpaid year's button is active
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2d63c655
    • Mahmoud Aglan's avatar
      Fix discount calculation: مصاريف تنمية excluded from discountable base · cd3c2724
      Mahmoud Aglan authored
      Business rule: the 35 EGP development fee is a flat non-discountable surcharge
      added AFTER all discounts are applied. Discount applies only to base_amount.
      
      Correct formula: discount = base × pct, total = (base - discount) + dev_fee
      Previous (wrong): discount = (base + dev_fee) × pct
      
      For member 51 (2023/2024): 410×50% = 205 discount, total = 205 + 35 = 240
      (was incorrectly: 445×50% = 222.50, total = 222.50)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      cd3c2724
    • Mahmoud Aglan's avatar
      Apply mandated 50% discount for 2023/2024 subscriptions · 2e65dd2e
      Mahmoud Aglan authored
      - Migration: retroactively applies 50% discount to all unpaid 2023/2024
        subscription rows (discount on gross total = base + dev fee)
      - SubscriptionGenerator: year-specific discount now applied on per-row total
        (base + dev_fee) and stored in discount_amount column, not just on base rate
      
      Business rule: SUBSCRIPTION_YEAR_ADJUSTMENT_2023 mandates 50% reduction on
      the final subscription total for all person types in that fiscal year.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2e65dd2e
    • Mahmoud Aglan's avatar
      Fix cron job: delegate to OverdueFineApplicator, enforce consecutive-year drop rule · fc2128c5
      Mahmoud Aglan authored
      - OverdueFineJob now delegates fine calculation/distribution/drop to
        OverdueFineApplicator::run() which already does proportional distribution
      - Added reinstatement expiry call (12-month window enforcement)
      - Only marks subscriptions overdue when financial_year < current (grace period)
      - SubscriptionCalculator: drop check now verifies 5 CONSECUTIVE unpaid years
        instead of just checking if oldest overdue >= 5 (prevents false drops when
        a member paid middle years)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      fc2128c5
    • Mahmoud Aglan's avatar
      Fix fine distribution: proportionally split across subscription rows per year · 5287a41a
      Mahmoud Aglan authored
      Previously the year-level fine (e.g. 897 EGP) was stamped identically on
      every row in the year, tripling the displayed fine. Now distributes
      proportionally based on each row's total_amount relative to the year total.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      5287a41a
    • Mahmoud Aglan's avatar
      Overhaul subscription display: FIFO enforcement, fine calculations, year grouping · 194da186
      Mahmoud Aglan authored
      - Add FIFO payment validation: must pay oldest year first before newer years
      - Add OverdueFineApplicator::applyForMember() for on-demand fine recalculation
      - Rewrite view with year-grouped sections, fine breakdown panels, totals
      - Add data migration to fix corrupted rows (paid_amount with no payment_id)
      - Show fine calculation details (percentage × base = amount, from rules engine)
      - Disable pay buttons for non-oldest years with Arabic tooltip
      - Summary cards showing total debt, fines, and years overdue
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      194da186
  9. 11 Jun, 2026 2 commits
  10. 10 Jun, 2026 1 commit
    • Mahmoud Aglan's avatar
      Fix membership fee calculations, subscription escalation, and over-25 children freeze · 0dd4abfc
      Mahmoud Aglan authored
      - TemporaryFeeCalculator: resolve current pricing_configs price instead of stored
        membership_value, matching SpouseFeeCalculator and ChildFeeCalculator behaviour
      - SubscriptionGenerator: add per-dependent dedup guards (spouse/child/temporary)
        to prevent duplicate subscription rows on repeated batch runs
      - Phase_89_001 migration: idempotent fix for subscription late-fine escalation rules
        (10/50/100/200/300% over 5 years, correct from the broken seed 100/200/300%)
      - Members show view: add warning banner listing active male children aged 25+ with
        direct freeze button, surfacing the existing freeze route that was never linked
      Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      0dd4abfc
  11. 08 Jun, 2026 1 commit
    • Mahmoud Aglan's avatar
      Fix children age display: compute dynamically from DOB, auto-separate at 25 · 110d7771
      Mahmoud Aglan authored
      - MemberController: SELECT TIMESTAMPDIFF for age_years/age_months in children query
      - children-table.php: compute age from DOB in view (fallback for static column)
      - show.php (member): same dynamic age + add 'separated' status translation
      - show.php (child): compute age from DOB dynamically, fix 25+ threshold check
      - AgeMonitorJob: add daily age recalculation for all children, change auto-freeze
        to auto-separate (status='separated', classification='separated')
      - AutoFreezeService: update processAutoFreeze() to separate instead of just freeze
      - DB fixes: corrected DOBs from NIDs, updated all ages, separated 3 children >= 25
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      110d7771
  12. 07 Jun, 2026 1 commit
    • Mahmoud Aglan's avatar
      Fix transfer fee calculation and remove dev fee from dependents · 7e3ac060
      Mahmoud Aglan authored
      - SeparationFeeCalculator: handle NULL qualification_id with fallback
        pricing lookup, use actual membership_type instead of hardcoded 'working'
      - SeparationFeeCalculator companion surcharge: use current pricing_configs
        instead of stale member.membership_value
      - SubscriptionGeneratorJob: set development_fee=0.00 for spouse/child/temp
        (matching SubscriptionGenerator service that was already fixed)
      - RetroactiveMembershipService: default dev fee to 0.00 for non-member types
      - RetroactiveWizardController: same default logic for missing form fields
      - Retroactive wizard JS: generate 0.00 dev fee for dependent subscriptions
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      7e3ac060
  13. 03 Jun, 2026 2 commits
    • Mahmoud Aglan's avatar
      Fix fee calculation: handle NULL qualification_id in pricing lookup · c8353344
      Mahmoud Aglan authored
      Members with qualification_id=NULL (old retroactive entries) were falling
      back to the stored membership_value (e.g. 119,800) instead of using the
      current pricing (150,000). Now when qualification is NULL, we look up the
      minimum price for that branch+type, which gives the correct base value.
      
      Also fixed 26 existing subscription records in live DB: removed dev fee
      (35.00) from spouse/child/temp subscriptions and recalculated totals.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      c8353344
    • Mahmoud Aglan's avatar
      Fix fee calculations: use current pricing, remove dev fee for dependents · 6873f19e
      Mahmoud Aglan authored
      Business rule fixes per ticket #68:
      
      1. Spouse/child fee percentages now use CURRENT membership value from
         pricing_configs (150k/225k/300k) instead of old stored value at creation
      
      2. Spouse annual subscription = 492 (SVC_ANNUAL_SPOUSE) WITHOUT dev fee
         Was incorrectly using child rate (222) + dev fee (35) = 257
      
      3. Child/temp annual subscription = 222 WITHOUT dev fee
         Was incorrectly adding 35 dev fee = 257
      
      4. Late marriage penalty: now calculated from LATER of (marriage_date,
         member_activated_at) to TODAY — not from marriage to member creation
      
      5. SubscriptionGenerator batch: spouse/child/temp subscriptions no longer
         include development_fee (set to 0.00). Only member keeps dev fee.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      6873f19e
  14. 01 Jun, 2026 3 commits
    • Mahmoud Aglan's avatar
      Overhaul coach create form: full validation, NID auto-parse, edge cases · e1f1837a
      Mahmoud Aglan authored
      Frontend:
      - Client-side NID parser (no API call) — extracts DOB, gender, age, governorate
      - Shows green badge with parsed info (governorate, gender, age)
      - Red highlight + Arabic message on every invalid field
      - Validates: code, name, employment_type, payment_model (non-academy),
        academy_id (academy), NID length, email format, phone format
      - Hides payment/rate fields for academy coaches (not needed)
      - Shows note explaining academy coaches follow salary system
      - Gender/DOB auto-locked when NID is valid, manual otherwise
      - Age displayed under DOB field
      
      Backend:
      - Strips non-digits from NID input
      - Uppercase code automatically
      - Checks NID uniqueness against existing coaches
      - Validates email with filter_var
      - Academy coach requires academy_id selected
      - payment_model defaults to 'salary' for academy, 'per_session' fallback
      - max_groups minimum 1
      - Success message includes coach name
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      e1f1837a
    • Mahmoud Aglan's avatar
      Migration: add updated_by/created_by to all 17 tables with autoTrackAuthor · 646d11e6
      Mahmoud Aglan authored
      Tables fixed (already applied to live DB directly):
      reservations, academy_settlements, achievement_definitions,
      activity_subscriptions, facility_grids, facility_monthly_plans,
      facility_zone_schedules, player_evaluations, player_injuries,
      pool_bookings, pool_configurations, pool_schedules,
      sa_player_documents, sa_pricing_rules, tournaments,
      training_groups, training_sessions
      
      Migration is idempotent — checks column existence before ALTER.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      646d11e6
    • Mahmoud Aglan's avatar
      Fix 2 boot failures: reservations.updated_by missing, sa_coaches.payment_model NULL · 299e67a6
      Mahmoud Aglan authored
      - reservations: added updated_by column (model has autoTrackAuthor=true but column didn't exist)
      - sa_coaches: academy coaches now default to payment_model='salary' instead of NULL (NOT NULL column)
      - Also applied column fix directly to live DB via SSH
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      299e67a6