File: /var/www/api_matriculas/routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Log;
use App\Http\Middleware\VerifyCsrfToken;
// ===============================
// 🔹 Auth
// ===============================
use App\Http\Controllers\AuthController;
// ===============================
// 🔹 Core Controllers
// ===============================
use App\Http\Controllers\{
ConfigurationController,
ContractController,
ContractFormatController,
CountryController,
CourseController,
PresencialController,
CourseLetterController,
DashboardController,
EnrollmentConfigController,
ExcelUploadController,
ExcelUploadLineController,
GenderController,
MyProfileController,
ParentController,
PeriodController,
PeriodPricingController,
PostulationController,
ProfileController,
RegionController,
RelationshipController,
ReportController,
StudentController,
UserController,
PaymentConceptConfigController,
WebhookGeneralController
};
use App\Http\Controllers\Odoo\OdooPublicController;
// ===============================
// 🔹 Toku Controllers
// ===============================
use App\Http\Controllers\Toku\{
PaymentMethodController,
CustomerController,
EventsController,
InvoiceController,
PaymentController,
RedirectionController,
SubscriptionController,
TransactionController,
WebhookController
};
use App\Http\Controllers\Toku\webhook\{
WebhookCustomerController,
WebhookInvoiceController,
WebhookPaymentController,
WebhookPaymentIntentController,
WebhookPaymentMethodController,
WebhookPayoutController,
WebhookSubscriptionController,
WebhookTransactionController
};
// ===============================
// 🔹 Signapis Controllers
// ===============================
use App\Http\Controllers\Signapis\{
SignapisDocumentController,
SignapisLogosController,
SignapisNotificationsController,
SignapisReportsController,
SignapisSigninController,
SignapisTemplatesController,
SignapisTestController,
SignapisWebhookController
};
// ===============================
// 🔹 Firmaki Controllers
// ===============================
use App\Http\Controllers\Firmaki\WebhookController as FirmakiWebhookController;
// ===============================
// 🔹 Rutas protegidas por Sanctum
// ===============================
Route::middleware('auth:sanctum')->get('/user', fn(Request $r) => $r->user());
// ===============================
// 🔹 Autenticación
// ===============================
Route::post('/login', [AuthController::class, 'login']);
Route::post('/activate-account', [AuthController::class, 'activateAccount']);
Route::post('/validate-code-account', [AuthController::class, 'validateCodeActivation']);
Route::post('/activate-password', [AuthController::class, 'activatePasswordWithCode']);
Route::post('/recovery', [AuthController::class, 'sendRecoveryCode']);
Route::post('/validate-code', [AuthController::class, 'validateCode']);
Route::post('/reset-password', [AuthController::class, 'resetPassword']);
Route::post('/sign-in', [AuthController::class, 'loginApi']);
Route::post('/logout', [AuthController::class, 'logout']);
// ===============================================
// 🔹 TODO el resto del API (usuarios + integraciones)
// ===============================================
Route::middleware(['auth.any'])->group(function () {
// =======================================
// 🔹 PERFIL / SESIÓN
// =======================================
Route::get('/me', [AuthController::class, 'validateSession']);
Route::get('/me-2/{id}', [AuthController::class, 'getUser']);
// =======================================
// 🔹 MI PERFIL
// =======================================
Route::get('/my-profile', [MyProfileController::class, 'show']);
Route::put('/my-profile', [MyProfileController::class, 'update']);
Route::put('/my-profile/password', [MyProfileController::class, 'updatePassword']);
Route::middleware(['auth.any'])->group(function () {
// =======================================
// 🔹 DASHBOARD
// =======================================
Route::get('/dashboard', [DashboardController::class, 'dashboard']);
// =======================================
// 🔹 CORE CRUD
// =======================================
Route::get('/profiles-list', fn(ProfileController $c) => $c->list(false));
Route::get('/profiles', [ProfileController::class, 'list']);
Route::post('/profiles/store', [ProfileController::class, 'store']);
Route::post('/profiles/permissions-matrix', [ProfileController::class, 'updatePermissionsMatrix']);
Route::get('/profiles/{id}', [ProfileController::class, 'show']);
Route::put('/profiles/{id}', [ProfileController::class, 'update']);
Route::delete('/profiles/{id}', [ProfileController::class, 'destroy']);
Route::get('/permissions', [ProfileController::class, 'getPermissions']);
Route::get('/courses-list', fn(CourseController $c) => $c->list(false));
Route::get('/courses', [CourseController::class, 'list']);
Route::post('/courses/store', [CourseController::class, 'store']);
Route::get('/courses/{id}', [CourseController::class, 'show']);
Route::put('/courses/{id}', [CourseController::class, 'update']);
Route::delete('/courses/{id}', [CourseController::class, 'destroy']);
Route::get('/course-letters-list', fn(CourseLetterController $c) => $c->list(false));
Route::get('/course-letters', [CourseLetterController::class, 'list']);
Route::post('/course-letters/store', [CourseLetterController::class, 'store']);
Route::get('/course-letters/{id}', [CourseLetterController::class, 'show']);
Route::put('/course-letters/{id}', [CourseLetterController::class, 'update']);
Route::delete('/course-letters/{id}', [CourseLetterController::class, 'destroy']);
Route::get('/genders-list', fn(GenderController $c) => $c->list(false));
Route::get('/genders', [GenderController::class, 'list']);
Route::post('/genders/store', [GenderController::class, 'store']);
Route::get('/genders/{id}', [GenderController::class, 'show']);
Route::put('/genders/{id}', [GenderController::class, 'update']);
Route::delete('/genders/{id}', [GenderController::class, 'destroy']);
Route::get('/relationships-list', fn(RelationshipController $c) => $c->list(false));
Route::get('/relationships', [RelationshipController::class, 'list']);
Route::post('/relationships/store', [RelationshipController::class, 'store']);
Route::get('/relationships/{id}', [RelationshipController::class, 'show']);
Route::put('/relationships/{id}', [RelationshipController::class, 'update']);
Route::delete('/relationships/{id}', [RelationshipController::class, 'destroy']);
Route::get('/countries-list', fn(CountryController $c) => $c->list(false));
Route::get('/countries', [CountryController::class, 'list']);
Route::post('/countries/store', [CountryController::class, 'store']);
Route::get('/countries/{id}', [CountryController::class, 'show']);
Route::put('/countries/{id}', [CountryController::class, 'update']);
Route::delete('/countries/{id}', [CountryController::class, 'destroy']);
Route::get('/regions-list', fn(RegionController $c) => $c->list(false));
Route::get('/regions', [RegionController::class, 'list']);
Route::post('/regions/store', [RegionController::class, 'store']);
Route::get('/regions/{id}', [RegionController::class, 'show']);
Route::put('/regions/{id}', [RegionController::class, 'update']);
Route::delete('/regions/{id}', [RegionController::class, 'destroy']);
Route::get('/students', [StudentController::class, 'list']);
Route::post('/students/store', [StudentController::class, 'store']);
Route::get('/students/{id}', [StudentController::class, 'show']);
Route::put('/students/{id}', [StudentController::class, 'update']);
Route::delete('/students/{id}', [StudentController::class, 'destroy']);
Route::put('/students/{studentId}/period/{periodId}/sibling-order-override', [StudentController::class, 'setSiblingOrderOverride']);
Route::get('/parents-list', fn(ParentController $c) => $c->list(true));
Route::get('/parents', [ParentController::class, 'list']);
Route::post('/parents/store', [ParentController::class, 'store']);
Route::get('/parents/{id}', [ParentController::class, 'show']);
Route::put('/parents/{id}', [ParentController::class, 'update']);
Route::delete('/parents/{id}', [ParentController::class, 'destroy']);
Route::get('/users', [UserController::class, 'list']);
Route::post('/users/store', [UserController::class, 'store']);
Route::get('/users/{id}', [UserController::class, 'show']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);
Route::get('/configuration', [ConfigurationController::class, 'showByCode']);
Route::post('/configuration', [ConfigurationController::class, 'storeOrUpdate']);
Route::get('/contract-formats', [ContractFormatController::class, 'list']);
Route::get('/contract-formats/{periodId}', [ContractFormatController::class, 'showByPeriod']);
Route::post('/contract-formats', [ContractFormatController::class, 'storeOrUpdate']);
Route::post('/contract-formats/copy', [ContractFormatController::class, 'copy']);
Route::get('postulations', [PostulationController::class, 'list']);
Route::post('postulations/store', [PostulationController::class, 'store']);
Route::get('postulations/{id}', [PostulationController::class, 'show']);
Route::put('postulations/{id}', [PostulationController::class, 'update']);
Route::delete('postulations/{id}', [PostulationController::class, 'destroy']);
Route::get('periods/my-periods', [PeriodController::class, 'myPeriods']);
Route::get('periods', [PeriodController::class, 'list']);
Route::post('periods', [PeriodController::class, 'store']);
Route::get('periods/{id}', [PeriodController::class, 'show']);
Route::put('periods/{id}', [PeriodController::class, 'update']);
Route::delete('periods/{id}', [PeriodController::class, 'destroy']);
Route::put('/periods/{id}/activate', [PeriodController::class, 'activate']);
Route::put('/periods/{id}/deactivate', [PeriodController::class, 'deactivate']);
Route::get('/get-period', [PeriodController::class, 'getPeriodActivate']);
Route::get('/contracts', [ContractController::class, 'list']);
Route::get('/contracts/incomplete-enrollments', [ContractController::class, 'incompleteEnrollments']);
Route::post('/contracts/recalculate-siblings', [ContractController::class, 'recalculateSiblings']);
Route::get('/contracts/{id}', [ContractController::class, 'show']);
Route::put('/contracts/{code}/update-parent', [ContractController::class, 'updateParent']);
Route::put('/contracts/{code}/change-parent', [ContractController::class, 'changeParent']);
Route::get('/contracts/{code}/get-contract', [ContractController::class, 'showByCode']);
Route::put('/contracts/{code}/signature', [ContractController::class, 'signature']);
Route::post('/contracts/{code}/upload-signed', [ContractController::class, 'uploadSignedPdf']);
Route::post('contracts', [ContractController::class, 'store']);
Route::put('/contracts/{id}', [ContractController::class, 'update']);
Route::delete('/contracts/{id}', [ContractController::class, 'destroy']);
// Route::get('/contracts/{id}/send-pdf', [ContractController::class, 'sendPDF'])->name('contracts.send_pdf');
Route::get('/get-contract', [ContractController::class, 'getContractActive']);
Route::get('/webhook-logs', [WebhookGeneralController::class, 'list']); // Listar Webhooks
// =======================================
// 🔹 REPORTES
// =======================================
Route::prefix('reports')->group(function () {
Route::get('/contracts', [ReportController::class, 'contractsReport']);
Route::get('/contracts/export-excel', [ReportController::class, 'contractsReportExcel']);
Route::get('/financial', [ReportController::class, 'financialReport']);
Route::get('/financial-by-period/{periodId}', [ReportController::class, 'financialReportByPeriod']);
Route::get('/financial/export-excel', [ReportController::class, 'financialReportExcel']);
Route::get('/comparative-multiple', [ReportController::class, 'comparativeReport']);
Route::get('/comparative-multiple/export-excel', [ReportController::class, 'comparativeReportExcel']);
Route::get('/odoo', [ReportController::class, 'odooReport']);
Route::get('/odoo/export-excel', [ReportController::class, 'odooReportExcel']);
});
// =======================================
// Presencial - Flujo agente
// =======================================
Route::prefix('presencial')->group(function () {
Route::get('/available-students/{parentId}', [PresencialController::class, 'availableStudents']);
Route::post('/preview-debts', [PresencialController::class, 'previewDebts']);
Route::post('/contracts', [PresencialController::class, 'createContract']);
Route::post('/payments', [PresencialController::class, 'registerPayment']);
Route::get('/payments/{contractId}', [PresencialController::class, 'getPayments']);
Route::get('/reconciliation', [PresencialController::class, 'reconciliation']);
Route::post('/pos-payment', [PresencialController::class, 'posPayment']);
Route::get('/payment-methods', [PresencialController::class, 'getPaymentMethods']);
Route::put('/payment-methods/{id}', [PresencialController::class, 'updatePaymentMethod']);
Route::get('/subscription-status/{paymentId}', [PresencialController::class, 'getSubscriptionStatus']);
Route::get('/pending-subscriptions/{contractId}', [PresencialController::class, 'getPendingSubscriptions']);
Route::post('/cancel-subscription/{paymentId}', [PresencialController::class, 'cancelSubscription']);
Route::post('/reverse-detail/{detailId}', [PresencialController::class, 'reverseDetail']);
Route::post('/toku-payment', [PresencialController::class, 'tokuPayment']);
Route::post('/toku-cancel/{paymentId}', [PresencialController::class, 'tokuCancel']);
Route::get('/toku-status/{paymentId}', [PresencialController::class, 'tokuStatus']);
Route::get('/pending-toku/{contractId}', [PresencialController::class, 'getPendingToku']);
});
// =======================================
// Integration Logs
// =======================================
Route::get('/integration-logs', function (Request $request) {
$query = \App\Models\ApiIntegrationLog::orderBy('created_at', 'desc');
if ($request->entity_type) $query->where('entity_type', $request->entity_type);
if ($request->status) $query->where('status', $request->status);
if ($request->date_from) $query->whereDate('created_at', '>=', $request->date_from);
if ($request->date_to) $query->whereDate('created_at', '<=', $request->date_to);
return genericResponse(['data' => $query->paginate(50), 'message' => 'ok', 'code' => 200], 200);
});
Route::get('/sync-logs', function (Request $request) {
$query = \App\Models\SyncLog::orderBy('created_at', 'desc');
if ($request->sync_type) $query->where('sync_type', $request->sync_type);
if ($request->status) $query->where('status', $request->status);
if ($request->date_from) $query->whereDate('created_at', '>=', $request->date_from);
if ($request->date_to) $query->whereDate('created_at', '<=', $request->date_to);
return genericResponse(['data' => $query->paginate(50), 'message' => 'ok', 'code' => 200], 200);
});
// =======================================
// Period Pricing Config
// =======================================
Route::prefix('period-pricing')->group(function () {
Route::get('/concept-codes', [PeriodPricingController::class, 'conceptCodes']);
Route::post('/import-excel', [PeriodPricingController::class, 'importExcel']);
Route::post('/copy', [PeriodPricingController::class, 'copy']);
Route::post('/bulk-delete', [PeriodPricingController::class, 'bulkDelete']);
Route::post('/bulk', [PeriodPricingController::class, 'bulkSave']);
Route::get('/{periodId}/export-excel', [PeriodPricingController::class, 'exportExcel']);
Route::get('/{periodId}', [PeriodPricingController::class, 'list']);
Route::post('/', [PeriodPricingController::class, 'store']);
Route::put('/{id}', [PeriodPricingController::class, 'update']);
Route::delete('/{id}', [PeriodPricingController::class, 'destroy']);
});
// =======================================
// Payment Concepts Config
// =======================================
Route::prefix('payment-concepts')->group(function () {
Route::get('/meta/currency-types', [PaymentConceptConfigController::class, 'currencyTypes']);
Route::get('/', [PaymentConceptConfigController::class, 'listConcepts']);
Route::put('/{id}', [PaymentConceptConfigController::class, 'updateConcept']);
Route::get('/{id}/details', [PaymentConceptConfigController::class, 'listDetails']);
Route::post('/{id}/details', [PaymentConceptConfigController::class, 'storeDetail']);
Route::put('/details/{detailId}', [PaymentConceptConfigController::class, 'updateDetail']);
Route::delete('/details/{detailId}', [PaymentConceptConfigController::class, 'destroyDetail']);
});
// =======================================
// Enrollment Period Configs
// =======================================
Route::prefix('enrollment-configs')->group(function () {
Route::get('/{periodId}', [EnrollmentConfigController::class, 'list']);
Route::post('/', [EnrollmentConfigController::class, 'storeOrUpdate']);
Route::put('/{id}/toggle', [EnrollmentConfigController::class, 'toggle']);
Route::delete('/{id}', [EnrollmentConfigController::class, 'destroy']);
});
// Excel Uploads
Route::prefix('excel-uploads')->group(function () {
Route::get('/', [ExcelUploadController::class, 'list']);
Route::get('/stats', [ExcelUploadController::class, 'stats']);
Route::get('/{id}', [ExcelUploadController::class, 'show']);
Route::post('/', [ExcelUploadController::class, 'store']);
Route::put('/{uploadId}/lines/{lineNumber}', [ExcelUploadController::class, 'updateLine']);
Route::post('/{id}/confirm', [ExcelUploadController::class, 'confirm']);
Route::post('/{id}/cancel', [ExcelUploadController::class, 'cancel']);
Route::delete('/{id}', [ExcelUploadController::class, 'destroy']);
Route::post('/{id}/reprocess', [ExcelUploadController::class, 'reprocess']);
Route::get('/{id}/logs', [ExcelUploadController::class, 'getLogs']);
Route::get('/{id}/download-all', [ExcelUploadController::class, 'downloadAllLines']);
});
// Excel Upload Types
Route::prefix('excel-upload-types')->group(function () {
Route::get('/', [ExcelUploadController::class, 'getTypes']);
Route::get('/{code}', [ExcelUploadController::class, 'getTypeDetail']);
Route::get('/{code}/template', [ExcelUploadController::class, 'downloadTemplate']);
Route::get('/{code}/stats', [ExcelUploadController::class, 'getTypeStats']);
});
// Upload Lines
Route::prefix('upload-lines')->group(function () {
Route::get('/', [ExcelUploadLineController::class, 'list']);
Route::get('/{id}', [ExcelUploadLineController::class, 'show']);
Route::post('/bulk-update', [ExcelUploadLineController::class, 'bulkUpdate']);
Route::post('/{id}/restore', [ExcelUploadLineController::class, 'restore']);
// Eliminar lÃnea individual
Route::delete('/{uploadId}/lines/{lineNumber}', [ExcelUploadLineController::class, 'deleteLine']);
// Eliminar múltiples lÃneas
Route::post('/{uploadId}/lines/bulk-delete', [ExcelUploadLineController::class, 'bulkDeleteLines']);
});
});
// ======================================
// 🔹 TOKU ROUTES (internas + webhooks)
// ======================================
Route::prefix('/toku')->group(function () {
// 🔸 Clientes internos (API)
Route::post('customers', [CustomerController::class, 'store']);
Route::put('customers/{id}', [CustomerController::class, 'update']);
Route::get('customers/{id}', [CustomerController::class, 'show']);
Route::delete('customers/{id}', [CustomerController::class, 'delete']);
// 🔸 Eventos / Facturas / Pagos / Suscripciones
Route::get('events', [EventsController::class, 'index']);
Route::post('invoices', [InvoiceController::class, 'store']);
Route::put('invoices/{id}', [InvoiceController::class, 'update']);
Route::get('invoices/{id}', [InvoiceController::class, 'show']);
Route::post('invoices/{id}/void', [InvoiceController::class, 'void']);
Route::delete('invoices/{id}', [InvoiceController::class, 'destroy']);
Route::get('invoices/customer/{id}', [InvoiceController::class, 'byCustomer']);
Route::post('payments', [PaymentController::class, 'storeOrUpdate']);
Route::put('payments', [PaymentController::class, 'update']);
Route::delete('payments', [PaymentController::class, 'destroy']);
Route::get('organization/payments', [PaymentController::class, 'index']);
Route::get('payments/{id}', [PaymentController::class, 'show']);
Route::delete('payment-methods/{id}', [PaymentMethodController::class, 'delete']);
Route::get('organization/payment-methods', [PaymentMethodController::class, 'list']);
Route::get('payment-methods/customers/{customer_id}', [PaymentMethodController::class, 'listByCustomer']);
Route::post('subscriptions/associate/payment-method', [PaymentMethodController::class, 'associateToSubscription']);
Route::post('subscriptions/associate/payment-method/batch', [PaymentMethodController::class, 'associateBatch']);
Route::post('redirection', [RedirectionController::class, 'store']);
Route::put('redirection', [RedirectionController::class, 'update']);
Route::post('subscriptions', [SubscriptionController::class, 'create']);
Route::put('subscriptions/{id}', [SubscriptionController::class, 'update']);
Route::get('subscriptions/{id}', [SubscriptionController::class, 'get']);
Route::delete('subscriptions/{id}', [SubscriptionController::class, 'delete']);
Route::get('subscriptions/customer/{id}', [SubscriptionController::class, 'getByCustomer']);
Route::get('transactions', [TransactionController::class, 'index']);
Route::get('transactions/{id}', [TransactionController::class, 'show']);
Route::get('transactions/{id}/fees', [TransactionController::class, 'fees']);
// Webhooks
Route::get('/webhook-endpoints', [WebhookController::class, 'index']); // Listar Webhooks
Route::post('/webhook-endpoints', [WebhookController::class, 'store']); // Crear Webhook
Route::put('/webhook-endpoints/{id}', [WebhookController::class, 'updateWebhook']); // Editar Webhook
Route::get('/webhook-endpoints/{id}', [WebhookController::class, 'show']); // Obtener Webhook
Route::post('/dummy_webhook', [WebhookController::class, 'testDummy']); // Envóo test Webhook
// ======================================
// 🔹 Webhooks (acepta X-App-Token o Bearer)
// ======================================
Route::prefix('webhooks')->group(function () {
Route::post('/transactions', [WebhookTransactionController::class, 'handle']);
Route::post('/customers', [WebhookCustomerController::class, 'handle']);
Route::post('/subscriptions', [WebhookSubscriptionController::class, 'handle']);
Route::post('/invoices', [WebhookInvoiceController::class, 'handle']);
Route::post('/payments', [WebhookPaymentController::class, 'handle']);
Route::post('/payouts', [WebhookPayoutController::class, 'handle']);
Route::post('/payment-methods', [WebhookPaymentMethodController::class, 'handle']);
Route::post('/payment-intents', [WebhookPaymentIntentController::class, 'handle']);
});
// Dummy webhook test
Route::post('/dummy_webhook', [WebhookController::class, 'testDummy']);
});
// ======================================
// 🔹 SIGNAPIS ROUTES
// ======================================
Route::prefix('/signapis')->group(function () {
// ======================================
// 🔹 RUTAS DE PRUEBAS
// ======================================
Route::post('/test/send', [SignapisTestController::class, 'sendToSignapis']);
Route::post('/test/webhook-register', [SignapisTestController::class, 'registerWebhookTest']);
Route::post('/test/webhook', [SignapisTestController::class, 'webhook']);
// ======================================
// 🔹 Webhooks
// ======================================
Route::get('/webhook', [SignapisWebhookController::class, 'getWebhook']);
Route::post('/webhook', [SignapisWebhookController::class, 'configureWebhook']);
Route::delete('/webhook', [SignapisWebhookController::class, 'deleteWebhook']);
Route::post('/webhook/test', [SignapisWebhookController::class, 'testWebhook']);
// ======================================
// 🔹 Logos
// ======================================
Route::post('/logos', [SignapisLogosController::class, 'createLogo']);
Route::get('/logos', [SignapisLogosController::class, 'listLogos']);
Route::get('/logos/{code}', [SignapisLogosController::class, 'getLogo']);
Route::delete('/logos/{code}', [SignapisLogosController::class, 'deleteLogo']);
// ======================================
// 🔹 Templates
// ======================================
Route::post('/templates', [SignapisTemplatesController::class, 'createTemplate']);
Route::get('/templates', [SignapisTemplatesController::class, 'listTemplates']);
Route::get('/templates/{code}/{type}', [SignapisTemplatesController::class, 'getTemplate']);
Route::patch('/templates/{code}/{type}', [SignapisTemplatesController::class, 'updateTemplate']);
Route::delete('/templates/{code}/{type}', [SignapisTemplatesController::class, 'deleteTemplate']);
Route::delete('/templates/{code}', [SignapisTemplatesController::class, 'deleteTemplatesByCode']);
Route::post('/templates/test', [SignapisTemplatesController::class, 'testTemplate']);
// ======================================
// 🔹 Notifications
// ======================================
Route::post('/signatories/{signatoryId}/resend', [SignapisNotificationsController::class, 'resendInvitation']);
// ======================================
// 🔹 Documentos
// ======================================
Route::post('/documents', [SignapisDocumentController::class, 'createDocument']); // Crear documento
Route::get('/documents/{documentId}', [SignapisDocumentController::class, 'getDocument']); // Obtener documento
// Firmantes
Route::post('/documents/signatories', [SignapisDocumentController::class, 'addSignatories']); // Agregar firmantes
Route::patch('/documents/signatories/{signatoryId}', [SignapisDocumentController::class, 'updateSignatory']); // Actualizar firmante
Route::delete('/documents/signatories/{signatoryId}', [SignapisDocumentController::class, 'deleteSignatory']); // Eliminar firmante
Route::post('/documents/signatories/{signatoryId}/reject', [SignapisDocumentController::class, 'rejectDocument']); // Rechazar documento
// Cancelaciones
Route::patch('/documents/{documentId}/cancel', [SignapisDocumentController::class, 'cancelDocumentById']); // Cancelar por ID interno
Route::patch('/documents/client/{documentClientId}/cancel', [SignapisDocumentController::class, 'cancelDocumentByClientId']); // Cancelar por ID cliente
// ======================================
// 🔹 Batches
// ======================================
Route::post('/documents/batch/file', [SignapisDocumentController::class, 'uploadBatchFile']);
Route::post('/documents/batch', [SignapisDocumentController::class, 'createBatch']);
Route::post('/documents/batch/signatories/{signatoryId}/sign', [SignapisDocumentController::class, 'signBatch']);
Route::post('/documents/batch/signatories/{signatoryId}/reject', [SignapisDocumentController::class, 'rejectBatch']);
Route::get('/documents/batch/{groupId}', [SignapisDocumentController::class, 'getBatch']);
Route::patch('/documents/batch/{groupId}/cancel', [SignapisDocumentController::class, 'cancelBatch']);
Route::post('/documents/batch/certify', [SignapisDocumentController::class, 'certifyBatch']);
Route::get('/documents/batch/{groupId}/summary/{email}', [SignapisDocumentController::class, 'getBatchSignerSummary']);
Route::patch('/documents/batch/{groupId}/summary/{email}', [SignapisDocumentController::class, 'updateBatchSigner']);
// ======================================
// 🔹 Documentos (Individual Signing)
// ======================================
Route::post('/documents/signatories/{signatoryId}/sign', [SignapisSigninController::class, 'signDocument']);
// ======================================
// 🔹 Reportes
// ======================================
Route::get('/reports/statusDocuments', [SignapisReportsController::class, 'getStatusDocumentsReport']);
Route::get('/reports/company', [SignapisReportsController::class, 'getCompanyReport']);
});
// ======================================
// 🔹 WEBHOOK DE PRUEBA
// ======================================
Route::post('/payment-webhook', function (Request $request) {
Log::info('Webhook /payment-webhook recibido', [
'ip' => $request->ip(),
'headers' => $request->headers->all(),
'payload' => $request->all(),
]);
return response()->json(['ok' => true], 200);
})->withoutMiddleware([VerifyCsrfToken::class]);
});
// =======================================
// API v1 - Endpoints para Opens (inbound)
// =======================================
Route::prefix('v1')->middleware(['api.v1'])->group(function () {
// Apoderados
Route::get('/parents', [OdooPublicController::class, 'listParents']);
Route::get('/parents/{rut}', [OdooPublicController::class, 'showParentByRut']);
Route::post('/parents', [OdooPublicController::class, 'createOrUpdateParents']);
// Alumnos
Route::get('/students', [OdooPublicController::class, 'listStudents']);
Route::get('/students/{rut}', [OdooPublicController::class, 'showStudentByRut']);
Route::post('/students', [OdooPublicController::class, 'createOrUpdateStudents']);
// Catálogos
Route::get('/relationships', [OdooPublicController::class, 'listRelationships']);
Route::get('/courses', [OdooPublicController::class, 'listCourses']);
Route::get('/course-letters', [OdooPublicController::class, 'listCourseLetters']);
Route::get('/genders', [OdooPublicController::class, 'listGenders']);
});
Route::post('/toku/webhooks', [WebhookGeneralController::class, 'handle']);
Route::post('/signapis-webhooks', [WebhookGeneralController::class, 'handle']);
Route::get('/contracts/{id}/send-pdf', [ContractController::class, 'sendPDF'])->name('contracts.send_pdf');
Route::get('/contracts/{id}/pdf-view', function ($id, ContractController $controller, Request $request) {
return $controller->generatePdf($id, $request, 'id');
});
Route::get('/contracts/{code}/pdf', function ($code, ContractController $controller, Request $request) {
return $controller->generatePdf($code, $request, 'code');
});
Route::get('/presencial/receipt/{paymentId}/pdf', [App\Http\Controllers\PresencialController::class, 'downloadReceipt']);
Route::get('/presencial/attachment/{paymentId}', [App\Http\Controllers\PresencialController::class, 'serveAttachment']);
Route::get('/contracts/{code}/pdf64', [ContractController::class, 'generatePDF64'])
->name('contracts.pdf');