import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn, Index, } from 'typeorm'; import { OnboardingSession } from './onboarding-session.entity'; export enum ScanType { PHOTO = 'photo', AUDIO = 'audio', BARCODE = 'barcode', } export enum ScanStatus { PENDING = 'pending', PROCESSING = 'processing', DETECTED = 'detected', CONFIRMED = 'confirmed', REJECTED = 'rejected', FAILED = 'failed', } @Entity({ schema: 'catalog', name: 'product_scans' }) @Index(['sessionId', 'status']) export class ProductScan { @PrimaryGeneratedColumn('uuid') id: string; @Column({ name: 'session_id' }) sessionId: string; @Column({ name: 'tenant_id', nullable: true }) tenantId: string; @Column({ type: 'enum', enum: ScanType }) type: ScanType; @Column({ type: 'enum', enum: ScanStatus, default: ScanStatus.PENDING }) status: ScanStatus; // Input data @Column({ name: 'media_url', type: 'text', nullable: true }) mediaUrl: string; @Column({ name: 'media_mime_type', length: 50, nullable: true }) mediaMimeType: string; @Column({ name: 'raw_text', type: 'text', nullable: true }) rawText: string; // OCR/Transcription results @Column({ name: 'detected_name', length: 150, nullable: true }) detectedName: string; @Column({ name: 'detected_price', type: 'decimal', precision: 10, scale: 2, nullable: true }) detectedPrice: number; @Column({ name: 'detected_barcode', length: 50, nullable: true }) detectedBarcode: string; @Column({ name: 'confidence_score', type: 'decimal', precision: 3, scale: 2, nullable: true }) confidenceScore: number; // Matched template @Column({ name: 'template_id', nullable: true }) templateId: string; @Column({ name: 'template_match_score', type: 'decimal', precision: 3, scale: 2, nullable: true }) templateMatchScore: number; // Final product created @Column({ name: 'product_id', nullable: true }) productId: string; // User corrections @Column({ name: 'user_confirmed_name', length: 150, nullable: true }) userConfirmedName: string; @Column({ name: 'user_confirmed_price', type: 'decimal', precision: 10, scale: 2, nullable: true }) userConfirmedPrice: number; // Metadata @Column({ type: 'jsonb', nullable: true }) metadata: Record; @Column({ name: 'error_message', type: 'text', nullable: true }) errorMessage: string; @Column({ name: 'processing_time_ms', type: 'int', nullable: true }) processingTimeMs: number; @CreateDateColumn({ name: 'created_at' }) createdAt: Date; // Relations @ManyToOne(() => OnboardingSession, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'session_id' }) session: OnboardingSession; }