fix(arcim): count already-linked invoices as done in the registration-link row (#2276)

The registration-link result row in ArcimMigrationWorkspace showed
`linked` over `scanned`, while its `unlinked` remainder subtracted both
`linked` and `alreadyLinked`. On a rerun where an earlier run had linked
every invoice (scanned 2, linked 0, alreadyLinked 2) the row read "0 av 2"
and, since unlinked was 0, carried no detail line to explain it: the step
looked failed when there was nothing left to do.

lib/invoices/link-migrated-registration-vouchers.ts reports each scanned
invoice into exactly one of seven buckets, so alreadyLinked is a subset of
scanned and is "done" in the same sense as linked. The row now shows
`linked + alreadyLinked` over `scanned` and, when alreadyLinked > 0, adds
a detail sentence ("2 var redan länkade sedan tidigare" / "2 were already
linked earlier") ahead of the existing unlinked breakdown, so the value
and the details agree. New key in both sv.json and en.json.

Other result rows checked: the documents import shows four separate
counts (no fraction) and the payment reconciliation result is not
rendered as a row, so neither has the same shape.

Fixes #2045


Claude-Session: https://claude.ai/code/session_015qgLgdt4mLmha1ZLFMwq1u

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-09-04 17:18:22 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5.1
parent 1976129478
commit 88a3b5fb0f
3 changed files with 23 additions and 11 deletions
@@ -1967,19 +1967,29 @@ function ResultStep({
}
if (results.registrationLinks && results.registrationLinks.scanned > 0) {
const links = results.registrationLinks
const unlinked = links.scanned - links.linked - links.alreadyLinked
// An invoice that already carried its link (a rerun over invoices an
// earlier run linked) is done, not failed: it counts towards the
// displayed total and gets its own detail line, so the value and the
// details agree. Without this a rerun read "0 av 2" with no explanation.
const done = links.linked + links.alreadyLinked
const unlinked = links.scanned - done
const details: string[] = []
if (links.alreadyLinked > 0) {
details.push(t('ext_arcim_registration_links_already_linked', { count: links.alreadyLinked }))
}
if (unlinked > 0) {
details.push(t('ext_arcim_registration_links_detail', {
unlinked,
noRef: links.noRef,
refNotFetched: links.refNotFetched ?? 0,
unresolved: links.unresolved + links.ambiguous,
amountMismatch: links.amountMismatch,
}))
}
entityLines.push({
label: t('ext_arcim_registration_links_label'),
value: t('ext_arcim_registration_links_value', { linked: links.linked, scanned: links.scanned }),
detail: unlinked > 0
? t('ext_arcim_registration_links_detail', {
unlinked,
noRef: links.noRef,
refNotFetched: links.refNotFetched ?? 0,
unresolved: links.unresolved + links.ambiguous,
amountMismatch: links.amountMismatch,
})
: undefined,
value: t('ext_arcim_registration_links_value', { linked: done, scanned: links.scanned }),
detail: details.length > 0 ? details.join('. ') : undefined,
failed: false,
})
}
+1
View File
@@ -5598,6 +5598,7 @@
"ext_arcim_registration_links_label": "Voucher links",
"ext_arcim_registration_links_value": "{linked} of {scanned} invoices linked to their booking voucher",
"ext_arcim_registration_links_detail": "{unlinked} not linked: {noRef} without a voucher number at the provider, {refNotFetched} whose provider details could not be fetched in time, {unresolved} without an unambiguous booking voucher, {amountMismatch} with a differing amount",
"ext_arcim_registration_links_already_linked": "{count, plural, one {# was already linked earlier} other {# were already linked earlier}}",
"ext_arcim_credit_notes_label": "Credit notes",
"ext_arcim_credit_notes_unlinked_detail": "{count, plural, one {# credit note was imported without a link to the invoice it credits: your old system sends no reference to the original invoice. Its amounts are reversed and the record is complete, but the link to the original invoice is missing.} other {# credit notes were imported without a link to the invoices they credit: your old system sends no reference to the original invoice. Their amounts are reversed and the records are complete, but the link to the original invoice is missing.}}",
"ext_arcim_migration_description": "Migrate bookkeeping from Fortnox, Visma, Bokio, Björn Lundén or Briox",
+1
View File
@@ -5598,6 +5598,7 @@
"ext_arcim_registration_links_label": "Verifikatkoppling",
"ext_arcim_registration_links_value": "{linked} av {scanned} fakturor kopplade till bokföringsverifikat",
"ext_arcim_registration_links_detail": "{unlinked} utan koppling: {noRef} saknar verifikatnummer hos leverantören, {refNotFetched} vars detaljer inte hann hämtas från leverantören, {unresolved} utan entydigt bokföringsverifikat, {amountMismatch} med avvikande belopp",
"ext_arcim_registration_links_already_linked": "{count, plural, one {# var redan länkad sedan tidigare} other {# var redan länkade sedan tidigare}}",
"ext_arcim_credit_notes_label": "Kreditfakturor",
"ext_arcim_credit_notes_unlinked_detail": "{count, plural, one {# kreditfaktura importerades utan koppling till fakturan den krediterar: ditt gamla system skickar ingen referens till ursprungsfakturan. Beloppen är omvända och posten är komplett, men kopplingen till ursprungsfakturan saknas.} other {# kreditfakturor importerades utan koppling till fakturorna de krediterar: ditt gamla system skickar ingen referens till ursprungsfakturan. Beloppen är omvända och posterna är kompletta, men kopplingen till ursprungsfakturan saknas.}}",
"ext_arcim_migration_description": "Migrera bokföring från Fortnox, Visma, Bokio, Björn Lundén eller Briox",