@extends('layouts.finance') @section('title', 'Monthly Report') @section('subtitle', 'Closed month business report') @section('content') @php $closing = $reportData['closing']; $status = $reportData['status']; $trend = $reportData['trend']; $previous = $reportData['previous']; $settings = $reportData['settings']; $bankAccounts = $reportData['bank_accounts']; $creditCards = $reportData['credit_cards']; $debts = $reportData['debts']; $collectibles = $reportData['collectibles']; $inventory = $reportData['inventory']; $products = $reportData['products']; $providers = $reportData['providers']; $expenseBreakdown = $reportData['expense_breakdown']; $topClients = $reportData['top_clients'] ?? collect(); $b2c = $reportData['b2c'] ?? ['orders' => 0, 'orders_delta' => null, 'vouchers' => 0, 'revenue' => 0, 'profit' => 0, 'avg_profit_per_voucher' => 0, 'trend' => ['labels' => [], 'orders' => [], 'profit' => []], 'products' => collect()]; $points = $reportData['points'] ?? ['summary' => ['quarterly' => 0, 'yearly' => 0, 'total' => 0, 'redeemed' => 0], 'by_product' => collect(), 'agent_targets' => collect()]; $support = $reportData['support'] ?? ['connected' => false, 'tickets_opened' => 0, 'tickets_resolved' => 0, 'avg_first_response' => '-', 'avg_resolution_time' => '-']; $assets = $reportData['assets']; $factory = $reportData['factory']; $periodStart = $closing->period_start?->format('d M Y') ?? $status['period_start']->format('d M Y'); $periodEnd = $closing->period_end?->format('d M Y') ?? $status['period_end']->format('d M Y'); $profitMargin = (float) $closing->total_sale > 0 ? ((float) $closing->net_profit / (float) $closing->total_sale) * 100 : 0; $trendMax = max(1, collect($trend['revenue'])->merge($trend['expenses'])->max()); $netWorthItems = collect([ ['label' => 'Inventory', 'amount' => (float) $inventory->sum('pkr_value'), 'class' => 'green'], ['label' => 'Bank balance', 'amount' => (float) $bankAccounts->sum('pkr_balance'), 'class' => 'blue'], ['label' => 'Collectible', 'amount' => (float) $collectibles->sum('pkr_outstanding'), 'class' => 'purple'], ['label' => 'In transit', 'amount' => (float) ($assets['in_transit_total'] ?? $assets['in_transit_amount'] ?? 0), 'class' => 'pink'], ['label' => 'Total debt', 'amount' => -1 * (float) ($assets['liabilities_total'] ?? 0), 'class' => 'red'], ]); $netWorthMax = max(1, $netWorthItems->max(fn ($row) => abs((float) $row['amount']))); $expenseTotal = max(1, (float) $expenseBreakdown->sum('amount_pkr')); $expenseColors = ['#2f7ed8', '#008000', '#e576a7', '#f5a400', '#22b98f', '#fb6a3a', '#5142ad', '#94a3b8']; $expenseStops = []; $expenseCursor = 0.0; foreach ($expenseBreakdown->take(8)->values() as $i => $row) { $share = ((float) $row['amount_pkr'] / $expenseTotal) * 100; $expenseStops[] = $expenseColors[$i % count($expenseColors)].' '.$expenseCursor.'% '.($expenseCursor + $share).'%'; $expenseCursor += $share; } $expenseDonut = $expenseStops ? 'conic-gradient('.implode(',', $expenseStops).')' : 'conic-gradient(#e5e7eb 0 100%)'; $productSoldRows = $products->filter(fn ($row) => (float) ($row['sold'] ?? 0) > 0)->sortByDesc('sold')->take(12)->values(); $productProfitRows = $products->filter(fn ($row) => abs((float) ($row['profit_pkr'] ?? 0)) > 0)->sortByDesc('profit_pkr')->take(8)->values(); $inventoryChartRows = $inventory->filter(fn ($row) => (float) ($row['pkr_value'] ?? 0) > 0)->sortByDesc('pkr_value')->take(14)->values(); $productSoldMax = max(1, (float) $productSoldRows->max('sold')); $productProfitMax = max(1, (float) $productProfitRows->max(fn ($row) => abs((float) ($row['profit_pkr'] ?? 0)))); $inventoryChartMax = max(1, (float) $inventoryChartRows->max('pkr_value')); $b2cOrderMax = max(1, collect($b2c['trend']['orders'] ?? [])->max()); $b2cProfitMax = max(1, collect($b2c['trend']['profit'] ?? [])->map(fn ($amount) => abs((float) $amount))->max()); $pointProductRows = collect($points['by_product'] ?? collect())->take(8)->values(); $pointProductMax = max(1, $pointProductRows->max(fn ($row) => max((float) ($row['quarterly'] ?? 0), (float) ($row['yearly'] ?? 0)))); $delta = fn ($current, $prev) => (float) $prev != 0.0 ? (((float) $current - (float) $prev) / abs((float) $prev)) * 100 : null; $fmtDelta = function ($current, $prev) use ($delta) { $value = $delta($current, $prev); if ($value === null) { return 'No previous month'; } return ($value >= 0 ? '+' : '').number_format($value, 1).'% vs previous month'; }; @endphp @push('styles') @endpush
{{ $settings['business_name'] ?? 'Examism Voucher Business' }}
{{ $closing->month->format('F Y') }} Monthly Business Report
Covered period: {{ $periodStart }} to {{ $periodEnd }}
Closed {{ $closing->closed_at?->format('d M Y, H:i') }} {{ $closing->accounts_closed_count }}/{{ $closing->accounts_required_count }} accounts closed

Executive Summary

Locked closing figures plus live balance-sheet detail
Revenue / Total Sale
{{ $metrics->money($closing->total_sale, 'PKR') }}
{{ $fmtDelta($closing->total_sale, $previous['total_sale']) }}
Expenses
{{ $metrics->money($closing->expense, 'PKR') }}
{{ $fmtDelta($closing->expense, $previous['expense']) }}
Net Profit
{{ $metrics->money($closing->net_profit, 'PKR') }}
{{ number_format($profitMargin, 1) }}% margin
Company Net Worth
{{ $metrics->money($closing->net_worth, 'PKR') }}
Captured at month close
Total Debt
{{ $metrics->money(($assets['liabilities_total'] ?? 0), 'PKR') }}
Cards + active debts
Inventory Value
{{ $metrics->money($inventory->sum('pkr_value'), 'PKR') }}
{{ number_format($inventory->sum('stock')) }} units in source inventory
Bank Balance
{{ $metrics->money($bankAccounts->sum('pkr_balance'), 'PKR') }}
{{ $bankAccounts->count() }} active accounts
Collectibles
{{ $metrics->money($collectibles->sum('pkr_outstanding'), 'PKR') }}
{{ $collectibles->count() }} open / partial
Store Credit Outstanding
{{ $metrics->money(($assets['store_credit_amount'] ?? 0), 'PKR') }}
From finance dashboard source

Financials & Growth

CoreRevenue, expenses and profit trend - last 6 months
Revenue vs Expenses
Monthly, last 6 months (PKR)
@foreach($trend['labels'] as $i => $label) @php $revenueHeight = max(3, ((float) $trend['revenue'][$i] / $trendMax) * 150); $expenseHeight = max(3, ((float) $trend['expenses'][$i] / $trendMax) * 150); @endphp
{{ \Illuminate\Support\Str::before($label, ' ') }}
@endforeach
Revenue Expenses
Net Profit & Margin
Monthly profit bars with margin shown in the titles
@foreach($trend['labels'] as $i => $label) @php $net = (float) $trend['revenue'][$i] - (float) $trend['expenses'][$i]; $margin = (float) $trend['revenue'][$i] > 0 ? ($net / (float) $trend['revenue'][$i]) * 100 : 0; $netHeight = max(3, (abs($net) / $trendMax) * 150); @endphp
{{ \Illuminate\Support\Str::before($label, ' ') }}
@endforeach
Net Worth Composition
Assets minus liabilities = {{ $metrics->money($closing->net_worth, 'PKR') }}
@foreach($netWorthItems as $item) @php $width = max(3, (abs((float) $item['amount']) / $netWorthMax) * 100); $isNegative = (float) $item['amount'] < 0; @endphp
{{ $item['label'] }}
@if(abs((float) $item['amount']) > 0) {{ $metrics->money(abs((float) $item['amount']), 'PKR') }} @endif
{{ $isNegative ? '-' : '' }}{{ $metrics->money(abs((float) $item['amount']), 'PKR') }}
@endforeach
Net worth {{ $metrics->money($closing->net_worth, 'PKR') }}
Expense Breakdown
This month, by category
@forelse($expenseBreakdown->take(8)->values() as $i => $row) @php $share = ((float) $row['amount_pkr'] / $expenseTotal) * 100; @endphp
{{ $row['label'] }} {{ $metrics->money($row['amount_pkr'], 'PKR') }}
@empty
No expenses recorded for this period.
@endforelse

Bank Balances by Account

LiveAcross all regions, PKR-equivalent shown for comparison
@foreach($bankAccounts->groupBy('currency') as $currency => $rows)
{{ $currency === 'PKR' ? 'Pakistan Banks' : ($currency === 'AUD' ? 'Australian Banks' : 'US Banks') }} ({{ $currency }})
{{ $metrics->money($rows->sum('native_balance'), $currency) }}
{{ $metrics->money($rows->sum('pkr_balance'), 'PKR') }} equivalent - {{ $rows->count() }} accounts
@endforeach

Account Balances

@foreach($bankAccounts->sortByDesc('pkr_balance') as $row) @endforeach
AccountGroupBankNative BalancePKR Eq.
{{ $row['name'] }}{{ $row['category'] }}{{ $row['bank'] }}{{ $metrics->money($row['native_balance'], $row['currency']) }}{{ $metrics->money($row['pkr_balance'], 'PKR') }}

Credit Cards & Payment Providers

Liability and settlement pipeline

Credit Card Utilisation

@foreach($creditCards as $card) @endforeach
CardPayableLimitUtil.
{{ $card['name'] }}{{ $metrics->money($card['payable'], $card['currency']) }}{{ $metrics->money($card['limit'], $card['currency']) }}{{ number_format($card['utilization'], 1) }}%

Payment Provider Pipeline

@foreach($providers as $provider) @endforeach
ProviderCollected TodayPending Settlement
{{ $provider['name'] }}{{ $metrics->money($provider['collected'], 'PKR') }}{{ $metrics->money($provider['pending'], 'PKR') }}

Product Performance

ProductSales volume, profit, and inventory on month-end closing
Units Sold by Product
Vouchers sold this period
@forelse($productSoldRows as $row) @php $width = max(2, ((float) $row['sold'] / $productSoldMax) * 100); @endphp
{{ $row['name'] }}
{{ number_format((float) $row['sold']) }} vouchers
@empty
No product sales found for this period.
@endforelse
Estimated Profit by Product
(Avg selling - avg buying - points) x sold (PKR)
@forelse($productProfitRows as $row) @php $profit = (float) ($row['profit_pkr'] ?? 0); $width = max(2, (abs($profit) / $productProfitMax) * 100); @endphp
{{ $row['name'] }}
{{ $profit < 0 ? '-' : '' }}{{ $metrics->money(abs($profit), 'PKR') }}
@empty
No product profit rows found for this period.
@endforelse
Inventory Value on Closing
Stock held at month-end, by product (PKR)
@forelse($inventoryChartRows as $row) @php $width = max(2, ((float) $row['pkr_value'] / $inventoryChartMax) * 100); @endphp
{{ $row['name'] }}
{{ $metrics->money($row['pkr_value'], 'PKR') }}
@empty
No inventory value found.
@endforelse

Product Ledger

@forelse($products as $row) @empty @endforelse
ProductOrdersSoldRevenueCOGSProfitAvg Selling / Voucher
{{ $row['name'] }} {{ $row['orders'] }} {{ number_format($row['sold']) }} {{ $metrics->money($row['revenue_pkr'], 'PKR') }} {{ $metrics->money($row['cogs_pkr'] ?? 0, 'PKR') }} {{ $metrics->money($row['profit_pkr'] ?? 0, 'PKR') }} {{ $metrics->money($row['avg_selling_pkr'], 'PKR') }}
No invoice product rows for this period.

Inventory Value On Closing

@foreach($inventory->sortByDesc('pkr_value') as $row) @endforeach
ProductIn StockAvg CostInventory Value
{{ $row['name'] }}{{ number_format($row['stock']) }}{{ $metrics->money($row['cost_price'], $row['currency']) }}{{ $metrics->money($row['pkr_value'], 'PKR') }}

Top Buying Clients

Highest-volume clients per product

{{ $topClients->first()['product'] ?? 'Product' }} - Top Clients

{{ $topClients->count() }} active client{{ $topClients->count() === 1 ? '' : 's' }} ranked by voucher usage
@forelse($topClients as $row) @empty @endforelse
ClientInstituteOrdersVouchersLast Order
{{ $row['client'] }} {{ $row['institute'] ?: '-' }} {{ number_format((int) $row['orders']) }} {{ number_format((float) $row['vouchers']) }} {{ ! empty($row['last_order']) ? \Illuminate\Support\Carbon::parse($row['last_order'])->format('d M') : '-' }}
No portal client rows found for this period.
Client rows are pulled from the portal point ledger for this closed month.

Direct Student Sales (B2C)

Retail ChannelVouchers sold directly to students, not through agents/institutes
Direct Student Orders
{{ number_format((int) $b2c['orders']) }}
@if($b2c['orders_delta'] !== null) {{ (float) $b2c['orders_delta'] >= 0 ? '+' : '' }}{{ number_format((float) $b2c['orders_delta'], 1) }}% vs prev. month @else No previous month @endif
Total B2C Profit (Mo.)
{{ $metrics->money($b2c['profit'], 'PKR') }}
From direct student orders
B2C Revenue (Mo.)
{{ $metrics->money($b2c['revenue'], 'PKR') }}
Gross sales to students
Avg Profit / Voucher
{{ $metrics->money($b2c['avg_profit_per_voucher'], 'PKR') }}
{{ number_format((int) $b2c['vouchers']) }} direct vouchers
B2C Orders by Month
Direct student orders - last 6 months
@foreach(($b2c['trend']['labels'] ?? []) as $i => $label) @php $height = max(3, ((float) ($b2c['trend']['orders'][$i] ?? 0) / $b2cOrderMax) * 150); @endphp
{{ \Illuminate\Support\Str::before($label, ' ') }}
@endforeach
B2C Profit by Month
Profit from direct student sales - last 6 months (PKR)
@foreach(($b2c['trend']['labels'] ?? []) as $i => $label) @php $profit = (float) ($b2c['trend']['profit'][$i] ?? 0); $height = max(3, (abs($profit) / $b2cProfitMax) * 150); @endphp
{{ \Illuminate\Support\Str::before($label, ' ') }}
@endforeach

Per-Voucher Direct Profit by Product

@forelse($b2c['products'] as $row) @empty @endforelse
ProductDirect OrdersStudent PriceAvg BuyingProfit / VoucherTotal Direct Profit
{{ $row['product'] }} {{ number_format((int) $row['direct_orders']) }} {{ $metrics->money($row['student_price'], 'PKR') }} {{ $metrics->money($row['avg_buying'], 'PKR') }} {{ $metrics->money($row['profit_per_voucher'], 'PKR') }} {{ $metrics->money($row['total_profit'], 'PKR') }}
No direct student sales found for this period.

Points Issued

Quarterly / YearlyProduct-wise and agent-wise points redemption tracking
Points by Product
Quarterly vs yearly issued (PKR)
@forelse($pointProductRows as $row) @php $quarterHeight = max(3, ((float) ($row['quarterly'] ?? 0) / $pointProductMax) * 150); $yearHeight = max(3, ((float) ($row['yearly'] ?? 0) / $pointProductMax) * 150); @endphp
{{ \Illuminate\Support\Str::limit($row['product'], 10) }}
@empty
No points issued for this period.
@endforelse
Quarterly Yearly
{{ $pointProductRows->first()['product'] ?? 'Product' }} Points Summary
{{ $closing->month->format('F Y') }} issued and redeemed points
Quarterly Points
{{ $metrics->money($points['summary']['quarterly'] ?? 0, 'PKR') }}
Yearly Points
{{ $metrics->money($points['summary']['yearly'] ?? 0, 'PKR') }}
Total Points
{{ $metrics->money($points['summary']['total'] ?? 0, 'PKR') }}
Redeemed Points
{{ $metrics->money($points['summary']['redeemed'] ?? 0, 'PKR') }}
Profit / Voucher
{{ $metrics->money($pointProductRows->first()['profit_per_voucher'] ?? 0, 'PKR') }}
Total Profit
{{ $metrics->money($products->sum('profit_pkr'), 'PKR') }}

Agent-wise Targets & Achievement

@forelse($points['agent_targets'] as $row) @php $target = max(1, (float) ($row['target'] ?? 0)); $achieved = (float) ($row['achieved'] ?? 0); $progress = min(100, ($achieved / $target) * 100); @endphp @empty @endforelse
AgentInstituteAchievedTarget ProgressYearly TargetAvg SellingProfit / Voucher
{{ $row['agent'] }} {{ $row['institute'] ?: '-' }} {{ number_format($achieved) }}/{{ number_format($target) }}
{{ number_format($progress, 0) }}%
{{ $metrics->money($row['yearly_target'] ?? 0, 'PKR') }} {{ $metrics->money($row['avg_selling'] ?? 0, 'PKR') }} {{ $metrics->money($row['profit_per_voucher'] ?? 0, 'PKR') }}
No agent point targets found for this period.

Support & Tickets

Needs Support-Desk FeedTicket volume, response and resolution SLAs
Tickets Opened
{{ number_format((int) $support['tickets_opened']) }}
Tickets Resolved
{{ number_format((int) $support['tickets_resolved']) }}
Avg First Response
{{ $support['avg_first_response'] }}
Avg Resolution Time
{{ $support['avg_resolution_time'] }}
@if(! $support['connected'])
No support-desk database/feed is connected in this app yet. The report section is ready and will populate when a ticket source is added.
@endif

Receivables, Debts & Giving

Collectibles, active debts, factory, charity and zakaat
Factory Revenue
{{ $metrics->money($factory['revenue'], 'PKR') }}
Factory Expense
{{ $metrics->money($factory['expense'], 'PKR') }}
Zakaat Estimate
{{ $metrics->money($factory['zakat'], 'PKR') }}
2.5% of positive net worth
Charity Estimate
{{ $metrics->money($factory['charity'], 'PKR') }}
2% of positive net profit

Open Collectibles

@forelse($collectibles as $row) @empty @endforelse
PartyOutstandingDue
{{ $row['party'] }}{{ $row['business'] ? ' · '.$row['business'] : '' }}{{ $metrics->money($row['outstanding'], $row['currency']) }}{{ $row['due'] }}
No open collectibles.

Active Debts

@forelse($debts as $row) @empty @endforelse
DebtTypeOutstanding
{{ $row['name'] }}{{ $row['lender'] ? ' · '.$row['lender'] : '' }}{{ $row['type'] }}{{ $metrics->money($row['amount'], $row['currency']) }}
No active debts.

Closing Checklist

@foreach($status['rows'] as $row) @endforeach
AccountTypeStatus
{{ $row['name'] }}
{{ $row['subtitle'] }}
{{ $row['type_label'] ?? ($row['kind'] === 'bank' ? 'Bank' : 'Credit') }} @if($row['is_closed'])Closed {{ $row['closing']?->closed_at?->format('d M Y') }}@elseOpen@endif

Report Notes

This report is generated from the locked monthly closing snapshot and the finance database records available for the same period. Closing KPIs use the saved snapshot; live balance-sheet sections use current account, debt, card, inventory, provider and collectible records.
@endsection