Fjern ubl-tools og profilopslaget fra sitet
Build & Deploy / deploy (push) Successful in 54s

Claude-Session: https://claude.ai/code/session_01GGe7kUhooMFuzY6GaDb2w9
This commit is contained in:
Asger Geel Weirsøe
2026-11-09 16:05:08 +01:00
parent dcad720d64
commit 8d6183f689
13 changed files with 3 additions and 1454 deletions
-3
View File
@@ -77,6 +77,3 @@ html[data-theme="terminal"] {
.hm-3 { background: color-mix(in srgb, var(--color-accent) 80%, var(--color-surface-2)); } .hm-3 { background: color-mix(in srgb, var(--color-accent) 80%, var(--color-surface-2)); }
.hm-4 { background: var(--color-accent); } .hm-4 { background: var(--color-accent); }
/* /profiler */
.copy { transition: color 0.15s; }
.copy:hover { color: var(--color-accent); text-decoration: underline; text-underline-offset: 3px; }
-60
View File
@@ -1,60 +0,0 @@
---
title: "ubl-tools"
description: "Read UBL e-invoices (Peppol BIS 3.0 and OIOUBL) in the terminal or as a printable page, and pull out the attached PDF. Everything happens on your own machine."
date: 2026-09-30
updated: 2026-10-01
extra:
lang: en
repo: ubl-tools
sprog: Rust
licens: MIT OR Apache-2.0
platforme: [Linux, macOS, Windows]
aur: [ubl-tools, ubl-tools-bin]
tags: [peppol, oioubl, nemhandel, e-invoicing, rust]
alternates: [{lang: da, path: /projekter/ubl-tools}, {lang: en, path: /en/projects/ubl-tools}]
---
An e-invoice is an XML file. Reading one means scrolling through a few hundred lines of `cbc:` and `cac:` elements, or uploading it to an online viewer. The viewers work, but they want the whole invoice, and that includes names, VAT numbers, bank details and what the customer bought. I'm not keen on sending all that to a stranger's server just to read it.
So I wrote `ubl`. It reads the file locally and shows it as an ordinary invoice: seller and buyer with their identifiers named properly (CVR, GLN, VAT numbers and Peppol endpoint IDs instead of bare scheme codes like `0184`), the lines with quantity, unit, price and VAT, the VAT breakdown per category and the totals. Payment details come along too, including Danish FI cards in the familiar `+71<…+…<` notation. If the invoice is wrapped in a Peppol envelope (SBDH), it unwraps it by itself.
It understands Peppol BIS Billing 3.0, OIOUBL 2.1 (the Danish NemHandel format) and other EN 16931 invoices and credit notes. OIOUBL has a small trap where `TaxExclusiveAmount` is actually the VAT amount and not the amount before VAT.. `ubl` knows about it, so the totals add up.
## Install
On Arch Linux it's on the AUR, as a source package and as a prebuilt binary:
```bash
yay -S ubl-tools # builds from source
yay -S ubl-tools-bin # prebuilt binary
```
On macOS from my Homebrew tap:
```bash
brew tap asger-weirsoee/tap
brew install ubl-tools
```
On Windows 10/11 with Scoop:
```powershell
scoop install https://asger.weirsoe.dk/tarballz/ubl-tools.json
```
You can also grab the zip from [tarballz](/tarballz/) and unpack it. The binary isn't code signed, so Windows may ask before the first run.
## Usage
```bash
ubl view invoice.xml # in the terminal
ubl view invoice.xml --open # as a page in the browser
ubl view invoice.xml --lang da # Danish labels
ubl extract invoice.xml other.xml # save the PDF next to each file
ubl extract *.xml -o ./bilag # or all of them into one folder
ubl open invoice.xml # save attachments, open in browser
```
`ubl extract` never overwrites anything. An identical file that's already there is reused, and a different one gets a new name. On Windows you can drop one or more XML files straight onto `ubl.exe` in Explorer: the PDFs are saved, the invoices open, and the window stays until you've read the result.
The HTML page is a single self-contained file with no external requests, laid out for A4 so it prints cleanly.
-5
View File
@@ -1,5 +0,0 @@
---
title: "Profil-opslag (Nemhandel & Peppol)"
description: "Søgbart opslag over Nemhandel OIOUBL- og Peppol BIS/PINT-profiler: profil-id'er, customization-id'er, indeholdte dokumenter og typisk anvendelse."
template: sider/profiler.html
---
-62
View File
@@ -1,62 +0,0 @@
---
title: "ubl-tools"
description: "Læs e-fakturaer i UBL (Peppol BIS 3.0 og OIOUBL) i terminalen eller som en side du kan printe, og træk den vedhæftede PDF ud. Alt foregår på din egen maskine."
date: 2026-09-30
updated: 2026-10-01
extra:
lang: da
repo: ubl-tools
sprog: Rust
licens: MIT OR Apache-2.0
platforme: [Linux, macOS, Windows]
aur: [ubl-tools, ubl-tools-bin]
tags: [peppol, oioubl, nemhandel, e-faktura, rust]
alternates: [{lang: da, path: /projekter/ubl-tools}, {lang: en, path: /en/projects/ubl-tools}]
---
En e-faktura er en XML-fil. Vil man læse en, skal man enten scrolle gennem et par hundrede linjer `cbc:` og `cac:`, eller uploade den til en online viewer. Viewerne virker fint, men de vil have hele fakturaen, og den indeholder navne, CVR-numre, bankoplysninger og hvad kunden har købt. Det har jeg det lidt stramt med at sende til en fremmed server bare for at kunne læse den.
Så jeg skrev `ubl`. Den læser filen lokalt og viser den som en almindelig faktura: sælger og køber med deres identifikatorer navngivet ordentligt (CVR, GLN, SE-nr. og Peppol-endpoints i stedet for skemakoder som `0184`), linjerne med antal, enhed, pris og moms, momsopgørelsen pr. kategori og totalerne. Betalingsoplysningerne kommer med, også danske FI-kort i den velkendte `+71<…+…<`-notation. Er fakturaen pakket ind i en Peppol-kuvert (SBDH), pakker den den selv ud.
Den forstår Peppol BIS Billing 3.0, OIOUBL 2.1 og andre EN 16931-fakturaer og kreditnotaer. OIOUBL har en lille finte, hvor `TaxExclusiveAmount` faktisk er momsbeløbet og ikke beløbet før moms.. det har den lært at tage højde for, så tallene passer.
## Installation
På Arch Linux ligger den på AUR, både som kildepakke og som færdigbygget binær:
```bash
yay -S ubl-tools # bygges fra kildekoden
yay -S ubl-tools-bin # færdigbygget binær
```
På macOS via min Homebrew-tap:
```bash
brew tap asger-weirsoee/tap
brew install ubl-tools
```
På Windows 10/11 med Scoop:
```powershell
scoop install https://asger.weirsoe.dk/tarballz/ubl-tools.json
```
Du kan også hente zip-filen fra [tarballz](/tarballz/) og pakke den ud. Binæren er ikke kodesigneret, så Windows spørger måske første gang den køres.
## Brug
```bash
ubl view faktura.xml # i terminalen
ubl view faktura.xml --open # som side i browseren
ubl view faktura.xml --lang da # danske labels
ubl extract faktura.xml anden.xml # gem PDF'en ved hver fil
ubl extract *.xml -o ./bilag # eller alle i én mappe
ubl open faktura.xml # gem bilag og åbn i browser
```
`ubl extract` overskriver aldrig noget. Ligger der allerede en identisk fil, genbruges den, og er den anderledes, får den nye et andet navn. På Windows kan du trække en eller flere XML-filer direkte over på `ubl.exe` i Stifinder, så gemmes PDF'erne og fakturaerne åbnes, og vinduet bliver stående til du har læst resultatet.
HTML-siden er én selvstændig fil uden eksterne forespørgsler, sat op til A4, så den printer pænt.
Skal du bare have afkodet en CustomizationID eller se hvilken profil en faktura følger, kan [UBL-tjekket](/ubl) her på siden gøre det direkte i browseren.
-5
View File
@@ -1,5 +0,0 @@
---
title: "UBL-tjek & identifikator-afkoder"
description: "Træk en UBL/OIOUBL-faktura ind eller indsæt en CustomizationID/ProfileID, så afkoder den profilen, syntaksen og EN 16931-status. Alt sker lokalt i browseren; filen sendes aldrig nogen steder."
template: sider/ubl.html
---
-5
View File
@@ -42,11 +42,6 @@
"title": "Homelab status", "title": "Homelab status",
"desc": "Live status for the public parts of my homelab." "desc": "Live status for the public parts of my homelab."
}, },
{
"href": "/ubl",
"title": "UBL check (Danish)",
"desc": "Drop in an e-invoice and get its profile, syntax and EN 16931 status decoded. It all runs in the browser, the file never leaves your machine."
},
{ {
"href": "/en/projects", "href": "/en/projects",
"title": "Projects", "title": "Projects",
-10
View File
@@ -50,16 +50,6 @@
"href": "/now", "href": "/now",
"title": "Now", "title": "Now",
"desc": "Hvad jeg roder med lige nu, plus et aktivitets-heatmap fra min egen Gitea." "desc": "Hvad jeg roder med lige nu, plus et aktivitets-heatmap fra min egen Gitea."
},
{
"href": "/profiler",
"title": "Profil-opslag",
"desc": "Søgbart opslag over Nemhandel OIOUBL- og Peppol BIS/PINT-profiler: id'er, dokumenter og typisk brug."
},
{
"href": "/ubl",
"title": "UBL-tjek",
"desc": "Træk en faktura ind og få profil, syntaks og EN 16931-status afkodet. Alt sker i browseren, filen forlader aldrig din maskine."
} }
] ]
} }
-961
View File
@@ -1,961 +0,0 @@
{
"standarder": [
"Nemhandel OIOUBL (UBL 2.1)",
"Peppol BIS 3.0",
"Peppol BIS 4.0 / PINT"
],
"kategorier": [
"Fakturering",
"Ordre til fakturering",
"Simple Ordrer",
"Katalog",
"Udvidet fakturering",
"Udvidet katalog",
"Udvidet ordre til fakturering",
"ForsyningsSpecifikation",
"Diverse"
],
"profiles": [
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Fakturering",
"navn": "Procurement-BilSim-1.0 (simpel fakturering)",
"id": "Procurement-BilSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse (kun ved afvisning)"
],
"anvendelse": "Ren fakturering: leverandør sender faktura/kreditnota/rykker til kunde. Ingen ordreproces, og kunden er ikke forpligtet til at kvittere.",
"bemaerkninger": "Obligatorisk profil og den mest udbredte rene faktura-pakke i Nemhandel. Kunden må afvise med ApplicationResponse, men skal ikke kvittere positivt.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Fakturering",
"navn": "urn:www.nesubl.eu:profiles:profile5:ver2.0 (NES5, Billing Basic)",
"id": "urn:www.nesubl.eu:profiles:profile5:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Invoice",
"CreditNote"
],
"anvendelse": "Internationalt NES-fakturaprofil: kunde modtager faktura og kreditnota fra leverandør.",
"bemaerkninger": "Obligatorisk profil. Den profil der ligger tættest på den gamle OIOXML-faktura, kun afløftede felter er tilladt. Bruges når fakturaafsender teknisk set ikke kan modtage en ApplicationResponse.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Ordre til fakturering",
"navn": "Procurement-OrdSim-BilSim-1.0 (simpel ordre + simpel fakturering)",
"id": "Procurement-OrdSim-BilSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Komplet simpel handel: simpel ordre efterfulgt af simpel fakturering. Dækker bestilling til betaling.",
"bemaerkninger": "Samlepakken de fleste vælger, når de vil kunne både bestille og fakturere. Ingen ordreændring/-annullering, det kræver en OrdAdv-variant.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Simple Ordrer",
"navn": "Procurement-OrdRes-1.0 (kun ordresvar)",
"id": "Procurement-OrdRes-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"OrderResponse"
],
"anvendelse": "Enkeltdokument-profil til alene at kunne udveksle en ordrebekræftelse (OrderResponse) uden at tilmelde sig en fuld ordreproces.",
"bemaerkninger": "Registerprofil af typen \"single\", findes i Nemhandelsregistret, men er ikke beskrevet i OIOUBL Profiler-guiden (G26) v1.3. Verificér mod registret før brug.",
"kilde": {
"label": "Nemhandelsregistret",
"url": "https://nemhandel.dk/nemhandelsregisteret"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Simple Ordrer",
"navn": "Procurement-OrdSim-1.0 (simpel ordre)",
"id": "Procurement-OrdSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple"
],
"anvendelse": "Ren ordreproces: kunde sender ordre, leverandør svarer med simpelt ordresvar. Ingen fakturering i profilen.",
"bemaerkninger": "Ren ordre-only proces; kombineres typisk med en faktureringsprofil.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Simple Ordrer",
"navn": "Procurement-OrdSimR-1.0 (simpel ordre m. krævet svar)",
"id": "Procurement-OrdSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple"
],
"anvendelse": "Som OrdSim, men leverandør skal altid sende ordresvar.",
"bemaerkninger": "R = 'Response required': samme dokumenter som OrdSim, men svaret er obligatorisk.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Simple Ordrer",
"navn": "urn:www.nesubl.eu:profiles:profile3:ver2.0 (NES3, \"Order Only\")",
"id": "urn:www.nesubl.eu:profiles:profile3:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order"
],
"anvendelse": "Leverandør modtager ordrer fra kunder. Intet ordresvar og ingen fakturering i profilen.",
"bemaerkninger": "Ældre NES-ordreprofil; OrdSim-varianterne anbefales i stedet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Katalog",
"navn": "Catalogue-CatBas-1.0 (basalt katalog)",
"id": "Catalogue-CatBas-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Catalogue",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Leverandør sender et produktkatalog til kunden og kan slette det igen. Kunden kan afvise med ApplicationResponse.",
"bemaerkninger": "Simpleste katalogprofil, ingen prisopdatering, ingen katalogforespørgsel.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Katalog",
"navn": "Catalogue-CatPriUpd-1.0 (kun prisopdatering)",
"id": "Catalogue-CatPriUpd-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"CataloguePricingUpdate",
"ApplicationResponse"
],
"anvendelse": "Leverandør opdaterer alene priserne i et allerede udvekslet katalog.",
"bemaerkninger": "\"Catalogue Pricing Update Only\" forudsætter at kataloget er sendt via en anden katalogprofil.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Katalog",
"navn": "Catalogue-CatPriUpdR-1.0 (kun prisopdatering m. krævet svar)",
"id": "Catalogue-CatPriUpdR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"CataloguePricingUpdate",
"ApplicationResponse"
],
"anvendelse": "Som CatPriUpd, men kunden skal kvittere for prisopdateringen.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Katalog",
"navn": "Catalogue-CatSim-1.0 (katalogforespørgsel + katalog)",
"id": "Catalogue-CatSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"CatalogueRequest",
"Catalogue",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Kunden beder om et katalog (CatalogueRequest), leverandøren sender det og kan slette det igen.",
"bemaerkninger": "CatBas udvidet med katalogforespørgsel fra kunden.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet fakturering",
"navn": "Procurement-BilSimR-1.0 (simpel fakturering m. krævet svar)",
"id": "Procurement-BilSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse"
],
"anvendelse": "Som BilSim, men kunden skal altid kvittere med et ApplicationResponse (accept/afvisning).",
"bemaerkninger": "R = 'Response required': kunden skal kvittere. Bemærk: tilmelding til BilSimR giver ikke automatisk BilSim; begge skal registreres hver for sig.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet fakturering",
"navn": "Procurement-BilSimReminderOnly-1.0 (kun rykker)",
"id": "Procurement-BilSimReminderOnly-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Reminder"
],
"anvendelse": "Enkeltdokument-profil til alene at kunne modtage rykkere.",
"bemaerkninger": "Registerprofil af typen \"single\", ikke i OIOUBL Profiler-guiden (G26) v1.3. Praktisk fordi Reminder ikke findes i Peppol BIS Billing og derfor kun kan sendes i OIOUBL-profilerne.",
"kilde": {
"label": "Nemhandelsregistret",
"url": "https://nemhandel.dk/nemhandelsregisteret"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet fakturering",
"navn": "Procurement-PayBas-1.0 (kontoudtog)",
"id": "Procurement-PayBas-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Statement",
"ApplicationResponse"
],
"anvendelse": "Leverandør sender kontoudtog (Statement) til kunden, en samlet oversigt over udestående poster, ikke en faktura.",
"bemaerkninger": "G26 kalder profilen direkte \"Statement\". Trods \"Pay\"-navnet er der ingen betalingsdokumenter i profilen.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet fakturering",
"navn": "Procurement-PayBasR-1.0 (kontoudtog m. krævet svar)",
"id": "Procurement-PayBasR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Statement",
"ApplicationResponse"
],
"anvendelse": "Som PayBas, men kunden skal kvittere for kontoudtoget.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet fakturering",
"navn": "urn:www.nesubl.eu:profiles:profile8:ver2.0 (NES8)",
"id": "urn:www.nesubl.eu:profiles:profile8:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Invoice",
"CreditNote",
"ApplicationResponse"
],
"anvendelse": "NES-faktureringsprofil med kvittering: faktura og kreditnota, hvor kunden kan svare med ApplicationResponse.",
"bemaerkninger": "NES5 udvidet med ApplicationResponse. Ingen Reminder.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "Catalogue-CatAdv-1.0 (avanceret katalog)",
"id": "Catalogue-CatAdv-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"CatalogueRequest",
"Catalogue",
"CatalogueItemSpecificationUpdate",
"CataloguePricingUpdate",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Fuld katalogproces: forespørgsel, katalog, opdatering af både varebeskrivelser og priser samt sletning.",
"bemaerkninger": "Den mest komplette katalogprofil: CatExt plus katalogforespørgsel.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "Catalogue-CatAdvR-1.0 (avanceret katalog m. krævet svar)",
"id": "Catalogue-CatAdvR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"CatalogueRequest",
"Catalogue",
"CatalogueItemSpecificationUpdate",
"CataloguePricingUpdate",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Som CatAdv, men modtageren skal kvittere for katalogdokumenterne.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "Catalogue-CatBasR-1.0 (basalt katalog m. krævet svar)",
"id": "Catalogue-CatBasR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Catalogue",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Som CatBas, men kunden skal kvittere for kataloget.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "Catalogue-CatExt-1.0 (udvidet katalog + opdatering)",
"id": "Catalogue-CatExt-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Catalogue",
"CatalogueItemSpecificationUpdate",
"CataloguePricingUpdate",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Katalogudveksling med efterfølgende opdatering af varebeskrivelser og priser samt sletning. Ingen katalogforespørgsel.",
"bemaerkninger": "CatBas udvidet med opdateringsdokumenter.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "Catalogue-CatExtR-1.0 (udvidet katalog + opdatering m. krævet svar)",
"id": "Catalogue-CatExtR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Catalogue",
"CatalogueItemSpecificationUpdate",
"CataloguePricingUpdate",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Som CatExt, men kunden skal kvittere.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "Catalogue-CatSimR-1.0 (katalogforespørgsel + katalog m. krævet svar)",
"id": "Catalogue-CatSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"CatalogueRequest",
"Catalogue",
"CatalogueDeletion",
"ApplicationResponse"
],
"anvendelse": "Som CatSim, men katalogsvar er påkrævet.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "urn:www.nesubl.eu:profiles:profile1:ver2.0 (NES1, \"Catalogue Only\")",
"id": "urn:www.nesubl.eu:profiles:profile1:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Catalogue",
"ApplicationResponse"
],
"anvendelse": "Ren katalogudsendelse: leverandør sender katalog, kunden kan afvise.",
"bemaerkninger": "Ældre NES-katalogprofil; Catalogue-CatBas-1.0 anbefales i stedet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet katalog",
"navn": "urn:www.nesubl.eu:profiles:profile2:ver2.0 (NES2, simpel katalogproces)",
"id": "urn:www.nesubl.eu:profiles:profile2:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Catalogue",
"CatalogueItemSpecificationUpdate",
"CataloguePricingUpdate"
],
"anvendelse": "Katalog med efterfølgende opdatering af varebeskrivelser og priser. Ingen kvittering i profilen.",
"bemaerkninger": "Ældre NES-katalogprofil; Catalogue-CatExt-1.0 anbefales i stedet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdAdv-BilSim-1.0 (avanceret ordre + simpel fakturering)",
"id": "Procurement-OrdAdv-BilSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponse",
"OrderResponseSimple",
"OrderChange",
"OrderCancellation",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Avanceret ordreproces (fuldt ordresvar samt ordreændring og -annullering) efterfulgt af simpel fakturering.",
"bemaerkninger": "Understøtter begge parter både OrdSim-BilSim og OrdAdv-BilSim, skal OrdAdv-BilSim bruges.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdAdv-BilSimR-1.0 (avanceret ordre + fakturering m. krævet fakturasvar)",
"id": "Procurement-OrdAdv-BilSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponse",
"OrderResponseSimple",
"OrderChange",
"OrderCancellation",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Som OrdAdv-BilSim, men fakturasvar (ApplicationResponse) er påkrævet.",
"bemaerkninger": "R sidder på fakturadelen, ordresvaret er stadig valgfrit.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdAdvR-BilSim-1.0 (avanceret ordre m. krævet ordresvar + simpel fakturering)",
"id": "Procurement-OrdAdvR-BilSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponse",
"OrderResponseSimple",
"OrderChange",
"OrderCancellation",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Som OrdAdv-BilSim, men ordresvar er påkrævet.",
"bemaerkninger": "R sidder på ordredelen, fakturasvaret er valgfrit.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdAdvR-BilSimR-1.0 (avanceret ordre + fakturering, begge svar krævet)",
"id": "Procurement-OrdAdvR-BilSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponse",
"OrderResponseSimple",
"OrderChange",
"OrderCancellation",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Avanceret ordre og fakturering hvor både ordresvar og fakturasvar er påkrævet.",
"bemaerkninger": "Strammeste variant af ordre-til-faktura-kæden.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdSel-BilSim-1.0 (sælgerinitieret ordre + simpel fakturering)",
"id": "Procurement-OrdSel-BilSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"OrderResponse",
"OrderResponseSimple",
"OrderChange",
"OrderCancellation",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Sælgerinitieret handel: leverandøren starter med en ordrebekræftelse (fx efter aftale i marken eller telefonisk), kunden kan ændre eller annullere, og der faktureres bagefter.",
"bemaerkninger": "Bemærk: ingen Order i profilen, \"Sel\" = seller initiated, så processen starter med OrderResponse.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdSel-BilSimR-1.0 (sælgerinitieret ordre + fakturering m. krævet svar)",
"id": "Procurement-OrdSel-BilSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"OrderResponse",
"OrderResponseSimple",
"OrderChange",
"OrderCancellation",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Som OrdSel-BilSim, men fakturasvar er påkrævet.",
"bemaerkninger": "Ingen Order i profilen, processen starter hos sælger.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdSim-BilSimR-1.0 (simpel ordre + fakturering m. krævet fakturasvar)",
"id": "Procurement-OrdSim-BilSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Simpel ordre + fakturering hvor fakturasvar (ApplicationResponse) er påkrævet.",
"bemaerkninger": "R sidder på fakturadelen.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdSimR-BilSim-1.0 (simpel ordre m. krævet ordresvar + fakturering)",
"id": "Procurement-OrdSimR-BilSim-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Som OrdSim-BilSim, men ordresvar er påkrævet.",
"bemaerkninger": "R sidder på ordredelen.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "Procurement-OrdSimR-BilSimR-1.0 (simpel ordre + fakturering, begge svar krævet)",
"id": "Procurement-OrdSimR-BilSimR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple",
"Invoice",
"CreditNote",
"Reminder",
"ApplicationResponse *"
],
"anvendelse": "Simpel ordre og fakturering hvor både ordresvar og fakturasvar er påkrævet.",
"bemaerkninger": "Begge R’er sat, modparten skal kvittere i begge led.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Udvidet ordre til fakturering",
"navn": "urn:www.nesubl.eu:profiles:profile7:ver2.0 (NES7, ordre til faktura)",
"id": "urn:www.nesubl.eu:profiles:profile7:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"Order",
"OrderResponseSimple",
"Invoice",
"CreditNote",
"ApplicationResponse *"
],
"anvendelse": "NES-profil for simpel ordre efterfulgt af simpel fakturering.",
"bemaerkninger": "Ældre NES-pendant til OrdSim-BilSim. Ingen Reminder i profilen.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "ForsyningsSpecifikation",
"navn": "Reference-Utility-1.0 (forsyningsspecifikation, UTS)",
"id": "Reference-Utility-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"UtilityStatement",
"ApplicationResponse"
],
"anvendelse": "Forsyningsbranchen (el/vand/varme/gas): leverandør sender detaljeret forbrugs-/forsyningsspecifikation der ledsager fakturaen; kunden kan svare med ApplicationResponse.",
"bemaerkninger": "Bruges som tillæg til en faktureringsprofil, UTS erstatter ikke fakturaen.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "ForsyningsSpecifikation",
"navn": "Reference-UtilityR-1.0 (forsyningsspecifikation m. krævet svar)",
"id": "Reference-UtilityR-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"UtilityStatement",
"ApplicationResponse"
],
"anvendelse": "Som Reference-Utility, men kunden skal kvittere for forsyningsspecifikationen.",
"bemaerkninger": "R = svar påkrævet.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"kategori": "Diverse",
"navn": "Procurement-TecRes-1.0 (kvittering på modtaget dokument)",
"id": "Procurement-TecRes-1.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"ApplicationResponse"
],
"anvendelse": "Ren kvitteringsprofil: bruges til at svare på et modtaget dokument, typisk når afsendelsen ikke kan behandles pga. tekniske fejl eller en ikke-understøttet profil.",
"bemaerkninger": "Bruges som ProfileID på selve ApplicationResponse’en, ikke som en forretningsproces man handler i.",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Nemhandel OIOUBL (UBL 2.1)",
"navn": "urn:www.cenbii.eu:profile:bii30:ver2.0 (forsendelsesadvis / despatch advice)",
"id": "urn:www.cenbii.eu:profile:bii30:ver2.0",
"customization": "OIOUBL-2.x",
"dokumenter": [
"DespatchAdvice"
],
"anvendelse": "Leverandør varsler en forsendelse, så kunden kan forberede modtagelse og afstemme leveringen mod ordren.",
"bemaerkninger": "CEN BII-profil optaget i OIOUBL (G26 afsnit 3.3.15). Ikke placeret i en registerkategori her, bekræft gruppen i Nemhandelsregistrets dropdown før brug.",
"kategori": "",
"kilde": {
"label": "OIOUBL Profiler (G26)",
"url": "https://oioubl21.oioubl.dk/documents/en/en/Guidelines/OIOUBL_GUIDE_PROFILES.pdf"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Billing 3.0",
"id": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
"customization": "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0",
"dokumenter": [
"Invoice",
"CreditNote"
],
"anvendelse": "Den centrale e-faktura/kreditnota-pakke i Peppol. CIUS af EN 16931. Bruges til EU-grænsehandel og DK/Peppol-fakturering.",
"bemaerkninger": "Langt den mest brugte BIS3-profil. Invoice Response er en separat profil. Bemærk: Reminder findes ikke i Peppol, brug OIOUBL-profilerne til rykkere.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS Billing 3.0",
"url": "https://docs.peppol.eu/poacc/billing/3.0/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Self-Billing 3.0",
"id": "urn:fdc:peppol.eu:2017:poacc:selfbilling:01:1.0",
"customization": "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0#conformant#urn:fdc:peppol.eu:2017:poacc:selfbilling:international:3.0",
"dokumenter": [
"Invoice (self-billed)",
"CreditNote"
],
"anvendelse": "Selvfakturering: køber udsteder fakturaen på vegne af sælger.",
"bemaerkninger": "Genbruger Billing-syntaks med self-billing customization.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · Self-Billing 3.0",
"url": "https://docs.peppol.eu/poacc/self-billing/3.0/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Invoice Response 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:invoice_response:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:invoice_response:3",
"dokumenter": [
"ApplicationResponse (Invoice Response)"
],
"anvendelse": "Køber sender struktureret status/svar på en modtaget faktura (accepteret, afvist, under behandling, betalt).",
"bemaerkninger": "Bruges sammen med Billing til at lukke faktura-livscyklussen. Peppol-pendant til OIOUBL-ernes \"R\"-profiler.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Message Level Response 3.0 (MLR)",
"id": "urn:fdc:peppol.eu:poacc:bis:mlr:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:mlr:3",
"dokumenter": [
"ApplicationResponse (Message Level Response)"
],
"anvendelse": "Teknisk kvittering på beskedniveau: bekræfter modtagelse/validering af et hvilket som helst dokument.",
"bemaerkninger": "Transport-/syntaks-niveau svar, ikke forretningsmæssigt indhold. Peppol-pendant til Procurement-TecRes-1.0.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Ordering 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:ordering:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:order:3 / urn:fdc:peppol.eu:poacc:trns:order_response:3",
"dokumenter": [
"Order",
"Order Response"
],
"anvendelse": "Fuld ordreproces: køber sender ordre, sælger svarer med ordrebekræftelse/-svar.",
"bemaerkninger": "Order = Trdm01, Order Response = Trdm76. Peppol-pendant til Procurement-OrdSim-1.0.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Order Only 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:order_only:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:order:3",
"dokumenter": [
"Order"
],
"anvendelse": "Kun afsendelse af ordre uden forventet struktureret ordresvar.",
"bemaerkninger": "Enkel ordre-only proces. Peppol-pendant til NES3 (\"Order Only\").",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Order Agreement 3.0 (Advanced Ordering)",
"id": "urn:fdc:peppol.eu:poacc:bis:order_agreement:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:order_agreement:3",
"dokumenter": [
"Order",
"Order Response (Advanced)"
],
"anvendelse": "Avanceret ordre der etablerer en bindende ordreaftale mellem parterne.",
"bemaerkninger": "Bruges hvor ordresvar danner juridisk aftale.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Catalogue 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:catalogue:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:catalogue:3",
"dokumenter": [
"Catalogue",
"ApplicationResponse (Catalogue Response)"
],
"anvendelse": "Sælger sender produktkatalog (priser/varer) til køber, der kan svare med accept/afvisning.",
"bemaerkninger": "Grundlag for efterfølgende ordrer. Peppol-pendant til Catalogue-CatBasR-1.0.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Catalogue without Response 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:catalogue_wo_response:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:catalogue:3",
"dokumenter": [
"Catalogue"
],
"anvendelse": "Katalogudsendelse uden forventet katalogsvar.",
"bemaerkninger": "Variant uden Catalogue Response.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Punch Out 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:punch_out:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:punch_out:3",
"dokumenter": [
"Catalogue (Punch Out)"
],
"anvendelse": "Punch-out katalog: køber 'hopper ud' til sælgers webshop og henter en kurv tilbage.",
"bemaerkninger": "Bruges i e-handels-/webshop-integrationer.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 3.0",
"navn": "Peppol BIS Despatch Advice 3.0",
"id": "urn:fdc:peppol.eu:poacc:bis:despatch_advice:3",
"customization": "urn:fdc:peppol.eu:poacc:trns:despatch_advice:3",
"dokumenter": [
"Despatch Advice (følgeseddel)"
],
"anvendelse": "Sælger sender forsendelses-/leveringsmeddelelse (hvad er afsendt, hvornår, hvordan) inden faktura.",
"bemaerkninger": "Logistik-dokument mellem ordre og faktura. Peppol-pendant til urn:www.cenbii.eu:profile:bii30:ver2.0 i OIOUBL.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · BIS v3",
"url": "https://docs.peppol.eu/poacc/upgrade-3/"
}
},
{
"standard": "Peppol BIS 4.0 / PINT",
"navn": "EU PINT Billing (v1.0.1; forløber for BIS Billing 4.0)",
"id": "urn:peppol:pint:billing-1@eu-1 (PINT EU Billing)",
"customization": "urn:peppol:pint:billing-1@eu-1",
"dokumenter": [
"Invoice",
"CreditNote"
],
"anvendelse": "Peppols internationale fakturamodel (PINT) tilpasset EU. Implementerer BIS Billing 3.0 som PINT-kompatibel uden ændringer; baner vej for grænseoverskridende fakturering mod lande med egne PINT-specs (AU/JP/MY/NZ/SG m.fl.).",
"bemaerkninger": "v1.0.0 udgivet okt. 2025, nu v1.0.1. CIUS af EN 16931. NB: identifikator-format afviger fra BIS3, verificér mod docs.peppol.eu/poac/eu/pint-eu inden brug.",
"kategori": "",
"kilde": {
"label": "docs.peppol.eu · EU PINT Billing",
"url": "https://docs.peppol.eu/poac/eu/pint-eu/"
}
},
{
"standard": "Peppol BIS 4.0 / PINT",
"navn": "Peppol BIS Billing 4.0 (kommende)",
"id": "(endnu ikke endeligt fastlagt)",
"customization": "(endnu ikke endeligt fastlagt)",
"dokumenter": [
"Invoice",
"CreditNote (forventet)"
],
"anvendelse": "Næste generation der lægger BIS og PINT sammen til ét globalt faktura-format. Forventet 2026, endnu ikke udgivet (pr. juni 2026).",
"bemaerkninger": "STATUS: under udarbejdelse pr. juni 2026, ID'er og indhold ikke endeligt publiceret. Brug BIS Billing 3.0 / EU PINT i mellemtiden.",
"kategori": "",
"kilde": {
"label": "Peppol roadmap",
"url": "https://docs.peppol.eu/poac/"
}
}
]
}
+1 -1
View File
@@ -31,7 +31,7 @@ def route_for_file(f):
return "/" + m[1].rstrip("/") if m[1] != "_index" else "/" return "/" + m[1].rstrip("/") if m[1] != "_index" else "/"
m = re.fullmatch(r"templates/sider/(.+)\.html", f) or re.fullmatch(r"data/(.+)\.json", f) m = re.fullmatch(r"templates/sider/(.+)\.html", f) or re.fullmatch(r"data/(.+)\.json", f)
if m: if m:
name = {"forside": "", "forside-en": "en", "profiles": "profiler"}.get(m[1], m[1]) name = {"forside": "", "forside-en": "en"}.get(m[1], m[1])
return "/en/" + name[:-3] if name.endswith("-en") else "/" + name return "/en/" + name[:-3] if name.endswith("-en") else "/" + name
return None return None
+1 -1
View File
@@ -8,7 +8,7 @@ import urllib.request
BASE, USER = "https://gitea.weircon.dk", "agw" BASE, USER = "https://gitea.weircon.dk", "agw"
HIDE = set() # repo-navne der skjules helt HIDE = set() # repo-navne der skjules helt
PINNED = ["ubl-tools", "gtk-ahfail", "pi3-smart-workspace"] # vises først, i den rækkefølge PINNED = ["gtk-ahfail", "pi3-smart-workspace"] # vises først, i den rækkefølge
WEEKS = 26 WEEKS = 26
MAANEDER = ["januar", "februar", "marts", "april", "maj", "juni", "juli", "august", MAANEDER = ["januar", "februar", "marts", "april", "maj", "juni", "juli", "august",
"september", "oktober", "november", "december"] "september", "oktober", "november", "december"]
+1 -1
View File
@@ -1,4 +1,4 @@
[{"type":"page","title":"Forside","url":"/"},{"type":"page","title":"CV","url":"/cv"},{"type":"page","title":"CV (English)","url":"/en/cv"},{"type":"page","title":"Home (English)","url":"/en"},{"type":"page","title":"Ask my CV (English)","url":"/en/chat"},{"type":"page","title":"Projekter","url":"/projekter"}, [{"type":"page","title":"Forside","url":"/"},{"type":"page","title":"CV","url":"/cv"},{"type":"page","title":"CV (English)","url":"/en/cv"},{"type":"page","title":"Home (English)","url":"/en"},{"type":"page","title":"Ask my CV (English)","url":"/en/chat"},{"type":"page","title":"Projekter","url":"/projekter"},
{%- for p in pages %}{% if p.components[0] == "projekter" %}{"type":"page","title":{{ ("Projekt: " ~ p.title) | json_encode | safe }},"url":"{{ p.path | trim_end(pat="/") }}","extra":{{ [p.extra.sprog, ...p.extra.aur, ...p.extra.tags] | join(sep=" ") | json_encode | safe }}},{% elif p.components[0] == "en" %}{"type":"page","title":{{ ("Project: " ~ p.title ~ " (English)") | json_encode | safe }},"url":"{{ p.path | trim_end(pat="/") }}","extra":{{ [p.extra.sprog, ...p.extra.aur, ...p.extra.tags] | join(sep=" ") | json_encode | safe }}},{% endif %}{% endfor -%} {%- for p in pages %}{% if p.components[0] == "projekter" %}{"type":"page","title":{{ ("Projekt: " ~ p.title) | json_encode | safe }},"url":"{{ p.path | trim_end(pat="/") }}","extra":{{ [p.extra.sprog, ...p.extra.aur, ...p.extra.tags] | join(sep=" ") | json_encode | safe }}},{% elif p.components[0] == "en" %}{"type":"page","title":{{ ("Project: " ~ p.title ~ " (English)") | json_encode | safe }},"url":"{{ p.path | trim_end(pat="/") }}","extra":{{ [p.extra.sprog, ...p.extra.aur, ...p.extra.tags] | join(sep=" ") | json_encode | safe }}},{% endif %}{% endfor -%}
{"type":"page","title":"Færdigbyggede pakker (tarballz)","url":"/tarballz/"},{"type":"page","title":"Blog","url":"/blog"},{"type":"page","title":"Tags","url":"/tags"},{"type":"page","title":"Profil-opslag (Nemhandel & Peppol)","url":"/profiler"},{"type":"page","title":"UBL-tjek & identifikator-afkoder","url":"/ubl"},{"type":"page","title":"Spørg mit CV (AI-chat)","url":"/chat"},{"type":"page","title":"Status (homelab)","url":"/status"},{"type":"page","title":"Now","url":"/now"},{"type":"page","title":"Uses","url":"/uses"},{"type":"page","title":"Kolofon","url":"/colophon"},{"type":"page","title":"Cookies","url":"/cookies"} {"type":"page","title":"Færdigbyggede pakker (tarballz)","url":"/tarballz/"},{"type":"page","title":"Blog","url":"/blog"},{"type":"page","title":"Tags","url":"/tags"},{"type":"page","title":"Spørg mit CV (AI-chat)","url":"/chat"},{"type":"page","title":"Status (homelab)","url":"/status"},{"type":"page","title":"Now","url":"/now"},{"type":"page","title":"Uses","url":"/uses"},{"type":"page","title":"Kolofon","url":"/colophon"},{"type":"page","title":"Cookies","url":"/cookies"}
{%- for p in pages %}{% if p.components[0] == "blog" %},{"type":"post","title":{{ p.title | json_encode | safe }},"url":"{{ p.path | trim_end(pat="/") }}","extra":{{ p.taxonomies.tags | default(value=[]) | join(sep=" ") | json_encode | safe }}}{% endif %}{% endfor %}] {%- for p in pages %}{% if p.components[0] == "blog" %},{"type":"post","title":{{ p.title | json_encode | safe }},"url":"{{ p.path | trim_end(pat="/") }}","extra":{{ p.taxonomies.tags | default(value=[]) | join(sep=" ") | json_encode | safe }}}{% endif %}{% endfor %}]
-156
View File
@@ -1,156 +0,0 @@
{% extends "base.html" %}
{% block main %}
{% set d = load_data(path="data/profiles.json") %}
<h1 class="text-4xl font-bold tracking-tight">Profil-opslag</h1>
<p class="mt-4 max-w-2xl text-muted">
Browse og søg i e-dokumentprofilerne for <strong class="text-text">Nemhandel OIOUBL</strong> og
<strong class="text-text">Peppol BIS/PINT</strong>: profil-/proces-id, customization-id, hvilke
dokumenter profilen indeholder og typisk anvendelse. Klik på et id for at kopiere det.
</p>
<p class="mt-3 max-w-2xl text-sm text-muted">
De danske profiler står i samme rækkefølge og under samme gruppenavne som i
<strong class="text-text">Nemhandelsregistrets</strong> profil-dropdown (“Profiler for: …”), så du kan
slå direkte op mellem registrering og dokumentindhold.
</p>
<div class="mt-8 flex flex-col gap-4 sm:flex-row sm:items-center">
<div class="relative flex-1">
<span class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted">⌕</span>
<input
id="p-search"
type="search"
placeholder="Søg profil, id, dokument…"
autocomplete="off"
aria-label="Søg profiler"
class="w-full wt-input wt-input--lg pl-9"
/>
</div>
<span id="p-count" class="text-sm text-muted">{{ d.profiles | length }} profiler</span>
</div>
<div class="mt-3 flex flex-wrap gap-2">
<button type="button" class="wt-btn wt-btn--ghost wt-btn--sm" data-std="" aria-pressed="true">Alle</button>
{% for s in d.standarder %}<button type="button" class="wt-btn wt-btn--ghost wt-btn--sm" data-std="{{ s }}" aria-pressed="false">{{ s }}</button>{% endfor %}
</div>
<div class="mt-3">
<span class="mr-2 text-xs text-muted">Nemhandelsregistrets kategori:</span>
<span class="mt-1 inline-flex flex-wrap gap-2 align-middle">
<button type="button" class="wt-btn wt-btn--ghost wt-btn--sm" data-kat="" aria-pressed="true">Alle</button>
{% for k in d.kategorier %}<button type="button" class="wt-btn wt-btn--ghost wt-btn--sm" data-kat="{{ k }}" aria-pressed="false">{{ k }}</button>{% endfor %}
</span>
</div>
<div class="mt-6 space-y-3">
{%- for p in d.profiles %}
<article
data-profile
data-standard="{{ p.standard }}"
data-kategori="{{ p.kategori }}"
data-search="{{ (p.standard ~ " " ~ p.kategori ~ " " ~ p.navn ~ " " ~ p.id ~ " " ~ p.customization ~ " " ~ (p.dokumenter | join(sep=" ")) ~ " " ~ p.anvendelse ~ " " ~ p.bemaerkninger) | lower }}"
class="wt-card wt-card--hover"
>
<div class="flex flex-wrap items-center gap-2">
<span class="wt-tag wt-tag--accent">
{{ p.standard }}
</span>
{% if p.kategori %}
<span
class="wt-tag wt-muted"
title="Gruppen profilen står under i Nemhandelsregistrets dropdown"
>
Register: {{ p.kategori }}
</span>
{% endif %}
</div>
<h2 class="mt-2 text-lg font-semibold tracking-tight">{{ p.navn }}</h2>
<dl class="mt-3 grid gap-1 text-xs sm:grid-cols-[10rem_1fr]">
<dt class="text-muted">Profil/proces-id</dt>
<dd>
<button type="button" data-copy="{{ p.id }}" title="Klik for at kopiere" class="copy break-all text-left font-mono">
{{ p.id }}
</button>
</dd>
<dt class="text-muted">Customization-id</dt>
<dd>
<button type="button" data-copy="{{ p.customization }}" title="Klik for at kopiere" class="copy break-all text-left font-mono">
{{ p.customization }}
</button>
</dd>
</dl>
<div class="mt-3 flex flex-wrap gap-1.5">
{% for doc in p.dokumenter %}
<span class="wt-tag">{{ doc }}</span>
{% endfor %}
</div>
<p class="mt-3 text-sm text-muted">{{ p.anvendelse }}</p>
<p class="mt-2 text-xs text-muted">
<span class="font-semibold text-muted">Bemærk:</span> {{ p.bemaerkninger }}
</p>
<p class="mt-3 text-xs"><a href="{{ p.kilde.url | safe }}" target="_blank" rel="noopener" class="text-accent/80 transition-colors hover:text-accent">Kilde: {{ p.kilde.label }} ↗</a></p>
</article>
{%- endfor %}
</div>
<p id="p-none" class="mt-6 text-sm text-muted" hidden>Ingen profiler matcher.</p>
<p class="mt-10 text-xs text-muted">
Kilder: OIOUBL Profiler-guiden (G26) v1.3 (dokumentlister, tabel 1-3), Nemhandelsregistret
(gruppering og profilnavne) og Peppol BIS/PINT (docs.peppol.eu). * = ApplicationResponse bruges kun
til afvisning; det forretningsmæssige svar på en ordre er altid OrderResponse/OrderResponseSimple.
Øjebliksbillede.. verificér altid id'er mod den officielle dokumentation før brug.
</p>
<script>
(function () {
var cards = [].slice.call(document.querySelectorAll('[data-profile]'));
var search = document.getElementById('p-search');
var stdChips = [].slice.call(document.querySelectorAll('button[data-std]'));
var katChips = [].slice.call(document.querySelectorAll('button[data-kat]'));
var count = document.getElementById('p-count');
var none = document.getElementById('p-none');
var q = '', std = '', kat = '';
function apply() {
var shown = 0;
cards.forEach(function (c) {
var okS = !std || c.getAttribute('data-standard') === std;
var okK = !kat || c.getAttribute('data-kategori') === kat;
var okQ = !q || c.getAttribute('data-search').indexOf(q) > -1;
var hit = okS && okK && okQ;
c.hidden = !hit;
if (hit) shown++;
});
count.textContent = shown + (shown === 1 ? ' profil' : ' profiler');
none.hidden = shown > 0;
}
search.addEventListener('input', function () { q = search.value.trim().toLowerCase(); apply(); });
function wire(group, attr, set) {
group.forEach(function (b) {
b.addEventListener('click', function () {
set(b.getAttribute(attr) || '');
group.forEach(function (x) { x.setAttribute('aria-pressed', x === b ? 'true' : 'false'); });
apply();
});
});
}
wire(stdChips, 'data-std', function (v) { std = v; });
wire(katChips, 'data-kat', function (v) { kat = v; });
document.addEventListener('click', function (e) {
var btn = e.target.closest && e.target.closest('[data-copy]');
if (!btn || !navigator.clipboard) return;
navigator.clipboard.writeText(btn.getAttribute('data-copy')).then(function () {
var orig = btn.textContent;
btn.textContent = 'kopieret ✓';
setTimeout(function () { btn.textContent = orig; }, 1200);
}).catch(function () {});
});
var qp = new URLSearchParams(location.search).get('q');
if (qp) { search.value = qp; q = qp.trim().toLowerCase(); }
apply();
})();
</script>
{% endblock %}
-184
View File
@@ -1,184 +0,0 @@
{% extends "base.html" %}
{% block main %}
{% set d = load_data(path="data/profiles.json") %}
<h1 class="text-4xl font-bold tracking-tight">UBL-tjek</h1>
<p class="mt-4 max-w-2xl text-muted">
Træk en <strong class="text-text">UBL/OIOUBL-faktura</strong> (eller andet UBL-dokument) ind, eller indsæt en
<strong class="text-text">CustomizationID/ProfileID</strong>, så afkoder den profilen, syntaksen og
EN 16931-status og kobler til <a href="/profiler" class="text-accent">profil-opslaget</a>.
Alt sker <strong class="text-text">lokalt i din browser</strong>; intet sendes nogen steder.
</p>
<p class="mt-3 max-w-2xl text-muted">
Vil du læse hele fakturaen eller have den vedhæftede PDF ud, så har jeg skrevet
<a href="/projekter/ubl-tools" class="text-accent hover:underline">ubl-tools</a> til terminalen,
også på Windows og macOS.
</p>
<div id="drop" class="mt-8 wt-dropzone">
<p class="text-muted">Træk en <code class="rounded bg-surface-2 px-1.5 py-0.5">.xml</code>-fil hertil, eller
<label class="cursor-pointer text-accent hover:underline">vælg en fil<input id="file" type="file" accept=".xml,text/xml,application/xml" class="hidden" /></label>.
</p>
</div>
<details class="mt-3">
<summary class="cursor-pointer text-sm text-muted">…eller indsæt XML / en identifikator manuelt</summary>
<textarea id="paste" rows="6" placeholder="Indsæt UBL-XML, eller bare en CustomizationID/ProfileID…"
class="mt-2 w-full wt-input wt-input--lg font-mono text-xs"></textarea>
<p class="mt-2"><button id="analyze" type="button" class="wt-btn wt-btn--primary">Afkod</button></p>
</details>
<div id="result" class="mt-6" hidden></div>
<p id="err" class="mt-6 text-sm" hidden></p>
<p class="mt-10 text-xs text-muted/80">
Heuristik mod kendte profiler (samme datagrundlag som <a href="/profiler" class="text-accent">/profiler</a>) +
EN 16931-/Peppol-/OIOUBL-mønstre. Privat: ingen upload, ingen sporing af indholdet.
</p>
<script type="application/json" id="profiles-data" >[{% for p in d.profiles %}{"standard":{{ p.standard | json_encode | safe }},"navn":{{ p.navn | json_encode | safe }},"id":{{ p.id | json_encode | safe }},"customization":{{ p.customization | json_encode | safe }},"dokumenter":{{ p.dokumenter | json_encode | safe }}}{% if not loop.last %},{% endif %}{% endfor %}]</script>
<script>
(function () {
var PROFILES = JSON.parse(document.getElementById('profiles-data').textContent || '[]');
var drop = document.getElementById('drop'), fileInput = document.getElementById('file'),
paste = document.getElementById('paste'), result = document.getElementById('result'),
err = document.getElementById('err');
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) {
return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
// Electronic Address Scheme (ISO 6523): de gængse, DK/Norden i fokus.
var EAS = {
'0088': 'GLN (GS1 Global Location Number)',
'0184': 'DK:CVR (dansk CVR-nummer)',
'0198': 'DK:SE (dansk SE-nummer)',
'0096': 'DK:P (dansk P-nummer)',
'0192': 'NO:ORG (norsk organisasjonsnummer)',
'0007': 'SE:ORG (svensk organisationsnummer)',
'0208': 'BE:CBE (belgisk virksomhedsnr.)',
'0151': 'AU:ABN', '0060': 'DUNS', '0235': 'JP', '0211': 'IT:PA',
'9915': 'Peppol test-deltager', '9930': 'DE:LWID (Leitweg-ID)',
};
function findEl(doc, name) {
var all = doc.getElementsByTagName('*');
for (var i = 0; i < all.length; i++) if (all[i].localName === name) return all[i];
return null;
}
function txt(doc, name) { var e = findEl(doc, name); return e ? (e.textContent || '').trim() : ''; }
// afkod en CustomizationID/ProfileID-streng til menneskesprog
function decode(custom, profile) {
var notes = [], standard = null, match = null;
var c = (custom || '').trim(), p = (profile || '').trim();
// 1) eksakt match mod kendte profiler
match = PROFILES.find(function (x) { return c && x.customization === c; })
|| PROFILES.find(function (x) { return p && x.id === p; })
|| PROFILES.find(function (x) { return c && x.id === c; });
// 2) mønster-heuristik (også når der ikke er fuldt match)
var blob = (c + ' ' + p).toLowerCase();
if (blob.indexOf('en16931') > -1) notes.push('EN 16931-kompatibel (CIUS af den europæiske kernefaktura)');
if (blob.indexOf('peppol.eu') > -1 || blob.indexOf('fdc:peppol') > -1) { standard = 'Peppol BIS'; notes.push('Peppol-netværket'); }
if (blob.indexOf('pint') > -1) { standard = 'Peppol PINT'; notes.push('PINT (Peppol International)'); }
if (blob.indexOf('billing:3.0') > -1) notes.push('Billing 3.0-proces');
if (blob.indexOf('selfbilling') > -1) notes.push('Selvfakturering (køber udsteder)');
if (blob.indexOf('oioubl') > -1) { standard = standard || 'OIOUBL (NemHandel)'; notes.push('OIOUBL, dansk UBL-tilpasning'); }
if (/procurement-/i.test(p)) { standard = standard || 'OIOUBL (NemHandel)'; if (/r-|r$|simr|advr/i.test(p)) notes.push("'R' = svar påkrævet"); }
return { match: match, standard: match ? match.standard : standard, notes: notes };
}
function badge(text, kind) {
return '<span class="wt-tag' + (kind === 'ok' ? ' wt-tag--accent' : '') + '">' + esc(text) + '</span>';
}
function row(dt, dd) {
return '<div class="grid gap-1 sm:grid-cols-[10rem_1fr]"><dt class="text-muted">' + esc(dt) +
'</dt><dd class="break-all font-mono">' + (dd || '<span class="text-muted">—</span>') + '</dd></div>';
}
function renderXml(doc) {
var root = doc.documentElement;
var docType = root ? root.localName : '?';
var ublv = txt(doc, 'UBLVersionID');
var custom = txt(doc, 'CustomizationID');
var profile = txt(doc, 'ProfileID');
var id = txt(doc, 'ID');
var dec = decode(custom, profile);
// EAS på parter
var endpoints = [];
var eps = doc.getElementsByTagName('*');
for (var i = 0; i < eps.length; i++) {
if (eps[i].localName === 'EndpointID') {
var scheme = eps[i].getAttribute('schemeID') || '';
endpoints.push({ scheme: scheme, val: (eps[i].textContent || '').trim() });
}
}
var epHtml = endpoints.slice(0, 4).map(function (e) {
return '<div>' + badge((EAS[e.scheme] || ('EAS ' + e.scheme || 'ukendt')), '') +
' <span class="font-mono text-xs">' + esc(e.val) + '</span></div>';
}).join('');
var head = dec.match
? '<div class="flex flex-wrap items-center gap-2">' + badge(dec.match.standard, 'ok') +
'</div><h2 class="mt-2 text-xl font-semibold tracking-tight">' + esc(dec.match.navn) + '</h2>'
: '<h2 class="text-xl font-semibold tracking-tight">' + esc(docType) +
(dec.standard ? ' <span class="text-muted text-base font-normal">· ' + esc(dec.standard) + '</span>' : '') + '</h2>';
result.innerHTML =
'<div class="wt-card">' + head +
'<dl class="mt-3 space-y-1 text-xs">' +
row('Dokumenttype', '<span class="font-semibold">' + esc(docType) + '</span> (UBL ' + (esc(ublv) || '2.x') + ')') +
row('ID', esc(id)) +
row('ProfileID', esc(profile)) +
row('CustomizationID', esc(custom)) +
'</dl>' +
(dec.notes.length ? '<div class="mt-3 flex flex-wrap gap-1.5">' + dec.notes.map(function (n) { return badge(n, ''); }).join('') + '</div>' : '') +
(epHtml ? '<p class="mt-3 text-xs text-muted">Parter (EAS):</p><div class="mt-1 space-y-1">' + epHtml + '</div>' : '') +
(dec.match ? '<p class="mt-3 text-xs"><a class="text-accent hover:underline" href="/profiler?q=' + encodeURIComponent(dec.match.id) + '">Se profilen i /profiler ↗</a></p>'
: '<p class="mt-3 text-xs text-muted">Ingen eksakt match i profil-databasen, afkodet ud fra mønstre.</p>') +
'</div>';
result.hidden = false; err.hidden = true;
}
function renderId(s) {
var dec = decode(s, s);
result.innerHTML = '<div class="wt-card">' +
(dec.match ? '<div class="flex flex-wrap items-center gap-2">' + badge(dec.match.standard, 'ok') +
'</div><h2 class="mt-2 text-xl font-semibold tracking-tight">' + esc(dec.match.navn) + '</h2>'
: '<h2 class="text-xl font-semibold tracking-tight">Identifikator</h2>') +
'<dl class="mt-3 space-y-1 text-xs">' + row('Streng', esc(s)) + '</dl>' +
(dec.notes.length ? '<div class="mt-3 flex flex-wrap gap-1.5">' + dec.notes.map(function (n) { return badge(n, ''); }).join('') + '</div>'
: '<p class="mt-3 text-xs text-muted">Genkendte ingen kendte mønstre.</p>') +
(dec.match ? '<p class="mt-3 text-xs"><a class="text-accent hover:underline" href="/profiler?q=' + encodeURIComponent(dec.match.id) + '">Se profilen i /profiler ↗</a></p>' : '') +
'</div>';
result.hidden = false; err.hidden = true;
}
function analyze(text) {
text = (text || '').trim();
if (!text) return;
if (text.indexOf('<') === 0 || text.indexOf('<?xml') === 0) {
var doc = new DOMParser().parseFromString(text, 'application/xml');
if (doc.getElementsByTagName('parsererror').length) {
err.textContent = 'Kunne ikke parse XML.. er filen velformet?'; err.hidden = false; result.hidden = true; return;
}
renderXml(doc);
} else {
renderId(text);
}
}
// fil-input + drag/drop
function readFile(f) { var r = new FileReader(); r.onload = function () { analyze(String(r.result)); }; r.readAsText(f); }
fileInput.addEventListener('change', function () { if (fileInput.files[0]) readFile(fileInput.files[0]); });
['dragenter', 'dragover'].forEach(function (ev) { drop.addEventListener(ev, function (e) {
e.preventDefault(); drop.classList.add('is-over'); }); });
['dragleave', 'drop'].forEach(function (ev) { drop.addEventListener(ev, function (e) {
e.preventDefault(); drop.classList.remove('is-over'); }); });
drop.addEventListener('drop', function (e) { var f = e.dataTransfer && e.dataTransfer.files[0]; if (f) readFile(f); });
document.getElementById('analyze').addEventListener('click', function () { analyze(paste.value); });
paste.addEventListener('keydown', function (e) { if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') analyze(paste.value); });
})();
</script>
{% endblock %}