- 22 Jul, 2026 17 commits
-
-
Fares authored
Foreign membership dependents (spouses, children, temporary) are included in the membership fee — zero additional charges. Add a "not Egyptian" checkbox that toggles between NID and passport number fields on all three dependent creation forms. Server-side validation skips NID requirement when non-Egyptian is checked and requires passport instead. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Non-working types (foreign, sports, seasonal, honorary) stay in 'potential' status after form fee since they skip the acceptance process. The payment section and pending detection now recognize this status for those types. Also adds a type-specific CTA guiding members to their registration form when needed (seasonal/honorary where fee=0 until filled). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Foreign members can now add spouse/children (allowsDependents=true), and the $10k fee routes through the cashier queue instead of inline processing, matching the standard activation path used by other membership types. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Step 6 now shows year cards where each financial year contains all family members (member + spouses + children + temps) with a single shared status dropdown and payment date. Replaces the flat per-person-per-year table. Backend format unchanged — same hidden input naming for full compatibility. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
- Payment request includes child's name + fee breakdown in notes JSON - Cashier/Treasury queues display child's name instead of parent's - Skip archive snapshot for child_separation (parent keeps membership) - Generate form_number for new member via FormNumberGenerator - Auto-complete transfer immediately after cashier payment (no manual button) - Hide manual "إتمام التحويل" button for child_separation type Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The سجل العمليات التفصيلي now shows step-by-step entries for ALL procedure types — death, waiver, and transfer/separation — not just death cases. Waiver and transfer timelines are reconstructed from request data (submission, approval, payment, data transfer, completion). Timeline entries are sorted chronologically and color-coded by type. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
payments table uses related_entity_type/related_entity_id, not payment_request_id. Simplified query to filter by payment_type directly. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The السجل التأميني page now shows a complete record of ALL procedures that affected a membership — death cases, waiver transfers, and transfer/separation requests. Works for both active and archived members. Shows: procedure details, role (source/target), fees, approval info, payments related to procedures, death audit timeline, archive snapshots. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Debt tables still show for reference but the payment navigation button is removed per user request — from create, show, and JS debt checker. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
WaiverProcessor now transfers ALL active data (dependents, payments, subscriptions, installments, fines, documents) from source to target member during waiver execution. Snapshot is taken first so archive retains the complete historical state. Changes: - WaiverProcessor::transferActiveData() moves spouses, children, temps, payments, subscriptions, installment_plans, fines, documents, and payment_requests from source to target member - ArchiveService snapshot now includes installment_cheques and installment_schedule for complete financial history - Archive show page displays cheques per installment plan - Member show page adds "عرض العضوية المؤرشفة" button for waiver transfers - Archive page adds "الانتقال إلى العضوية الحالية" link to current holder Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
form_number was being stripped by the model's mass-assignment guard, so it was never saved to the database despite being in the POST data. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The form_number wasn't showing because earlier payment requests had notes without form_number. Now both cashier process and queue views fall back to reading form_number directly from death_cases table when not in notes JSON. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
- Form number input added to death registration (shown for primary_member type) - Stored in death_cases.form_number column (new migration Phase_99_002) - Passed through payment request notes JSON to cashier - Cashier process/queue views now display form_number from notes for death_fee - saveFillForm() auto-triggers complete() — no manual button needed Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The archive show page now displays ALL original data: - Dependents from snapshot (not live DB where they may have been moved) - Full payments history with amounts and receipt numbers - All annual subscriptions with status and amounts - Installment plans with expandable payment schedules - Fines with amounts and reasons - Documents with file details - Financial summary box (membership value + total paid) - Insurance record link for death case audit trail Previously, dependents showed empty because children/temps are moved during death transfer. Now uses snapshot related_data as source of truth. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
- Add DeathAuditService for full Arabic audit logging of every step - Create death_case_audit_log table (migration Phase_99_001) - Transfer active installment plans to new membership on completion - Duplicate documents to new membership (originals preserved on archived) - Create annual subscriptions for new membership (current financial year) - Set membership_value to current plan price (not old historical value) - Add "عرض العضوية الأصلية" button linking to archived member - Add "السجل التأميني" (Insurance Record) page on member profile - Add insurance-record route and view with timeline UI - Update architecture map with new services, tables, and flows Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 21 Jul, 2026 21 commits
-
-
Fares authored
The cashier payment page was displaying the deceased husband's info (name, form number, membership number). For death_fee payments, the recipient is the wife — extracted from the notes JSON. Form/membership numbers are hidden since the wife doesn't have them yet. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The board approval percentage calculation had fragile fallbacks that could miss the pricing_configs data and fall back to the old membership_value. Added cascading fallbacks: PricingEngine → branch+qual → branch-only → any active pricing → membership_value (last resort). Also fixed the JS preview in show.php which was using the stored membership_value (114,000) instead of the current plan price (150,000) for the real-time calculation hint. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Child separation is not a death/full transfer — the parent stays active with their original membership number. The separated child gets a brand new sequential number via MemberNumberGenerator::getNextMembershipNumber(). Only full_transfer type archives the source member and passes the same number to the new member. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Form now collects for spouses: date_of_birth, nationality, marriage_date, join_date, payment_date. For children: date_of_birth, join_date. Validates spouse minimum age (SPOUSE_MIN_AGE rule, default 21) and requires marriage_date. Non-Egyptian spouses get addition_fee calculated as SPOUSE_FOREIGN_FEE% of current plan price at completion time. TransferProcessor now uses submitted dates instead of defaults and stores nationality and addition_fee on the spouse record. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The column was in the model's fillable but never had a migration. Causes 'Column not found' error when storing female child separation requests. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Empty form fields post as '' which ?? doesn't catch (only null). MySQL rejects '' for decimal columns. Switched to ?: so empty strings fall through to the '0.00' default. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Reflects that deceased is excluded from annual sub, trustee fee uses current plan price via PricingEngine, and Pricing module is now a dependency. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The deceased member should not be charged annual subscription — the primary spouse becomes the new member. Trustee fee percentage now uses the current membership plan price from pricing_configs (e.g. 150,000) instead of the historical membership_value stored at enrollment time (e.g. 114,000). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The TransferProcessor::execute() was failing with "Field 'date_of_birth' doesn't have a default value" because: 1. Child's date_of_birth could be empty string (not null), bypassing ?? operator 2. Children table has no phone_mobile column, causing NOT NULL violation on members 3. Spouse creation was missing required fields (date_of_birth, marriage_date, join_date) 4. Temporary member creation was missing required fields (date_of_birth, gender, category) Changes: - Sanitize DOB: treat empty string and '0000-00-00' as null before NID fallback - Add phone_mobile fallback chain: subject → source member → placeholder - Spouse inserts now include all NOT NULL fields with sensible defaults - Children inserts include child_order - Temporary member inserts include category, date_of_birth, gender with NID parsing - Death module: fix secondary spouse phone_mobile NULL issue Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Death module: - Annual subscription now includes ALL family members (spouses, children, temps + dev fee) - Temporary members distribution UI added to create form - Payment receipt created in primary spouse's name (not deceased) - Form number field added to membership application - Deceased member name stored on new membership record - Full Arabic audit trail logging on completion Waiver module: - Mark ALL family subscriptions as paid after completion (not just member) - Set activated_by_payment_id on all dependents - Copy membership_value from source to target member - Add transferred_from_waiver_id and waived_from_member_name to members - Display waiver source badge and archive section on member profile Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Expanded the special discounts system to support: - Discount types: percentage, fixed amount, or free subscription - Date range (effective_from/effective_to) for time-bounded offers - Conditions: none (direct), full_payment, or min_payment threshold - Bonus: free subscription years granted when discount activates - Applies-to targeting: membership_fee, subscription, or all Added SpecialDiscountService for evaluating conditional discounts and applying free subscription bonuses on member.activated event. Updated form UI with dynamic visibility and validation. Migration: Phase_98_003 adds new columns to special_discounts table. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
The children table requires date_of_birth (NOT NULL). The dependent creation loop now derives DOB from national_id via NationalIdParser, falling back to a placeholder if neither is available. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
When creating the new member record, date_of_birth may be NULL on the child record. Now attempts to derive DOB and gender from national_id via NationalIdParser before falling back to a placeholder. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
1. isCurrentYearSubscriptionCovered() was comparing activation date against its own fiscal year (always true) — now correctly compares against the current fiscal year's July 1st. 2. Annual subscription in calculate() now includes all family members (spouses, children, temps) not just the member alone. 3. marriage_date and dep count columns are only included in INSERT when non-null, preventing column-not-found error if migration hasn't run. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
1. Subscriptions now marked as paid: after waiver completes, sync subscriptions for target member and mark current FY as paid since the fee was already collected in the waiver payment. 2. Membership date: set created_at to today on waiver completion so the member profile shows the actual membership start date. 3. Total paid shows correctly: BillingService now recognizes activated_by_payment_id as proof that form_fee and membership_fee are paid (covers waiver_fee and separation_fee payment types). 4. Waiver list shows names: fix $r['member_name'] → $r['source_name'] to match the SQL alias from WaiverRequest::search(). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Each subscription row now independently stores: - receipt_number: denormalized from receipts table for quick audit access - paid_by: FK to employees — who processed the payment - paid_at: already existed Migration adds columns and backfills existing paid rows from payments/receipts. View shows "بيانات السداد" column with date, receipt number, and employee name. Model query now JOINs employees for paid_by_name display. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
feat(transfers): gender-based separation logic — males use work/grad/age25, females use marriage date - Males: effective_date = min(max(work_date, graduation_date), date_turned_25) — unchanged - Females: effective_date = marriage_date only (no work/graduation/age25 fields) - Add data-gender attribute to child select options for JS detection - Show male-specific fields (employment, graduation, work_date, date25) only for males - Show marriage_date field only for females - Females bypass age >= 25 filter in dropdown (eligible at any age via marriage) - Server-side age validation skipped for female children - Add marriage_date column to migration and model fillable - Frontend dynamically switches between male/female form based on selected child's gender Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
- Fix effective date: use min(max(work_date, graduation_date), date_turned_25) instead of min(work_date, date_turned_25) - Make graduation_date mandatory when child is employed - Annual subscription now includes all family members (member + spouses + children + temps) - Add dependents section to form: user specifies counts and details (name, national_id) for each person joining new membership - TransferProcessor creates dependent records (spouses, children, temporary_members) from notes JSON on completion - Migration adds target_spouses_count, target_children_count, target_temps_count columns - Updated architecture map Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Root causes of duplicate members in yearly subscriptions: 1. No DB-level unique constraint allowed race conditions between SubscriptionGenerator, SyncService, and RetroactiveMembershipService 2. SyncService set person_id=NULL for member rows vs Generator's person_id=memberId 3. RetroactiveMembershipService did blind INSERTs with no dedup check Fix: - Migration removes existing duplicates (keeps paid row, lowest ID tiebreak) - Normalizes NULL person_id on member rows - Adds UNIQUE INDEX (member_id, financial_year, person_type, person_id) - All insert paths catch Duplicate entry exceptions as race guard - SyncService now sets person_id=memberId matching Generator - RetroactiveMembershipService checks for existing row before INSERT Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Fares authored
Tests cover e(), money(), percentage(), arabic_date(), age_from_dob(), now(), and today() helpers. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 18 Jul, 2026 2 commits
-
-
Mahmoud Aglan authored
feat(transfers): skip annual subscription fee when member activated after July 1; fix bad financial_year data Business rule: members activated on/after July 1 of current FY have the annual subscription included in their membership fee — do not charge again. - SeparationFeeCalculator::isCurrentYearSubscriptionCovered(): returns true if activated_at >= July 1 of the member's current fiscal year - calculate() and calculateForChildSeparation(): set annual_subscription_fee to 0.00 when covered; return annual_sub_covered flag - create.php fee preview: shows "
✅ مشمول في العضوية" note when annual sub is waived; fee row shows 0.00 DB fix (applied directly): UPDATE subscriptions SET financial_year = '2025/2026' WHERE financial_year = '2025' — 168 rows corrected to proper YYYY/YYYY+1 format Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Generator now allows amt*count >= remaining (not forced equal). All cheques get the same amount; no last-cheque manipulation. Preview and guard alert only block when total < remaining. Server-side storeBatch already accepted grandTotal >= planTotal. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-