name('landing'); // Guest Routes (Authentication) Route::middleware('guest')->group(function () { Route::get('/login', [SimpleLoginController::class, 'showLoginForm'])->name('login'); Route::post('/login', [SimpleLoginController::class, 'login'])->middleware('throttle:5,1'); // Limit 5 attempts per minute }); Route::get('/dev-login', function () { auth()->loginUsingId(2); return redirect('/gmail-inbox'); }); Route::post('/logout', [SimpleLoginController::class, 'logout'])->name('logout')->middleware('auth'); // ================== WhatsApp (CRM) ================== use App\Http\Controllers\Whatsapp\OnboardingController; use App\Http\Controllers\Whatsapp\WebhookController; use App\Http\Controllers\Whatsapp\AccountsController; use App\Http\Controllers\Whatsapp\MessagesController; use App\Http\Controllers\Whatsapp\InboxController; use App\Http\Controllers\Whatsapp\SyncController; use App\Http\Controllers\Whatsapp\TemplateController; // CSRF (para desactivar donde aplique) use App\Http\Middleware\VerifyCsrfToken as AppCsrf; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as FrameworkCsrf; /* ========================================================================== | Webhooks públicos (Meta → CRM) |========================================================================== */ Route::get('/webhooks/whatsapp', [WebhookController::class, 'verify']); // GET Verify Route::post('/webhooks/whatsapp', [WebhookController::class, 'receive']) ->withoutMiddleware([AppCsrf::class, FrameworkCsrf::class]); // POST (sin CSRF) /* ========================================================================== | WhatsApp Public / Service Routes (Connection & Onboarding) |========================================================================== */ Route::prefix('whatsapp')->name('whatsapp.')->group(function () { Route::get('/onboarding/start', [OnboardingController::class, 'start'])->name('onboarding.start'); Route::get('/onboarding/status', [OnboardingController::class, 'status'])->name('onboarding.status'); Route::get('/onboarding/callback', [OnboardingController::class, 'callback'])->name('onboarding.callback'); Route::post('/onboarding/disconnect', [OnboardingController::class, 'disconnect']) ->name('onboarding.disconnect') ->withoutMiddleware([AppCsrf::class, FrameworkCsrf::class]); // Sincronización de contactos + historial Route::post('/sync-history', [SyncController::class, 'syncHistory']) ->name('sync-history') ->withoutMiddleware([AppCsrf::class, FrameworkCsrf::class]); // Endpoint interno de captura (ya estaba público, lo agrupamos aquí) Route::post('/onboarding/capture', [OnboardingController::class, 'capture']) ->name('onboarding.capture') ->withoutMiddleware([AppCsrf::class, FrameworkCsrf::class]); }); // Citas public download Route::get('/citas/public/{cita}/ics', [\App\Http\Controllers\CitaController::class, 'exportIcs'])->name('citas.public.ics'); /* -------------------------------------------------------------------------- | Protected Routes (Authenticated Users) |-------------------------------------------------------------------------- */ Route::middleware('auth')->group(function () { /* -------------------------------------------------------------------------- | Dashboards & Templates (Access Dashboard Permission) |-------------------------------------------------------------------------- */ Route::middleware('permission:access dashboard')->group(function () { Route::controller(DashboardController::class)->group(function () { Route::get('/dashboard', 'index')->name('index'); }); /* -------------------------------------------------------------------------- | Páginas wowdash existentes (sin cambios) |-------------------------------------------------------------------------- */ require __DIR__.'/wowdash.php'; // User Management (Real CRUD) Route::controller(UserManagementController::class)->middleware('permission:manage users')->group(function () { Route::get('/usuarios', 'index')->name('usuarios.index'); Route::post('/usuarios', 'store')->name('usuarios.store'); Route::get('/usuarios/{id}', 'show')->name('usuarios.show'); Route::put('/usuarios/{id}', 'update')->name('usuarios.update'); Route::delete('/usuarios/{id}', 'destroy')->name('usuarios.destroy'); }); // Company Management (Real CRUD) Route::resource('empresas', \App\Http\Controllers\EmpresaController::class)->middleware('role:Super Administrador|Admin'); Route::middleware('scope.company')->group(function () { // Client Management (Real CRUD) Route::resource('clientes', \App\Http\Controllers\ClienteController::class)->except(['create', 'edit']); // Mailjet Senders Management (Real CRUD) Route::resource('mailjet-remitentes', \App\Http\Controllers\MailjetRemitenteController::class); Route::post('/mailjet-remitentes/enviar-codigo', [\App\Http\Controllers\MailjetRemitenteController::class, 'enviarCodigo'])->name('mailjet-remitentes.enviar-codigo'); Route::post('/mailjet-remitentes/{id}/check-status', [\App\Http\Controllers\MailjetRemitenteController::class, 'checkStatus'])->name('mailjet-remitentes.check-status'); // Listas de Clientes Route::resource('listas', \App\Http\Controllers\ListaController::class); Route::post('/listas/{id}/agregar-clientes', [\App\Http\Controllers\ListaController::class, 'agregarClientes'])->name('listas.agregar-clientes'); Route::delete('/listas/{listaId}/clientes/{clienteId}', [\App\Http\Controllers\ListaController::class, 'eliminarCliente'])->name('listas.eliminar-cliente'); // Email Masivo / Diseñador Route::get('/email-masivo', [\App\Http\Controllers\EmailMasivoController::class, 'index'])->name('email.masivo'); Route::get('/email-masivo/mis-diseños', [\App\Http\Controllers\EmailMasivoController::class, 'misDiseños'])->name('email.mis.diseños'); Route::get('/email-masivo/editar/{diseño}', [\App\Http\Controllers\EmailMasivoController::class, 'editar'])->name('email.editar'); Route::get('/email/diseno/editar/{id}', [\App\Http\Controllers\EmailMasivoController::class, 'editarDiseno'])->name('email.diseno.editar'); Route::get('/email/diseno/enviar/{id}', [\App\Http\Controllers\EmailMasivoController::class, 'mostrarEnvioDiseno'])->name('email.diseno.enviar'); Route::put('/email/diseno/actualizar/{id}', [\App\Http\Controllers\EmailMasivoController::class, 'actualizarDiseno'])->name('email.diseno.actualizar'); Route::delete('/email/diseno/eliminar/{id}', [\App\Http\Controllers\EmailMasivoController::class, 'eliminarDiseno'])->name('email.diseno.eliminar'); Route::get('/email/template/{template}', [\App\Http\Controllers\EmailMasivoController::class, 'getTemplate'])->name('email.template'); Route::post('/email/diseno/guardar', [\App\Http\Controllers\EmailMasivoController::class, 'guardarDiseno'])->name('email.diseno.guardar'); Route::post('/email/diseno/enviar', [\App\Http\Controllers\EmailMasivoController::class, 'enviarDiseno'])->name('email.diseno.enviar.post'); Route::get('/email/listas/ajax', [\App\Http\Controllers\EmailMasivoController::class, 'getListasAjax'])->name('email.listas.ajax'); Route::get('/email/clientes/ajax', [\App\Http\Controllers\EmailMasivoController::class, 'getClientesAjax'])->name('email.clientes.ajax'); Route::get('/email-masivo/estadisticas', [\App\Http\Controllers\EmailMasivoController::class, 'estadisticas'])->name('email.estadisticas'); // Gmail & Corporate Email Route::get('/gmail-inbox', [\App\Http\Controllers\CorreoController::class, 'gmail'])->name('emails.gmail'); Route::get('/gmail/auth', [\App\Http\Controllers\CorreoController::class, 'gmailAuth'])->name('gmail.auth'); Route::get('gmail-auth-verify', [\App\Http\Controllers\CorreoController::class, 'gmailCallback'])->name('gmail.callback'); Route::get('/gmail/logout', [\App\Http\Controllers\CorreoController::class, 'gmailLogout'])->name('gmail.logout'); Route::post('/enviar-correo', [\App\Http\Controllers\CorreoController::class, 'enviar_correo'])->name('correos.enviar'); Route::get('/correos/detalle/{id}', [\App\Http\Controllers\CorreoController::class, 'getMessageDetails'])->name('emails.detalle'); Route::get('/gmail-message/{id}', [\App\Http\Controllers\CorreoController::class, 'getMessageDetails'])->name('emails.gmail-message'); Route::post('/correos/bulk-delete', [\App\Http\Controllers\CorreoController::class, 'bulkDestroy'])->name('correos.bulk-delete'); Route::post('/emails/bulk-destroy', [\App\Http\Controllers\CorreoController::class, 'bulkDestroy'])->name('emails.bulk-destroy'); Route::post('/correos/corporate-config', [\App\Http\Controllers\CorreoController::class, 'saveCorporateConfig'])->name('correos.corporate-config'); Route::post('/corporate-config', [\App\Http\Controllers\CorreoController::class, 'saveCorporateConfig'])->name('corporate.config'); Route::get('/correos/corporate-messages', [\App\Http\Controllers\CorreoController::class, 'getCorporateMessages'])->name('correos.corporate-messages'); Route::get('/corporate-messages', [\App\Http\Controllers\CorreoController::class, 'getCorporateMessages'])->name('corporate.messages'); Route::post('/correos/toggle-label', [\App\Http\Controllers\CorreoController::class, 'toggleLabel'])->name('correos.toggle-label'); Route::post('/correos/corporate-test', [\App\Http\Controllers\CorreoController::class, 'testCorporateConnection'])->name('correos.corporate-test'); Route::post('/corporate-test', [\App\Http\Controllers\CorreoController::class, 'testCorporateConnection'])->name('corporate.test'); Route::post('/correos/corporate-disconnect', [\App\Http\Controllers\CorreoController::class, 'disconnectCorporate'])->name('correos.corporate-disconnect'); Route::post('/corporate-disconnect', [\App\Http\Controllers\CorreoController::class, 'disconnectCorporate'])->name('corporate.disconnect'); // Tracking Management (Real CRUD) Route::resource('seguimientos', \App\Http\Controllers\SeguimientoController::class); Route::get('/clientes/{clienteId}/seguimientos', [\App\Http\Controllers\SeguimientoController::class, 'getSeguimientosByCliente'])->name('clientes.seguimientos'); // Citas (Calendario) Route::get('/citas', [\App\Http\Controllers\CitaController::class, 'index'])->name('citas.index'); Route::get('/citas/data', [\App\Http\Controllers\CitaController::class, 'getCitas'])->name('citas.data'); Route::post('/citas', [\App\Http\Controllers\CitaController::class, 'store'])->name('citas.store'); Route::put('/citas/{cita}', [\App\Http\Controllers\CitaController::class, 'update'])->name('citas.update'); Route::delete('/citas/{cita}', [\App\Http\Controllers\CitaController::class, 'destroy'])->name('citas.destroy'); Route::get('/citas/{cita}/ics', [\App\Http\Controllers\CitaController::class, 'exportIcs'])->name('citas.ics'); Route::post('/citas/{cita}/notificar-whatsapp', [\App\Http\Controllers\CitaController::class, 'notificarWhatsapp'])->name('citas.notificar-whatsapp'); Route::get('/citas/search-invitados', [\App\Http\Controllers\CitaController::class, 'searchInvitados'])->name('citas.search-invitados'); Route::get('/whatsapp/integracion/threads/{threadId}/citas', [\App\Http\Controllers\CitaController::class, 'getCitasByThread'])->name('whatsapp.integracion.threads.citas'); Route::get('/whatsapp/integracion/client-info', [\App\Http\Controllers\Whatsapp\InboxController::class, 'getClientInfo'])->name('whatsapp.integracion.client-info'); Route::post('/whatsapp/integracion/save-client', [\App\Http\Controllers\Whatsapp\InboxController::class, 'saveClient'])->name('whatsapp.integracion.save-client'); Route::get('/whatsapp/integracion/threads/{threadId}/seguimientos', [\App\Http\Controllers\Whatsapp\InboxController::class, 'getThreadSeguimientos'])->name('whatsapp.integracion.threads.seguimientos'); Route::post('/whatsapp/integracion/threads/{threadId}/seguimientos', [\App\Http\Controllers\Whatsapp\InboxController::class, 'saveThreadSeguimiento'])->name('whatsapp.integracion.threads.seguimientos.save'); // Kanban (Funnel) Route::get('kanban', [\App\Http\Controllers\HomeController::class, 'kanban'])->name('kanban'); /* ========================================================================== | UI interna del CRM (inbox, onboarding, cuenta) - View CRM Permission | 👇 No uses 'api.whatsapp' aquí para no exigir headers en navegador |========================================================================= */ Route::prefix('whatsapp')->name('whatsapp.')->middleware('permission:view crm')->group(function () { // Actualizar estado de pivote Route::put('threads/{thread}/pivot-status', [\App\Http\Controllers\Whatsapp\InboxController::class, 'updatePivotStatus']) ->name('threads.update-pivot-status') ->withoutMiddleware([AppCsrf::class, FrameworkCsrf::class]); // Integraciones Route::get('/integrations', [AccountsController::class, 'index'])->name('integrations.index'); Route::put('/integrations/{integration}', [AccountsController::class, 'update'])->name('integrations.update'); Route::delete('/integrations/{integration}', [AccountsController::class, 'destroy'])->name('integrations.destroy'); // Cuenta / WABA Route::get('/account', [AccountsController::class, 'show'])->name('account.show'); Route::post('/account/subscribe', [AccountsController::class, 'subscribe'])->name('account.subscribe'); Route::post('/account/unsubscribe', [AccountsController::class, 'unsubscribe'])->name('account.unsubscribe'); Route::post('/account/rotate-token', [AccountsController::class, 'rotateToken'])->name('account.rotate'); // Templates Route::get('/templates', [TemplateController::class, 'index'])->name('templates.index'); Route::post('/templates/sync', [TemplateController::class, 'syncFromMeta'])->name('templates.sync'); Route::post('/templates', [TemplateController::class, 'store'])->name('templates.store'); Route::get('/templates/{template}', [TemplateController::class, 'show'])->name('templates.show'); Route::post('/templates/{template}/refresh-status', [TemplateController::class, 'refreshStatus'])->name('templates.refresh'); Route::delete('/templates/{template}', [TemplateController::class, 'destroy'])->name('templates.destroy'); // Enviar una plantilla Route::post('/threads/{thread}/template', [MessagesController::class, 'sendTemplate'])->name('messages.sendTemplate'); // Inbox UI Route::get('/inbox', [InboxController::class, 'index'])->name('inbox.index'); Route::get('/inbox/thread/{thread}', [InboxController::class, 'thread'])->name('inbox.thread'); Route::get('/threads', [InboxController::class, 'search'])->name('threads.search'); Route::get('/threads/poll', [InboxController::class, 'poll'])->name('threads.poll'); Route::post('/threads/{thread}/star', [InboxController::class, 'star'])->name('threads.star'); Route::post('/threads/{thread}/read', [InboxController::class, 'markRead'])->name('threads.read'); Route::post('/threads/{thread}/toggle-ai', [InboxController::class, 'toggleAi'])->name('threads.toggle-ai'); // Mensajería UI (CRM) Route::post('/messages/{thread}/send', [MessagesController::class, 'send'])->name('messages.send'); Route::post('/messages/{thread}/attach', [MessagesController::class, 'attach'])->name('messages.attach'); Route::post('/send-test', [MessagesController::class, 'sendTest'])->name('messages.test'); // Media UI (proxy Graph) Route::get('/media/{mediaId}', [MessagesController::class, 'media'])->name('messages.media'); // Alias rápido para abrir el inbox desde el menú Route::get('/chat/whatsapp', [InboxController::class, 'index'])->name('chat.whatsapp'); }); // Asistente Virtual AI Route::get('/ai-assistant/config', [\App\Http\Controllers\AiAssistantConfigController::class, 'edit'])->name('ai-assistant.config'); Route::post('/ai-assistant/config', [\App\Http\Controllers\AiAssistantConfigController::class, 'update'])->name('ai-assistant.config.update'); // SMS Masivo Route::resource('mensajeria', \App\Http\Controllers\SmsController::class); Route::post('/enviar_sms_IPCOM', [\App\Http\Controllers\SmsController::class, 'enviar_sms_IPCOM'])->name('enviar_sms_IPCOM'); Route::post('/enviar-mensaje', [\App\Http\Controllers\SmsController::class, 'enviar_sms'])->name('enviar_sms'); Route::post('/sms/obtener-conversacion', [\App\Http\Controllers\SmsController::class, 'obtenerConversacion'])->name('chat.obtenerMensajesSms'); Route::get('/sms/listas/ajax', [\App\Http\Controllers\SmsController::class, 'getListasSmsAjax'])->name('sms.listas.ajax'); Route::get('/sms/clientes/ajax', [\App\Http\Controllers\SmsController::class, 'getClientesSmsAjax'])->name('sms.clientes.ajax'); Route::get('/sms/listas/{lista}/numbers', [\App\Http\Controllers\SmsController::class, 'getListNumbers'])->name('sms.listas.numbers'); Route::get('/obtenerFechas', [\App\Http\Controllers\SmsController::class, 'obtenerFechas'])->name('fechasMensajes'); }); // End of CRM & company-scoped group }); // End of Dashboard/Templates group }); // End of auth middleware group ℼ佄呃偙⁅瑨汭ਾ格浴慬杮∽獥㸢㰊敨摡ਾ††洼瑥⁡档牡敳㵴唢䙔㠭㸢 †㰠敭慴渠浡㵥瘢敩灷牯≴挠湯整瑮∽楷瑤㵨敤楶散眭摩桴‬湩瑩慩⵬捳污㵥⸱∰ਾ††琼瑩敬㐾㐰ⴠ倠ꇃ楧慮渠湥潣瑮慲慤⼼楴汴㹥 †㰠ⴡ‭潇杯敬䘠湯獴ⴠ㸭 †㰠楬歮爠汥∽牰捥湯敮瑣•牨晥∽瑨灴㩳⼯潦瑮⹳潧杯敬灡獩挮浯㸢 †㰠楬歮爠汥∽牰捥湯敮瑣•牨晥∽瑨灴㩳⼯潦瑮⹳獧慴楴⹣潣≭挠潲獳牯杩湩ਾ††氼湩牨晥∽瑨灴㩳⼯潦瑮⹳潧杯敬灡獩挮浯振獳㼲慦業祬伽瑵楦㩴杷瑨㍀〰㐻〰㔻〰㘻〰搦獩汰祡猽慷≰爠汥∽瑳汹獥敨瑥㸢 †㰠ⴡ‭慔汩楷摮䌠卓漠⁲瑳湡慤摲猠祴楬杮瘠慩䌠乄ⴠ㸭 †㰠捳楲瑰猠捲∽瑨灴㩳⼯摣⹮慴汩楷摮獣⹳潣≭㰾猯牣灩㹴 †㰠捳楲瑰ਾ††††慴汩楷摮挮湯楦⁧‽੻††††††桴浥㩥笠 †††††††攠瑸湥㩤笠 †††††††††映湯䙴浡汩㩹笠 †††††††††††猠湡㩳嬠伧瑵楦❴‬猧湡⵳敳楲❦ⱝ †††††††††素ਬ††††††††੽††††††੽††††੽††⼼捳楲瑰ਾ⼼敨摡ਾ戼摯⁹汣獡㵳戢ⵧ桷瑩⁥整瑸猭慬整㠭〰映湯⵴慳獮洠湩栭猭牣敥汦硥映敬⵸潣瑩浥⵳散瑮牥樠獵楴祦挭湥整⁲⵰‶湡楴污慩敳⁤敳敬瑣潩㩮杢猭慬整ㄭ〰㸢 †㰠楤⁶汣獡㵳洢硡眭洭⁤⵷畦汬琠硥⵴散瑮牥猠慰散礭㠭㸢 †††㰠ⴡ‭楍楮慭楬瑳嘠獩慵ⴭਾ††††搼癩挠慬獳∽灳捡ⵥ⵹∲ਾ††††††格‱汣獡㵳琢硥⵴ㅛ〲硰⁝潦瑮氭杩瑨氠慥楤杮渭湯⁥牴捡楫杮琭杩瑨牥琠硥⵴汳瑡ⵥ〲‰敳敬瑣渭湯≥㐾㐰⼼ㅨਾ††††††格′汣獡㵳琢硥⵴砲潦瑮洭摥畩整瑸猭慬整㤭〰琠慲正湩ⵧ楴桧≴倾ꇃ楧慮渠湥潣瑮慲慤⼼㉨ਾ††††††瀼挠慬獳∽整瑸猭慬整㔭〰琠硥⵴浳洠硡眭砭⁳硭愭瑵敬摡湩ⵧ敲慬數≤ਾ††††††††潌猠湥楴潭ⱳ氠⁡썰枡湩⁡畱⁥畢捳獡渠硥獩整漠栠⁡楳潤洠癯摩⹡ †††††㰠瀯ਾ††††⼼楤㹶ਊ††††ℼⴭ䄠瑣潩畂瑴湯ⴠ㸭 †††㰠楤⁶汣獡㵳瀢⵴∴ਾ††††††愼栠敲㵦⼢•汣獡㵳椢汮湩ⵥ汦硥椠整獭挭湥整⁲番瑳晩⵹散瑮牥瀠⵸‶祰㌭戠牯敤⁲潢摲牥猭慬整㈭〰琠硥⵴浳映湯⵴敭楤浵爠畯摮摥砭整瑸猭慬整㜭〰戠ⵧ桷瑩⁥潨敶㩲杢猭慬整㔭‰潨敶㩲潢摲牥猭慬整㌭〰琠慲獮瑩潩⵮污畤慲楴湯㈭〰猠慨潤⵷浳㸢 †††††††删来敲慳⁲污椠楮楣੯††††††⼼㹡 †††㰠搯癩ਾ††⼼楤㹶㰊戯摯㹹㰊栯浴㹬�