feat(analytics): add valuation handler, AVM service, and market index improvements

Add property valuation query handler with AVM (Automated Valuation Model)
service integration. Improve market index, heatmap, and price trend handlers
with proper dependency injection and error handling.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-09 09:41:46 +07:00
parent 1e0436e95f
commit cd25d4df2e
25 changed files with 587 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
import { type PropertyType } from '@prisma/client';
import { AggregateRoot } from '@modules/shared/domain/aggregate-root';
import { AggregateRoot } from '@modules/shared';
import { MarketIndexUpdatedEvent } from '../events/market-index-updated.event';
export interface MarketIndexProps {

View File

@@ -1,4 +1,4 @@
import { AggregateRoot } from '@modules/shared/domain/aggregate-root';
import { AggregateRoot } from '@modules/shared';
export interface ValuationProps {
propertyId: string;

View File

@@ -1,4 +1,4 @@
import { type DomainEvent } from '@modules/shared/domain/domain-event';
import { type DomainEvent } from '@modules/shared';
export class MarketIndexUpdatedEvent implements DomainEvent {
readonly eventName = 'market-index.updated';

View File

@@ -1,3 +1,4 @@
export * from './entities';
export * from './events';
export * from './repositories';
export * from './services';

View File

@@ -0,0 +1,39 @@
import { type PropertyType } from '@prisma/client';
export const AVM_SERVICE = Symbol('AVM_SERVICE');
export interface AVMParams {
propertyId?: string;
latitude?: number;
longitude?: number;
areaM2?: number;
propertyType?: PropertyType;
yearBuilt?: number;
floor?: number;
totalFloors?: number;
}
export interface Comparable {
propertyId: string;
address: string;
district: string;
priceVND: string;
pricePerM2: number;
areaM2: number;
propertyType: PropertyType;
distanceMeters: number;
soldAt: string;
}
export interface ValuationResult {
estimatedPrice: string;
confidence: number;
pricePerM2: number;
comparables: Comparable[];
modelVersion: string;
}
export interface IAVMService {
estimateValue(params: AVMParams): Promise<ValuationResult>;
getComparables(propertyId: string, radiusMeters: number): Promise<Comparable[]>;
}

View File

@@ -0,0 +1 @@
export { AVM_SERVICE, type IAVMService, type AVMParams, type ValuationResult, type Comparable } from './avm-service';