*/ public function share(Request $request): array { return [ ...parent::share($request), 'auth' => [ 'user' => $request->user()?->load(['contractor', 'employeeProfile', 'customerProfile']), 'roles' => $request->user()?->getRoleNames() ?? [], 'permissions' => $request->user()?->getAllPermissions()->pluck('name') ?? [], ], 'flash' => [ 'success' => $request->session()->get('success'), 'error' => $request->session()->get('error'), ], 'sidebarBadges' => fn () => $request->user() ? (function () use ($request) { $user = $request->user(); // Drafts belong to their creator. Submitted requests are // relevant only when the current user is an assigned approver. $ownDraftRequisitions = MaterialRequisition::where('status', 'draft') ->where('requested_by', $user->id) ->count(); $assignedRequisitionApprovals = ApprovalChain::where('status', 'pending') ->where('type', 'material_requisition') ->whereHas('steps', function ($query) use ($user) { $query->where('approver_id', $user->id) ->where('status', 'pending'); }) ->count(); $ownDraftPurchaseOrders = PurchaseOrder::where('status', 'draft') ->where('requested_by', $user->id) ->count(); $isAdmin = $user->user_type === 'admin' || $user->hasRole(['Super Admin', 'admin', 'Main Contractor Admin']); $assignedApprovalsQuery = ApprovalChain::where('status', 'pending') ->whereHas('steps', function ($query) use ($user) { $query->where('approver_id', $user->id) ->where('status', 'pending'); }); if ($user->hasRole('Project Manager') && !$isAdmin) { $assignedApprovalsQuery->where(function ($q) { $q->whereNull('type') ->orWhere('type', '!=', 'project_estimation'); })->where('approvable_type', '!=', Project::class); } $assignedApprovals = $assignedApprovalsQuery->count(); return [ 'pending_requisitions' => $ownDraftRequisitions + $assignedRequisitionApprovals, 'pending_purchase_orders' => $ownDraftPurchaseOrders, 'pending_approvals' => $assignedApprovals, ]; })() : null, 'projectOptions' => fn () => $request->user() ? Project::where('current_wizard_step', '>=', 7) ->with('parentProject:id,ulid,name,code') ->get(['id', 'ulid', 'name', 'code', 'project_type', 'parent_project_id', 'status']) : [], 'unconfirmed_payments' => fn () => $request->user() ? (function () use ($request) { $user = $request->user(); $isSiteOps = $user->hasAnyRole([ 'Site Technical', 'Construction Supervisor', 'Site Operations', 'Site Engineer', 'Site Supervisor', ]); if ($isSiteOps) { return ['count' => 0, 'total_amount' => 0, 'items' => []]; } $userType = strtolower($user->user_type ?? ''); $roles = strtolower($user->getRoleNames()->implode(',')); $isExecutive = in_array($userType, ['admin', 'super_admin', 'project_manager']) || $user->hasAnyRole(['Super Admin', 'admin', 'Admin', 'Project Manager', 'Executive']); $visibleProjectIds = Project::query()->pluck('projects.id')->all(); $pendingInvoices = \Modules\FinancialManagement\Models\FinancialInvoice::with('project:id,name,code') ->whereIn('project_id', $visibleProjectIds) ->where('status', 'payment_sent') ->get(['id', 'ulid', 'invoice_number', 'project_id', 'total_amount', 'retention_amount', 'status', 'payment_proof_path', 'payment_proof_name', 'payment_proof_submitted_at']) ->map(fn ($inv) => [ 'id' => 'inv_' . $inv->id, 'ulid' => $inv->ulid, 'number' => $inv->invoice_number, 'project_name' => $inv->project?->name ?? 'Project', 'amount' => (float) $inv->total_amount, 'retention_amount' => (float) $inv->retention_amount, 'has_proof' => !empty($inv->payment_proof_path), 'proof_name' => $inv->payment_proof_name, 'type' => 'invoice', 'confirm_url' => route('finance.receive-payment', $inv->ulid), 'view_url' => route('finance.show', $inv->ulid), ]); $pendingRetentions = \Modules\FinancialManagement\Models\RetentionEntry::with('project:id,name,code') ->whereIn('project_id', $visibleProjectIds) ->where('type', 'credit') ->whereIn('status', ['payment_sent', 'submitted']) ->get(['id', 'ulid', 'project_id', 'amount', 'status', 'description', 'media_path', 'media_original_name']) ->map(fn ($ret) => [ 'id' => 'ret_' . $ret->id, 'ulid' => $ret->ulid, 'number' => 'Retention Release', 'project_name' => $ret->project?->name ?? 'Project', 'amount' => (float) $ret->amount, 'type' => 'retention', 'status' => $ret->status, 'confirm_url' => route('retention.confirm', $ret->ulid), 'view_url' => route('retention.index'), ]); $merged = $pendingInvoices->concat($pendingRetentions); return [ 'count' => $merged->count(), 'total_amount' => (float) $merged->sum('amount'), 'items' => $merged->values()->all(), ]; })() : ['count' => 0, 'total_amount' => 0, 'items' => []], 'retention_reminders' => fn () => $request->user() ? (function () use ($request) { $user = $request->user(); $isSiteOps = $user->hasAnyRole([ 'Site Technical', 'Construction Supervisor', 'Site Operations', 'Site Engineer', 'Site Supervisor', ]); if ($isSiteOps) { return ['count' => 0, 'items' => []]; } $userType = strtolower($user->user_type ?? ''); $roles = strtolower($user->getRoleNames()->implode(',')); $isExecutive = in_array($userType, ['admin', 'super_admin', 'project_manager']) || $user->hasAnyRole(['Super Admin', 'admin', 'Admin', 'Project Manager', 'Executive']); $visibleProjectIds = Project::query()->pluck('projects.id')->all(); if ($isExecutive) { // Remind Executive to check payment received when payment proof is submitted $proofSubmittedInvoices = \Modules\FinancialManagement\Models\FinancialInvoice::with('project:id,name,code') ->whereIn('project_id', $visibleProjectIds) ->where('status', 'payment_sent') ->whereNotNull('payment_proof_submitted_at') ->get(['id', 'ulid', 'invoice_number', 'project_id', 'total_amount', 'retention_amount', 'penalty_amount', 'payment_proof_name', 'payment_proof_submitted_at']) ->map(fn ($inv) => [ 'id' => 'inv_proof_' . $inv->id, 'ulid' => $inv->ulid, 'invoice_number' => $inv->invoice_number, 'project_name' => $inv->project?->name ?? 'Project', 'amount' => (float) $inv->total_amount, 'retention_amount' => (float) $inv->retention_amount + (float) $inv->penalty_amount, 'base_retention_amount' => (float) $inv->retention_amount, 'penalty_amount' => (float) $inv->penalty_amount, 'role_target' => 'executive', 'action_type' => 'check_payment_received', 'title' => 'Payment Received Check Needed', 'message' => "Contractor submitted payment proof for Invoice {$inv->invoice_number}. Please check and confirm receipt.", 'view_url' => route('finance.show', $inv->ulid), ]); return [ 'count' => $proofSubmittedInvoices->count(), 'items' => $proofSubmittedInvoices->values()->all(), ]; } else { // Remind Contractor Admin to pay 10% and send payment proof for approved invoices $awaitingProofInvoices = \Modules\FinancialManagement\Models\FinancialInvoice::with('project:id,name,code') ->whereIn('project_id', $visibleProjectIds) ->whereIn('status', ['approved', 'sent']) ->whereNull('payment_proof_submitted_at') ->get(['id', 'ulid', 'invoice_number', 'project_id', 'total_amount', 'retention_amount', 'penalty_amount', 'retention_rate']) ->map(fn ($inv) => [ 'id' => 'inv_pay_' . $inv->id, 'ulid' => $inv->ulid, 'invoice_number' => $inv->invoice_number, 'project_name' => $inv->project?->name ?? 'Project', 'amount' => (float) $inv->total_amount, 'retention_amount' => (float) $inv->retention_amount + (float) $inv->penalty_amount, 'base_retention_amount' => (float) $inv->retention_amount, 'penalty_amount' => (float) $inv->penalty_amount, 'retention_rate' => (float) $inv->retention_rate, 'role_target' => 'contractor', 'action_type' => 'send_payment_proof', 'title' => '10% Payment & Proof Reminder', 'message' => "Invoice {$inv->invoice_number} is approved. Please remit the payment" . ((float) $inv->penalty_amount > 0 ? " (including penalty)" : "") . " and upload payment proof.", 'view_url' => route('finance.show', $inv->ulid), ]); return [ 'count' => $awaitingProofInvoices->count(), 'items' => $awaitingProofInvoices->values()->all(), ]; } })() : ['count' => 0, 'items' => []], ]; } }