M-Bus Gateway
← Tilbage til blog
· ejendomsinvestor· due diligence· varmeregnskab· portefølje· BEK 563· OCR· MID

Varmeregnskab for ejendomsinvestor — due diligence og portefølje

Varmeregnskab ved ejendomsinvestering: due diligence-tjekliste for varmeanlæg, OCR af historiske regnskaber, á conto-niveau-analyse, MID-certifikat-status og portefølje-normalisering.

Af M-Bus Gateway

En ejendomsportefølje med ukorrekte varmeregnskaber er en skjult risikofaktor. Her er due diligence-processen og den løbende portefølje-analyse.


Due diligence — varmeregnskab ved køb

Ejendomskøb: 24 lejligheder, varmeregnskab siden 2019

Tjekliste — hvad du bør undersøge:

1. Er BEK 563 overholdt?
   → Årsafregninger udsendt inden 4 måneder efter periodesslutning?
   → Korrekt 30/70-fordeling dokumenteret?
   → Pro-rata ved fraflytninger? (Fejl = tilbagebetalingskrav)
   Risiko: Op til 5 års krav fra lejere ved systematiske fejl

2. Á conto-niveau:
   → Er á conto sat korrekt? For lavt = stor efterbetaling ved overtagelse
   → Platform: Importer historiske regnskaber → beregn korrekt niveau
   → Typisk problemer: Á conto frosset i 5+ år trods stigende priser

3. MID-certifikat status:
   → Alle målere der bruges til fakturering: MID-godkendt?
   → Udløbne MID-certifikater → afregning kan anfægtes
   → Tjek kalibreringsoplysninger på alle HCA og varmemålere

4. AES-nøgler:
   → Krypterede HCA-målere (Engelmann, Brunata Multical):
     Overgiver sælger AES-nøglerne?
   → Manglende AES-nøgler = blindspot i aflæsning
   → EU EED art. 9c: Nøgler skal overdrages ved ejerskifte

5. Gateway og infrastruktur:
   → Eksisterer der allerede fjernaflæsning?
   → Platform-kontrakt og abonnement — videreføres? Opsigelsesvilkår?
   → Gateway-hardware: Raspberry Pi vs. kommerciels unit?

OCR af historiske varmeregnskaber

# server/src/tools/due_diligence_ocr.py

async def analyze_historical_settlements(
    pdf_paths: list[str],
    property_metadata: dict,
) -> dict:
    """
    OCR-analyser historiske årsafregninger for due diligence.
    Identificér fejl, mangler og risikofaktorer.
    """
    results = []

    for pdf_path in pdf_paths:
        # OCR-extraktion:
        extracted = await ocr_settlement_pdf(pdf_path)

        # Valider BEK 563-krav:
        issues = []

        # 1. Kontrollér 30/70-fordeling:
        if extracted.get("fixed_pct") and abs(extracted["fixed_pct"] - 30) > 2:
            issues.append({
                "severity": "warning",
                "type": "wrong_distribution",
                "detail": f"Fast del = {extracted['fixed_pct']}% (skal være 30%)",
            })

        # 2. Kontrollér fremsendelse inden deadline:
        if extracted.get("sent_date") and extracted.get("period_end"):
            deadline = extracted["period_end"] + timedelta(days=122)  # 4 måneder
            if extracted["sent_date"] > deadline:
                days_late = (extracted["sent_date"] - deadline).days
                issues.append({
                    "severity": "critical",
                    "type": "late_settlement",
                    "detail": f"Afregning {days_late} dage for sent",
                })

        # 3. Kontrollér pro-rata pr. fraflytning:
        if extracted.get("move_outs", 0) > 0 and not extracted.get("has_prorata"):
            issues.append({
                "severity": "high",
                "type": "missing_prorata",
                "detail": f"{extracted['move_outs']} fraflytninger uden pro-rata",
            })

        results.append({
            "year": extracted.get("period_year"),
            "issues": issues,
            "risk_score": _calculate_risk_score(issues),
        })

    return {
        "total_issues": sum(len(r["issues"]) for r in results),
        "critical_issues": sum(
            1 for r in results for i in r["issues"] if i["severity"] == "critical"
        ),
        "risk_score": max(r["risk_score"] for r in results) if results else 0,
        "years": results,
    }

Portefølje-normalisering

# Sammenlign ejendomme på tværs af portefølje:

@router.get("/portfolio/heat-benchmark")
async def portfolio_heat_benchmark(
    session: AsyncSession = Depends(get_session),
    current_user: User = Depends(require_role("landlord")),
) -> list[PropertyBenchmark]:
    """
    kWh/m²/år normaliseret pr. ejendom — sammenlign varmeeffektivitet.
    Graddage-normaliseret for fair sammenligning.
    """
    properties = await get_all_properties(session, current_user.tenant_id)

    results = []
    for prop in properties:
        kwh_per_m2 = await get_normalized_heat_intensity(
            session, prop.id,
            period_start=date.today().replace(month=6, day=1).replace(year=date.today().year - 1),
            period_end=date.today().replace(month=5, day=31),
        )

        # Benchmark kategorisering:
        if kwh_per_m2 < 80:
            category = "excellent"
            label = "Energiklasse A/B"
        elif kwh_per_m2 < 120:
            category = "good"
            label = "Energiklasse C"
        elif kwh_per_m2 < 180:
            category = "average"
            label = "Energiklasse D/E"
        else:
            category = "poor"
            label = "Energiklasse F/G — renovering anbefalet"

        results.append(PropertyBenchmark(
            property_id=prop.id,
            name=prop.name,
            kwh_per_m2=kwh_per_m2,
            category=category,
            label=label,
            units=prop.unit_count,
        ))

    return sorted(results, key=lambda x: x.kwh_per_m2)

Á conto-analyse — identifikér undervurderede ejendomme

Investor-problem: Sælger har sat á conto kunstigt lavt

Symptom: Lejere betaler 400 DKK/md á conto
Faktisk varmebehov: 700 DKK/md baseret på historisk forbrug

Konsekvens ved overtagelse:
  → Du skal sende efterbetalingskrav på 3.600 DKK pr. lejer (12 mdr. × 300 DKK)
  → Juridisk: DIN ret → men lejerne er sure (dårlig stemning ved overtagelse)
  → Alternativ: Du bærer underskuddet selv (ikke juridisk pligt)

Platform-analyse:
  → Importér historiske fjernvarmeregninger via OCR
  → Beregn korrekt á conto baseret på historisk forbrug + graddage
  → Gap-analyse: Faktisk á conto vs. beregnet á conto pr. lejlighed

Due diligence-output:
  "Gennemsnitlig á conto-mangel: 2.800 DKK/lejer/år
   Potentiel efterbetalingsrisiko: 20 lejligheder × 2.800 DKK = 56.000 DKK
   Anbefaling: Justér á conto senest 3 måneder efter overtagelse"

MID-certifikat risiko i portefølje

Portefølje: 8 ejendomme, 160 målere

Platform-rapport — MID-status pr. måler:

Kategori          | Antal | Handling
------------------|-------|------------------------------------------
OK (> 12 mdr.)   | 120   | Ingen handling
Warning (< 6 mdr)| 28    | Plan udskiftning næste sæson
Udløbet           | 12    | KRITISK — afregning kan anfægtes

Udløbne MID-certifikater:
  → Lejerne kan anfægte beregningsgrundlaget (huslejenævnet)
  → Udlejer risikerer at skulle omberegne afregning
  → Udskiftning: Ny måler + ny installation = 800-1.500 DKK pr. måler

ROI på platform-MID-tracking:
  → Platform-abonnement: 49 DKK/enhed/md
  → Pris for anfægtet afregning: 5.000-15.000 DKK (sagsomkostninger)
  → Undgå 1 sag = 100+ måneders abonnement sparet

Konklusion

Ejendomsinvestorer bør gennemgå 5 års varmeregnskaber via OCR-analyse inden køb — manglende pro-rata, forkert 30/70-fordeling og for sent udsendte afregninger er skjulte risikofaktorer. Platform-import af historiske data muliggør portefølje-normalisering (kWh/m²/år graddage-korrigeret), á conto-gap-analyse og MID-certifikat-statusoverblik. Systematiske fejl i overdragne ejendomme kan skabe efterbetalingskrav fra lejere — due diligence beskytter investeringen.

Se varmeregnskab ejendomshandel overdragelse eller MID certifikat guide.