+
{
await requireAuth(event);
console.log('[Delete Generated EOI] Request received');
+ console.log('[Delete Generated EOI] Request headers:', getHeaders(event));
+ console.log('[Delete Generated EOI] Request method:', getMethod(event));
try {
const body = await readBody(event);
@@ -15,12 +17,13 @@ export default defineEventHandler(async (event) => {
const query = getQuery(event);
console.log('[Delete Generated EOI] Interest ID:', interestId);
+ console.log('[Delete Generated EOI] Query params:', query);
if (!interestId) {
console.error('[Delete Generated EOI] No interest ID provided');
throw createError({
statusCode: 400,
- statusMessage: 'Interest ID is required',
+ statusMessage: 'Interest ID is required. Please provide a valid interest ID.',
});
}
diff --git a/server/api/get-expenses.ts b/server/api/get-expenses.ts
index 44ce6a6..4d41b27 100644
--- a/server/api/get-expenses.ts
+++ b/server/api/get-expenses.ts
@@ -3,6 +3,43 @@ import { getExpenses, getCurrentMonthExpenses } from '@/server/utils/nocodb';
import { processExpenseWithCurrency } from '@/server/utils/currency';
import type { ExpenseFilters } from '@/utils/types';
+// Retry operation wrapper for database calls
+async function retryOperation(
+ operation: () => Promise,
+ maxRetries: number = 3,
+ baseDelay: number = 1000
+): Promise {
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
+ try {
+ return await operation();
+ } catch (error: any) {
+ console.log(`[get-expenses] Attempt ${attempt}/${maxRetries} failed:`, error.message);
+
+ // Don't retry on authentication/authorization errors
+ if (error.statusCode === 401 || error.statusCode === 403) {
+ throw error;
+ }
+
+ // Don't retry on client errors (4xx except 404)
+ if (error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 404) {
+ throw error;
+ }
+
+ // If this is the last attempt, throw the error
+ if (attempt === maxRetries) {
+ throw error;
+ }
+
+ // For retryable errors (5xx, network errors, timeouts), wait before retry
+ const delay = baseDelay * Math.pow(2, attempt - 1); // Exponential backoff
+ console.log(`[get-expenses] Retrying in ${delay}ms...`);
+ await new Promise(resolve => setTimeout(resolve, delay));
+ }
+ }
+
+ throw new Error('Retry operation failed unexpectedly');
+}
+
export default defineEventHandler(async (event) => {
console.log('[get-expenses] API called with query:', getQuery(event));
@@ -10,6 +47,7 @@ export default defineEventHandler(async (event) => {
// Set proper headers
setHeader(event, 'Cache-Control', 'no-cache');
setHeader(event, 'Content-Type', 'application/json');
+
// Check authentication first
try {
await requireSalesOrAdmin(event);
@@ -36,7 +74,7 @@ export default defineEventHandler(async (event) => {
console.log('[get-expenses] No date filters provided, defaulting to current month');
try {
- const result = await getCurrentMonthExpenses();
+ const result = await retryOperation(() => getCurrentMonthExpenses());
// Process expenses with currency conversion
const processedExpenses = await Promise.all(
@@ -57,6 +95,13 @@ export default defineEventHandler(async (event) => {
});
}
+ if (dbError.statusCode === 404) {
+ throw createError({
+ statusCode: 404,
+ statusMessage: 'No expense records found for the current month.'
+ });
+ }
+
throw createError({
statusCode: 500,
statusMessage: 'Unable to fetch expense data. Please try again later.'
@@ -86,7 +131,7 @@ export default defineEventHandler(async (event) => {
console.log('[get-expenses] Fetching expenses with filters:', filters);
try {
- const result = await getExpenses(filters);
+ const result = await retryOperation(() => getExpenses(filters));
// Process expenses with currency conversion
const processedExpenses = await Promise.all(
@@ -126,6 +171,13 @@ export default defineEventHandler(async (event) => {
});
}
+ if (dbError.statusCode === 404) {
+ throw createError({
+ statusCode: 404,
+ statusMessage: 'No expense records found matching the specified criteria.'
+ });
+ }
+
throw createError({
statusCode: 500,
statusMessage: 'Unable to fetch expense data. Please try again later.'
diff --git a/server/api/interests/duplicates/find.ts b/server/api/interests/duplicates/find.ts
index d1ca86d..835f440 100644
--- a/server/api/interests/duplicates/find.ts
+++ b/server/api/interests/duplicates/find.ts
@@ -19,11 +19,12 @@ export default defineEventHandler(async (event) => {
let url = `${config.url}/api/v2/tables/${interestTableId}/records`;
- // Add date filtering if specified
+ // Add date filtering if specified (include records without Created At)
if (dateRange && dateRange > 0) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - dateRange);
- const dateFilter = `(Created At,gte,${cutoffDate.toISOString()})`;
+ // Include records without Created At OR within date range
+ const dateFilter = `((Created At,gte,${cutoffDate.toISOString()}),or,(Created At,is,null))`;
url += `?where=${encodeURIComponent(dateFilter)}`;
}