Bug/gh issues fiz (#1103)
* refactor: optimize page loading and data fetching * fix: resolve recurring production runtime errors * feat: add MCP company and customer updates * fix: handle year-end tax adjustments * feat: harden annual report compliance * fix: expand invoice logo and font support * fix: sanitize API route error responses * fix: sanitize user-facing error messages * feat: persist onboarding and tax assessment notices * fix: reduce cloud backup audit churn * feat: refine invoice editor layout * fix: show saved tax adjustments in INK2 * fix: complete annual report API mappings * docs: record operational safeguards and decisions * fix: harden annual report review findings * fix: adjust column span for description based on VAT registration * New css class name
This commit is contained in:
@@ -121,7 +121,7 @@ describe('POST /api/transactions/[id]/ignore', () => {
|
||||
const { status, body } = await parseJsonResponse(response)
|
||||
|
||||
expect(status).toBe(500)
|
||||
expect(body).toEqual({ error: 'db down' })
|
||||
expect(body).toEqual({ error: 'Något gick fel. Försök igen.' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -174,6 +174,6 @@ describe('DELETE /api/transactions/[id]/ignore', () => {
|
||||
const { status, body } = await parseJsonResponse(response)
|
||||
|
||||
expect(status).toBe(500)
|
||||
expect(body).toEqual({ error: 'db down' })
|
||||
expect(body).toEqual({ error: 'Något gick fel. Försök igen.' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
/**
|
||||
* POST /api/transactions/[id]/ignore
|
||||
@@ -47,7 +48,7 @@ export const POST = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
.eq('company_id', companyId)
|
||||
|
||||
if (updateError) {
|
||||
return NextResponse.json({ error: updateError.message }, { status: 500 })
|
||||
return NextResponse.json({ error: getUserErrorMessage(updateError) }, { status: 500 })
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
@@ -74,7 +75,7 @@ export const DELETE = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
.eq('company_id', companyId)
|
||||
|
||||
if (updateError) {
|
||||
return NextResponse.json({ error: updateError.message }, { status: 500 })
|
||||
return NextResponse.json({ error: getUserErrorMessage(updateError) }, { status: 500 })
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
|
||||
@@ -6,6 +6,7 @@ import { errorResponseFromCode } from '@/lib/errors/get-structured-error'
|
||||
import { eventBus } from '@/lib/events/bus'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import type { Invoice, SupplierInvoice, Transaction } from '@/types'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -81,7 +82,7 @@ export const POST = withRouteContext(
|
||||
txLog.error('match_batch_allocate RPC error', error)
|
||||
return errorResponseFromCode('BATCH_RPC_FAILED', txLog, {
|
||||
requestId,
|
||||
details: { message: error.message },
|
||||
details: { message: getUserErrorMessage(error) },
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { logMatchEvent } from '@/lib/invoices/match-log'
|
||||
import { eventBus } from '@/lib/events/bus'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import type { SupplierInvoice, SupplierInvoiceItem, Transaction } from '@/types'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -320,7 +321,7 @@ export const POST = withRouteContext(
|
||||
}
|
||||
return errorResponseFromCode('MATCH_SI_JE_FAILED', txLog, {
|
||||
requestId,
|
||||
details: { reason: err instanceof Error ? err.message : 'unknown' },
|
||||
details: { reason: err instanceof Error ? getUserErrorMessage(err) : 'unknown' },
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ describe('POST /api/transactions/[id]/uncategorize', () => {
|
||||
const { status, body } = await parseJsonResponse(response)
|
||||
|
||||
expect(status).toBe(500)
|
||||
expect(body).toEqual({ error: 'Period is locked' })
|
||||
expect(body).toEqual({ error: 'Kunde inte hantera transaktionen. Försök igen.' })
|
||||
})
|
||||
|
||||
it('returns 200 and reverses entry on success', async () => {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { reverseEntry } from '@/lib/bookkeeping/engine'
|
||||
import { bookkeepingErrorResponse } from '@/lib/bookkeeping/errors'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { getErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -49,8 +50,10 @@ export const POST = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
} catch (err) {
|
||||
const typed = bookkeepingErrorResponse(err)
|
||||
if (typed) return typed
|
||||
const message = err instanceof Error ? err.message : 'Reversal failed'
|
||||
return NextResponse.json({ error: message }, { status: 500 })
|
||||
return NextResponse.json(
|
||||
{ error: getErrorMessage(err, { context: 'transaction' }) },
|
||||
{ status: 500 },
|
||||
)
|
||||
}
|
||||
|
||||
// Reset transaction categorization
|
||||
|
||||
@@ -187,6 +187,6 @@ describe('GET /api/transactions', () => {
|
||||
const { status, body } = await parseJsonResponse<{ error: string }>(response)
|
||||
|
||||
expect(status).toBe(500)
|
||||
expect(body.error).toBe('boom')
|
||||
expect(body.error).toBe('Något gick fel. Försök igen.')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -14,6 +14,7 @@ import { bookkeepingErrorResponse } from '@/lib/bookkeeping/errors'
|
||||
import { eventBus } from '@/lib/events/bus'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import type { BookingTemplateLibraryLine, Transaction } from '@/types'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -108,7 +109,7 @@ export const POST = withRouteContext(
|
||||
opLog.error('chart_of_accounts lookup failed', accountsError)
|
||||
return errorResponseFromCode('BULK_BOOK_RPC_FAILED', opLog, {
|
||||
requestId,
|
||||
details: { message: accountsError.message },
|
||||
details: { message: getUserErrorMessage(accountsError) },
|
||||
})
|
||||
}
|
||||
const validSet = new Set(
|
||||
@@ -283,7 +284,7 @@ export const POST = withRouteContext(
|
||||
opLog.error('bulk_book_transactions RPC error', error)
|
||||
return errorResponseFromCode('BULK_BOOK_RPC_FAILED', opLog, {
|
||||
requestId,
|
||||
details: { message: error.message },
|
||||
details: { message: getUserErrorMessage(error) },
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { scopeTransactionsToAccount } from '@/lib/reconciliation/bank-reconcilia
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { validateBody } from '@/lib/api/validate'
|
||||
import { CreateTransactionSchema } from '@/lib/api/schemas'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
const MAX_ROWS = 500
|
||||
|
||||
@@ -98,7 +99,7 @@ export async function GET(request: Request) {
|
||||
const { data, error } = await query
|
||||
|
||||
if (error) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 })
|
||||
return NextResponse.json({ error: getUserErrorMessage(error) }, { status: 500 })
|
||||
}
|
||||
|
||||
const rows = data || []
|
||||
@@ -147,7 +148,7 @@ export const POST = withRouteContext(
|
||||
// is invalid input, not a server fault: surface it as 400 with the PG
|
||||
// code so the client maps it to a friendly message.
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code, type: 'database_error' },
|
||||
{ error: getUserErrorMessage(error), code: error.code, type: 'database_error' },
|
||||
{ status: 400 },
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user