Files
dennis 236053cd7f Initial import: 10 Radix skills across 3 categories
Kategoriserer danske regnskabs-/ERP-skills, ERP-data-afstemnings-
skill og to devops-workflows (gitea-issue-agent, kanban-workflows)
som Radix-medlemmers AI-agenter kan dele.

Struktur:
  skills/<kategori>/<skill-navn>/SKILL.md
  skills/<kategori>/<skill-navn>/{references,templates,scripts}/

Indekseret af index.json (genereret af scripts/rebuild_index.py).
Kør `python3 scripts/rebuild_index.py --check` i CI for at fange
synkroniseringsfejl.
2026-06-15 14:41:04 +02:00

8.5 KiB

Coop ↔ Uniconta Reconciliation Reference (Aktualiseret 2025-05-26)

Konkrete felter, mappings og pitfalls fra det aktuelle Coop-Uniconta projekt.


Coop (SAP export) — Kontoudtog.xlsx

Kolonne Navn Type Match-brug
Entry Date Entry Date datetime Sekundær
Document Type Document Type string Filter + match-type
Document Date Document Date datetime Sekundær
Posting Date Posting Date datetime Primær dato
Reference Reference string (75% non-null) Primær match-nøgle
Net Due Date Net Due Date datetime Forfaldsdato
Amount Amount in Local Currency float Primær beløb
Document Currency Local Currency string ('DKK') Filter
Document Number Document Number int Audit/trace
Text Text string (20% non-null) Sekundær match
Payment Reference Payment Reference string (12% non-null) OCR/trace
User Name User Name string Audit

Coop Document Types (2024-2025)

Type Andel Beskrivelse Uniconta-modpart
RE ~50% Regning/betaling Betaling/Faktura
ZV ~15% Udbetalingsforslag/faktura Betaling
RG ~6% Kontoafstemning Kreditnota
KG ~5% Kontoafstemning gruppe (bonus/rabat) Kreditnota
ZC ~3% Kreditering Kreditnota
ZP ~0.4% Betaling Betaling
XX ~0% (filtreret fra) Manuelt bogført/migrering

VIGTIGT: ZV-poster er positive fakturaer udstedt til kunder. De har typisk ingen Reference/Faktura-nummer og matches via abs(beløb) + dato mod Uniconta Betalinger.


Uniconta — Coop danmark.xlsx

Fil-struktur

  • Række 1: Konto-info (Checked, Konto, Kontonavn, Adresse, Bynavn)
  • Række 2-3: Tomme
  • Række 4: Kolonne-headers: Dato, Faktura, Forfaldsdato, Bilag, Tekst, Beløb, Resterende, Forfalden, Konteringstype, Sum
  • Række 5+: Data
Kolonne Navn Type Match-brug
Dato Dato datetime Primær dato
Faktura Faktura mixed int/str, 0=ingen Primær match-nøgle
Forfaldsdato Forfaldsdato datetime Sekundær
Bilag Bilag mixed int/str Audit
Tekst Tekst string Tekst-match
Beløb Beløb float/tekst Primær beløb
Resterende Resterende float Filter
Forfalden Forfalden float Filter
Konteringstype Konteringstype string Filter + match-bonus
Sum Sum float IGNORE — løbende saldo

Uniconta Konteringstyper

Type Beskrivelse Match-modpart (Coop)
Faktura Faktura udstedt RE (betaling) eller ZV
Betaling Betaling modtaget RE, ZP, ZV
Kreditnota Kreditnota RG, ZC, KG
Primo Primo-saldo XX (filtreres fra)
Afslutning Årsafslutning
Overførsel Overførselsbilag
Manuel Manuel posting
Rabat Rabat KG

Match-nøgle-observationer

Fakturanumre overlapper IDENTISK

  • Coop Reference og Uniconta Faktura bruger identiske 4-5 cifrede tal.
  • Eksempler: 46344, 44907, 48456, 49495, 51519
  • 2.970 unikke RE-references findes som Faktura-numre i Uniconta.
  • Dette er den stærkeste match-signal — langt stærkere end beløb+dato alene.

Modsat fortegn er NORMALT

Coop type Coop fortegn Uniconta type Uniconta fortegn Match
RE (betaling) Negativ (-) Faktura Positiv (+) abs(beløb)
ZV (faktura) Positiv (+) Betaling Negativ (-) abs(beløb)
RG (kreditnota) Positiv (+) Kreditnota Negativ (-) abs(beløb)
KG (rabat) Positiv (+) Kreditnota Negativ (-) abs(beløb)

Implikation: Match-motoren SKAL sammenligne abs(beløb), ikke rå beløb.

Dato-tolerance

  • Faktura-reference matches: ±21 dage fungerer fint
  • Generelle beløb+dato matches: ±21 dage fanger de fleste
  • ZV↔Betaling matches: ±30 dage anbefales (betalingsforslag vs. faktura)

Normalisering

Beløb (dansk format)

Nogle Uniconta-celler indeholder tekststrenge som -2.543.803,93:

def parse_danish_number(val):
    if pd.isna(val) or val is None: return None
    if isinstance(val, (int, float)): return float(val)
    s = str(val).strip().replace('\xa0','').replace('\u202f','').replace(' DKK','')
    if s.lower() in ('nan',''): return None
    if s.endswith('.0'): s = s[:-2]
    if '.' in s and ',' in s:
        s = s.replace('.','').replace(',','.')
    elif ',' in s:
        s = s.replace(',','.')
    try: return float(s)
    except: return None

Tekst

def normalize_text(t):
    if not t or pd.isna(t): return ''
    return re.sub(r'\s+',' ',str(t).lower().strip()).strip()

Konto-specifikt mønster

"Coop 0010014808"

  • Uniconta indeholder mange poster med teksten "Coop 0010014808"
  • Beløb varierer fra -1.155.458,24 til -65.000
  • Nogle har fakturanummer, andre har ikke
  • Dette ligner en samlet konto-kontering for Coop-omsætning, ikke enkeltfakturaer
  • Disse poster er svære at matche automatisk og bør behandles særskilt

Bonus/rabat-poster

  • Coop KG: "CCM Purchasing Rebate Credit"
  • Uniconta Rabat: sjælden, men findes
  • Disse bør matches separat via beløb + dato + bonus-tekst

Specifikke problemer opdaget (V6.1)

  1. Faktura 46344 — Uniconta Faktura +441.720, Coop RE -441.720, men også Uniconta Betaling -430.732,50. Delvis kreditnota.

  2. Faktura 51519 — Uniconta Faktura +244.926, Coop RE -244.926, Uniconta Betaling -244.926. Dobbeltregistrering (Coop+Uni betaling).

  3. Faktura 48323 — Ingen Coop-betaling, men Uniconta Betaling -240.000 findes. Faktura er BETALT via Uniconta-betaling.

  4. Faktura 47140/47347 (DELVIST BETALT) — Coop har både negativ og positiv RE med samme reference. Netto-sum giver korrekt status.

  5. Dobbelt-registrering — Samme betaling findes som både Coop RE og Uniconta Betaling. Ved summing af begge får man 2x betalt. Løsning: brug netto-sum og dedupliker.

  6. MR8M-modregninger — Positive Coop RE med "MR8M Credit memo" tekst er modregninger. De skal trækkes fra i netto-beregning, ikke lægges til med abs().


Afstemningsstrategi der virkede (V6.1 anbefalet)

Fase 1: Reference-match (RE↔Faktura, RG↔Kreditnota)

  • Krav: Coop.Reference == Uniconta.Faktura
  • Krav: abs(Coop.Amount) ≈ abs(Uniconta.Amount) ±5 kr (tolerance)
  • Krav: Dato ±21 dage
  • Bonus: Korrekt konteringstype
  • Score ~250
  • Resultat 2024-2025: ~2.421 matches

Fase 2: ZV↔Faktura

  • Coop ZV (positive fakturaer) matcher Uniconta Faktura
  • abs(beløb) ±5 kr + dato ±21 dage
  • Bonus: Document Number == Faktura
  • Resultat 2024-2025: ~173 matches

Fase 3: RE↔Betaling uden reference

  • Coop RE uden fakturanummer matcher Uniconta Betaling
  • abs(beløb) ±5 kr + dato ±21 dage
  • Bonus: tekst-lighed
  • Resultat 2024-2025: ~192 matches

Fase 4: Generel abs(beløb)+dato

  • abs(beløb) ±5 kr + dato ±21 dage
  • Konteringstype-bonus, tekst-lighed, reference-bonus
  • Score ≥ 40
  • Resultat 2024-2025: ~1.939 matches

Fase 5: Mange-til-én

  • Sum af 2-3 Uniconta-poster == Coop-postering ±5 kr
  • Dato ±14 dage, max 25 kandidater
  • Resultat 2024-2025: ~276 matches

Total matches 2024-2025: 5.001 ud af 7.328 Coop / 6.717 Uniconta (~68%)

Uafstemt: ~2.327 Coop (31,8%) + ~2.211 Uniconta (32,9%)


Faktura-status: Netto-baseret + deduplikering

Dobbelt-registrering

Samme betaling findes som både Coop RE og Uniconta Betaling.

# Beregn NETTO Coop betalinger (ikke abs-sum!)
coop_net = sum(c['amount'] for c in coop 
               if c['reference'] == fnr and c['doc_type'] in ('RE','ZP'))
coop_paid = abs(coop_net) if coop_net < 0 else 0

# Beregn NETTO Uniconta betalinger
uni_net = sum(u['amount'] for u in uni 
            if u['faktura'] == fnr and u['konteringstype'] == 'Betaling')
uni_paid = abs(uni_net) if uni_net < 0 else 0

# Dedupliker
if coop_paid > 0 and uni_paid > 0:
    if abs(coop_paid - uni_paid) <= AMT_TOL:
        betalt = coop_paid  # Samme betaling
    else:
        betalt = max(coop_paid, uni_paid)
elif coop_paid > 0: betalt = coop_paid
elif uni_paid > 0: betalt = uni_paid
else: betalt = 0

Resultat: 2.968 BETALT, 2 DELVIST, 186 UBETALT


Bevar original rådata

Exportér ALTID:

  • Original række-nummer (Excel-rækkeindeks)
  • Filnavn og ark-navn
  • Rå JSON med alle kolonner Så brugeren kan spore enhver match tilbage til kildefilen.