- 22 Jun, 2026 2 commits
-
-
Mahmoud Aglan authored
Reflects new debt verification, excess fee calculation, document uploads, and two-phase dependent validation added in the rewrite. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Full implementation of waiver module per club bylaws: - Debt verification (subscriptions + fines + payment requests) blocks form - Dependent count comparison with excess detection - Board sets excess fee percentage during approval - Document upload support (waiver form + target membership form) - Auto-computed fields (no manual input for existing members) - Enhanced show view with dependent comparison and fee breakdown Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 21 Jun, 2026 3 commits
-
-
Mahmoud Aglan authored
This reverts commit 57e37bea.
-
Mahmoud Aglan authored
Connects to Supabase (source of truth) to query player profiles and send real-time push notifications by inserting into the notifications table. Supports broadcast, demographic-filtered, and individual sends with scheduling, templates, and full campaign history. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Per bylaws requirements for التنازل عن العضوية: 1. Target member's dependents must NOT exceed source member's original dependent count — blocks with error if exceeded, requiring board approval + extra fees before proceeding. 2. All annual subscriptions must be paid (no pending/overdue) before the waiver can be completed. 3. Show view now displays dependent counts and renewal status. 4. Create view updated with full bylaws summary (5 conditions). 5. Displays current membership value (from pricing_configs) not old stored value. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 19 Jun, 2026 1 commit
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 17 Jun, 2026 3 commits
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 13 Jun, 2026 9 commits
-
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Fix DIVORCE_CHILD_UNDER_12 rule: 15% → 5% per bylaws - Fix eligibility: use spouse's join_date (not member's created_at) for 5-year check - Add suggested percentage based on spouse_order (50% first, 75% second) - Implement children transfer with age-based fees on completion - Board approval now includes children selection with fee preview - Complete action transfers selected children to new membership - Show view displays spouse order, join date, children assignment details Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
When a subscription year is marked as paid, the member row's paid_amount must include the 35 EGP dev fee (single flat charge per family). Previously only total_amount + fine_amount was stored, causing remaining balance to show dev fee as unpaid despite full payment. Fixes: SubscriptionController::payYear(), RetroactiveMembershipService (both createRetroactiveSubscription and processRetroactiveRenewal). Migration Phase_92_006 corrects existing paid rows in the database. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Pre-check national_id before insert (shows member name if exists) - Translate common DB errors: duplicate national_id, phone, foreign key, data too long — all shown in Arabic with actionable guidance - Raw PDO errors no longer shown to users Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
These fields were editable, allowing users to accidentally set paid_amount on 'overdue' rows (causing fine calculation to skip them). Now paid_amount is always hidden=0 (server sets it for 'paid' status) and fine shows "تلقائي" (calculated automatically by the system). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The elseif branch accepted form's paid_amount even when status was 'overdue', causing paid_amount to equal total_amount without a payment record. This made fine calculator see unpaid=0 and skip the year. Now only status='paid' sets paid_amount; all other statuses get 0. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Migration Phase_92_005: - Fix missing dev fee on member rows - Apply 50% discount to 2023/2024 rows that missed it - Recalculate total_amount where it doesn't match (base - discount) - Fix paid rows with 0 paid_amount (set paid_amount = total) - Reset all fine_amounts to 0 (recalculated on page visit) Code fixes: - OverdueFineApplicator: only write fine_amount if actually changed - SubscriptionCalculator: expose subscription_total in fine details - SubscriptionController: pick single dev fee per year (not SUM) - View: show correct base (subscription_total) in fine detail panel - RetroactiveMembershipService: don't accept form paid_amount for status=paid (server calculates correct value); remove dev fee from paid_amount (dev fee is invoice-level, not per-row) - RetroactiveWizardController: remove misleading 492/527 defaults - OverdueFineJob: run year-round (grace period handled by calculator) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
processRetroactiveRenewal() was setting paid_amount = total_amount when status='paid' but not creating a payment record, causing fine_amount to stay at 0 (calculator sees paid_amount == total_amount → skips the year). Now creates a retroactive payment via createRetroactivePayment() before setting paid_amount, ensuring payment_id is always populated. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- RetroactiveMembershipService::createRetroactiveSubscription() now applies year-specific discounts from RuleEngine (SUBSCRIPTION_YEAR_ADJUSTMENT_{year}) regardless of form input — server-side enforcement - Retroactive wizard JS: uses year-specific rates (410/185 for 2023, 492/222 for 2025+) and shows discount percentage visually per row - total_amount = base - discount (dev fee excluded, added at invoice level) - For paid rows: paid_amount includes dev fee since that's what was collected Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 12 Jun, 2026 7 commits
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 11 Jun, 2026 2 commits
-
-
Mahmoud Aglan authored
- Foreign bill: branch-specific fee lookup, exchange rate conversion, EGP display - Seasonal bill: duration, nationality, dates, base amount, discounts, VAT, family members - Sports bill: improved breakdown with separator and total line - Form fee: add in_queue status to bill item - Controller: type-specific payment types, validation whitelist, descriptions - View: conditional installment option, working-only family links, type-specific labels Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Membership types (seasonal, sports, honorary, foreign) are now selectable at creation time instead of being post-creation conversions from working. Each type has its own fee logic, billing, activation path, and subscription rules. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 10 Jun, 2026 1 commit
-
-
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:Claude Sonnet 4.6 <noreply@anthropic.com>
-
- 08 Jun, 2026 1 commit
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 07 Jun, 2026 1 commit
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 03 Jun, 2026 2 commits
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 01 Jun, 2026 3 commits
-
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 31 May, 2026 5 commits
-
-
Mahmoud Aglan authored
Each missing field shows as its own red error banner at the top of the page instead of one long string with invisible newlines. 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
Client-side: validates ALL mandatory DB fields before allowing next/submit - Step 1: name, phone, gender, date_of_birth (or NID) - Step 2: form_date, join_date - Step 3: membership_value - Step 5: each spouse needs name, DOB/NID, marriage_date, join_date each child needs name, DOB/NID, join_date each temp member needs name, DOB/NID, category - Red border + Arabic error on each missing field, scrolls to first error Server-side: full validation before any DB write - Rejects with clear Arabic messages listing every missing field - No more placeholder dates or fake phone numbers - If anything bypasses JS, server still blocks with human-readable errors Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- spouses: add spouse_order, gender, classification, fallback date_of_birth - children: add child_order, relationship, classification, fallback date_of_birth - temporary_members: fallback date_of_birth, gender - members: phone_mobile defaults to placeholder, date_of_birth fallback - installment_plans: down_payment_receipt cast to string (VARCHAR column) - All dates go through safeDate() — rejects garbage, parses valid formats - All timestamps go through safeTimestamp() — never produces invalid datetime - financial_year '2020/2021' extracted correctly for created_at - bccomp amounts always cast to string to avoid type errors - Null-safe on every optional field — zero room for SQL errors Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- phone_mobile column is NOT NULL; pass empty string instead of null - financial_year '2020/2021' was used directly in created_at datetime; extract first year - Add client-side step validation with red border highlights instead of alert() popups Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-