← back to Omega Watches 2

src/types/index.ts

298 lines

// ============================================================================
// OMEGA WATCHES 2.0 — ENTERPRISE TYPE DEFINITIONS
// Dual-Ledger: MSRP Snapshots + Secondary Market Events
// ============================================================================

// --- Watch Reference (Master Entity) ---
export interface WatchReference {
  id: string;
  brand: string;
  collection: string;
  model_name: string;
  reference_number: string;
  calibre: string | null;
  case_material: string | null;
  case_diameter_mm: number | null;
  dial_color: string | null;
  year_introduced: number | null;
  year_discontinued: number | null;
  is_limited_edition: boolean;
  limited_edition_count: number | null;
  notes: string | null;
  created_at: string;
  updated_at: string;
}

// --- MSRP Snapshot (Ledger 1: Primary Market) ---
export interface MSRPSnapshot {
  msrp_id: string;
  reference_id: string;
  region_code: string;
  currency: string;
  msrp_amount: number;
  captured_date: string;
  source_url: string;
  page_hash: string | null;
  parser_version: string;
  created_at: string;
}

export interface MSRPChangeEvent {
  id: string;
  reference_id: string;
  region_code: string;
  change_date: string;
  old_price: number;
  new_price: number;
  currency: string;
  pct_change: number;
}

// --- Market Event (Ledger 2: Secondary Market) ---
export type EventType =
  | "auction_realized"
  | "marketplace_sold"
  | "dealer_sold"
  | "dealer_ask"
  | "forum_listing"
  | "price_guide";

export type SellerType =
  | "auction_house"
  | "dealer"
  | "private"
  | "marketplace"
  | "unknown";

export type FeeSemantics =
  | "hammer_only"
  | "price_realised"
  | "total_to_buyer"
  | "unknown";

export type ConditionGrade =
  | "new_unworn"
  | "excellent"
  | "very_good"
  | "good"
  | "fair"
  | "poor"
  | "parts_only"
  | "unknown";

export interface MarketEvent {
  event_id: string;
  source_name: string;
  source_listing_id: string;
  event_type: EventType;
  reference_id: string | null;
  reference_number_raw: string | null;
  serial_number: string | null;
  year_text: string | null;
  case_material: string | null;
  movement: string | null;
  condition_raw: string | null;
  condition_normalized: ConditionGrade;
  provenance_raw: string | null;
  sale_date: string | null;
  location_text: string | null;
  seller_type: SellerType;
  // Price fields (dual-ledger fee semantics)
  price_amount: number | null;
  currency: string;
  hammer_price: number | null;
  buyers_premium: number | null;
  total_to_buyer: number | null;
  fee_semantics: FeeSemantics;
  // FX normalization
  price_usd: number | null;
  fx_rate: number | null;
  fx_source: string | null;
  // Inflation adjustment
  price_usd_real: number | null;
  cpi_base_year: number | null;
  // Metadata
  images_json: string[] | null;
  source_url: string;
  scraped_at: string;
  page_hash: string | null;
  parser_version: string;
  // Quality
  quality_score: number | null;
  is_quarantined: boolean;
  quarantine_reason: string | null;
  created_at: string;
}

// --- Data Source ---
export type SourceAccessMethod = "api" | "scrape" | "manual" | "export";

export interface DataSource {
  id: string;
  name: string;
  display_name: string;
  source_type: string;
  access_method: SourceAccessMethod;
  base_url: string | null;
  robots_txt_compliant: boolean;
  tos_reviewed: boolean;
  tos_allows_collection: boolean | null;
  reliability_score: number;
  coverage_years_from: number | null;
  coverage_years_to: number | null;
  notes: string | null;
  is_active: boolean;
  created_at: string;
  updated_at: string;
}

// --- Collector Run ---
export type JobStatus =
  | "pending"
  | "running"
  | "completed"
  | "failed"
  | "cancelled";

export interface CollectorRun {
  run_id: string;
  source_id: string;
  job_type: string;
  status: JobStatus;
  started_at: string | null;
  completed_at: string | null;
  records_fetched: number;
  records_parsed: number;
  records_inserted: number;
  records_updated: number;
  records_quarantined: number;
  records_deduplicated: number;
  error_message: string | null;
  parser_version: string;
  metadata: Record<string, any> | null;
  created_at: string;
}

// --- Parser Version ---
export interface ParserVersion {
  id: string;
  source_id: string;
  version: string;
  selectors_json: Record<string, any>;
  dom_hash: string | null;
  is_current: boolean;
  tested_at: string | null;
  test_pass_rate: number | null;
  notes: string | null;
  created_at: string;
}

// --- Quarantine Record ---
export interface QuarantineRecord {
  id: string;
  event_id: string | null;
  msrp_id: string | null;
  reason: string;
  severity: "low" | "medium" | "high" | "critical";
  details: Record<string, any> | null;
  resolved: boolean;
  resolved_by: string | null;
  resolved_at: string | null;
  resolution_notes: string | null;
  created_at: string;
}

// --- Condition Mapping ---
export interface ConditionMapping {
  id: string;
  source_name: string;
  source_category: string;
  normalized_grade: ConditionGrade;
  score_0_100: number;
  version: number;
  created_at: string;
}

// --- FX Rate ---
export interface FXRate {
  id: string;
  currency_from: string;
  currency_to: string;
  rate: number;
  rate_date: string;
  source: string;
  created_at: string;
}

// --- Audit Log ---
export interface AuditLogEntry {
  id: string;
  table_name: string;
  record_id: string;
  operation: "INSERT" | "UPDATE" | "DELETE";
  old_values: Record<string, any> | null;
  new_values: Record<string, any> | null;
  changed_by: string;
  ip_address: string | null;
  changed_at: string;
}

// --- API Response Wrappers ---
export interface ApiResponse<T> {
  success: boolean;
  data: T;
  meta?: {
    total?: number;
    page?: number;
    per_page?: number;
    timestamp: string;
  };
}

export interface ApiError {
  success: false;
  error: {
    code: string;
    message: string;
    details?: any;
  };
}

// --- Dashboard / Control Plane ---
export interface SystemHealth {
  database: { ok: boolean; latency: number };
  collectors: {
    active: number;
    failed_24h: number;
    last_run: string | null;
  };
  msrp: {
    snapshots_today: number;
    sources_reporting: number;
    last_capture: string | null;
  };
  market_events: {
    total: number;
    quarantined: number;
    last_ingested: string | null;
  };
  uptime: number;
  version: string;
}

export interface TimeSeriesPoint {
  date: string;
  value: number;
  source?: string;
  event_type?: EventType;
  condition?: ConditionGrade;
  fee_semantics?: FeeSemantics;
}

export interface PriceDistribution {
  bucket_low: number;
  bucket_high: number;
  count: number;
  avg_condition_score: number;
}