From c91b8e541981c87bf2a4a72c23979ab1bf142312 Mon Sep 17 00:00:00 2001 From: Adrian Flores Cortes Date: Fri, 30 Jan 2026 12:24:45 -0600 Subject: [PATCH] feat: Update TypeScript types across modules Updated types: - audit.types.ts: Enhanced audit trail types - auth.types.ts: Session and token types - education.types.ts, reviews.types.ts: Course and enrollment types - investment.types.ts: Portfolio types - llm.types.ts: LLM integration types - market-data.types.ts: Market data types - financial.types.ts: Payment processing types New: - trading/entity.types.ts: Trading entity definitions Services: - Update course and enrollment services Co-Authored-By: Claude Opus 4.5 --- src/modules/audit/types/audit.types.ts | 283 ++++++++++ src/modules/auth/types/auth.types.ts | 308 +++++++++++ .../education/services/course.service.ts | 40 +- .../education/services/enrollment.service.ts | 26 +- .../education/types/education.types.ts | 259 +++++++++- src/modules/education/types/reviews.types.ts | 19 + .../investment/types/investment.types.ts | 132 +++++ src/modules/llm/types/llm.types.ts | 224 +++++++- .../market-data/types/market-data.types.ts | 91 +++- src/modules/payments/types/financial.types.ts | 384 ++++++++++++++ src/modules/trading/types/entity.types.ts | 483 ++++++++++++++++++ 11 files changed, 2200 insertions(+), 49 deletions(-) create mode 100644 src/modules/trading/types/entity.types.ts diff --git a/src/modules/audit/types/audit.types.ts b/src/modules/audit/types/audit.types.ts index 7898541..4420303 100644 --- a/src/modules/audit/types/audit.types.ts +++ b/src/modules/audit/types/audit.types.ts @@ -237,3 +237,286 @@ export interface AuditStats { bySeverity: Record; criticalEvents: number; } + +// ============================================================================ +// System Events Types (from 03-system_events.sql) +// ============================================================================ + +export type SystemEventType = + | 'startup' + | 'shutdown' + | 'job_start' + | 'job_complete' + | 'job_failed' + | 'health_check' + | 'config_reload' + | 'error' + | 'warning' + | 'maintenance'; + +export type SystemEnvironment = + | 'development' + | 'staging' + | 'production'; + +export interface SystemEvent { + id: string; + eventType: string; + severity: EventSeverity; + serviceName: string; + component: string | null; + environment: SystemEnvironment; + hostname: string | null; + eventName: string; + message: string; + stackTrace: string | null; + correlationId: string | null; + jobId: string | null; + durationMs: number | null; + metadata: Record; + tags: string[] | null; + createdAt: Date; +} + +export interface CreateSystemEventInput { + eventType: string; + severity?: EventSeverity; + serviceName: string; + component?: string; + environment?: SystemEnvironment; + hostname?: string; + eventName: string; + message: string; + stackTrace?: string; + correlationId?: string; + jobId?: string; + durationMs?: number; + metadata?: Record; + tags?: string[]; +} + +export interface SystemEventFilters { + eventType?: string; + severity?: EventSeverity; + serviceName?: string; + environment?: SystemEnvironment; + jobId?: string; + dateFrom?: Date; + dateTo?: Date; + limit?: number; + offset?: number; +} + +// ============================================================================ +// Trading Audit Types (from 04-trading_audit.sql) +// ============================================================================ + +export type TradingAction = + | 'order_placed' + | 'order_filled' + | 'order_cancelled' + | 'position_opened' + | 'position_closed' + | 'position_modified' + | 'stop_loss_triggered' + | 'take_profit_triggered'; + +export type TradingSide = 'buy' | 'sell'; + +export type OrderType = + | 'market' + | 'limit' + | 'stop' + | 'stop_limit' + | 'trailing_stop'; + +export interface TradingAudit { + id: string; + userId: string; + botId: string | null; + action: string; + actionStatus: EventStatus; + orderId: string | null; + positionId: string | null; + symbol: string; + side: TradingSide; + orderType: OrderType | null; + quantity: string; + price: string | null; + executedPrice: string | null; + pnl: string | null; + fees: string | null; + strategyId: string | null; + signalId: string | null; + isPaperTrading: boolean; + executionTimeMs: number | null; + brokerResponse: Record | null; + metadata: Record; + createdAt: Date; +} + +export interface CreateTradingAuditInput { + userId: string; + botId?: string; + action: string; + actionStatus: EventStatus; + orderId?: string; + positionId?: string; + symbol: string; + side: TradingSide; + orderType?: OrderType; + quantity: string; + price?: string; + executedPrice?: string; + pnl?: string; + fees?: string; + strategyId?: string; + signalId?: string; + isPaperTrading?: boolean; + executionTimeMs?: number; + brokerResponse?: Record; + metadata?: Record; +} + +export interface TradingAuditFilters { + userId?: string; + botId?: string; + symbol?: string; + action?: string; + side?: TradingSide; + isPaperTrading?: boolean; + dateFrom?: Date; + dateTo?: Date; + limit?: number; + offset?: number; +} + +// ============================================================================ +// API Request Logs Types (from 05-api_request_logs.sql) +// ============================================================================ + +export type HttpMethod = + | 'GET' + | 'POST' + | 'PUT' + | 'PATCH' + | 'DELETE' + | 'OPTIONS' + | 'HEAD'; + +export interface ApiRequestLog { + id: string; + requestId: string; + method: HttpMethod; + path: string; + queryParams: Record | null; + headers: Record | null; + bodySize: number | null; + userId: string | null; + apiKeyId: string | null; + ipAddress: string; + userAgent: string | null; + statusCode: number; + responseSize: number | null; + responseTimeMs: number; + serviceName: string | null; + version: string | null; + errorCode: string | null; + errorMessage: string | null; + createdAt: Date; +} + +export interface CreateApiRequestLogInput { + requestId: string; + method: HttpMethod; + path: string; + queryParams?: Record; + headers?: Record; + bodySize?: number; + userId?: string; + apiKeyId?: string; + ipAddress: string; + userAgent?: string; + statusCode: number; + responseSize?: number; + responseTimeMs: number; + serviceName?: string; + version?: string; + errorCode?: string; + errorMessage?: string; +} + +export interface ApiRequestLogFilters { + userId?: string; + method?: HttpMethod; + path?: string; + statusCode?: number; + minResponseTime?: number; + ipAddress?: string; + dateFrom?: Date; + dateTo?: Date; + limit?: number; + offset?: number; +} + +// ============================================================================ +// Data Access Logs Types (from 06-data_access_logs.sql) +// ============================================================================ + +export type DataCategory = + | 'pii' + | 'financial' + | 'health' + | 'credentials'; + +export type DataAccessType = + | 'view' + | 'export' + | 'modify' + | 'delete'; + +export interface DataAccessLog { + id: string; + accessorUserId: string; + accessorRole: string; + targetUserId: string | null; + dataCategory: DataCategory; + dataFields: string[] | null; + accessType: DataAccessType; + accessReason: string | null; + requestId: string | null; + ipAddress: string | null; + userAgent: string | null; + consentVerified: boolean; + legalBasis: string | null; + retentionDays: number | null; + createdAt: Date; +} + +export interface CreateDataAccessLogInput { + accessorUserId: string; + accessorRole: string; + targetUserId?: string; + dataCategory: DataCategory; + dataFields?: string[]; + accessType: DataAccessType; + accessReason?: string; + requestId?: string; + ipAddress?: string; + userAgent?: string; + consentVerified?: boolean; + legalBasis?: string; + retentionDays?: number; +} + +export interface DataAccessLogFilters { + accessorUserId?: string; + targetUserId?: string; + dataCategory?: DataCategory; + accessType?: DataAccessType; + consentVerified?: boolean; + dateFrom?: Date; + dateTo?: Date; + limit?: number; + offset?: number; +} diff --git a/src/modules/auth/types/auth.types.ts b/src/modules/auth/types/auth.types.ts index d60bac8..3baba0d 100644 --- a/src/modules/auth/types/auth.types.ts +++ b/src/modules/auth/types/auth.types.ts @@ -218,3 +218,311 @@ export interface JWTRefreshPayload { iat: number; exp: number; } + +// ============================================================================ +// Phone Channel Type (DDL: auth.phone_channel) +// ============================================================================ +export type PhoneChannel = 'sms' | 'whatsapp'; + +// ============================================================================ +// Auth Event Type (DDL: auth.auth_event_type) +// ============================================================================ +export type AuthEventType = + | 'login' + | 'logout' + | 'register' + | 'password_change' + | 'password_reset_request' + | 'password_reset_complete' + | 'email_verification' + | 'phone_verification' + | 'mfa_enabled' + | 'mfa_disabled' + | 'session_expired' + | 'account_suspended' + | 'account_reactivated' + | 'failed_login' + | 'oauth_linked' + | 'oauth_unlinked'; + +// ============================================================================ +// Rate Limit Scope Type +// ============================================================================ +export type RateLimitScope = 'ip' | 'user' | 'email' | 'global'; + +// ============================================================================ +// Notification Types +// ============================================================================ +export type NotificationType = + | 'alert_triggered' + | 'trade_executed' + | 'deposit_confirmed' + | 'withdrawal_completed' + | 'distribution_received' + | 'system_announcement' + | 'security_alert' + | 'account_update'; + +export type NotificationPriority = 'low' | 'normal' | 'high' | 'urgent'; +export type NotificationIconType = 'success' | 'warning' | 'error' | 'info'; +export type PushPlatform = 'web' | 'ios' | 'android'; + +// ============================================================================ +// Email Verification (DDL: auth.email_verifications) +// ============================================================================ +export interface EmailVerification { + id: string; + userId: string; + email: string; + token: string; + expiresAt: Date; + verifiedAt?: Date; + isVerified: boolean; + ipAddress?: string; + userAgent?: string; + createdAt: Date; +} + +/** Database row type (snake_case) for auth.email_verifications */ +export interface EmailVerificationRow { + id: string; + user_id: string; + email: string; + token: string; + expires_at: Date; + verified_at: Date | null; + is_verified: boolean; + ip_address: string | null; + user_agent: string | null; + created_at: Date; +} + +// ============================================================================ +// Phone Verification (DDL: auth.phone_verifications) +// ============================================================================ +export interface PhoneVerification { + id: string; + userId: string; + phoneNumber: string; + verificationCode: string; + channel: PhoneChannel; + expiresAt: Date; + verifiedAt?: Date; + isVerified: boolean; + sendAttempts: number; + verificationAttempts: number; + maxAttempts: number; + ipAddress?: string; + userAgent?: string; + createdAt: Date; +} + +/** Database row type (snake_case) for auth.phone_verifications */ +export interface PhoneVerificationRow { + id: string; + user_id: string; + phone_number: string; + verification_code: string; + channel: PhoneChannel; + expires_at: Date; + verified_at: Date | null; + is_verified: boolean; + send_attempts: number; + verification_attempts: number; + max_attempts: number; + ip_address: string | null; + user_agent: string | null; + created_at: Date; +} + +// ============================================================================ +// Password Reset Token (DDL: auth.password_reset_tokens) +// ============================================================================ +export interface PasswordResetToken { + id: string; + userId: string; + email: string; + token: string; + expiresAt: Date; + usedAt?: Date; + isUsed: boolean; + ipAddress?: string; + userAgent?: string; + createdAt: Date; +} + +/** Database row type (snake_case) for auth.password_reset_tokens */ +export interface PasswordResetTokenRow { + id: string; + user_id: string; + email: string; + token: string; + expires_at: Date; + used_at: Date | null; + is_used: boolean; + ip_address: string | null; + user_agent: string | null; + created_at: Date; +} + +// ============================================================================ +// Auth Log (DDL: auth.auth_logs) +// ============================================================================ +export interface AuthLog { + id: string; + eventType: AuthEventType; + userId?: string; + email?: string; + ipAddress?: string; + userAgent?: string; + sessionId?: string; + success: boolean; + failureReason?: string; + metadata?: Record; + createdAt: Date; +} + +/** Database row type (snake_case) for auth.auth_logs */ +export interface AuthLogRow { + id: string; + event_type: AuthEventType; + user_id: string | null; + email: string | null; + ip_address: string | null; + user_agent: string | null; + session_id: string | null; + success: boolean; + failure_reason: string | null; + metadata: Record | null; + created_at: Date; +} + +// ============================================================================ +// Login Attempt (DDL: auth.login_attempts) +// ============================================================================ +export interface LoginAttempt { + id: string; + email?: string; + userId?: string; + ipAddress: string; + userAgent?: string; + success: boolean; + failureReason?: string; + attemptedAt: Date; + metadata?: Record; + createdAt: Date; +} + +/** Database row type (snake_case) for auth.login_attempts */ +export interface LoginAttemptRow { + id: string; + email: string | null; + user_id: string | null; + ip_address: string; + user_agent: string | null; + success: boolean; + failure_reason: string | null; + attempted_at: Date; + metadata: Record | null; + created_at: Date; +} + +// ============================================================================ +// Rate Limiting Config (DDL: auth.rate_limiting_config) +// ============================================================================ +export interface RateLimitingConfig { + id: string; + endpoint: string; + description?: string; + maxRequests: number; + windowSeconds: number; + blockDurationSeconds?: number; + scope: RateLimitScope; + isActive: boolean; + metadata?: Record; + createdAt: Date; + updatedAt: Date; + createdById?: string; + updatedById?: string; +} + +/** Database row type (snake_case) for auth.rate_limiting_config */ +export interface RateLimitingConfigRow { + id: string; + endpoint: string; + description: string | null; + max_requests: number; + window_seconds: number; + block_duration_seconds: number | null; + scope: RateLimitScope; + is_active: boolean; + metadata: Record | null; + created_at: Date; + updated_at: Date; + created_by_id: string | null; + updated_by_id: string | null; +} + +// ============================================================================ +// Notification (DDL: auth.notifications) +// ============================================================================ +export interface Notification { + id: string; + userId: string; + type: NotificationType; + title: string; + message: string; + priority: NotificationPriority; + data?: Record; + actionUrl?: string; + iconType: NotificationIconType; + channels: string[]; + isRead: boolean; + readAt?: Date; + createdAt: Date; +} + +/** Database row type (snake_case) for auth.notifications */ +export interface NotificationRow { + id: string; + user_id: string; + type: NotificationType; + title: string; + message: string; + priority: NotificationPriority; + data: Record | null; + action_url: string | null; + icon_type: NotificationIconType; + channels: string[]; + is_read: boolean; + read_at: Date | null; + created_at: Date; +} + +// ============================================================================ +// User Push Token (DDL: auth.user_push_tokens) +// ============================================================================ +export interface UserPushToken { + id: string; + userId: string; + token: string; + platform: PushPlatform; + deviceInfo?: Record; + isActive: boolean; + lastUsedAt?: Date; + createdAt: Date; + updatedAt: Date; +} + +/** Database row type (snake_case) for auth.user_push_tokens */ +export interface UserPushTokenRow { + id: string; + user_id: string; + token: string; + platform: PushPlatform; + device_info: Record | null; + is_active: boolean; + last_used_at: Date | null; + created_at: Date; + updated_at: Date; +} diff --git a/src/modules/education/services/course.service.ts b/src/modules/education/services/course.service.ts index a0da8e2..9953159 100644 --- a/src/modules/education/services/course.service.ts +++ b/src/modules/education/services/course.service.ts @@ -102,18 +102,23 @@ class CourseService { async getCategories(): Promise { const result = await db.query>( - `SELECT * FROM education.categories ORDER BY sort_order, name` + `SELECT * FROM education.categories ORDER BY display_order, name` ); return result.rows.map((row) => ({ id: row.id as string, name: row.name as string, slug: row.slug as string, description: row.description as string | undefined, - icon: row.icon as string | undefined, parentId: row.parent_id as string | undefined, - sortOrder: row.sort_order as number, + displayOrder: (row.display_order as number) || 0, + iconUrl: row.icon_url as string | undefined, + color: row.color as string | undefined, + isActive: (row.is_active as boolean) ?? true, createdAt: new Date(row.created_at as string), updatedAt: new Date(row.updated_at as string), + // Backward-compatible aliases + sortOrder: (row.display_order as number) || 0, + icon: row.icon_url as string | undefined, })); } @@ -129,21 +134,31 @@ class CourseService { name: row.name as string, slug: row.slug as string, description: row.description as string | undefined, - icon: row.icon as string | undefined, parentId: row.parent_id as string | undefined, - sortOrder: row.sort_order as number, + displayOrder: (row.display_order as number) || 0, + iconUrl: row.icon_url as string | undefined, + color: row.color as string | undefined, + isActive: (row.is_active as boolean) ?? true, createdAt: new Date(row.created_at as string), updatedAt: new Date(row.updated_at as string), + // Backward-compatible aliases + sortOrder: (row.display_order as number) || 0, + icon: row.icon_url as string | undefined, }; } async createCategory(input: CreateCategoryInput): Promise { const slug = input.slug || generateSlug(input.name); + // Support both new and deprecated field names + const iconUrl = input.iconUrl || input.icon; + const displayOrder = input.displayOrder ?? input.sortOrder ?? 0; + const isActive = input.isActive ?? true; + const result = await db.query>( - `INSERT INTO education.categories (name, slug, description, icon, parent_id, sort_order) - VALUES ($1, $2, $3, $4, $5, $6) + `INSERT INTO education.categories (name, slug, description, icon_url, color, parent_id, display_order, is_active) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *`, - [input.name, slug, input.description, input.icon, input.parentId, input.sortOrder || 0] + [input.name, slug, input.description, iconUrl, input.color, input.parentId, displayOrder, isActive] ); const row = result.rows[0]; return { @@ -151,11 +166,16 @@ class CourseService { name: row.name as string, slug: row.slug as string, description: row.description as string | undefined, - icon: row.icon as string | undefined, parentId: row.parent_id as string | undefined, - sortOrder: row.sort_order as number, + displayOrder: (row.display_order as number) || 0, + iconUrl: row.icon_url as string | undefined, + color: row.color as string | undefined, + isActive: (row.is_active as boolean) ?? true, createdAt: new Date(row.created_at as string), updatedAt: new Date(row.updated_at as string), + // Backward-compatible aliases + sortOrder: (row.display_order as number) || 0, + icon: row.icon_url as string | undefined, }; } diff --git a/src/modules/education/services/enrollment.service.ts b/src/modules/education/services/enrollment.service.ts index ae6480e..8a68b02 100644 --- a/src/modules/education/services/enrollment.service.ts +++ b/src/modules/education/services/enrollment.service.ts @@ -40,20 +40,32 @@ function transformEnrollment(row: Record): Enrollment { } function transformLessonProgress(row: Record): LessonProgress { + const isCompleted = (row.is_completed || row.video_completed) as boolean || false; + const lastPosition = (row.last_position_seconds || row.video_progress_seconds || row.video_watched_seconds || 0) as number; + const totalWatch = (row.total_watch_time_seconds || row.video_watched_seconds || 0) as number; + const watchPct = parseFloat(row.watch_percentage as string) || 0; + return { id: row.id as string, userId: row.user_id as string, - enrollmentId: row.enrollment_id as string, lessonId: row.lesson_id as string, - isCompleted: (row.is_completed || row.video_completed) as boolean || false, - videoProgressSeconds: row.video_progress_seconds as number | undefined, + enrollmentId: row.enrollment_id as string, + isCompleted, + lastPositionSeconds: lastPosition, + totalWatchTimeSeconds: totalWatch, + watchPercentage: watchPct, + firstViewedAt: row.first_viewed_at ? new Date(row.first_viewed_at as string) : undefined, + lastViewedAt: row.last_viewed_at ? new Date(row.last_viewed_at as string) : undefined, completedAt: row.completed_at ? new Date(row.completed_at as string) : undefined, - xpEarned: (row.xp_earned as number) || 0, - notes: row.notes as string | undefined, createdAt: new Date(row.created_at as string), updatedAt: new Date(row.updated_at as string), - videoWatchedSeconds: row.video_watched_seconds as number, - videoCompleted: (row.is_completed || row.video_completed) as boolean || false, + // Backward-compatible aliases + videoProgressSeconds: lastPosition, + videoWatchedSeconds: totalWatch, + videoCompleted: isCompleted, + startedAt: row.first_viewed_at ? new Date(row.first_viewed_at as string) : undefined, + xpEarned: (row.xp_earned as number) || 0, + notes: row.notes as string | undefined, }; } diff --git a/src/modules/education/types/education.types.ts b/src/modules/education/types/education.types.ts index a9b83fb..161a1e3 100644 --- a/src/modules/education/types/education.types.ts +++ b/src/modules/education/types/education.types.ts @@ -80,7 +80,7 @@ export enum AchievementTypeEnum { } // ============================================================================ -// Category +// Category (Aligned with education.categories DDL) // ============================================================================ export interface Category { @@ -88,22 +88,54 @@ export interface Category { name: string; slug: string; description?: string; - icon?: string; parentId?: string; - sortOrder: number; + displayOrder: number; + iconUrl?: string; + color?: string; + isActive: boolean; createdAt: Date; updatedAt: Date; + + // Backward-compatible aliases + /** @deprecated Use displayOrder instead */ + sortOrder?: number; + /** @deprecated Use iconUrl instead */ + icon?: string; +} + +/** Row type for DB mapping (snake_case) - education.categories */ +export interface CategoryRow { + id: string; + name: string; + slug: string; + description: string | null; + parent_id: string | null; + display_order: number; + icon_url: string | null; + color: string | null; + is_active: boolean; + created_at: Date; + updated_at: Date; } export interface CreateCategoryInput { name: string; slug?: string; description?: string; - icon?: string; + iconUrl?: string; + color?: string; parentId?: string; + displayOrder?: number; + isActive?: boolean; + // Backward-compatible aliases + /** @deprecated Use iconUrl instead */ + icon?: string; + /** @deprecated Use displayOrder instead */ sortOrder?: number; } +export interface UpdateCategoryInput extends Partial {} + // ============================================================================ // Course (Aligned with education.courses DDL) // ============================================================================ @@ -402,27 +434,61 @@ export interface CreateEnrollmentInput { export interface LessonProgress { id: string; userId: string; - enrollmentId: string; lessonId: string; + enrollmentId: string; isCompleted: boolean; - videoProgressSeconds?: number; + lastPositionSeconds: number; + totalWatchTimeSeconds: number; + watchPercentage: number; + firstViewedAt?: Date; + lastViewedAt?: Date; completedAt?: Date; - startedAt?: Date; - xpEarned: number; - notes?: string; createdAt: Date; updatedAt: Date; // Backward-compatible aliases - /** @deprecated Use videoProgressSeconds instead */ + /** @deprecated Use lastPositionSeconds instead */ + videoProgressSeconds?: number; + /** @deprecated Use lastPositionSeconds instead */ videoWatchedSeconds?: number; /** @deprecated Use isCompleted instead */ videoCompleted?: boolean; + /** @deprecated Use firstViewedAt instead */ + startedAt?: Date; + /** @deprecated Not in DDL - use generic metadata if needed */ + xpEarned?: number; + /** @deprecated Not in DDL - use generic metadata if needed */ + notes?: string; +} + +/** Row type for DB mapping (snake_case) - education.progress */ +export interface LessonProgressRow { + id: string; + user_id: string; + lesson_id: string; + enrollment_id: string; + is_completed: boolean; + last_position_seconds: number; + total_watch_time_seconds: number; + watch_percentage: string; // DECIMAL comes as string from PG + first_viewed_at: Date | null; + last_viewed_at: Date | null; + completed_at: Date | null; + created_at: Date; + updated_at: Date; } export interface UpdateLessonProgressInput { + lastPositionSeconds?: number; + totalWatchTimeSeconds?: number; + watchPercentage?: number; + isCompleted?: boolean; + completedAt?: Date; + /** @deprecated Use lastPositionSeconds instead */ videoWatchedSeconds?: number; + /** @deprecated Use isCompleted instead */ videoCompleted?: boolean; + /** @deprecated Not in DDL */ userNotes?: string; } @@ -616,6 +682,179 @@ export interface CreateActivityLogInput { userAgent?: string; } +// ============================================================================ +// Video (Aligned with education.videos DDL) +// ============================================================================ + +export type VideoStatus = 'uploading' | 'uploaded' | 'processing' | 'ready' | 'error' | 'deleted'; +export type VideoStorageProvider = 's3' | 'r2' | 'cloudflare_stream'; + +export interface VideoTranscodedVersion { + resolution: string; // e.g., '1080p', '720p', '480p' + storageKey: string; + cdnUrl: string; + fileSizeBytes: number; +} + +export interface VideoCaption { + language: string; + url: string; +} + +export interface VideoMetadata { + tags?: string[]; + language?: string; + difficulty?: DifficultyLevel; + captions?: VideoCaption[]; + transcript?: string; + videoCodec?: string; + audioCodec?: string; + bitrateKbps?: number; + fps?: number; + resolution?: string; // e.g., '1920x1080' +} + +export interface Video { + id: string; + courseId: string; + lessonId?: string; + uploadedBy: string; + title: string; + description?: string; + originalFilename: string; + storageProvider: VideoStorageProvider; + storageBucket: string; + storageKey: string; + storageRegion?: string; + fileSizeBytes: number; + mimeType: string; + durationSeconds?: number; + status: VideoStatus; + processingStartedAt?: Date; + processingCompletedAt?: Date; + processingError?: string; + cdnUrl?: string; + thumbnailUrl?: string; + transcodedVersions?: VideoTranscodedVersion[]; + metadata: VideoMetadata; + uploadId?: string; + uploadPartsCompleted: number; + uploadPartsTotal?: number; + uploadProgressPercent: number; + createdAt: Date; + updatedAt: Date; + uploadedAt?: Date; + deletedAt?: Date; +} + +/** Row type for DB mapping (snake_case) - education.videos */ +export interface VideoRow { + id: string; + course_id: string; + lesson_id: string | null; + uploaded_by: string; + title: string; + description: string | null; + original_filename: string; + storage_provider: string; + storage_bucket: string; + storage_key: string; + storage_region: string | null; + file_size_bytes: string; // BIGINT comes as string from PG + mime_type: string; + duration_seconds: number | null; + status: string; + processing_started_at: Date | null; + processing_completed_at: Date | null; + processing_error: string | null; + cdn_url: string | null; + thumbnail_url: string | null; + transcoded_versions: unknown; // JSONB + metadata: unknown; // JSONB + upload_id: string | null; + upload_parts_completed: number; + upload_parts_total: number | null; + upload_progress_percent: number; + created_at: Date; + updated_at: Date; + uploaded_at: Date | null; + deleted_at: Date | null; +} + +export interface CreateVideoInput { + courseId: string; + lessonId?: string; + title: string; + description?: string; + originalFilename: string; + storageBucket: string; + storageKey: string; + storageProvider?: VideoStorageProvider; + storageRegion?: string; + fileSizeBytes: number; + mimeType?: string; + metadata?: VideoMetadata; + uploadPartsTotal?: number; +} + +export interface UpdateVideoInput { + title?: string; + description?: string; + lessonId?: string; + status?: VideoStatus; + durationSeconds?: number; + cdnUrl?: string; + thumbnailUrl?: string; + transcodedVersions?: VideoTranscodedVersion[]; + metadata?: VideoMetadata; + processingStartedAt?: Date; + processingCompletedAt?: Date; + processingError?: string; + uploadPartsCompleted?: number; + uploadProgressPercent?: number; + uploadedAt?: Date; +} + +export interface InitiateMultipartUploadInput { + courseId: string; + lessonId?: string; + title: string; + originalFilename: string; + fileSizeBytes: number; + mimeType: string; + partsTotal: number; +} + +export interface CompleteMultipartUploadInput { + videoId: string; + uploadId: string; + parts: { partNumber: number; eTag: string }[]; +} + +// ============================================================================ +// Review Helpful Votes (Aligned with education.review_helpful_votes DDL) +// ============================================================================ + +export interface ReviewHelpfulVote { + id: string; + userId: string; + reviewId: string; + createdAt: Date; +} + +/** Row type for DB mapping (snake_case) - education.review_helpful_votes */ +export interface ReviewHelpfulVoteRow { + id: string; + user_id: string; + review_id: string; + created_at: Date; +} + +export interface CreateReviewHelpfulVoteInput { + userId: string; + reviewId: string; +} + // ============================================================================ // Attachments (for lesson attachments JSONB field) // ============================================================================ diff --git a/src/modules/education/types/reviews.types.ts b/src/modules/education/types/reviews.types.ts index 1d1fbb2..8bd787d 100644 --- a/src/modules/education/types/reviews.types.ts +++ b/src/modules/education/types/reviews.types.ts @@ -19,10 +19,29 @@ export interface CourseReview { helpfulVotes: number; createdAt: Date; updatedAt: Date; + // Computed/joined fields (not in DDL) userName?: string; userAvatar?: string; } +/** Row type for DB mapping (snake_case) - education.course_reviews */ +export interface CourseReviewRow { + id: string; + user_id: string; + course_id: string; + enrollment_id: string; + rating: number; + title: string | null; + content: string | null; + is_approved: boolean; + is_featured: boolean; + approved_by: string | null; + approved_at: Date | null; + helpful_votes: number; + created_at: Date; + updated_at: Date; +} + export interface CourseReviewWithUser extends CourseReview { user: { id: string; diff --git a/src/modules/investment/types/investment.types.ts b/src/modules/investment/types/investment.types.ts index b7b41e4..44bceb1 100644 --- a/src/modules/investment/types/investment.types.ts +++ b/src/modules/investment/types/investment.types.ts @@ -69,6 +69,32 @@ export enum TransactionStatusEnum { CANCELLED = 'cancelled', } +// Alineado con investment.withdrawal_status (DDL 06-withdrawal_requests.sql) +export type WithdrawalStatus = + | 'pending' + | 'under_review' + | 'approved' + | 'processing' + | 'completed' + | 'rejected' + | 'cancelled'; + +export enum WithdrawalStatusEnum { + PENDING = 'pending', + UNDER_REVIEW = 'under_review', + APPROVED = 'approved', + PROCESSING = 'processing', + COMPLETED = 'completed', + REJECTED = 'rejected', + CANCELLED = 'cancelled', +} + +// Tipo de destino de retiro +export type WithdrawalDestinationType = 'wallet' | 'bank' | 'crypto'; + +// Fuente del snapshot de rendimiento +export type SnapshotSource = 'cron' | 'manual' | 'system'; + // ============================================================================ // Interfaces // ============================================================================ @@ -148,3 +174,109 @@ export interface WithdrawalDestinationDetails { crypto_network?: string; payment_method: 'bank_transfer' | 'crypto' | 'other'; } + +// ============================================================================ +// Entity Interfaces (Alineado con DDL tables) +// ============================================================================ + +/** + * investment.risk_questionnaire (DDL 02-risk_questionnaire.sql) + * Risk assessment questionnaire responses (valid for 1 year) + */ +export interface RiskQuestionnaire { + id: string; + user_id: string; + responses: RiskQuestionnaireResponse[]; + total_score: number; + calculated_profile: RiskProfile; + recommended_agent: TradingAgent | null; + completed_at: Date; + expires_at: Date; + ip_address: string | null; + user_agent: string | null; + completion_time_seconds: number | null; + created_at: Date; +} + +/** + * investment.withdrawal_requests (DDL 06-withdrawal_requests.sql) + * Withdrawal requests from PAMM accounts + */ +export interface WithdrawalRequest { + id: string; + account_id: string; + user_id: string; + request_number: string; + amount: number; + currency: string; + status: WithdrawalStatus; + destination_type: WithdrawalDestinationType; + destination_details: WithdrawalDestinationDetails; + fee_amount: number; + fee_percentage: number; + net_amount: number; // Generated column + requires_approval: boolean; + reviewed_by: string | null; + reviewed_at: Date | null; + review_notes: string | null; + processed_at: Date | null; + completed_at: Date | null; + transaction_reference: string | null; + rejection_reason: string | null; + cancelled_at: Date | null; + cancellation_reason: string | null; + ip_address: string | null; + user_agent: string | null; + metadata: Record; + created_at: Date; + updated_at: Date; +} + +/** + * investment.daily_performance (DDL 07-daily_performance.sql) + * Daily performance snapshots for PAMM accounts + */ +export interface DailyPerformance { + id: string; + account_id: string; + product_id: string; + snapshot_date: Date; + opening_balance: number; + closing_balance: number; + daily_pnl: number; + daily_return_percentage: number; + cumulative_pnl: number; + cumulative_return_percentage: number; + deposits: number; + withdrawals: number; + distributions_received: number; + trades_executed: number; + winning_trades: number; + losing_trades: number; + win_rate: number | null; + max_drawdown: number | null; + sharpe_ratio: number | null; + volatility: number | null; + high_water_mark: number | null; + lowest_point: number | null; + snapshot_source: SnapshotSource; + metadata: Record; + created_at: Date; +} + +/** + * investment.distribution_history (DDL 08-distribution_history.sql) + * Daily distribution records per investment account + */ +export interface DistributionHistory { + id: string; + account_id: string; + product_id: string; + distribution_date: Date; + gross_amount: number; + fee_amount: number; + net_amount: number; + balance_before: number; + balance_after: number; + created_at: Date; +} diff --git a/src/modules/llm/types/llm.types.ts b/src/modules/llm/types/llm.types.ts index c6f22ee..886203e 100644 --- a/src/modules/llm/types/llm.types.ts +++ b/src/modules/llm/types/llm.types.ts @@ -77,14 +77,42 @@ export interface ToolCall { export interface UserPreferences { id: string; userId: string; - communicationTone: CommunicationTone; - verbosityLevel: VerbosityLevel; - alertFrequency: AlertFrequency; - preferredLanguage: string; + + // Communication preferences + language: string; + tone: CommunicationTone; + verbosity: VerbosityLevel; + + // Trading preferences preferredSymbols: string[]; - preferredTimeframes: string[]; - tradingExperience: string; + preferredTimeframe: string; riskTolerance: string; + + // Notification preferences + proactiveAlerts: boolean; + alertFrequency: AlertFrequency; + notificationHoursStart: string; + notificationHoursEnd: string; + timezone: string; + + // Interests + topicsOfInterest: string[]; + + // Experience level + tradingExperienceLevel: string; + + // Analysis preferences + preferredAnalysisTypes: string[]; + + // Response format + includeCharts: boolean; + includeDataTables: boolean; + includeExplanations: boolean; + + // Onboarding + onboardingCompleted: boolean; + onboardingCompletedAt?: Date; + createdAt: Date; updatedAt: Date; } @@ -99,9 +127,27 @@ export interface UserMemory { memoryType: MemoryType; key: string; value: string; - confidence: number; + + // Importance + importanceScore: number; + + // Source sourceConversationId?: string; + extractedFrom?: string; + extractionMethod: string; + + // Validity + isActive: boolean; expiresAt?: Date; + + // Confirmation + requiresConfirmation: boolean; + confirmedByUser: boolean; + confirmedAt?: Date; + + // Metadata + metadata?: Record; + createdAt: Date; updatedAt: Date; } @@ -112,14 +158,48 @@ export interface UserMemory { export interface Embedding { id: string; - sourceType: string; - sourceId: string; + + // Content type and reference + contentType: string; + contentId?: string; + + // Content content: string; + contentHash?: string; + + // Metadata + title?: string; + description?: string; + + // Vector embedding embedding: number[]; - modelName: string; - dimensions: number; - metadata?: Record; + embeddingModel: string; + + // Access control + userId?: string; + isPublic: boolean; + + // Categorization + category?: string; + subcategory?: string; + tags: string[]; + + // Relevance + importanceScore: number; + + // Context + contextMetadata?: Record; + + // Source + sourceUrl?: string; + sourceType?: string; + + // Validity + isActive: boolean; + expiresAt?: Date; + createdAt: Date; + updatedAt: Date; } // ============================================================================ @@ -166,3 +246,123 @@ export interface MessageRow { metadata: Record | null; created_at: Date; } + +export interface UserPreferencesRow { + id: string; + user_id: string; + + // Communication preferences + language: string; + tone: string; + verbosity: string; + + // Trading preferences + preferred_symbols: string[]; + preferred_timeframe: string; + risk_tolerance: string; + + // Notification preferences + proactive_alerts: boolean; + alert_frequency: string; + notification_hours_start: string; + notification_hours_end: string; + timezone: string; + + // Interests + topics_of_interest: string[]; + + // Experience level + trading_experience_level: string; + + // Analysis preferences + preferred_analysis_types: string[]; + + // Response format + include_charts: boolean; + include_data_tables: boolean; + include_explanations: boolean; + + // Onboarding + onboarding_completed: boolean; + onboarding_completed_at: Date | null; + + created_at: Date; + updated_at: Date; +} + +export interface UserMemoryRow { + id: string; + user_id: string; + memory_type: string; + key: string; + value: string; + + // Importance + importance_score: number; + + // Source + source_conversation_id: string | null; + extracted_from: string | null; + extraction_method: string; + + // Validity + is_active: boolean; + expires_at: Date | null; + + // Confirmation + requires_confirmation: boolean; + confirmed_by_user: boolean; + confirmed_at: Date | null; + + // Metadata + metadata: Record | null; + + created_at: Date; + updated_at: Date; +} + +export interface EmbeddingRow { + id: string; + + // Content type and reference + content_type: string; + content_id: string | null; + + // Content + content: string; + content_hash: string | null; + + // Metadata + title: string | null; + description: string | null; + + // Vector embedding + embedding: number[]; + embedding_model: string; + + // Access control + user_id: string | null; + is_public: boolean; + + // Categorization + category: string | null; + subcategory: string | null; + tags: string[]; + + // Relevance + importance_score: number; + + // Context + context_metadata: Record | null; + + // Source + source_url: string | null; + source_type: string | null; + + // Validity + is_active: boolean; + expires_at: Date | null; + + created_at: Date; + updated_at: Date; +} diff --git a/src/modules/market-data/types/market-data.types.ts b/src/modules/market-data/types/market-data.types.ts index c8ee363..10fad80 100644 --- a/src/modules/market-data/types/market-data.types.ts +++ b/src/modules/market-data/types/market-data.types.ts @@ -1,10 +1,21 @@ /** * Market Data Module Types * OHLCV data types for the market data module + * Aligned with DDL: apps/database/ddl/schemas/market_data/tables/ */ +// ============================================================================= +// Enums and Constants +// ============================================================================= + export type Timeframe = '5m' | '15m' | '1h' | '4h' | '1d'; +export type AssetType = 'forex' | 'crypto' | 'commodity' | 'stock' | 'index'; + +// ============================================================================= +// API/Business Types +// ============================================================================= + export interface OHLCV { timestamp: Date; open: number; @@ -31,7 +42,34 @@ export interface HistoricalDataOptions { to: Date; } -export interface OhlcvDataRow { +// ============================================================================= +// Database Row Types - Aligned with market_data schema DDL +// ============================================================================= + +/** + * Ticker entity - maps to market_data.tickers table + * DDL: apps/database/ddl/schemas/market_data/tables/01-tickers.sql + */ +export interface TickerRow { + id: number; + symbol: string; + name: string; + asset_type: AssetType; + base_currency: string; + quote_currency: string; + is_ml_enabled: boolean; + supported_timeframes: string[]; + polygon_ticker: string | null; + is_active: boolean; + created_at: Date; + updated_at: Date; +} + +/** + * OHLCV 5-minute candle - maps to market_data.ohlcv_5m table + * DDL: apps/database/ddl/schemas/market_data/tables/02-ohlcv_5m.sql + */ +export interface Ohlcv5mRow { id: string; ticker_id: number; timestamp: Date; @@ -41,16 +79,49 @@ export interface OhlcvDataRow { close: string; volume: string; vwap: string | null; + ts_epoch: string | null; created_at: Date; } -export interface TickerRow { - id: number; - symbol: string; - name: string; - asset_type: string; - exchange: string | null; - base_currency: string; - quote_currency: string; - is_active: boolean; +/** + * OHLCV 15-minute candle - maps to market_data.ohlcv_15m table + * DDL: apps/database/ddl/schemas/market_data/tables/03-ohlcv_15m.sql + */ +export interface Ohlcv15mRow { + id: string; + ticker_id: number; + timestamp: Date; + open: string; + high: string; + low: string; + close: string; + volume: string; + vwap: string | null; + candle_count: number; + created_at: Date; } + +/** + * Staging row for bulk imports - maps to market_data.ohlcv_5m_staging table + * DDL: apps/database/ddl/schemas/market_data/tables/04-staging.sql + */ +export interface OhlcvStagingRow { + ticker_id: number | null; + timestamp: Date | null; + open: string | null; + high: string | null; + low: string | null; + close: string | null; + volume: string | null; + vwap: string | null; + ts_epoch: string | null; +} + +// ============================================================================= +// Backwards Compatibility Alias +// ============================================================================= + +/** + * @deprecated Use Ohlcv5mRow instead + */ +export type OhlcvDataRow = Ohlcv5mRow; diff --git a/src/modules/payments/types/financial.types.ts b/src/modules/payments/types/financial.types.ts index 09fa1f7..e81ca2e 100644 --- a/src/modules/payments/types/financial.types.ts +++ b/src/modules/payments/types/financial.types.ts @@ -171,3 +171,387 @@ export interface WalletTransactionRow { created_at: Date; updated_at: Date; } + +// ============================================================================ +// Invoice (from financial.invoices) +// ============================================================================ + +export interface InvoiceLineItem { + description: string; + quantity: number; + unitPrice: number; + amount: number; +} + +export interface BillingAddress { + line1?: string; + line2?: string; + city?: string; + state?: string; + postalCode?: string; + country?: string; +} + +export interface Invoice { + id: string; + userId: string; + subscriptionId?: string; + stripeInvoiceId?: string; + stripeCustomerId?: string; + invoiceNumber?: string; + invoiceType: InvoiceType; + status: InvoiceStatus; + subtotal: number; + tax: number; + total: number; + amountPaid: number; + amountDue: number; + currency: CurrencyCode; + invoiceDate: Date; + dueDate?: Date; + periodStart?: Date; + periodEnd?: Date; + paid: boolean; + paidAt?: Date; + attempted: boolean; + attemptCount: number; + nextPaymentAttempt?: Date; + hostedInvoiceUrl?: string; + invoicePdfUrl?: string; + billingEmail?: string; + billingName?: string; + billingAddress?: BillingAddress; + lineItems: InvoiceLineItem[]; + description?: string; + notes?: string; + metadata: Record; + createdAt: Date; + updatedAt: Date; + finalizedAt?: Date; + voidedAt?: Date; +} + +export interface InvoiceRow { + id: string; + user_id: string; + subscription_id: string | null; + stripe_invoice_id: string | null; + stripe_customer_id: string | null; + invoice_number: string | null; + invoice_type: string; + status: string; + subtotal: string; + tax: string; + total: string; + amount_paid: string; + amount_due: string; + currency: string; + invoice_date: Date; + due_date: Date | null; + period_start: Date | null; + period_end: Date | null; + paid: boolean; + paid_at: Date | null; + attempted: boolean; + attempt_count: number; + next_payment_attempt: Date | null; + hosted_invoice_url: string | null; + invoice_pdf_url: string | null; + billing_email: string | null; + billing_name: string | null; + billing_address: Record | null; + line_items: unknown[]; + description: string | null; + notes: string | null; + metadata: Record; + created_at: Date; + updated_at: Date; + finalized_at: Date | null; + voided_at: Date | null; +} + +// ============================================================================ +// Wallet Audit Log (from financial.wallet_audit_log) +// ============================================================================ + +export type ActorType = 'user' | 'system' | 'admin' | 'api'; + +export interface WalletAuditLog { + id: string; + walletId: string; + action: WalletAuditAction; + actorId?: string; + actorType: ActorType; + oldValues?: Record; + newValues?: Record; + balanceBefore?: number; + balanceAfter?: number; + transactionId?: string; + reason?: string; + metadata: Record; + ipAddress?: string; + userAgent?: string; + createdAt: Date; +} + +export interface WalletAuditLogRow { + id: string; + wallet_id: string; + action: string; + actor_id: string | null; + actor_type: string; + old_values: Record | null; + new_values: Record | null; + balance_before: string | null; + balance_after: string | null; + transaction_id: string | null; + reason: string | null; + metadata: Record; + ip_address: string | null; + user_agent: string | null; + created_at: Date; +} + +// ============================================================================ +// Currency Exchange Rates (from financial.currency_exchange_rates) +// ============================================================================ + +export type ExchangeRateSource = 'manual' | 'api' | 'stripe' | 'coinbase'; + +export interface CurrencyExchangeRate { + id: string; + fromCurrency: CurrencyCode; + toCurrency: CurrencyCode; + rate: number; + source: ExchangeRateSource; + provider?: string; + validFrom: Date; + validTo?: Date; + metadata: Record; + createdAt: Date; + updatedAt: Date; +} + +export interface CurrencyExchangeRateRow { + id: string; + from_currency: string; + to_currency: string; + rate: string; + source: string; + provider: string | null; + valid_from: Date; + valid_to: Date | null; + metadata: Record; + created_at: Date; + updated_at: Date; +} + +// ============================================================================ +// Wallet Limits (from financial.wallet_limits) +// ============================================================================ + +export interface WalletLimit { + id: string; + walletId?: string; + walletType?: WalletType; + subscriptionPlan?: SubscriptionPlan; + minDeposit?: number; + maxDeposit?: number; + minWithdrawal?: number; + maxWithdrawal?: number; + minTransfer?: number; + maxTransfer?: number; + dailyDepositLimit?: number; + dailyWithdrawalLimit?: number; + dailyTransferLimit?: number; + weeklyDepositLimit?: number; + weeklyWithdrawalLimit?: number; + weeklyTransferLimit?: number; + monthlyDepositLimit?: number; + monthlyWithdrawalLimit?: number; + monthlyTransferLimit?: number; + maxPendingTransactions?: number; + maxDailyTransactionCount?: number; + minBalance: number; + maxBalance?: number; + currency: CurrencyCode; + priority: number; + active: boolean; + validFrom: Date; + validTo?: Date; + description?: string; + metadata: Record; + createdAt: Date; + updatedAt: Date; +} + +export interface WalletLimitRow { + id: string; + wallet_id: string | null; + wallet_type: string | null; + subscription_plan: string | null; + min_deposit: string | null; + max_deposit: string | null; + min_withdrawal: string | null; + max_withdrawal: string | null; + min_transfer: string | null; + max_transfer: string | null; + daily_deposit_limit: string | null; + daily_withdrawal_limit: string | null; + daily_transfer_limit: string | null; + weekly_deposit_limit: string | null; + weekly_withdrawal_limit: string | null; + weekly_transfer_limit: string | null; + monthly_deposit_limit: string | null; + monthly_withdrawal_limit: string | null; + monthly_transfer_limit: string | null; + max_pending_transactions: number | null; + max_daily_transaction_count: number | null; + min_balance: string; + max_balance: string | null; + currency: string; + priority: number; + active: boolean; + valid_from: Date; + valid_to: Date | null; + description: string | null; + metadata: Record; + created_at: Date; + updated_at: Date; +} + +// ============================================================================ +// Customer (from financial.customers) +// ============================================================================ + +export interface Customer { + id: string; + userId: string; + stripeCustomerId?: string; + stripeDefaultPaymentMethodId?: string; + billingName?: string; + billingEmail?: string; + billingPhone?: string; + billingAddressLine1?: string; + billingAddressLine2?: string; + billingCity?: string; + billingState?: string; + billingPostalCode?: string; + billingCountry?: string; + taxId?: string; + taxIdType: string; + legalName?: string; + currency: CurrencyCode; + locale: string; + isActive: boolean; + delinquent: boolean; + delinquentSince?: Date; + metadata: Record; + createdAt: Date; + updatedAt: Date; +} + +export interface CustomerRow { + id: string; + user_id: string; + stripe_customer_id: string | null; + stripe_default_payment_method_id: string | null; + billing_name: string | null; + billing_email: string | null; + billing_phone: string | null; + billing_address_line1: string | null; + billing_address_line2: string | null; + billing_city: string | null; + billing_state: string | null; + billing_postal_code: string | null; + billing_country: string | null; + tax_id: string | null; + tax_id_type: string; + legal_name: string | null; + currency: string; + locale: string; + is_active: boolean; + delinquent: boolean; + delinquent_since: Date | null; + metadata: Record; + created_at: Date; + updated_at: Date; +} + +// ============================================================================ +// Payment Method (from financial.payment_methods) +// ============================================================================ + +export type SavedPaymentType = 'card' | 'bank_account' | 'sepa_debit' | 'crypto_wallet'; +export type PaymentMethodStatus = 'pending_verification' | 'active' | 'expired' | 'failed' | 'removed'; +export type CardBrand = 'visa' | 'mastercard' | 'amex' | 'discover' | 'diners' | 'jcb' | 'unionpay'; +export type CardFunding = 'credit' | 'debit' | 'prepaid' | 'unknown'; +export type BankAccountType = 'checking' | 'savings'; +export type CryptoNetwork = 'ethereum' | 'bitcoin' | 'polygon' | 'solana' | 'binance'; + +export interface PaymentMethodDisplayInfo { + last4?: string; + brand?: string; + bankName?: string; + network?: string; +} + +export interface SavedPaymentMethod { + id: string; + userId: string; + customerId?: string; + stripePaymentMethodId?: string; + stripeFingerprint?: string; + paymentType: SavedPaymentType; + status: PaymentMethodStatus; + displayInfo: PaymentMethodDisplayInfo; + isDefault: boolean; + cardBrand?: CardBrand; + cardLast4?: string; + cardExpMonth?: number; + cardExpYear?: number; + cardFunding?: CardFunding; + bankName?: string; + bankLast4?: string; + bankAccountType?: BankAccountType; + cryptoNetwork?: CryptoNetwork; + cryptoAddressLast8?: string; + verifiedAt?: Date; + verificationMethod?: string; + billingAddress: BillingAddress; + metadata: Record; + createdAt: Date; + updatedAt: Date; + expiresAt?: Date; + removedAt?: Date; +} + +export interface PaymentMethodRow { + id: string; + user_id: string; + customer_id: string | null; + stripe_payment_method_id: string | null; + stripe_fingerprint: string | null; + payment_type: string; + status: string; + display_info: Record; + is_default: boolean; + card_brand: string | null; + card_last4: string | null; + card_exp_month: number | null; + card_exp_year: number | null; + card_funding: string | null; + bank_name: string | null; + bank_last4: string | null; + bank_account_type: string | null; + crypto_network: string | null; + crypto_address_last8: string | null; + verified_at: Date | null; + verification_method: string | null; + billing_address: Record; + metadata: Record; + created_at: Date; + updated_at: Date; + expires_at: Date | null; + removed_at: Date | null; +} diff --git a/src/modules/trading/types/entity.types.ts b/src/modules/trading/types/entity.types.ts new file mode 100644 index 0000000..66b06c6 --- /dev/null +++ b/src/modules/trading/types/entity.types.ts @@ -0,0 +1,483 @@ +/** + * Entity Types for Trading Schema + * ================================ + * TypeScript interfaces aligned with trading.* DDL tables + * + * Tables covered: + * - trading.symbols (01-symbols.sql) + * - trading.bots (04-bots.sql) + * - trading.signals (08-signals.sql) + * - trading.trading_metrics (09-trading_metrics.sql) + * - trading.paper_balances (10-paper_balances.sql) + */ + +import { + BotType, + BotStatus, + Timeframe, + SignalType, + ConfidenceLevel, + TradingBotStrategyConfig, +} from './order.types'; + +// ============================================================================ +// Symbol Entity (trading.symbols) +// ============================================================================ + +/** + * Symbol - Catálogo de instrumentos financieros operables + * Aligned with: trading.symbols (01-symbols.sql) + */ +export interface Symbol { + id: string; // UUID + symbol: string; // e.g., BTC/USDT, EUR/USD + name: string; + baseAsset: string; // e.g., BTC, EUR + quoteAsset: string; // e.g., USDT, USD + + // Tipo + assetClass: AssetClass; + exchange?: string; // binance, coinbase + + // Precisión + pricePrecision: number; + quantityPrecision: number; + + // Límites + minQuantity?: number; + maxQuantity?: number; + minNotional?: number; + + // Estado + isActive: boolean; + isTradeable: boolean; + + // Timestamps + createdAt: Date; + updatedAt: Date; +} + +export type AssetClass = 'crypto' | 'forex' | 'stocks' | 'commodities'; + +export interface CreateSymbolDto { + symbol: string; + name: string; + baseAsset: string; + quoteAsset: string; + assetClass: AssetClass; + exchange?: string; + pricePrecision?: number; + quantityPrecision?: number; + minQuantity?: number; + maxQuantity?: number; + minNotional?: number; + isActive?: boolean; + isTradeable?: boolean; +} + +export interface UpdateSymbolDto { + name?: string; + exchange?: string; + pricePrecision?: number; + quantityPrecision?: number; + minQuantity?: number; + maxQuantity?: number; + minNotional?: number; + isActive?: boolean; + isTradeable?: boolean; +} + +export interface SymbolFilters { + assetClass?: AssetClass; + exchange?: string; + isActive?: boolean; + isTradeable?: boolean; + search?: string; + limit?: number; + offset?: number; +} + +// ============================================================================ +// TradingBot Entity (trading.bots) +// ============================================================================ + +/** + * TradingBot - Trading bots configurados por usuarios + * Aligned with: trading.bots (04-bots.sql) + */ +export interface TradingBot { + id: string; // UUID + userId: string; // UUID + + // Configuración básica + name: string; + botType: BotType; + status: BotStatus; + + // Símbolos a operar + symbols: string[]; + timeframe: Timeframe; + + // Capital + initialCapital: number; + currentCapital: number; + + // Risk management + maxPositionSizePct: number; // % del capital + maxDailyLossPct: number; + maxDrawdownPct: number; + + // Estrategia + strategyType?: StrategyType; + strategyConfig: TradingBotStrategyConfig; + + // Estadísticas + totalTrades: number; + winningTrades: number; + totalProfitLoss: number; + winRate: number; + + // Metadata + startedAt?: Date; + stoppedAt?: Date; + lastTradeAt?: Date; + + // Timestamps + createdAt: Date; + updatedAt: Date; +} + +export type StrategyType = 'atlas' | 'orion' | 'nova' | 'custom'; + +export interface CreateTradingBotDto { + name: string; + botType?: BotType; + symbols: string[]; + timeframe?: Timeframe; + initialCapital: number; + maxPositionSizePct?: number; + maxDailyLossPct?: number; + maxDrawdownPct?: number; + strategyType?: StrategyType; + strategyConfig?: TradingBotStrategyConfig; +} + +export interface UpdateTradingBotDto { + name?: string; + status?: BotStatus; + symbols?: string[]; + timeframe?: Timeframe; + maxPositionSizePct?: number; + maxDailyLossPct?: number; + maxDrawdownPct?: number; + strategyType?: StrategyType; + strategyConfig?: TradingBotStrategyConfig; +} + +export interface TradingBotFilters { + userId?: string; + botType?: BotType; + status?: BotStatus; + strategyType?: StrategyType; + limit?: number; + offset?: number; +} + +// ============================================================================ +// TradingSignal Entity (trading.signals) +// ============================================================================ + +/** + * TradingSignal - Señales de trading generadas por modelos ML + * Aligned with: trading.signals (08-signals.sql) + * + * INTERFAZ entre Trading y ML: + * ML escribe señales aquí, Trading las consume + */ +export interface TradingSignal { + id: string; // UUID + + // Origen de la señal + source: SignalSource; + modelVersion?: string; + + // Target + symbol: string; + timeframe: Timeframe; + + // Señal + signalType: SignalType; + confidence: ConfidenceLevel; + confidenceScore?: number; // 0.0000 to 1.0000 + + // Precios objetivo + entryPrice?: number; + targetPrice?: number; + stopLoss?: number; + + // Predicciones + predictedDeltaHigh?: number; // % esperado de subida + predictedDeltaLow?: number; // % esperado de bajada + + // Resultado (se actualiza después) + actualOutcome?: SignalOutcome; + actualDelta?: number; + outcomeAt?: Date; + + // Validez + validFrom: Date; + validUntil: Date; + isActive: boolean; + + // Metadata + metadata: Record; + + // Timestamps + createdAt: Date; +} + +export type SignalSource = 'ml_atlas' | 'ml_orion' | 'ml_nova' | 'manual'; +export type SignalOutcome = 'hit_target' | 'hit_stop' | 'expired' | 'cancelled'; + +export interface CreateTradingSignalDto { + source: SignalSource; + modelVersion?: string; + symbol: string; + timeframe: Timeframe; + signalType: SignalType; + confidence: ConfidenceLevel; + confidenceScore?: number; + entryPrice?: number; + targetPrice?: number; + stopLoss?: number; + predictedDeltaHigh?: number; + predictedDeltaLow?: number; + validUntil: Date; + metadata?: Record; +} + +export interface UpdateTradingSignalDto { + actualOutcome?: SignalOutcome; + actualDelta?: number; + outcomeAt?: Date; + isActive?: boolean; +} + +export interface TradingSignalFilters { + symbol?: string; + timeframe?: Timeframe; + source?: SignalSource; + signalType?: SignalType; + confidence?: ConfidenceLevel; + isActive?: boolean; + startDate?: Date; + endDate?: Date; + limit?: number; + offset?: number; +} + +// ============================================================================ +// TradingMetrics Entity (trading.trading_metrics) +// ============================================================================ + +/** + * TradingMetrics - Métricas diarias de performance por bot + * Aligned with: trading.trading_metrics (09-trading_metrics.sql) + */ +export interface TradingMetrics { + id: string; // UUID + botId: string; // UUID + + // Período + metricDate: Date; + + // Capital + startingCapital: number; + endingCapital: number; + peakCapital: number; + + // Trading + totalTrades: number; + winningTrades: number; + losingTrades: number; + + // PnL + grossProfit: number; + grossLoss: number; + netProfit: number; + + // Ratios + winRate: number; + profitFactor: number; // gross_profit / gross_loss (>1 es rentable) + sharpeRatio?: number; + maxDrawdown: number; // Máximo drawdown del día (%) + + // Trades + avgWin: number; + avgLoss: number; + largestWin: number; + largestLoss: number; + + // Tiempos promedio + avgTradeDurationMinutes?: number; + + // Metadata + metadata: Record; + + // Timestamps + createdAt: Date; + updatedAt: Date; +} + +export interface CreateTradingMetricsDto { + botId: string; + metricDate: Date; + startingCapital: number; + endingCapital: number; + peakCapital: number; + totalTrades?: number; + winningTrades?: number; + losingTrades?: number; + grossProfit?: number; + grossLoss?: number; + netProfit?: number; + winRate?: number; + profitFactor?: number; + sharpeRatio?: number; + maxDrawdown?: number; + avgWin?: number; + avgLoss?: number; + largestWin?: number; + largestLoss?: number; + avgTradeDurationMinutes?: number; + metadata?: Record; +} + +export interface UpdateTradingMetricsDto { + endingCapital?: number; + peakCapital?: number; + totalTrades?: number; + winningTrades?: number; + losingTrades?: number; + grossProfit?: number; + grossLoss?: number; + netProfit?: number; + winRate?: number; + profitFactor?: number; + sharpeRatio?: number; + maxDrawdown?: number; + avgWin?: number; + avgLoss?: number; + largestWin?: number; + largestLoss?: number; + avgTradeDurationMinutes?: number; + metadata?: Record; +} + +export interface TradingMetricsFilters { + botId?: string; + startDate?: Date; + endDate?: Date; + limit?: number; + offset?: number; +} + +// ============================================================================ +// PaperBalance Entity (trading.paper_balances) +// ============================================================================ + +/** + * PaperBalance - Balances virtuales para paper trading + * Aligned with: trading.paper_balances (10-paper_balances.sql) + * + * Permite a usuarios practicar sin riesgo real + */ +export interface PaperBalance { + id: string; // UUID + userId: string; // UUID + + // Asset y balance + asset: string; // e.g., USDT + total: number; + available: number; + locked: number; + + // Tracking + initialBalance: number; + totalDeposits: number; + totalWithdrawals: number; + totalPnl: number; + + // Reset tracking + lastResetAt?: Date; + resetCount: number; + + // Timestamps + createdAt: Date; + updatedAt: Date; +} + +export interface CreatePaperBalanceDto { + userId: string; + asset?: string; // defaults to USDT + initialBalance?: number; // defaults to 10000.00 +} + +export interface UpdatePaperBalanceDto { + total?: number; + available?: number; + locked?: number; + totalDeposits?: number; + totalWithdrawals?: number; + totalPnl?: number; +} + +export interface ResetPaperBalanceDto { + initialBalance?: number; // defaults to 10000.00 +} + +export interface PaperBalanceFilters { + userId?: string; + asset?: string; + limit?: number; + offset?: number; +} + +// ============================================================================ +// Result Types +// ============================================================================ + +export interface SymbolListResult { + symbols: Symbol[]; + total: number; + limit: number; + offset: number; +} + +export interface TradingBotListResult { + bots: TradingBot[]; + total: number; + limit: number; + offset: number; +} + +export interface TradingSignalListResult { + signals: TradingSignal[]; + total: number; + limit: number; + offset: number; +} + +export interface TradingMetricsListResult { + metrics: TradingMetrics[]; + total: number; + limit: number; + offset: number; +} + +export interface PaperBalanceListResult { + balances: PaperBalance[]; + total: number; + limit: number; + offset: number; +}