diff --git a/app/api/reports/ink2/route.ts b/app/api/reports/ink2/route.ts
index 08556d29..d056aabf 100644
--- a/app/api/reports/ink2/route.ts
+++ b/app/api/reports/ink2/route.ts
@@ -6,6 +6,7 @@ import {
} from '@/lib/reports/ink2/sru-generator'
import { withRouteContext } from '@/lib/api/with-route-context'
import { errorResponseFromCode } from '@/lib/errors/get-structured-error'
+import { encodeISO88591 } from '@/lib/reports/sru-encoding'
import JSZip from 'jszip'
/**
@@ -67,13 +68,3 @@ export const GET = withRouteContext(
}
},
)
-
-/** Encode a string as ISO 8859-1 bytes; characters outside Latin-1 become '?'. */
-function encodeISO88591(str: string): Uint8Array {
- const bytes = new Uint8Array(str.length)
- for (let i = 0; i < str.length; i++) {
- const code = str.charCodeAt(i)
- bytes[i] = code <= 0xFF ? code : 0x3F
- }
- return bytes
-}
diff --git a/app/api/reports/ne-bilaga/route.ts b/app/api/reports/ne-bilaga/route.ts
index 15331b33..67981b65 100644
--- a/app/api/reports/ne-bilaga/route.ts
+++ b/app/api/reports/ne-bilaga/route.ts
@@ -1,12 +1,13 @@
import { NextResponse } from 'next/server'
import { generateNEDeclaration } from '@/lib/reports/ne-bilaga/ne-engine'
import {
- generateSRUFile,
- sruFileToString,
- getSRUFilename,
+ generateNESRUSubmission,
+ getZipFilename,
} from '@/lib/reports/ne-bilaga/sru-generator'
import { withRouteContext } from '@/lib/api/with-route-context'
import { errorResponseFromCode } from '@/lib/errors/get-structured-error'
+import { encodeISO88591 } from '@/lib/reports/sru-encoding'
+import JSZip from 'jszip'
/**
* GET /api/reports/ne-bilaga
@@ -34,14 +35,23 @@ export const GET = withRouteContext(
const declaration = await generateNEDeclaration(supabase, companyId!, periodId)
if (format === 'sru') {
- const sruFile = generateSRUFile(declaration)
- const sruContent = sruFileToString(sruFile)
- const filename = getSRUFilename(declaration)
+ const submission = generateNESRUSubmission(declaration)
- return new NextResponse(sruContent, {
+ // Skatteverket requires ISO 8859-1 (Latin-1); UTF-8 mojibakes å/ä/ö and is rejected.
+ const infoBytes = encodeISO88591(submission.infoSru)
+ const blanketterBytes = encodeISO88591(submission.blanketterSru)
+
+ const zip = new JSZip()
+ zip.file('INFO.SRU', infoBytes)
+ zip.file('BLANKETTER.SRU', blanketterBytes)
+
+ const zipArrayBuffer = await zip.generateAsync({ type: 'arraybuffer' })
+ const filename = getZipFilename(declaration)
+
+ return new NextResponse(zipArrayBuffer, {
status: 200,
headers: {
- 'Content-Type': 'text/plain; charset=utf-8',
+ 'Content-Type': 'application/zip',
'Content-Disposition': `attachment; filename="${filename}"`,
'X-Request-Id': requestId,
},
diff --git a/components/bookkeeping/year-end/EfDeclarationSection.tsx b/components/bookkeeping/year-end/EfDeclarationSection.tsx
index 90f77db0..38dac11e 100644
--- a/components/bookkeeping/year-end/EfDeclarationSection.tsx
+++ b/components/bookkeeping/year-end/EfDeclarationSection.tsx
@@ -361,11 +361,11 @@ export function EfDeclarationSection({
diff --git a/components/reports/NEDeclarationView.tsx b/components/reports/NEDeclarationView.tsx
index 53e7b822..1c03f894 100644
--- a/components/reports/NEDeclarationView.tsx
+++ b/components/reports/NEDeclarationView.tsx
@@ -12,6 +12,7 @@ import { formatCurrency } from '@/lib/utils'
export function NEDeclarationView({ periodId }: { periodId: string }) {
const [data, setData] = useState(null)
const [loading, setLoading] = useState(false)
+ const [downloading, setDownloading] = useState(false)
const [error, setError] = useState(null)
const fetchDeclaration = async () => {
@@ -32,8 +33,24 @@ export function NEDeclarationView({ periodId }: { periodId: string }) {
}
}
- const downloadSRU = () => {
- window.open(`/api/reports/ne-bilaga?period_id=${periodId}&format=sru`, '_blank')
+ const downloadSRU = async () => {
+ setDownloading(true)
+ try {
+ const res = await fetch(`/api/reports/ne-bilaga?period_id=${periodId}&format=sru`)
+ if (!res.ok) throw new Error('Download failed')
+ const blob = await res.blob()
+ const filename = res.headers.get('Content-Disposition')?.match(/filename="(.+)"/)?.[1] || 'NE_SRU.zip'
+ const url = URL.createObjectURL(blob)
+ const a = document.createElement('a')
+ a.href = url
+ a.download = filename
+ a.click()
+ URL.revokeObjectURL(url)
+ } catch {
+ setError('Kunde inte ladda ner SRU-filer')
+ } finally {
+ setDownloading(false)
+ }
}
// NE ruta labels
@@ -72,9 +89,9 @@ export function NEDeclarationView({ periodId }: { periodId: string }) {
{loading ? 'Laddar...' : 'Hämta NE-bilaga'}
{data && (
-