99e99d66c5
- 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>
128 lines
3.9 KiB
TypeScript
128 lines
3.9 KiB
TypeScript
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 // 0–100 hard criteria score
|
||
softFactorScore: number // 0–100 soft factors score
|
||
confidenceModifier: number // -20 to +5 adjustment
|
||
dataQualityModifier: number // -15 to 0 adjustment
|
||
totalScore: number // final 0–100
|
||
}
|
||
|
||
export interface ScoreFactor {
|
||
criterion: string
|
||
weight: number // 0–1 relative weight
|
||
score: number // 0–100
|
||
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 // 0–100
|
||
matchStrength: MatchStrength
|
||
scoreBreakdown: ScoreBreakdown
|
||
confidenceLevel: number // 0–1 numeric
|
||
confidenceLevelLabel?: ConfidenceLevel
|
||
dataConfidenceScore?: number // 0–1 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
|
||
}
|