middleware('throttle:register'); Route::post('/login', [AuthController::class, 'login'])->middleware('throttle:login'); // Email testing routes (should be protected in production) Route::post('/email/send-test', [EmailTestController::class, 'sendTest']); Route::get('/email/anti-spam-info', [EmailTestController::class, 'getAntiSpamInfo']); // Protected routes (require authentication) Route::middleware('auth:sanctum')->group(function () { // Auth routes Route::post('/logout', [AuthController::class, 'logout']); Route::get('/me', [AuthController::class, 'me']); Route::get('/user', function (Request $request) { return $request->user(); }); // ============================================ // Contas (Accounts) // ============================================ // Rotas específicas ANTES do apiResource Route::post('accounts/recalculate-all', [AccountController::class, 'recalculateBalances']); Route::post('accounts/{id}/recalculate', [AccountController::class, 'recalculateBalance']); Route::post('accounts/{id}/adjust-balance', [AccountController::class, 'adjustBalance']); // Resource principal Route::apiResource('accounts', AccountController::class); Route::get('accounts-total', [AccountController::class, 'totalBalance']); // ============================================ // Centros de Custo (Cost Centers) // ============================================ Route::apiResource('cost-centers', CostCenterController::class); Route::post('cost-centers/{id}/keywords', [CostCenterController::class, 'addKeyword']); Route::delete('cost-centers/{id}/keywords/{keywordId}', [CostCenterController::class, 'removeKeyword']); Route::post('cost-centers/match', [CostCenterController::class, 'matchByText']); // ============================================ // Categorias (Categories) // ============================================ // Rotas específicas ANTES do apiResource Route::post('categories/categorize-batch/preview', [CategoryController::class, 'categorizeBatchPreview']); Route::post('categories/categorize-batch', [CategoryController::class, 'categorizeBatch']); Route::post('categories/categorize-batch/manual', [CategoryController::class, 'categorizeBatchManual']); Route::post('categories/match', [CategoryController::class, 'matchByText']); Route::post('categories/reorder', [CategoryController::class, 'reorder']); // Resource principal Route::apiResource('categories', CategoryController::class); // Rotas com parâmetros (depois do apiResource) Route::post('categories/{id}/keywords', [CategoryController::class, 'addKeyword']); Route::delete('categories/{id}/keywords/{keywordId}', [CategoryController::class, 'removeKeyword']); // ============================================ // Contas Passivo (Liability Accounts) // ============================================ // Rotas específicas ANTES do apiResource (para evitar conflito com {id}) Route::get('liability-accounts/pending-reconciliation', [LiabilityAccountController::class, 'pendingReconciliation']); Route::post('liability-accounts/import', [LiabilityAccountController::class, 'import']); Route::get('liability-summary', [LiabilityAccountController::class, 'summary']); // Resource principal Route::apiResource('liability-accounts', LiabilityAccountController::class); // Rotas com parâmetros (depois do apiResource) Route::get('liability-accounts/{id}/installments', [LiabilityAccountController::class, 'installments']); Route::put('liability-accounts/{accountId}/installments/{installmentId}', [LiabilityAccountController::class, 'updateInstallment']); // Conciliação de parcelas Route::get('liability-accounts/{accountId}/installments/{installmentId}/eligible-transactions', [LiabilityAccountController::class, 'eligibleTransactions']); Route::post('liability-accounts/{accountId}/installments/{installmentId}/reconcile', [LiabilityAccountController::class, 'reconcile']); Route::delete('liability-accounts/{accountId}/installments/{installmentId}/reconcile', [LiabilityAccountController::class, 'unreconcile']); // ============================================ // Transações (Transactions) // ============================================ Route::apiResource('transactions', TransactionController::class); Route::get('transactions-by-week', [TransactionController::class, 'byWeek']); Route::get('transactions-summary', [TransactionController::class, 'summary']); // Ações em transações Route::post('transactions/{transaction}/complete', [TransactionController::class, 'complete']); Route::post('transactions/{transaction}/quick-complete', [TransactionController::class, 'quickComplete']); Route::post('transactions/{transaction}/cancel', [TransactionController::class, 'cancel']); Route::post('transactions/{transaction}/revert', [TransactionController::class, 'revert']); Route::post('transactions/{transaction}/duplicate', [TransactionController::class, 'duplicate']); // Divisão de transações Route::post('transactions/{transaction}/split', [TransactionController::class, 'split']); Route::post('transactions/{transaction}/unsplit', [TransactionController::class, 'unsplit']); Route::get('transactions/{transaction}/splits', [TransactionController::class, 'getSplits']); // Transferências entre contas Route::post('transactions/transfer', [TransactionController::class, 'transfer']); Route::post('transactions/{transaction}/unlink-transfer', [TransactionController::class, 'unlinkTransfer']); // Conciliação com Passivos Route::get('transactions/{transaction}/liability-installments', [TransactionController::class, 'findLiabilityInstallments']); Route::post('transactions/{transaction}/reconcile-liability', [TransactionController::class, 'reconcileWithLiability']); // ============================================ // Importação de Extratos (Bank Statement Import) // ============================================ Route::post('import/upload', [ImportController::class, 'upload']); Route::post('import/headers', [ImportController::class, 'getHeaders']); Route::post('import/process', [ImportController::class, 'import']); Route::get('import/mappings', [ImportController::class, 'mappings']); Route::get('import/mappings/{id}', [ImportController::class, 'getMapping']); Route::put('import/mappings/{id}', [ImportController::class, 'updateMapping']); Route::delete('import/mappings/{id}', [ImportController::class, 'deleteMapping']); Route::get('import/presets', [ImportController::class, 'presets']); Route::post('import/presets/create', [ImportController::class, 'createFromPreset']); Route::get('import/history', [ImportController::class, 'history']); Route::get('import/fields', [ImportController::class, 'fields']); // Detecção de Transferências entre Contas (Transfer Detection) // ============================================================ Route::get('transfer-detection', [TransferDetectionController::class, 'index']); Route::get('transfer-detection/stats', [TransferDetectionController::class, 'stats']); Route::get('transfer-detection/{transaction}/pairs', [TransferDetectionController::class, 'findPairs']); Route::post('transfer-detection/confirm', [TransferDetectionController::class, 'confirm']); Route::post('transfer-detection/confirm-batch', [TransferDetectionController::class, 'confirmBatch']); Route::post('transfer-detection/ignore', [TransferDetectionController::class, 'ignore']); Route::post('transfer-detection/delete-both', [TransferDetectionController::class, 'deleteBoth']); // Detecção de Reembolsos (Refund Detection) // ============================================================ Route::get('refund-detection', [TransferDetectionController::class, 'refunds']); Route::post('refund-detection/confirm', [TransferDetectionController::class, 'confirmRefund']); Route::post('refund-detection/confirm-batch', [TransferDetectionController::class, 'confirmRefundBatch']); Route::post('refund-detection/ignore', [TransferDetectionController::class, 'ignoreRefund']); Route::post('refund-detection/undo', [TransferDetectionController::class, 'undoRefund']); // ============================================ // Dashboard // ============================================ Route::get('dashboard/summary', [DashboardController::class, 'summary']); Route::get('dashboard/cashflow', [DashboardController::class, 'cashflow']); Route::get('dashboard/expenses-by-category', [DashboardController::class, 'expensesByCategory']); Route::get('dashboard/income-by-category', [DashboardController::class, 'incomeByCategory']); Route::get('dashboard/payment-variances', [DashboardController::class, 'paymentVariances']); Route::get('dashboard/calendar', [DashboardController::class, 'calendar']); Route::get('dashboard/calendar-day', [DashboardController::class, 'calendarDay']); Route::get('dashboard/upcoming', [DashboardController::class, 'upcomingTransactions']); Route::get('dashboard/overdue', [DashboardController::class, 'overdueTransactions']); // ============================================ // Transações Recorrentes (Recurring Transactions) // ============================================ // Rotas de listagem geral Route::get('recurring/frequencies', [RecurringTemplateController::class, 'frequencies']); Route::get('recurring/pending', [RecurringTemplateController::class, 'allPendingInstances']); Route::get('recurring/overdue', [RecurringTemplateController::class, 'overdueInstances']); Route::get('recurring/due-soon', [RecurringTemplateController::class, 'dueSoonInstances']); Route::post('recurring/regenerate-all', [RecurringTemplateController::class, 'regenerateAll']); // Criar a partir de transação existente Route::post('recurring/from-transaction', [RecurringTemplateController::class, 'createFromTransaction']); // Templates CRUD Route::apiResource('recurring', RecurringTemplateController::class)->parameters(['recurring' => 'recurringTemplate']); // Ações em templates Route::post('recurring/{recurringTemplate}/pause', [RecurringTemplateController::class, 'pause']); Route::post('recurring/{recurringTemplate}/resume', [RecurringTemplateController::class, 'resume']); Route::get('recurring/{recurringTemplate}/instances', [RecurringTemplateController::class, 'instances']); // Ações em instâncias Route::post('recurring-instances/{recurringInstance}/pay', [RecurringTemplateController::class, 'markAsPaid']); Route::post('recurring-instances/{recurringInstance}/reconcile', [RecurringTemplateController::class, 'reconcile']); Route::get('recurring-instances/{recurringInstance}/candidates', [RecurringTemplateController::class, 'findCandidates']); Route::post('recurring-instances/{recurringInstance}/skip', [RecurringTemplateController::class, 'skip']); Route::post('recurring-instances/{recurringInstance}/cancel', [RecurringTemplateController::class, 'cancel']); Route::put('recurring-instances/{recurringInstance}', [RecurringTemplateController::class, 'updateInstance']); });