model App { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tenantId String tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) type String // App type identifier e.g., "sample-data-sync" config String @default("{}") // JSON configuration icon String? isActive Boolean @default(true) installedByUserId String? installedByUser User? @relation("appInstalledByUser", fields: [installedByUserId], references: [id]) syncRuns AppSyncRun[] @@unique([tenantId, type]) @@index([tenantId]) } model DataConnection { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tenantId String tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) name String type String // Connection type e.g., "rest-api", "oauth2", "webhook" config String @default("{}") // Encrypted JSON credentials description String? @@index([tenantId]) } model AppSyncRun { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt appId String app App @relation(fields: [appId], references: [id], onDelete: Cascade) tenantId String tenant Tenant @relation(fields: [tenantId], references: [id]) taskKey String // e.g., "sync-products" taskName String // e.g., "Sync Products" description String? status String @default("pending") // pending, running, completed, partial, failed, cancelled, reverted executionMode String @default("manual") // manual, scheduled, webhook startedAt DateTime? completedAt DateTime? duration Int @default(0) // Duration in milliseconds itemsProcessed Int @default(0) itemsCreated Int @default(0) itemsUpdated Int @default(0) itemsFailed Int @default(0) error String? metadata String @default("{}") createdByUserId String? createdByUser User? @relation("appSyncRunCreatedByUser", fields: [createdByUserId], references: [id]) logs AppSyncRunLog[] syncItems AppSyncItem[] @@index([appId, taskKey]) @@index([tenantId]) } model AppSyncRunLog { id String @id @default(cuid()) createdAt DateTime @default(now()) syncRunId String syncRun AppSyncRun @relation(fields: [syncRunId], references: [id], onDelete: Cascade) type String @default("info") // info, success, warning, error message String metadata String? @@index([syncRunId]) } model AppSyncItem { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt syncRunId String syncRun AppSyncRun @relation(fields: [syncRunId], references: [id], onDelete: Cascade) objectType String // e.g., "product", "customer" sourceId String // ID from external system destinationId String? // ID in our system description String? status String @default("pending") // synced, failed, skipped, pending, reverted action String? // created, updated, deleted, skipped sourceData String // JSON of source data destinationData String? // JSON of destination data error String? rolledBackData String? // JSON of rollback information rolledBackAt DateTime? @@index([syncRunId]) @@index([objectType, sourceId]) }