diff --git a/components/ExpenseCreateModal.vue b/components/ExpenseCreateModal.vue new file mode 100644 index 0000000..1f82ab7 --- /dev/null +++ b/components/ExpenseCreateModal.vue @@ -0,0 +1,322 @@ + + + + + diff --git a/components/ExpenseList.vue b/components/ExpenseList.vue index a6325d9..35fb800 100644 --- a/components/ExpenseList.vue +++ b/components/ExpenseList.vue @@ -1,148 +1,187 @@ diff --git a/server/api/create-expense.ts b/server/api/create-expense.ts new file mode 100644 index 0000000..94c504e --- /dev/null +++ b/server/api/create-expense.ts @@ -0,0 +1,79 @@ +import { requireSalesOrAdmin } from '@/server/utils/auth'; +import { getNocoDbConfiguration } from '@/server/utils/nocodb'; +import type { Expense } from '@/utils/types'; + +export default defineEventHandler(async (event) => { + try { + // Ensure only sales/admin users can create expenses + await requireSalesOrAdmin(event); + + const body = await readBody(event); + console.log('[create-expense] Creating expense with data:', body); + + // Validate required fields + const requiredFields = ['Establishment Name', 'Price', 'Category', 'Payer', 'Time']; + for (const field of requiredFields) { + if (!body[field]) { + throw createError({ + statusCode: 400, + statusMessage: `Missing required field: ${field}` + }); + } + } + + // Get NocoDB configuration + const config = getNocoDbConfiguration(); + const expenseTableId = "mxfcefkk4dqs6uq"; // Expense table ID from nocodb.ts + + // Prepare expense data for NocoDB + const expenseData = { + "Establishment Name": body["Establishment Name"], + Price: body.Price, + Category: body.Category, + Payer: body.Payer, + Time: body.Time, + Contents: body.Contents || null, + "Payment Method": body["Payment Method"] || "Card", + currency: body.currency || "EUR", + Paid: body.Paid || false + }; + + console.log('[create-expense] Sending to NocoDB:', expenseData); + + // Create the expense in NocoDB + const response = await $fetch(`${config.url}/api/v2/tables/${expenseTableId}/records`, { + method: 'POST', + headers: { + 'xc-token': config.token, + 'Content-Type': 'application/json' + }, + body: expenseData + }); + + console.log('[create-expense] Expense created successfully:', response.Id); + + return response; + + } catch (error: any) { + console.error('[create-expense] Failed to create expense:', error); + + if (error.statusCode === 403) { + throw createError({ + statusCode: 403, + statusMessage: 'Access denied. This feature requires sales team or administrator privileges.' + }); + } + + if (error.statusCode === 400) { + throw createError({ + statusCode: 400, + statusMessage: error.statusMessage + }); + } + + throw createError({ + statusCode: 500, + statusMessage: 'Failed to create expense. Please try again later.' + }); + } +});