Files
accounted/app/api/import/documents/preview/route.ts
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

55 lines
2.2 KiB
TypeScript

import { NextResponse } from 'next/server'
import { ensureInitialized } from '@/lib/init'
import { withRouteContext } from '@/lib/api/with-route-context'
import { validateBody } from '@/lib/api/validate'
import { UnderlagImportPreviewSchema } from '@/lib/api/schemas'
import { buildUnderlagPlan } from '@/lib/documents/underlag-import'
import { errorResponse, errorResponseFromCode } from '@/lib/errors/get-structured-error'
ensureInitialized()
/**
* POST /api/import/documents/preview: plan which verifikat each underlag file
* belongs to, from the voucher reference in its filename.
*
* Read-only by construction. Only the NAMES are sent, so a user can review the
* whole plan (including the misses) before a single byte is uploaded, and
* before a single irreversible link is written.
*
* Scoped to the fiscal year the caller declares: `A31` identifies a verifikat
* only inside a year, because source systems restart numbering annually.
*/
export const POST = withRouteContext('import.documents.preview', async (request, ctx) => {
const { supabase, companyId, log, requestId } = ctx
const validation = await validateBody(request, UnderlagImportPreviewSchema)
if (!validation.success) return validation.response
const { file_names: fileNames, fiscal_period_id: fiscalPeriodId } = validation.data
// The period must belong to this company: buildUnderlagPlan filters entries
// by it, and an unowned id would silently produce an all-misses plan rather
// than an honest error.
const { data: period, error: periodError } = await supabase
.from('fiscal_periods')
.select('id')
.eq('id', fiscalPeriodId)
.eq('company_id', companyId!)
.maybeSingle()
if (periodError) {
log.error('underlag import preview period lookup failed', periodError)
return errorResponse(periodError, log, { requestId })
}
if (!period) {
return errorResponseFromCode('FISCAL_PERIOD_NOT_FOUND', log, { requestId })
}
try {
const plan = await buildUnderlagPlan(supabase, companyId!, fileNames, fiscalPeriodId)
return NextResponse.json({ data: plan })
} catch (err) {
log.error('underlag import preview failed', err as Error, { fileCount: fileNames.length })
return errorResponse(err, log, { requestId })
}
})