diff --git a/app/(dashboard)/page.tsx b/app/(dashboard)/page.tsx index 51fa3067..2c8c6102 100644 --- a/app/(dashboard)/page.tsx +++ b/app/(dashboard)/page.tsx @@ -59,34 +59,53 @@ export default async function DashboardPage() { hasBankConnected: (transactionCount || 0) > 0, } - // Fetch current year transactions summary - const startOfYear = new Date(new Date().getFullYear(), 0, 1).toISOString() - const startOfMonth = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString() + // Fetch current year date boundaries + const startOfYearStr = new Date(new Date().getFullYear(), 0, 1).toISOString().split('T')[0] + const startOfMonthStr = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString().split('T')[0] - const { data: transactions } = await supabase - .from('transactions') - .select('amount, amount_sek, is_business, category, date') - .eq('user_id', user.id) - .gte('date', startOfYear.split('T')[0]) + // Fetch posted journal entry lines for revenue/expense accounts (classes 3-7) + const { data: journalLines } = await supabase + .from('journal_entry_lines') + .select('account_number, debit_amount, credit_amount, journal_entry:journal_entries!inner(entry_date, status)') + .eq('journal_entry.status', 'posted') + .gte('journal_entry.entry_date', startOfYearStr) - // Calculate summaries - const ytdTransactions = transactions || [] - const mtdTransactions = ytdTransactions.filter( - (t) => t.date >= startOfMonth.split('T')[0] - ) + // Calculate totals from journal entry lines using account classes + const calculateTotals = (lines: typeof journalLines, fromDate: string) => { + const filtered = (lines || []).filter((l) => { + const entry = l.journal_entry as unknown as { entry_date: string; status: string } + return entry.entry_date >= fromDate + }) - const calculateTotals = (txns: typeof ytdTransactions) => { - const income = txns - .filter((t) => t.is_business && t.amount > 0) - .reduce((sum, t) => sum + Number(t.amount_sek || t.amount), 0) - const expenses = txns - .filter((t) => t.is_business && t.amount < 0) - .reduce((sum, t) => sum + Math.abs(Number(t.amount_sek || t.amount)), 0) - return { income, expenses, net: income - expenses } + let revenue = 0 + let expenses = 0 + + for (const line of filtered) { + const acct = line.account_number + if (acct.startsWith('3')) { + // Revenue: class 3 — credit-normal accounts + revenue += Math.round(((line.credit_amount || 0) - (line.debit_amount || 0)) * 100) / 100 + } else if (acct.startsWith('4') || acct.startsWith('5') || acct.startsWith('6') || acct.startsWith('7')) { + // Expenses: classes 4-7 — debit-normal accounts + expenses += Math.round(((line.debit_amount || 0) - (line.credit_amount || 0)) * 100) / 100 + } + } + + revenue = Math.round(revenue * 100) / 100 + expenses = Math.round(expenses * 100) / 100 + + return { income: revenue, expenses, net: Math.round((revenue - expenses) * 100) / 100 } } - const ytdTotals = calculateTotals(ytdTransactions) - const mtdTotals = calculateTotals(mtdTransactions) + const ytdTotals = calculateTotals(journalLines, startOfYearStr) + const mtdTotals = calculateTotals(journalLines, startOfMonthStr) + + // Fetch uncategorized transaction counts (still useful for the alert) + const { data: transactions } = await supabase + .from('transactions') + .select('amount, amount_sek, is_business') + .eq('user_id', user.id) + .gte('date', startOfYearStr) const uncategorizedTxns = (transactions || []).filter( (t) => t.is_business === null diff --git a/app/api/invoices/[id]/send/route.ts b/app/api/invoices/[id]/send/route.ts index bf647d1b..d7dcfe1e 100644 --- a/app/api/invoices/[id]/send/route.ts +++ b/app/api/invoices/[id]/send/route.ts @@ -134,7 +134,7 @@ export async function POST( subject: generateInvoiceEmailSubject(emailData), html: generateInvoiceEmailHtml(emailData), text: generateInvoiceEmailText(emailData), - replyTo: (company as CompanySettings & { email?: string }).email || undefined, + replyTo: company.email || undefined, fromName: company.company_name, attachments: [ { diff --git a/components/bookkeeping/JournalEntryForm.tsx b/components/bookkeeping/JournalEntryForm.tsx index ede79797..eacaf04f 100644 --- a/components/bookkeeping/JournalEntryForm.tsx +++ b/components/bookkeeping/JournalEntryForm.tsx @@ -110,7 +110,7 @@ export default function JournalEntryForm({ } // Auto-fill line description from account name when selecting an account - if (field === 'account_number' && value && !updated[index].line_description) { + if (field === 'account_number' && value) { const account = accounts.find((a) => a.account_number === value) if (account) { updated[index].line_description = account.account_name diff --git a/components/transactions/TransactionBookingDialog.tsx b/components/transactions/TransactionBookingDialog.tsx index 92cdc724..d2fb8981 100644 --- a/components/transactions/TransactionBookingDialog.tsx +++ b/components/transactions/TransactionBookingDialog.tsx @@ -27,8 +27,8 @@ function buildInitialLines(transaction: TransactionWithInvoice): FormLine[] { if (isExpense) { return [ - { account_number: '', debit_amount: amountStr, credit_amount: '', line_description: '' }, { account_number: '1930', debit_amount: '', credit_amount: amountStr, line_description: 'Företagskonto' }, + { account_number: '', debit_amount: amountStr, credit_amount: '', line_description: '' }, ] } diff --git a/lib/bookkeeping/engine.ts b/lib/bookkeeping/engine.ts index b165f8e7..5c09ba01 100644 --- a/lib/bookkeeping/engine.ts +++ b/lib/bookkeeping/engine.ts @@ -129,8 +129,9 @@ function buildLineInserts( amount_in_currency: line.amount_in_currency ? Math.round(line.amount_in_currency * 100) / 100 : null, exchange_rate: line.exchange_rate || null, line_description: line.line_description || null, - cost_center_id: line.cost_center || null, - project_id: line.project || null, + tax_code: line.tax_code || null, + cost_center: line.cost_center || null, + project: line.project || null, sort_order: index, })) } diff --git a/lib/email/resend.ts b/lib/email/resend.ts index a4a35eab..ac840144 100644 --- a/lib/email/resend.ts +++ b/lib/email/resend.ts @@ -116,5 +116,5 @@ export async function sendEmail(options: SendEmailOptions): Promise