Files
property-match/src/domain/match.ts
T
Benjamin Sutter 99e99d66c5 feat: unit-level matching architecture — match against Einheiten, not Objekte
- domain/property: add getEffectiveUnits() — returns explicit units or synthesises
  one from property-level data so all properties work uniformly at unit level
- domain/match: add unitId? field — every Match references a specific unit
- domain/unifiedResult: add unit? to VerifiedPortfolioResult + ExternalMarketResult
- MockupNeedProvider: generateSyntheticMatches iterates getEffectiveUnits(prop);
  computeScore uses unit-level areaSqm + rentPricePerSqm; resultId for PRE-MARKET
  signals matches useSchattenmarktSignals signal ID format
- useUnifiedResults: resolve unit from match.unitId for VERIFIED_PORTFOLIO/EXTERNAL_MARKET
- matchCardAdapter: unit now extracted for all result types; unitId from match.unitId
- IntelligenceMatchCard: regular cards show unit chip (floor + label + m²) when a
  named unit is known — only adds context, never shows for synthetic/whole-property units

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 20:03:54 +02:00

128 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { MatchStrength, MatchStatus, RiskLevel, ResultType, ConfidenceLevel, AssetType } from './enums'
// ── PropertyNeedMatch (Matchability tab) ──────────────────────────────────────
export interface PropertyNeedMatch {
matchId: string
score: number
needId: string
needTitle: string
company: string
areaRequired: string
budget: string
locations: string[]
assetType: AssetType
timing: string
mustHaves: string[]
matchHighlights: string[]
}
// ── Score Building Blocks ─────────────────────────────────────────────────────
export interface ScoreBreakdown {
hardMatchScore: number // 0100 hard criteria score
softFactorScore: number // 0100 soft factors score
confidenceModifier: number // -20 to +5 adjustment
dataQualityModifier: number // -15 to 0 adjustment
totalScore: number // final 0100
}
export interface ScoreFactor {
criterion: string
weight: number // 01 relative weight
score: number // 0100
contribution: number // weighted points added to total
explanation: string
}
// ── Explainability Types ──────────────────────────────────────────────────────
/** Canonical tradeoff type (F004) */
export interface TradeOff {
criterion: string
concern: string
severity: 'LOW' | 'MEDIUM' | 'HIGH'
mitigation?: string
impactOnScore?: number
}
/** @deprecated Use TradeOff — kept for backward compatibility */
export type Tradeoff = TradeOff
export interface Risk {
category: string // e.g. "Datenverfügbarkeit", "Standortrisiko"
description: string
level: RiskLevel
mitigation?: string
}
export interface MissingDataItem {
field: string
importance: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW'
description: string
impact: string // how it affects the match score
}
export interface NextBestAction {
label: string // e.g. "Besichtigung anfragen"
description?: string
priority: 'HIGH' | 'MEDIUM' | 'LOW'
actionType: 'CONTACT' | 'VERIFY' | 'REVIEW' | 'SHORTLIST' | 'COMPARE' | 'SCHEDULE'
externalUrl?: string
}
export interface AlternativeStrategy {
title: string
description: string
expectedScore?: number
reasoning?: string
}
// ── Match (core entity) ───────────────────────────────────────────────────────
export interface Match {
id: string
needId: string
// Result reference — works for all three result types
resultId?: string // preferred: generic result ID
resultType?: ResultType
propertyId: string // legacy alias for resultId (VERIFIED_PORTFOLIO)
unitId?: string // specific rentable unit this match refers to
// Scoring
matchScore: number // 0100
matchStrength: MatchStrength
scoreBreakdown: ScoreBreakdown
confidenceLevel: number // 01 numeric
confidenceLevelLabel?: ConfidenceLevel
dataConfidenceScore?: number // 01 data quality contribution
// Explainability
positiveFactors: ScoreFactor[]
negativeFactors: ScoreFactor[]
tradeoffs: TradeOff[]
tradeOffs?: TradeOff[] // alias for F004 naming convention
risks?: Risk[]
missingData?: MissingDataItem[]
nextBestActions?: NextBestAction[]
explainabilitySummary: string
explanation?: string // alias / longer form
// Risk
riskLevel: RiskLevel
uncertaintyIndicators: string[]
// Alternatives
alternativeStrategies?: AlternativeStrategy[]
// Review / lifecycle
status?: MatchStatus
isApproved?: boolean // legacy — prefer status
reviewedBy?: string
reviewedAt?: string
organizationId?: string
createdAt: string
updatedAt: string
}