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:
@@ -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'
|
||||
|
||||
// GET /api/documents/:id/extraction-status
|
||||
//
|
||||
@@ -29,7 +30,7 @@ export const GET = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
.eq('company_id', companyId)
|
||||
.maybeSingle()
|
||||
|
||||
if (error) return NextResponse.json({ error: error.message }, { status: 500 })
|
||||
if (error) return NextResponse.json({ error: getUserErrorMessage(error) }, { status: 500 })
|
||||
if (!data) return NextResponse.json({ error: 'Not found' }, { status: 404 })
|
||||
|
||||
const extractedAt = data.extracted_at as string | null
|
||||
|
||||
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server'
|
||||
import { requireAuth } from '@/lib/auth/require-auth'
|
||||
import { createServiceClient } from '@/lib/supabase/server'
|
||||
import { contentDisposition } from '@/lib/api/content-disposition'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
/**
|
||||
* GET /api/documents/:id/inline
|
||||
@@ -83,7 +84,7 @@ export async function GET(
|
||||
|
||||
if (downloadError || !blob) {
|
||||
return NextResponse.json(
|
||||
{ error: `Failed to download document: ${downloadError?.message ?? 'unknown error'}` },
|
||||
{ error: `Failed to download document: ${getUserErrorMessage(downloadError) ?? 'unknown error'}` },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { linkToJournalEntry } from '@/lib/core/documents/document-service'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { errorResponseFromCode } from '@/lib/errors/get-structured-error'
|
||||
import { LinkDocumentSchema } from '@/lib/api/schemas'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -73,7 +74,7 @@ export const POST = withRouteContext(
|
||||
// Non-fatal: the verifikat ↔ underlag link already succeeded.
|
||||
opLog.warn('inbox item stamp after link failed', {
|
||||
inboxItemId: body.inbox_item_id,
|
||||
reason: inboxError.message,
|
||||
reason: getUserErrorMessage(inboxError),
|
||||
})
|
||||
} else if (!stamped || stamped.length === 0) {
|
||||
// Zero rows updated means the supplied inbox_item_id / document_id
|
||||
@@ -100,7 +101,7 @@ export const POST = withRouteContext(
|
||||
// pin is row-level UX on the /transactions list.
|
||||
opLog.warn('transaction pin after link failed', {
|
||||
transactionId: body.transaction_id,
|
||||
reason: pinError.message,
|
||||
reason: getUserErrorMessage(pinError),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -125,7 +126,7 @@ export const POST = withRouteContext(
|
||||
}
|
||||
return errorResponseFromCode('DOC_LINK_FAILED', opLog, {
|
||||
requestId,
|
||||
details: { reason: message || 'unknown' },
|
||||
details: { reason: getUserErrorMessage(err) },
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ensureInitialized } from '@/lib/init'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { deleteDocument } from '@/lib/core/documents/document-service'
|
||||
import { eventBus } from '@/lib/events'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -34,7 +35,7 @@ export const GET = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
|
||||
if (signError) {
|
||||
return NextResponse.json(
|
||||
{ error: `Failed to create download URL: ${signError.message}` },
|
||||
{ error: `Failed to create download URL: ${getUserErrorMessage(signError)}` },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
@@ -80,7 +81,7 @@ export const DELETE = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
} catch (error) {
|
||||
console.error('[documents/DELETE] Failed to delete document:', error)
|
||||
return NextResponse.json(
|
||||
{ error: error instanceof Error ? error.message : 'Failed to delete document' },
|
||||
{ error: error instanceof Error ? getUserErrorMessage(error) : 'Failed to delete document' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { verifyIntegrity } from '@/lib/core/documents/document-service'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -21,7 +22,7 @@ export const POST = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
} catch (error) {
|
||||
console.error('[documents/verify/POST] Verification failed:', error)
|
||||
return NextResponse.json(
|
||||
{ error: error instanceof Error ? error.message : 'Verification failed' },
|
||||
{ error: error instanceof Error ? getUserErrorMessage(error) : 'Verification failed' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { createNewVersion, validateDocumentFile } from '@/lib/core/documents/document-service'
|
||||
import { getErrorMessage as getUserErrorMessage } from '@/lib/errors/get-error-message'
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
@@ -42,7 +43,7 @@ export const POST = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
} catch (error) {
|
||||
console.error('[documents/versions/POST] Version creation failed:', error)
|
||||
return NextResponse.json(
|
||||
{ error: error instanceof Error ? error.message : 'Version creation failed' },
|
||||
{ error: error instanceof Error ? getUserErrorMessage(error) : 'Version creation failed' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
@@ -83,7 +84,7 @@ export const GET = withRouteContext<{ params: Promise<{ id: string }> }>(
|
||||
.order('version', { ascending: true })
|
||||
|
||||
if (versionsError) {
|
||||
return NextResponse.json({ error: versionsError.message }, { status: 500 })
|
||||
return NextResponse.json({ error: getUserErrorMessage(versionsError) }, { status: 500 })
|
||||
}
|
||||
|
||||
return NextResponse.json({ data: versions })
|
||||
|
||||
@@ -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'
|
||||
|
||||
/**
|
||||
* GET /api/documents/counts?journal_entry_ids=id1,id2,...
|
||||
@@ -34,7 +35,7 @@ export const GET = withRouteContext('document.counts', async (request, ctx) => {
|
||||
.in('journal_entry_id', ids)
|
||||
|
||||
if (error) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 })
|
||||
return NextResponse.json({ error: getUserErrorMessage(error) }, { status: 500 })
|
||||
}
|
||||
|
||||
// Group and count by journal_entry_id
|
||||
|
||||
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import { uploadDocument, validateDocumentFile } from '@/lib/core/documents/document-service'
|
||||
import { withRouteContext } from '@/lib/api/with-route-context'
|
||||
import { getErrorMessage } from '@/lib/errors/get-error-message'
|
||||
import { errorResponse, errorResponseFromCode } from '@/lib/errors/get-structured-error'
|
||||
import type { DocumentUploadSource } from '@/types'
|
||||
|
||||
@@ -78,7 +79,7 @@ export const POST = withRouteContext(
|
||||
if (/locked\/closed fiscal period|Bokföringen är låst/i.test(message)) {
|
||||
return errorResponseFromCode('DOC_UPLOAD_PERIOD_LOCKED', opLog, {
|
||||
requestId,
|
||||
details: { reason: message },
|
||||
details: { reason: getErrorMessage(err) },
|
||||
})
|
||||
}
|
||||
// Magic-byte validation rejections (validateDocumentMagicBytes) are a
|
||||
@@ -88,7 +89,7 @@ export const POST = withRouteContext(
|
||||
opLog.warn('document upload rejected by content validation', { reason: message })
|
||||
return errorResponseFromCode('DOC_UPLOAD_INVALID_CONTENT', opLog, {
|
||||
requestId,
|
||||
details: { reason: message },
|
||||
details: { reason: getErrorMessage(err) },
|
||||
})
|
||||
}
|
||||
// Full error is logged above; the raw message can leak storage-layer
|
||||
|
||||
Reference in New Issue
Block a user