- 18 Jul, 2026 4 commits
-
-
Mahmoud Aglan authored
- Complete rewrite of show.php: 6 KPI cards (original amount, down payment, remaining balance, interest, monthly payment, member's outstanding balance), progress bar showing paid vs total installments, financial breakdown panels (paid vs remaining split), grand total formula ribbon, overdue alerts, next-due-date card with countdown, enhanced schedule table with status highlighting and per-row pay forms - Add recalculate() action to InstallmentController: corrects pending-only installment rows to flat simple-interest formula without touching paid rows - Register POST /installments/{id}/recalculate route Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
SubscriptionSyncService::syncForDependent() inserts a pending subscription row for the current financial year whenever a spouse, child, or temporary member becomes active. Triggered via two paths in Subscriptions bootstrap: - Cashier path: spouse.fee_paid / child.fee_paid / temporary.fee_paid - Zero-fee path: *.added events where fee = 0 (immediate activation) Guards: member must be active + non-exempt type; dedup prevents duplicates. Rates resolved identically to SubscriptionGenerator (year-specific catalog code → generic code → hard fallback). Never throws — safe in event context. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
All calculation sites now use: interest = remaining × (rate/100) × (months/12) instead of diminishing-balance amortization. Changes across all 6 sites: - InstallmentCalculator: flat interest, equal monthly instalments - PricingEngine: same formula - RetroactiveMembershipService: same formula - retroactive-wizard JS: updated preview + shows المبلغ المتبقي in summary - Members/show.php: preview panel now includes months factor (was missing) - Installments/create.php: added live المبلغ المتبقي preview panel Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Native HTML5 constraint validation fires on hidden fields (display:none panels), causing "not focusable" errors on inst_months. Custom validateStep() handles all validation — novalidate disables the duplicate browser check. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
- 09 Jul, 2026 1 commit
-
-
Mahmoud Aglan authored
- Show loading spinner on submit button while saving - Display error in a prominent red banner at top of wizard on failure - Error message is now shown directly (not buried in generic alerts) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 07 Jul, 2026 1 commit
-
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 06 Jul, 2026 1 commit
-
-
Mahmoud Aglan authored
When enabled, all active members and dependents get subscriptions from 2023/2024 (system start) regardless of their actual join date. Toggle via business_rules table — set enabled:false to revert to join-date logic. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 04 Jul, 2026 6 commits
-
-
Mahmoud Aglan authored
The column is 'notes', not 'description'. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Added phase to SubscriptionDataMigration that removes unpaid subscriptions for dependents who are archived or no longer active (e.g., temporary members who became inactive, frozen children). 2. Fixed WaiverProcessor referencing non-existent 'reason' column in fines table — correct column is 'notes'. 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
The fallback `$sub['person_id'] ?? $memberId` silently assigned member's own ID to spouse/child/temporary subscription rows when person_index didn't map. Now resolves by name from the dependent table, or skips the row entirely if no match is found. 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
- Remove unpaid subscriptions before 2023/2024 (system didn't exist) - Apply 50% discount to all 2023/2024 subscriptions - Fix amounts/discounts for all years based on historical rate table - Reset and recalculate all fines from scratch - Delete orphaned subscription rows with no matching dependent Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 03 Jul, 2026 9 commits
-
-
Mahmoud Aglan authored
Documents the SubscriptionDataMigration service: phases, rate table, production results, and root cause of orphaned person_ids. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
When matching orphaned person_ids, also search archived/inactive records since subscriptions may reference people who were active at creation time. Validate method also checks ALL records, not just active ones. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Adds SubscriptionDataMigration service that: - Fixes orphaned person_id references (matched wrong ID to dependent) - Removes exact duplicate subscription rows - Corrects zero/wrong amounts using historical rate table - Creates missing subscriptions for all members from join date to present - Applies overdue fines proportionally per SubscriptionCalculator rules CLI commands: php cli.php subscriptions:migrate Run the migration php cli.php subscriptions:migrate --dry-run Preview changes php cli.php subscriptions:validate Check data integrity Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Documents the PHP truthiness bug (0.00 ?: fallback), the fix applied, production data corrections, and new Docker cron infrastructure. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Docker cached the apt-get layer from before cron was added. ARG before RUN forces layer rebuild. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Previous deploy used cached layers without cron installed. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
PHP's ?: operator treats '0.00' as truthy, preventing fallback to generic service codes. Now returns empty string for missing/zero rows, with hard fallback defaults as last resort. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Install cron package in Dockerfile and start cron daemon in entrypoint (hourly: php cli.php cron). This was missing — cron jobs never ran. 2. SubscriptionGeneratorJob now delegates to SubscriptionGenerator service which handles exemptions, year-specific rates/discounts, per-person dedup. 3. Financial year 2026/2027 subscriptions will generate on next cron run (July 1-7 window still active). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Debt check now covers ALL financial types: subscriptions, fines, installments, payment requests, unpaid sales, and seasonal memberships — for member + all dependents. 2. Board approval screen shows ALL target dependents (not just excess) with full details (name, age, DOB, category, within-allowance flag). Board decides per-person fees independently. 3. Receipt/payment request includes per-individual itemized breakdown with calculation method, person type, age category — stored as structured JSON for audit trail. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 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 2 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>
-