- 01 Jul, 2026 1 commit
-
-
Mahmoud Aglan authored
- Added GET /api/members/{id}/debts endpoint returning comprehensive debt check as JSON (clear, debts array, total) - Create page now fetches and displays target member debts live after selection via AJAX — shows detailed debt table or green "clear" badge - Form submission blocked if target has outstanding debts, with error message and direct link to payment page - Made waiver request document upload required (HTML validation) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 28 Jun, 2026 1 commit
-
-
Mahmoud Aglan authored
After the cashier collects the waiver fee, the system now automatically executes the waiver completion (membership transfer) without requiring a manual "إتمام التنازل" button click. The auto-complete validates all conditions first: - Fee paid (status = fee_paid) - Target member specified - Board approval exists - No debts on source or target member - Excess dependent fees properly set If any condition fails, the waiver stays in fee_paid status with a clear checklist showing what's still needed, plus a manual fallback button for edge cases. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 26 Jun, 2026 4 commits
-
-
Mahmoud Aglan authored
MySQL rejects empty strings for DATE columns. The approve form sends empty strings for persons without a DOB (spouses, temporary members). Convert empty strings to null for date_of_birth, relationship, status, and notes fields before INSERT. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The generic payment process page (linked from waiver "الانتقال إلى السداد") was recording payments in the payments table but never updating the source records (subscriptions.paid_amount, fines.paid_amount, installment_schedule.paid_amount). This caused the debt check to keep showing debts as unpaid after payment. Added handleSubscriptionPayment, handleFinePayment, and handleInstallmentPayment methods that mark the underlying records as paid (oldest first). Also fixed waiver debt check using wrong fines status ('pending' instead of 'imposed'/'appeal_upheld') which is what fines actually use. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- New table `waiver_individual_fees` stores fee per person (not per category) - Board approval screen shows each excess person as a separate card with: name, DOB, age, age category, relationship, independent fee type/rate - Children 25+ flagged with warning and "فصل العضوية" button - Live JS calculates per-person amounts and updates grand total instantly - Fee breakdown section shows individual names when individual fees exist - Fix: /members/{id}/financial → /payments/process/{id} (was 404) - WaiverProcessor::getExcessIndividuals() identifies the specific excess persons - WaiverProcessor::saveIndividualFees() persists per-person board decisions - Age categories expanded: under_12, 12_to_16, 16_to_18, 18_to_25, 25_plus Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
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:Claude Opus 4.6 <noreply@anthropic.com>
-
- 23 Jun, 2026 1 commit
-
-
Mahmoud Aglan authored
The button linked to /members/{id}/financials which doesn't exist. Changed to /members/{id} where the financial summary actually lives. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 22 Jun, 2026 5 commits
-
-
Mahmoud Aglan authored
Replace GROUP BY with correlated subqueries for snapshot data. MySQL strict mode requires all SELECT columns in GROUP BY. 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
New member-centric archive view inside شئون العضوية: - Searchable listing with filters (name, number, NID, phone, status, date, operator) - Detailed show page with member data, dependents, financials, number chain - Linked member navigation (old
↔ new after transfer/waiver/death) - Audit trail display with before/after field changes - Sidebar with archive info, snapshots, and number chain timeline Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
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>
-