- 16 Jul, 2026 12 commits
-
-
Mahmoud Aglan authored
- Migration: add installment_amounts JSONB (nullable) to product_installment_plans - ProductInstallmentPlan: new buildSchedule() method — uses explicit piaster amounts per slot where set, auto-calculates remainder evenly for blank slots; downPaymentAmount/regularInstallmentAmount respect slot[0] override - ProductForm: syncInstallmentSlots() keeps slot array in sync when count changes; plan rows load/save installment_amounts (stored as piasters, shown as pounds); slot inputs appear under collapsible "تحديد مبلغ كل قسط" toggle per plan row - Wizard confirm(): uses buildSchedule() so each Installment row gets its correct explicit or auto-calculated amount - Wizard blade breakdown preview: renders individual amounts when slots differ, uniform "N × amount" when all regular slots match Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- New migration: billing_cycle (one_time/annual), member_price, non_member_price on products; product_installment_plans table (per-product, per-tier plan templates) - ProductInstallmentPlan model with scopeActive/forTier, downPaymentAmount/regularInstallmentAmount helpers - Product model: priceForTier(), isAnnual(), installmentPlans() relationship - ProductForm: annual billing section with member/non-member dual prices and installment plan builder (add/remove rows, upsert on save) - Registration wizard: essentialProducts() and hotbuyResults() now return billing_cycle and plans[]; addHotbuyItem() carries plans into cart; setHotbuyPlan() selects a plan per cart item; confirm() generates PaymentPlan + Installment rows for annual items with a selected plan - Wizard blade: annual cart items show purple "سنوي" badge, plan pills (full payment + per-plan buttons), and installment breakdown preview on selection Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Two bugs: 1. save() wrote bare key "allow_proration" but ProrationService reads dotted "enrollment.allow_proration" — now always writes "{group}.{key}" 2. loadAllSettings() tried to read bare keys but DB had dotted keys from seeder — now strips group prefix on read so UI always sees bare keys Result: toggle saves correctly, ProrationService reads the live value, mid-month enrollment now shows prorated fee (e.g. day 16 = 15/30 × fee). Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
JSONB column has NOT NULL constraint — pass empty array instead of null when no price override metadata exists. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Fields already existed on the guardians table (occupation, workplace) but had no UI. Now: - Registration wizard step 2 shows المهنة + جهة العمل fields (optional) - Saved to Guardian on create; updates existing guardian if already found - Pre-populated when selecting an existing guardian via search - Participant show → أولياء الأمور tab adds المهنة / جهة العمل column Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Add allow_proration (boolean) and renewal_day (number, 1-28) to the enrollment settings schema with descriptive hints so admins can find and toggle partial monthly payment from the UI. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add is_essential boolean to products (migration + model + form toggle) - Essential products appear as quick-add buttons in registration wizard step 5 (no search needed), highlighted when added to cart - New EssentialDeliveries page (/inventory/essential-deliveries): lists all players who bought essential products, mark استلم/لم يستلم per item with who delivered and when - Delivery tracking: add is_delivered, delivered_at, delivered_by to invoice_items; hotbuy cart items now store itemable_type/id for proper morph link - Admin price override now stored in invoice item metadata (original_price, overridden_price, override_reason) and displayed on invoice print with crossed-out original price - "أساسي" badge on product list; "تسليم الأساسيات" button on product list header and sidebar Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Payment modes: - Full (default): pays entire invoice amount - Partial: enter amount paid now, remainder stays as balance due on invoice - Split: two methods, amount1 + calculated remainder, both recorded as payments All 7 PaymentMethod values now available: - cash: no extra fields - card: transaction_reference (required) - bank_transfer: transaction_reference (required), bank_name (optional) - online (Instapay/digital wallets): transaction_reference (required) - wallet (club wallet): deducts from member balance - cheque: cheque_number (required), bank_name (optional) - other: notes field Each payment recorded with gateway_data JSON (ref, cheque_number, bank_name) Enrollment payment_status only set to 'paid' when full amount covered Validation rules built dynamically from active mode + method combination Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- EnrollmentSettingsSeeder: fix Organization → Academy class name - ReceiptTemplate: add defaultInvoiceFields/Settings + defaultPaymentFields/Settings - ReceiptSettings: rewritten with pos/invoice/payment tabs; each tab loads its own ReceiptTemplate (type='invoice'|'payment') and saves independently - receipt-settings.blade.php: 3-tab UI with field toggles + appearance settings per document type; link to branding page for logo/colors - print/invoice.blade.php: all 15 fields now gated by invoice template flags (logo, academy name, branch, tax number, client details, items table, subtotal, discount, tax, service fee, paid amount, payments history, signature, terms & conditions, footer text) - print/payment-receipt.blade.php: all 11 fields gated by payment template; footer text pulled from template settings instead of hardcoded string Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
CapRover volume remounts can override build-time chown, leaving storage/logs owned by root. Explicitly touch + chown the log file at container start before php-fpm runs. Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- AuthService: accepts email or phone for login (identifier-based lookup) - Login UI: updated to text input with Arabic labels - EgyptianNidDecoder: decodes 14-digit NID → birth date, gender, governorate - ProrationResult DTO + ProrationService: mid-month enrollment fee proration (x/30 of remaining days based on configurable renewal day) - EnrollmentSettingsSeeder: seeds enrollment.allow_proration and enrollment.renewal_day per academy - NewRegistrationWizard: rewritten — player-first flow, NID auto-decode locks birth/gender/governorate, foreign player toggle, guardian name deduced from player name, phone-only guardian, super admin price override, proration display - EnrollmentService: applies proration to invoice creation - EnrollExistingWizard: adds proratedProgramFee computed property, review step shows original vs prorated fee - Migration: adds governorate column to people table Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
- 11 Jul, 2026 6 commits
-
-
Mahmoud Aglan authored
Every entity list now has clickable rows that navigate to rich detail pages with KPIs, tabbed content, and related data. New show pages: - TrainerShow: groups, schedule, attendance, financial, qualifications - EmployeeShow: personal info, team hierarchy, documents, timeline - GroupShow: enrollments, schedule, sessions, attendance stats - ProgramShow: groups, enrollments, settings, requirements - FacilityShow: layouts, segments, reservations, schedule - ProductShow: stock levels, movements, analytics Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The old 'inventory.adjustments.wizard' route was removed — now just 'inventory.adjustments'. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The wizard was overengineered for this flow. Programs are created via the existing ProgramForm. Updated dashboard and program-list links. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Stock Count fix: dispatch StockCountCompleted event after completing a count so the ProcessCountAdjustments listener creates inventory movements. Made listener synchronous for immediate feedback. 2. Stock Adjustment: route now points to the existing wizard component instead of the plain form. 3. Purchase Orders: new CreatePurchaseOrderWizard with 4-step flow (supplier → warehouse/dates → items → review & confirm). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The PaymentMethod and PaymentStatus enums were passed directly to __() which expects a string, causing "Cannot access offset of type enum on array". Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Production had no trainers/employees and only 1 branch. Rewrote seeder to be fully self-contained: creates 2 new branches, 19 people, 11 employees, 12 trainers, then populates all HR tables. Cleans up prior data on re-run. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 10 Jul, 2026 10 commits
-
-
Mahmoud Aglan authored
Covers: 11 employees (6 staff + 4 trainer-employees + 1 resigned), all 12 trainers with bios/sports/qualifications/availability, 3 months of compensation history, 2 closed payroll periods with payslips, advances in all states, rate history. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- SKU is NOT NULL in the database but was nullable in wizard validation, causing a crash when submitted without a SKU value - Auto-generate SKU (PRD-0001, SRV-0001, DIG-0001) when not provided - Catch QueryException in both product forms to show friendly error instead of crashing on unique constraint violations Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add explicit $table = 'trainer_compensations' to TrainerCompensation model (Laravel resolved singular 'trainer_compensation' by default) - Wrap TrainerDuesWidget query in try/catch so dashboard loads even if the compensation migration hasn't been run yet Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- InvoiceService::create() now auto-generates number if not provided - Invoice list/show views fall back to billable.person.name_ar when contact_name is null (matches print view behavior) - Fix participant link to use model route binding (uuid) not raw ID - CSV export no longer restricts to current month by default — exports all invoices matching the active filters (status, search) - CreateInvoiceWizard falls back to participantName for contact_name Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
InvoiceService::create() was not setting issue_date or due_date, causing a NOT NULL violation on the invoices table when the POS checkout flow creates an invoice without explicitly passing dates. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-
Mahmoud Aglan authored
- Add cascading filters across all list pages (activity→program→group, program→trainer, direction→movement type) - Make sidebar sections collapsible with auto-expand on active page - Route all "Create" buttons to wizards instead of plain forms - Fix low stock count mismatch between dashboard and product list Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-
Mahmoud Aglan authored
Instances no longer hold WhatsApp API credentials. They send messages via the el-captain-manager messaging hub API using MESSAGING_HUB_URL and MESSAGING_HUB_KEY env vars. The hub handles Meta Graph API calls, rate limiting, and delivery tracking centrally. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Root cause: format_money() was used in 20+ views but never defined, causing silent fatal errors on every print attempt. Also simplified ReceiptController to render standalone HTML pages instead of depending on ReceiptTemplate records that may not exist in the DB. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 09 Jul, 2026 12 commits
-
-
Mahmoud Aglan authored
Cast config values to string with null-coalescing fallback, and add empty-string defaults to env() calls so instances without WhatsApp configured still boot without TypeError. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The demo_academy DB doesn't have organizations/users tables with those exact names. Use plain indexed columns instead. 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
- WhatsAppService: send text, template, image, document messages - Bulk send to groups/status/custom selections - Message log with status tracking (sent/delivered/read/failed) - Three Livewire pages: Send Message, Send Template, Message Log - Migration for whatsapp_messages table - Added 'whatsapp' channel to NotificationChannel enum - Wired into NotificationService for automated notifications - Sidebar section "واتساب" with 3 items - Config via WHATSAPP_PHONE_NUMBER_ID + WHATSAPP_ACCESS_TOKEN env vars Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Auto-seed default sections on first visit when none exist - Every section now shows skeleton placeholders when empty (branches, partners, pricing, trainers, stats, schedule) - Converted remaining dark sections to light theme (branches, trainers, pricing, contact, schedule) for consistency - Stats band keeps dark bg for visual contrast - Fresh deploy = beautiful skeleton website ready for client to imagine Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Fixes Route [inventory.purchase-orders.create] not defined error by adding the missing routes and creating PurchaseOrderForm + PurchaseOrderShow Livewire components with full Arabic UI. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Default background: white, text: dark gray, accent: blue - Hero/navbar/footer stay dark (branded primary color) - All sections show skeleton placeholder cards when no data exists - Removed all hard-coded oklch dark values from section views - Cards, testimonials, FAQ items now use white bg + subtle borders - Empty states show shimmer animation + "لم تُضف ... بعد" message Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Use null-coalescing for age_from/age_to/duration_months (columns don't exist yet) - Handle __PHP_Incomplete_Class from stale cache by re-fetching on type mismatch - Add cache:clear to deploy entrypoint to prevent stale cache after rebuilds Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Livewire's ExtendedCompilerEngine misparses @if inside <script> tags. Replaced inline Blade conditionals with @php block + json_encode. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Route / now serves academy public website (no auth required) - Dashboard moved to /dashboard - Login/Dashboard button added to website navbar (desktop + mobile) - Added "الموقع الإلكتروني" section to sidebar with all 9 CMS pages - Added missing inventory items (POs, Kits, Stock Counts) to sidebar - Configured explicit middleware redirects for guest/auth flows Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add branch_id accessor to User model (resolves from role_user pivot) - Create AppliesRoleScope trait for one-liner scope enforcement - Enhance PermissionService: include head_trainer_id in group lookup, add training_programs and invoices table support for own_groups scope - Apply AppliesRoleScope to 16 list components: ParticipantList, GroupList, EnrollmentList, AttendanceList, InvoiceList, ProgramList, EvaluationList, CashSessionList, WalletList, AssignmentList, PersonList, FacilityList, ProductList, PurchaseOrderList, KitList, StockCountList Now trainers only see their assigned groups/participants, branch managers only see their branch data, parents only see their children, and receptionists are branch-scoped. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Detect on mount if user already has Trainer/Employee/Guardian records - Show green notice when record exists, amber warning when role implies record but none exists (orphan state) - Allow entity creation on save even without role change when entities are missing (repair orphaned users from before the redesign) - Disable create toggles when record already exists to prevent duplicates Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-