XML generation for skattemelding (corporate tax return) submission to Skatteetaten.
Generates three XML documents:
skattemeldingUpersonlig(v5) — minimal:partsnummer,inntektsaar, and optionallyinntektOgUnderskudd/underskuddTilFremfoering/fremfoertUnderskuddFraTidligereAar. Other fields (income, formue, deductions) are derived by Skatteetaten from the næringsspesifikasjon. PerskattemeldingUpersonlig_v5_ekstern.xsd.naeringsspesifikasjon(v6) — resultatregnskap, balanseregnskap, virksomhet,skalBekreftesAvRevisor. Sum/derived fields (erAvledet="true") are computed by Skatteetaten and not emitted. Pernaeringsspesifikasjon_v6_ekstern.xsd.skattemeldingOgNaeringsspesifikasjonRequest(v2) — envelope wrapping both inner documents base64-encoded. Perskattemeldingognaeringsspesifikasjonrequest_v2.xsd.
Ported from wenche/skattemelding_xml.py, wenche/naeringsspesifikasjon_xml.py,
and wenche/skattemelding_konvolutt.py in the Python Wenche project.
Partsnummer
partsnummer (and partsreferanse in næringsspesifikasjon) is Skatteetaten's
internal integer ID for the company. It must be fetched from the pre-filled
draft API (GET /api/skattemelding/v2/{år}/{orgnr}) before generating the
XML for actual submission.
When called without :partsnummer in opts, the generators fall back to
aarsregnskap.selskap.org_nummer as a placeholder. This passes XSD
validation (org_nummer fits xsd:long) but Skatteetaten will reject the
actual submission unless replaced with the real partsnummer.
Summary
Functions
Calculates {samletVerdiFoerEventuellVerdsettingsrabatt, samletGjeld} for
<formueOgGjeld>.
Returns net value behind the shares, floored at zero, for display/control.
Generates the naeringsspesifikasjon XML document (v6).
Generates a <forskjellMellomRegnskapsmessigOgSkattemessigVerdi> block
from a list of permanent-forskjell maps. Returns "" for an empty list.
Generates the request envelope wrapping skattemelding + naeringsspesifikasjon.
Generates the skattemeldingUpersonlig XML document (v5).
Generates a <spesifikasjonAvForholdRelevanteForBeskatning> block from a
list of holding maps. Returns an empty string for an empty list.
Extracts the partsnummer from a skattemeldingUpersonlig XML document.
Functions
Calculates {samletVerdiFoerEventuellVerdsettingsrabatt, samletGjeld} for
<formueOgGjeld>.
samlet_verdi_bak_aksjene is treated as an explicit net override and takes
precedence. Otherwise, formuesverdi_aksjer replaces the book value of
share/fund holdings while bank deposits and receivables are included at face
value. Returns {nil, nil} when no valuation input is present.
Returns net value behind the shares, floored at zero, for display/control.
@spec generer_naeringsspesifikasjon_xml( Wenche.Models.Aarsregnskap.t(), keyword() ) :: String.t()
Generates the naeringsspesifikasjon XML document (v6).
Options
:partsnummer— Skatteetaten's integer ID. Defaults toaarsregnskap.selskap.org_nummer.:permanent_forskjeller— list of maps emitted as<forskjellMellomRegnskapsmessigOgSkattemessigVerdi><permanentForskjell>…. Required for SKD to apply fritaksmetoden — without these explicit "tilbakeføring av utbytte" / "treprosent" / "gevinst-fradrag" / "tap-tillegg" declarations, SKD taxes the full regnskapsmessig income. Seegenerer_permanent_forskjell_block/1for the expected shape.:kontaktperson— map with:navn(required),:telefonnummer(optional),:epostadresse(optional). Emitted as<kontaktperson>inside<virksomhet>. SKD's post-acceptance audit appears to read this as the "spor til utførende" (named human to contact about the submission); omitting it has been observed to cause SKD to returninnkommendeForespoerselManglerSporTilUtfoerendein the tilbakemelding after a successful Altinn signing.
Generates a <forskjellMellomRegnskapsmessigOgSkattemessigVerdi> block
from a list of permanent-forskjell maps. Returns "" for an empty list.
Each entry must include:
:type—tekniskNavnfrom the 2025 permanentForskjellstype kodeliste. Examples relevant to fritaksmetoden::tilbakefoeringAvInntektsfoertUtbytte(0815, fradrag),:skattepliktigDelAvUtbytterOgUtdelinger(0653, tillegg = 3 %),:regnskapsmessigGevinstVedRealisasjonAvFinansielleInstrumenter(0833, fradrag),:regnskapsmessigTapVedRealisasjonAvFinansielleInstrumenter(0633, tillegg).:beloep—Decimal.tor integer NOK (always positive; the kodeliste'skategoridetermines whether SKD treats it as tillegg or fradrag). Decimal beloep is rounded per line for emission as an integer. Rounding mode is:half_upfor most types; the 3 % addback (:skattepliktigDelAvUtbytterOgUtdelinger) floors instead, per skatteloven § 2-38 (6) and the SKD veiledning convention.:beskrivelse— optional free text.
Entries with :beloep <= 0 (after rounding) are dropped — SKD
rejects zero-valued permanent forskjeller as invalid.
Generates the request envelope wrapping skattemelding + naeringsspesifikasjon.
Both inner documents are base64-encoded into <dokument><content> entries.
Options
:inntektsaar— required for the envelope element.:tin— TIN/organisasjonsnummer (recommended).:innsendingstype—"komplett"(default) or"ikkeKomplett".:innsendingsformaal—"egenfastsetting"(default),"klage", or"endringsanmodning".:dokumentreferanse— optional list of{dokumenttype, dokumentidentifikator}pairs to emit as<dokumentreferanseTilGjeldendeDokument>entries.:opprettet_av— text used for<opprettetAv>(default"Wenche"). Override to identify the originating end-user system.
Generates the skattemeldingUpersonlig XML document (v5).
Options
:partsnummer— Skatteetaten's integer ID for the company. Defaults toaarsregnskap.selskap.org_nummer.:fremfoert_underskudd— loss carryforward from prior years (integer kroner). Defaults tokonfig.underskudd_til_fremfoering. Element is emitted only when value is > 0.:aksjespesifikasjon— list of holding maps emitted as<spesifikasjonAvForholdRelevanteForBeskatning>. Seegenerer_spesifikasjon_av_forhold_relevante_for_beskatning/1for the expected map shape. Required for SKD to apply fritaksmetoden to dividends and gains on aksje/verdipapir holdings — without it, SKD taxes the full income.konfig.formuesverdi_aksjer— summed formuesverdi of share/fund holdings. When present, emits<formueOgGjeld>with XSD-backed overstyring fields so SKD can derive value behind the company's shares.konfig.samlet_verdi_bak_aksjene— explicit net value behind the shares. When present, this override takes precedence over:formuesverdi_aksjer.
Generates a <spesifikasjonAvForholdRelevanteForBeskatning> block from a
list of holding maps. Returns an empty string for an empty list.
Each holding map must include :type, which selects the forekomst variant:
:aksje_i_aksjonaerregisteret— Norwegian AS in aksjonærregisteret. Expected keys::selskapets_navn,:selskapets_organisasjonsnummer,:landkode,:er_omfattet_av_fritaksmetoden,:aksjeklasse,:isinnummer,:antall_aksjer,:utbytte,:gevinst_ved_realisasjon_av_aksje,:tap_ved_realisasjon_av_aksje.:aksje_ikke_i_aksjonaerregisteret— foreign shares held via custodian. Adds:kontofoerers_navn,:kontonummer,:finansproduktidentifikator,:finansproduktidentifikatortype.:verdipapirfond— mutual fund. Expected keys::fondets_navn,:fondets_organisasjonsnummer,:landkode,:er_omfattet_av_fritaksmetoden,:isinnummer,:antall_andeler,:utbytte,:renteinntekt,:gevinst_ved_realisasjon_av_andel_i_aksjedel,:tap_ved_realisasjon_av_andel_i_aksjedel,:gevinst_ved_realisasjon_av_andel_i_rentedel,:tap_ved_realisasjon_av_andel_i_rentedel.
All numeric fields are emitted only when non-nil. id is assigned by
index (1-based) in the order received.
Extracts the partsnummer from a skattemeldingUpersonlig XML document.
Used after fetching the pre-filled draft from
GET /api/skattemelding/v2/{år}/{orgnr} to learn Skatteetaten's internal
ID for the company.
Returns {:ok, integer} or {:error, :partsnummer_not_found}.