authorizeCockpitView(); $context = $this->resolveCockpitContext($request); $viewData = $this->buildCockpitViewData($context, true); if (function_exists('activity')) { activity('managementtools') ->withProperties([ 'business_id' => $context['businessId'], 'start_date' => $context['startDate']->toDateString(), 'end_date' => $context['endDate']->toDateString(), 'active_tab' => $context['activeTab'], ]) ->log('executive_cockpit_viewed'); } return view('managementtools::executive_cockpit.index', $viewData); } public function content(Request $request) { $this->authorizeCockpitView(); $context = $this->resolveCockpitContext($request); return view('managementtools::executive_cockpit.partials.content', $this->buildCockpitViewData($context, true)); } public function drillTab(Request $request) { $this->authorizeCockpitView(); $context = $this->resolveCockpitContext($request); $tabPayload = $this->cockpitService->buildDrilldownTabForViewer( $context['businessId'], $context['startDate'], $context['endDate'], $context['activeTab'], auth()->user() ); if (! $tabPayload) { abort(404); } return view('managementtools::executive_cockpit.partials.drill_tab_body', [ 'data' => [ 'trend_month_labels' => $tabPayload['trend_month_labels'], 'drilldown_labels' => $tabPayload['drilldown_labels'], ], 'tab_key' => $tabPayload['tab_key'], 'section' => $tabPayload['section'], ]); } public function saveTargets(Request $request) { $this->authorizeCockpitManage(); $businessId = (int) $request->session()->get('user.business_id'); $request->validate([ 'targets.sales_this_month' => 'nullable|numeric', 'targets.gross_margin_estimate' => 'nullable|numeric', 'targets.workforce_productivity' => 'nullable|numeric', ]); $metrics = $request->input('targets', []); foreach (['sales_this_month', 'gross_margin_estimate', 'workforce_productivity'] as $metric) { if (! isset($metrics[$metric]) || $metrics[$metric] === '') { continue; } MtExecutiveTarget::create([ 'business_id' => $businessId, 'metric_key' => $metric, 'target_value' => (float) $metrics[$metric], 'effective_from' => Carbon::today()->toDateString(), 'created_by' => auth()->id(), ]); if (function_exists('activity')) { activity('managementtools') ->withProperties([ 'business_id' => $businessId, 'metric' => $metric, 'target_value' => (float) $metrics[$metric], ]) ->log('executive_target_saved'); } } return redirect()->back()->with('status', ['success' => true, 'msg' => __('managementtools::lang.targets_saved')]); } public function exportPdf(Request $request) { $this->authorizeCockpitView(); $businessId = (int) $request->session()->get('user.business_id'); $start = Carbon::parse($this->mtUtil->parseInputDate($request->input('start_date')) ?: Carbon::today()->subDays(29)->toDateString())->startOfDay(); $end = Carbon::parse($this->mtUtil->parseInputDate($request->input('end_date')) ?: Carbon::today()->toDateString())->endOfDay(); $data = $this->cockpitService->build($businessId, $start, $end); $html = view('managementtools::executive_cockpit.pdf', compact('data'))->render(); $mpdf = new \Mpdf\Mpdf(['tempDir' => storage_path('app/mpdf-temp')]); $mpdf->WriteHTML($html); return Response::make($mpdf->Output('executive-cockpit.pdf', 'S'), 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="executive-cockpit.pdf"', ]); } public function exportBoardPackPdf(Request $request) { $this->authorizeCockpitView(); $businessId = (int) $request->session()->get('user.business_id'); $start = Carbon::parse($this->mtUtil->parseInputDate($request->input('start_date')) ?: Carbon::today()->subDays(29)->toDateString())->startOfDay(); $end = Carbon::parse($this->mtUtil->parseInputDate($request->input('end_date')) ?: Carbon::today()->toDateString())->endOfDay(); $data = $this->cockpitService->build($businessId, $start, $end); if (class_exists(\Modules\IntegrationHub\Events\ExecutiveCockpitExported::class)) { event(new \Modules\IntegrationHub\Events\ExecutiveCockpitExported($businessId, $data)); } $html = view('managementtools::executive_cockpit.board_pack_pdf', compact('data'))->render(); $mpdf = new \Mpdf\Mpdf(['tempDir' => storage_path('app/mpdf-temp')]); $mpdf->WriteHTML($html); return Response::make($mpdf->Output('board-pack.pdf', 'S'), 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="board-pack.pdf"', ]); } public function saveNote(Request $request) { $this->authorizeCockpitManage(); $businessId = (int) $request->session()->get('user.business_id'); $request->validate([ 'title' => 'required|string|max:255', 'note' => 'required|string|max:5000', ]); MtExecutiveNote::create([ 'business_id' => $businessId, 'user_id' => auth()->id(), 'title' => $request->input('title'), 'note' => $request->input('note'), 'note_date' => Carbon::today()->toDateString(), 'visibility' => 'leadership', ]); if (function_exists('activity')) { activity('managementtools') ->withProperties([ 'business_id' => $businessId, 'title' => $request->input('title'), ]) ->log('executive_note_saved'); } return redirect()->back()->with('status', ['success' => true, 'msg' => __('managementtools::lang.note_saved')]); } protected function resolveCockpitContext(Request $request): array { $businessId = (int) $request->session()->get('user.business_id'); $start = $this->mtUtil->parseInputDate($request->input('start_date')) ?: Carbon::today()->subDays(29)->toDateString(); $end = $this->mtUtil->parseInputDate($request->input('end_date')) ?: Carbon::today()->toDateString(); $validTabs = ['finance', 'sales', 'maintenance', 'projects', 'workforce', 'crm', 'accounting', 'manufacturing', 'ie']; $activeTab = in_array($request->input('tab'), $validTabs, true) ? $request->input('tab') : 'finance'; return [ 'businessId' => $businessId, 'startDate' => Carbon::parse($start)->startOfDay(), 'endDate' => Carbon::parse($end)->endOfDay(), 'activeTab' => $activeTab, ]; } protected function buildCockpitViewData(array $context, bool $lazyDrillTabs = false): array { $data = $this->cockpitService->buildForViewer( $context['businessId'], $context['startDate'], $context['endDate'], auth()->user(), $lazyDrillTabs, $context['activeTab'] ); $startDate = $this->mtUtil->formatForInput($context['startDate']->toDateString()); $endDate = $this->mtUtil->formatForInput($context['endDate']->toDateString()); return [ 'data' => $data, 'start_date' => $startDate, 'end_date' => $endDate, 'active_tab' => $context['activeTab'], 'quick_links' => $this->quickLinks(), 'date_presets' => $this->datePresets(), 'export_urls' => $this->exportUrls($startDate, $endDate), 'content_url' => action([self::class, 'content']), 'drill_tab_url' => action([self::class, 'drillTab']), 'lazy_drill_tabs' => true, ]; } protected function quickLinks(): array { return [ ['title' => __('managementtools::lang.open_sales_report'), 'url' => url('/reports/product-sell-report')], ['title' => __('managementtools::lang.open_payment_report'), 'url' => url('/reports/sell-payment-report')], ['title' => __('managementtools::lang.open_maintenance_board'), 'url' => url('/maintenance/dashboard')], ['title' => __('managementtools::lang.open_ticket_center'), 'url' => url('/management-tools/tickets')], ['title' => __('managementtools::lang.open_project_center'), 'url' => url('/management-tools/project-categories')], ['title' => __('managementtools::lang.open_crm_board'), 'url' => url('/crm/dashboard')], ['title' => __('managementtools::lang.open_accounting_dashboard'), 'url' => url('/accounting/dashboard')], ['title' => __('managementtools::lang.open_manufacturing_board'), 'url' => url('/manufacturing/production')], ['title' => __('managementtools::lang.open_ie_dashboard'), 'url' => url('/industrial-engineering/dashboard')], ]; } protected function datePresets(): array { $today = Carbon::today(); return [ [ 'key' => '7d', 'label' => __('managementtools::lang.range_7_days'), 'start' => $this->mtUtil->formatForInput($today->copy()->subDays(6)->toDateString()), 'end' => $this->mtUtil->formatForInput($today->toDateString()), ], [ 'key' => '30d', 'label' => __('managementtools::lang.range_30_days'), 'start' => $this->mtUtil->formatForInput($today->copy()->subDays(29)->toDateString()), 'end' => $this->mtUtil->formatForInput($today->toDateString()), ], [ 'key' => 'month', 'label' => __('managementtools::lang.range_this_month'), 'start' => $this->mtUtil->formatForInput($today->copy()->startOfMonth()->toDateString()), 'end' => $this->mtUtil->formatForInput($today->toDateString()), ], ]; } protected function exportUrls(string $startDate, string $endDate): array { $urls = [ 'board_pack' => action([self::class, 'exportBoardPackPdf'], [ 'start_date' => $startDate, 'end_date' => $endDate, ]), 'pdf' => action([self::class, 'exportPdf'], [ 'start_date' => $startDate, 'end_date' => $endDate, ]), ]; if (\Module::has('IntegrationHub') && \Module::isEnabled('IntegrationHub') && auth()->user()->can('integrationhub.export')) { $urls['bi_exports'] = url('/integrationhub/exports'); } return $urls; } protected function authorizeCockpitView(): void { if ( ! auth()->user()->can('managementtools.access') || ! auth()->user()->can('managementtools.daily_report_all') || ! auth()->user()->can('managementtools.board_view') ) { abort(403, 'Unauthorized action.'); } } protected function authorizeCockpitManage(): void { if ( ! auth()->user()->can('managementtools.access') || ! auth()->user()->can('managementtools.daily_report_all') || ! auth()->user()->can('managementtools.board_manage') ) { abort(403, 'Unauthorized action.'); } } }