# 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`: ```python 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 ```python 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. ```python # 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.