2026-02-16 00:04:44 +00:00
|
|
|
// Prisma schema for Vorteq Quest Portal
|
|
|
|
|
// PostgreSQL 16 database
|
|
|
|
|
|
|
|
|
|
generator client {
|
|
|
|
|
provider = "prisma-client-js"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
datasource db {
|
|
|
|
|
provider = "postgresql"
|
|
|
|
|
url = env("DATABASE_URL")
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-16 02:08:09 +00:00
|
|
|
// =============================================================================
|
|
|
|
|
// AUTH DOMAIN - User Authentication & Authorization
|
|
|
|
|
// =============================================================================
|
2026-02-16 00:04:44 +00:00
|
|
|
|
2026-02-16 02:08:09 +00:00
|
|
|
// Core user authentication table (Better Auth compatible)
|
|
|
|
|
model auth_user {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
email String @unique
|
|
|
|
|
email_verified Boolean @default(false)
|
|
|
|
|
name String?
|
|
|
|
|
image String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
// Password authentication
|
|
|
|
|
password_hash String?
|
|
|
|
|
|
|
|
|
|
// Account security
|
|
|
|
|
deactivated Boolean @default(false)
|
|
|
|
|
deactivated_at DateTime?
|
|
|
|
|
deactivation_reason String?
|
|
|
|
|
|
|
|
|
|
// Login tracking
|
|
|
|
|
login_count Int @default(0)
|
|
|
|
|
failed_login_count Int @default(0)
|
|
|
|
|
last_login_at DateTime?
|
|
|
|
|
last_login_ip String?
|
|
|
|
|
last_failed_login_at DateTime?
|
|
|
|
|
|
|
|
|
|
// Two-factor authentication
|
|
|
|
|
two_factor_enabled Boolean @default(false)
|
|
|
|
|
two_factor_secret String?
|
|
|
|
|
two_factor_backup_codes String?
|
|
|
|
|
|
|
|
|
|
// SSO fields
|
|
|
|
|
sso_provider String?
|
|
|
|
|
sso_id String?
|
|
|
|
|
|
|
|
|
|
// Relationships
|
|
|
|
|
auth_user_type_id String
|
|
|
|
|
auth_user_type auth_user_type @relation(fields: [auth_user_type_id], references: [id])
|
|
|
|
|
auth_domain_id String?
|
|
|
|
|
auth_domain auth_domain? @relation(fields: [auth_domain_id], references: [id])
|
|
|
|
|
|
|
|
|
|
sessions auth_session[]
|
|
|
|
|
accounts auth_account[]
|
|
|
|
|
password_history auth_password_history[]
|
|
|
|
|
password_resets auth_password_reset[]
|
|
|
|
|
security_answers auth_security_answer[]
|
|
|
|
|
quest_user quest_user?
|
|
|
|
|
|
|
|
|
|
@@index([email])
|
|
|
|
|
@@index([auth_user_type_id])
|
|
|
|
|
@@index([auth_domain_id])
|
|
|
|
|
@@map("auth_user")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// User session table (Better Auth compatible)
|
|
|
|
|
model auth_session {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
user_id String
|
|
|
|
|
token String @unique
|
|
|
|
|
expires_at DateTime
|
|
|
|
|
ip_address String?
|
|
|
|
|
user_agent String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
user auth_user @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([user_id])
|
|
|
|
|
@@index([token])
|
|
|
|
|
@@index([expires_at])
|
|
|
|
|
@@map("auth_session")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OAuth/Social provider accounts (Better Auth compatible)
|
|
|
|
|
model auth_account {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
user_id String
|
|
|
|
|
account_id String
|
|
|
|
|
provider_id String
|
|
|
|
|
access_token String?
|
|
|
|
|
refresh_token String?
|
|
|
|
|
id_token String?
|
|
|
|
|
access_token_expires_at DateTime?
|
|
|
|
|
refresh_token_expires_at DateTime?
|
|
|
|
|
scope String?
|
|
|
|
|
password String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
user auth_user @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([provider_id, account_id])
|
|
|
|
|
@@index([user_id])
|
|
|
|
|
@@map("auth_account")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OAuth client configuration
|
|
|
|
|
model auth_oauth_client {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
client_id String @unique
|
|
|
|
|
client_secret String
|
|
|
|
|
redirect_uris String[] // Array of allowed redirect URIs
|
|
|
|
|
grant_types String[] // Array of allowed grant types
|
|
|
|
|
name String
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
revoked Boolean @default(false)
|
|
|
|
|
|
|
|
|
|
access_tokens auth_oauth_access_token[]
|
|
|
|
|
refresh_tokens auth_oauth_refresh_token[]
|
|
|
|
|
|
|
|
|
|
@@map("auth_oauth_client")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OAuth access tokens
|
|
|
|
|
model auth_oauth_access_token {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
access_token String @unique
|
|
|
|
|
client_id String
|
|
|
|
|
user_id String?
|
|
|
|
|
expires_at DateTime
|
|
|
|
|
scopes String[] // Array of scopes
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
client auth_oauth_client @relation(fields: [client_id], references: [client_id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([access_token])
|
|
|
|
|
@@index([expires_at])
|
|
|
|
|
@@map("auth_oauth_access_token")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OAuth refresh tokens
|
|
|
|
|
model auth_oauth_refresh_token {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
refresh_token String @unique
|
|
|
|
|
access_token_id String?
|
|
|
|
|
client_id String
|
|
|
|
|
user_id String?
|
|
|
|
|
expires_at DateTime
|
|
|
|
|
scopes String[] // Array of scopes
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
revoked Boolean @default(false)
|
|
|
|
|
|
|
|
|
|
client auth_oauth_client @relation(fields: [client_id], references: [client_id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([refresh_token])
|
|
|
|
|
@@index([expires_at])
|
|
|
|
|
@@map("auth_oauth_refresh_token")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// User type/role definitions
|
|
|
|
|
model auth_user_type {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
is_admin Boolean @default(false)
|
|
|
|
|
is_customer Boolean @default(false)
|
|
|
|
|
is_internal Boolean @default(false)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
users auth_user[]
|
feat(F-008,F-009,F-010): complete Phase 1 foundation with middleware, navigation, and migrations
Implements authentication middleware with rate limiting, comprehensive permission
system, full portal navigation with sidebar and header, company selection flow,
and data migration tooling from SQL Server to PostgreSQL.
Key additions:
- Middleware: auth guards, rate limiting, session management
- Permissions: role-based access control with hierarchical permission rules
- Navigation: responsive sidebar with expandable sections, header with notifications
- Company selector: multi-company user support with session-based active company
- Data migration: comprehensive script for migrating auth and quest domain tables
- Schema: added auth_user_type_permission_group junction table
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 11:07:44 +00:00
|
|
|
permission_groups auth_user_type_permission_group[]
|
2026-02-16 02:08:09 +00:00
|
|
|
|
|
|
|
|
@@map("auth_user_type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Domain/company grouping for multi-tenant scenarios
|
|
|
|
|
model auth_domain {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
users auth_user[]
|
|
|
|
|
|
|
|
|
|
@@map("auth_domain")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Password history for preventing reuse
|
|
|
|
|
model auth_password_history {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
user_id String
|
|
|
|
|
password_hash String
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
user auth_user @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([user_id])
|
|
|
|
|
@@map("auth_password_history")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Password reset tokens
|
|
|
|
|
model auth_password_reset {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
user_id String
|
|
|
|
|
token String @unique
|
|
|
|
|
expires_at DateTime
|
|
|
|
|
used_at DateTime?
|
|
|
|
|
ip_address String?
|
|
|
|
|
min_time_bypass Boolean @default(false)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
user auth_user @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([token])
|
|
|
|
|
@@index([user_id])
|
|
|
|
|
@@index([expires_at])
|
|
|
|
|
@@map("auth_password_reset")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Permission groups (roles)
|
|
|
|
|
model auth_permission_group {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
rules auth_permission_group_rule[]
|
feat(F-008,F-009,F-010): complete Phase 1 foundation with middleware, navigation, and migrations
Implements authentication middleware with rate limiting, comprehensive permission
system, full portal navigation with sidebar and header, company selection flow,
and data migration tooling from SQL Server to PostgreSQL.
Key additions:
- Middleware: auth guards, rate limiting, session management
- Permissions: role-based access control with hierarchical permission rules
- Navigation: responsive sidebar with expandable sections, header with notifications
- Company selector: multi-company user support with session-based active company
- Data migration: comprehensive script for migrating auth and quest domain tables
- Schema: added auth_user_type_permission_group junction table
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 11:07:44 +00:00
|
|
|
user_types auth_user_type_permission_group[]
|
2026-02-16 02:08:09 +00:00
|
|
|
|
|
|
|
|
@@map("auth_permission_group")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Permission rules (individual permissions)
|
|
|
|
|
model auth_permission_rule {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
auth_permission_rule_category_id String?
|
|
|
|
|
category auth_permission_rule_category? @relation(fields: [auth_permission_rule_category_id], references: [id])
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
groups auth_permission_group_rule[]
|
|
|
|
|
|
|
|
|
|
@@index([auth_permission_rule_category_id])
|
|
|
|
|
@@map("auth_permission_rule")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Permission rule categories for organization
|
|
|
|
|
model auth_permission_rule_category {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
rules auth_permission_rule[]
|
|
|
|
|
|
|
|
|
|
@@map("auth_permission_rule_category")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Junction table: permission groups to rules (many-to-many)
|
|
|
|
|
model auth_permission_group_rule {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_permission_group_id String
|
|
|
|
|
auth_permission_rule_id String
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
group auth_permission_group @relation(fields: [auth_permission_group_id], references: [id], onDelete: Cascade)
|
|
|
|
|
rule auth_permission_rule @relation(fields: [auth_permission_rule_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([auth_permission_group_id, auth_permission_rule_id])
|
|
|
|
|
@@index([auth_permission_group_id])
|
|
|
|
|
@@index([auth_permission_rule_id])
|
|
|
|
|
@@map("auth_permission_group_rule")
|
|
|
|
|
}
|
|
|
|
|
|
feat(F-008,F-009,F-010): complete Phase 1 foundation with middleware, navigation, and migrations
Implements authentication middleware with rate limiting, comprehensive permission
system, full portal navigation with sidebar and header, company selection flow,
and data migration tooling from SQL Server to PostgreSQL.
Key additions:
- Middleware: auth guards, rate limiting, session management
- Permissions: role-based access control with hierarchical permission rules
- Navigation: responsive sidebar with expandable sections, header with notifications
- Company selector: multi-company user support with session-based active company
- Data migration: comprehensive script for migrating auth and quest domain tables
- Schema: added auth_user_type_permission_group junction table
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 11:07:44 +00:00
|
|
|
// Junction table: user types to permission groups (many-to-many)
|
|
|
|
|
model auth_user_type_permission_group {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_type_id String
|
|
|
|
|
auth_permission_group_id String
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
user_type auth_user_type @relation(fields: [auth_user_type_id], references: [id], onDelete: Cascade)
|
|
|
|
|
group auth_permission_group @relation(fields: [auth_permission_group_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([auth_user_type_id, auth_permission_group_id])
|
|
|
|
|
@@index([auth_user_type_id])
|
|
|
|
|
@@index([auth_permission_group_id])
|
|
|
|
|
@@map("auth_user_type_permission_group")
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-16 02:08:09 +00:00
|
|
|
// Security questions for account recovery
|
|
|
|
|
model auth_security_question {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
question String @unique
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
sort_order Int @default(0)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
answers auth_security_answer[]
|
|
|
|
|
|
|
|
|
|
@@map("auth_security_question")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// User security question answers
|
|
|
|
|
model auth_security_answer {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
user_id String
|
|
|
|
|
auth_security_question_id String
|
|
|
|
|
answer_hash String
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
user auth_user @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
question auth_security_question @relation(fields: [auth_security_question_id], references: [id])
|
|
|
|
|
|
|
|
|
|
@@unique([user_id, auth_security_question_id])
|
|
|
|
|
@@index([user_id])
|
|
|
|
|
@@map("auth_security_answer")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// QUEST DOMAIN - Portal-specific user and company data
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Quest-specific user data (extends auth_user)
|
|
|
|
|
model quest_user {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_id String @unique
|
|
|
|
|
is_sub_user Boolean @default(false)
|
|
|
|
|
api_token String? @unique
|
|
|
|
|
api_token_expires_at DateTime?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
auth_user auth_user @relation(fields: [auth_user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
companies quest_user_company[]
|
|
|
|
|
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@map("quest_user")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Company/customer information
|
|
|
|
|
model quest_company {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
epicor_cust_id String @unique
|
|
|
|
|
display_name String
|
|
|
|
|
can_access_invoices Boolean @default(false)
|
|
|
|
|
invoicing_email String?
|
|
|
|
|
order_ack_email String?
|
|
|
|
|
receives_so_emails Boolean @default(false)
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
users quest_user_company[]
|
|
|
|
|
|
|
|
|
|
@@index([epicor_cust_id])
|
|
|
|
|
@@map("quest_company")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Junction table: users to companies (many-to-many with active company tracking)
|
|
|
|
|
model quest_user_company {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
quest_user_id String
|
|
|
|
|
quest_company_id String
|
|
|
|
|
is_active_company Boolean @default(false)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
user quest_user @relation(fields: [quest_user_id], references: [id], onDelete: Cascade)
|
|
|
|
|
company quest_company @relation(fields: [quest_company_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([quest_user_id, quest_company_id])
|
|
|
|
|
@@index([quest_user_id])
|
|
|
|
|
@@index([quest_company_id])
|
|
|
|
|
@@map("quest_user_company")
|
2026-02-16 00:04:44 +00:00
|
|
|
}
|
2026-02-16 02:16:28 +00:00
|
|
|
|
|
|
|
|
// Account request for new user registration
|
|
|
|
|
model quest_account_request {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
first_name String
|
|
|
|
|
last_name String
|
|
|
|
|
email String
|
|
|
|
|
phone String?
|
|
|
|
|
company_name String
|
|
|
|
|
epicor_cust_id String?
|
|
|
|
|
message String?
|
|
|
|
|
request_processed Boolean @default(false)
|
|
|
|
|
processed_at DateTime?
|
|
|
|
|
processed_by String?
|
|
|
|
|
approved Boolean @default(false)
|
|
|
|
|
rejection_reason String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
@@index([email])
|
|
|
|
|
@@index([request_processed])
|
|
|
|
|
@@map("quest_account_request")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Notification/alert system
|
|
|
|
|
model quest_notification {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
title String
|
|
|
|
|
text String
|
|
|
|
|
is_alert Boolean @default(false)
|
|
|
|
|
display_date DateTime
|
|
|
|
|
display_time String?
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
alert_reads quest_user_notification_alert_read[]
|
|
|
|
|
|
|
|
|
|
@@index([is_alert])
|
|
|
|
|
@@index([display_date])
|
|
|
|
|
@@index([is_active])
|
|
|
|
|
@@map("quest_notification")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tracking which users have read alert notifications
|
|
|
|
|
model quest_user_notification_alert_read {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
quest_notification_id String
|
|
|
|
|
auth_user_id String
|
|
|
|
|
read_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
notification quest_notification @relation(fields: [quest_notification_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([quest_notification_id, auth_user_id])
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@map("quest_user_notification_alert_read")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Email event definitions (types of emails that can be sent)
|
|
|
|
|
model quest_email_event {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
user_subscriptions quest_user_email_event[]
|
|
|
|
|
|
|
|
|
|
@@map("quest_email_event")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// User subscriptions to email events (many-to-many)
|
|
|
|
|
model quest_user_email_event {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_id String
|
|
|
|
|
quest_email_event_id String
|
|
|
|
|
subscribed Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
email_event quest_email_event @relation(fields: [quest_email_event_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([auth_user_id, quest_email_event_id])
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@map("quest_user_email_event")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Email log for tracking sent emails
|
|
|
|
|
model quest_email_log {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
to_addresses String[] // Array of recipient emails
|
|
|
|
|
from_address String
|
|
|
|
|
subject String
|
|
|
|
|
body String
|
|
|
|
|
sent_at DateTime @default(now())
|
|
|
|
|
status String @default("sent") // sent, failed, pending
|
|
|
|
|
error_message String?
|
|
|
|
|
quest_email_event_id String?
|
|
|
|
|
auth_user_id String?
|
|
|
|
|
|
|
|
|
|
@@index([sent_at])
|
|
|
|
|
@@index([status])
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@map("quest_email_log")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Plant/facility definitions
|
|
|
|
|
model quest_plant {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
code String @unique
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
inventory_assignments quest_inventory_plant[]
|
|
|
|
|
|
|
|
|
|
@@map("quest_plant")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inventory type definitions (WIP, Finished Goods, etc.)
|
|
|
|
|
model quest_inventory_type {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
code String @unique
|
|
|
|
|
description String?
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
sort_order Int @default(0)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
plant_assignments quest_inventory_plant[]
|
|
|
|
|
|
|
|
|
|
@@map("quest_inventory_type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Junction: which inventory types are available at which plants
|
|
|
|
|
model quest_inventory_plant {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
quest_plant_id String
|
|
|
|
|
quest_inventory_type_id String
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
plant quest_plant @relation(fields: [quest_plant_id], references: [id], onDelete: Cascade)
|
|
|
|
|
inventory_type quest_inventory_type @relation(fields: [quest_inventory_type_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([quest_plant_id, quest_inventory_type_id])
|
|
|
|
|
@@index([quest_plant_id])
|
|
|
|
|
@@index([quest_inventory_type_id])
|
|
|
|
|
@@map("quest_inventory_plant")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tracking processed order acknowledgement emails to prevent duplicates
|
|
|
|
|
model quest_processed_order_acknowledgement_email {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
epicor_order_num Int
|
|
|
|
|
epicor_cust_id String
|
|
|
|
|
epicor_po_num String?
|
|
|
|
|
sent_at DateTime @default(now())
|
|
|
|
|
quest_company_id String?
|
|
|
|
|
|
|
|
|
|
@@unique([epicor_order_num, epicor_cust_id])
|
|
|
|
|
@@index([epicor_cust_id])
|
|
|
|
|
@@index([sent_at])
|
|
|
|
|
@@map("quest_processed_order_acknowledgement_email")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// SHIPMENT REQUEST DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Shipment request header
|
|
|
|
|
model ship_request {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_id String
|
|
|
|
|
quest_company_id String
|
|
|
|
|
ship_to_address String
|
|
|
|
|
order_number String?
|
|
|
|
|
po_number String?
|
|
|
|
|
release_number String?
|
|
|
|
|
pickup_date DateTime?
|
|
|
|
|
instructions String?
|
|
|
|
|
email_recipients String[] // Array of email addresses
|
|
|
|
|
is_submitted Boolean @default(false)
|
|
|
|
|
submitted_at DateTime?
|
|
|
|
|
is_cancelled Boolean @default(false)
|
|
|
|
|
cancelled_at DateTime?
|
|
|
|
|
cancelled_by String?
|
|
|
|
|
last_cart_activity DateTime @default(now())
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
details ship_request_detail[]
|
|
|
|
|
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@index([quest_company_id])
|
|
|
|
|
@@index([is_submitted])
|
|
|
|
|
@@index([is_cancelled])
|
|
|
|
|
@@map("ship_request")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shipment request line items
|
|
|
|
|
model ship_request_detail {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
ship_request_id String
|
|
|
|
|
part_num String
|
|
|
|
|
lot_num String?
|
|
|
|
|
plant String
|
|
|
|
|
warehouse String?
|
|
|
|
|
quantity Float
|
|
|
|
|
notes String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
request ship_request @relation(fields: [ship_request_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([ship_request_id])
|
|
|
|
|
@@map("ship_request_detail")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// ALLOCATION REQUEST DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Coil allocation request header
|
|
|
|
|
model alloc_request {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_id String
|
|
|
|
|
quest_company_id String
|
|
|
|
|
job_number String
|
|
|
|
|
ship_to_address String
|
|
|
|
|
order_number String?
|
|
|
|
|
po_number String?
|
|
|
|
|
release_number String?
|
|
|
|
|
pickup_date DateTime?
|
|
|
|
|
instructions String?
|
|
|
|
|
email_recipients String[] // Array of email addresses
|
|
|
|
|
is_submitted Boolean @default(false)
|
|
|
|
|
submitted_at DateTime?
|
|
|
|
|
is_cancelled Boolean @default(false)
|
|
|
|
|
cancelled_at DateTime?
|
|
|
|
|
cancelled_by String?
|
|
|
|
|
last_cart_activity DateTime @default(now())
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
details alloc_request_detail[]
|
|
|
|
|
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@index([quest_company_id])
|
|
|
|
|
@@index([job_number])
|
|
|
|
|
@@index([is_submitted])
|
|
|
|
|
@@map("alloc_request")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocation request line items
|
|
|
|
|
model alloc_request_detail {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
alloc_request_id String
|
|
|
|
|
part_num String
|
|
|
|
|
lot_num String?
|
|
|
|
|
coil_number String?
|
|
|
|
|
quantity Float
|
|
|
|
|
notes String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
request alloc_request @relation(fields: [alloc_request_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([alloc_request_id])
|
|
|
|
|
@@map("alloc_request_detail")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocation plant assignments (which plants can allocate)
|
|
|
|
|
model alloc_plant {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
plant_code String @unique
|
|
|
|
|
plant_name String
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
@@map("alloc_plant")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// INVOICE UPLOAD DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Invoice upload batch status
|
|
|
|
|
model inv_upload_status {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
sort_order Int @default(0)
|
|
|
|
|
|
|
|
|
|
uploads inv_upload[]
|
|
|
|
|
|
|
|
|
|
@@map("inv_upload_status")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Invoice upload batch
|
|
|
|
|
model inv_upload {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_id String
|
|
|
|
|
original_filename String
|
|
|
|
|
storage_filename String
|
|
|
|
|
file_path String
|
|
|
|
|
file_size Int
|
|
|
|
|
total_pages Int?
|
|
|
|
|
inv_upload_status_id String
|
|
|
|
|
upload_notes String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
processed_at DateTime?
|
|
|
|
|
|
|
|
|
|
status inv_upload_status @relation(fields: [inv_upload_status_id], references: [id])
|
|
|
|
|
entries inv_upload_entry[]
|
|
|
|
|
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@index([inv_upload_status_id])
|
|
|
|
|
@@index([created_at])
|
|
|
|
|
@@map("inv_upload")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Individual invoice entries from upload
|
|
|
|
|
model inv_upload_entry {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
inv_upload_id String
|
|
|
|
|
invoice_number String
|
|
|
|
|
epicor_cust_id String?
|
|
|
|
|
quest_company_id String?
|
|
|
|
|
job_number String?
|
|
|
|
|
page_number Int?
|
|
|
|
|
storage_filename String?
|
|
|
|
|
file_path String?
|
|
|
|
|
is_ignored Boolean @default(false)
|
|
|
|
|
is_replaced Boolean @default(false)
|
|
|
|
|
send_error String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
sent_at DateTime?
|
|
|
|
|
|
|
|
|
|
upload inv_upload @relation(fields: [inv_upload_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([inv_upload_id])
|
|
|
|
|
@@index([invoice_number])
|
|
|
|
|
@@index([epicor_cust_id])
|
|
|
|
|
@@index([quest_company_id])
|
|
|
|
|
@@map("inv_upload_entry")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// FINANCE/AP CHECK PROCESSING DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// AP check processing status definitions
|
|
|
|
|
model finance_ap_check_processing_status {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
sort_order Int @default(0)
|
|
|
|
|
|
|
|
|
|
batches finance_ap_check_processing_batch[]
|
|
|
|
|
|
|
|
|
|
@@map("finance_ap_check_processing_status")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AP check processing batch tracking
|
|
|
|
|
model finance_ap_check_processing_batch {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
auth_user_id String
|
|
|
|
|
group_id String
|
|
|
|
|
original_filename String
|
|
|
|
|
generated_csv_filename String?
|
|
|
|
|
generated_csv_path String?
|
|
|
|
|
finance_ap_check_processing_status_id String
|
|
|
|
|
error_message String?
|
|
|
|
|
record_count Int @default(0)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
processed_at DateTime?
|
|
|
|
|
|
|
|
|
|
status finance_ap_check_processing_status @relation(fields: [finance_ap_check_processing_status_id], references: [id])
|
|
|
|
|
|
|
|
|
|
@@index([auth_user_id])
|
|
|
|
|
@@index([group_id])
|
|
|
|
|
@@index([finance_ap_check_processing_status_id])
|
|
|
|
|
@@map("finance_ap_check_processing_batch")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// PAINT SCHEDULE DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Paint line types
|
|
|
|
|
model paint_line_type {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
|
|
|
|
|
lines paint_line[]
|
|
|
|
|
|
|
|
|
|
@@map("paint_line_type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paint plants
|
|
|
|
|
model paint_plant {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
code String @unique
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
|
|
|
|
|
plant_lines paint_plant_line[]
|
|
|
|
|
|
|
|
|
|
@@map("paint_plant")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paint lines
|
|
|
|
|
model paint_line {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
paint_line_type_id String
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
|
|
|
|
|
line_type paint_line_type @relation(fields: [paint_line_type_id], references: [id])
|
|
|
|
|
plant_lines paint_plant_line[]
|
|
|
|
|
schedules paint_schedule[]
|
|
|
|
|
|
|
|
|
|
@@map("paint_line")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Junction: which lines are at which plants
|
|
|
|
|
model paint_plant_line {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
paint_plant_id String
|
|
|
|
|
paint_line_id String
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
|
|
|
|
|
plant paint_plant @relation(fields: [paint_plant_id], references: [id], onDelete: Cascade)
|
|
|
|
|
line paint_line @relation(fields: [paint_line_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([paint_plant_id, paint_line_id])
|
|
|
|
|
@@map("paint_plant_line")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paint schedule entries
|
|
|
|
|
model paint_schedule {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
paint_line_id String
|
|
|
|
|
job_id String?
|
|
|
|
|
part_description String?
|
|
|
|
|
customer String?
|
|
|
|
|
quantity Int?
|
|
|
|
|
estimated_run_time Float?
|
|
|
|
|
start_time DateTime?
|
|
|
|
|
notes String?
|
|
|
|
|
is_complete Boolean @default(false)
|
|
|
|
|
line_speed Float?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
line paint_line @relation(fields: [paint_line_id], references: [id])
|
|
|
|
|
|
|
|
|
|
@@index([paint_line_id])
|
|
|
|
|
@@index([start_time])
|
|
|
|
|
@@index([is_complete])
|
|
|
|
|
@@map("paint_schedule")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// DOCUMENTATION/KNOWLEDGE BASE DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Documentation categories
|
|
|
|
|
model doc_category {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
icon String?
|
|
|
|
|
sort_order Int @default(0)
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
articles doc_article[]
|
|
|
|
|
|
|
|
|
|
@@map("doc_category")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Documentation articles
|
|
|
|
|
model doc_article {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
title String
|
|
|
|
|
content String
|
|
|
|
|
doc_category_id String
|
|
|
|
|
is_published Boolean @default(false)
|
|
|
|
|
sort_order Int @default(0)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
created_by String?
|
|
|
|
|
updated_by String?
|
|
|
|
|
|
|
|
|
|
category doc_category @relation(fields: [doc_category_id], references: [id])
|
|
|
|
|
permission_groups doc_article_permission_group[]
|
|
|
|
|
|
|
|
|
|
@@index([doc_category_id])
|
|
|
|
|
@@index([is_published])
|
|
|
|
|
@@map("doc_article")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Junction: which permission groups can see which articles
|
|
|
|
|
model doc_article_permission_group {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
doc_article_id String
|
|
|
|
|
auth_permission_group_id String
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
article doc_article @relation(fields: [doc_article_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([doc_article_id, auth_permission_group_id])
|
|
|
|
|
@@map("doc_article_permission_group")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// WAVE/EDI PROCESSING DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Wave process definitions
|
|
|
|
|
model wave_process {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
is_enabled Boolean @default(true)
|
|
|
|
|
schedule_cron String?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
history wave_process_history[]
|
|
|
|
|
|
|
|
|
|
@@map("wave_process")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wave process execution history
|
|
|
|
|
model wave_process_history {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
wave_process_id String
|
|
|
|
|
started_at DateTime @default(now())
|
|
|
|
|
completed_at DateTime?
|
|
|
|
|
status String @default("running") // running, success, failed
|
|
|
|
|
result_message String?
|
|
|
|
|
error_message String?
|
|
|
|
|
|
|
|
|
|
process wave_process @relation(fields: [wave_process_id], references: [id])
|
|
|
|
|
|
|
|
|
|
@@index([wave_process_id])
|
|
|
|
|
@@index([started_at])
|
|
|
|
|
@@index([status])
|
|
|
|
|
@@map("wave_process_history")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// LTS (LONG-TERM SCHEDULER) TASK DOMAIN
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// Task types
|
|
|
|
|
model lts_task_type {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String?
|
|
|
|
|
|
|
|
|
|
tasks lts_task[]
|
|
|
|
|
|
|
|
|
|
@@map("lts_task_type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Scheduled tasks
|
|
|
|
|
model lts_task {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
lts_task_type_id String
|
|
|
|
|
name String
|
|
|
|
|
description String?
|
|
|
|
|
command String
|
|
|
|
|
is_enabled Boolean @default(true)
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
task_type lts_task_type @relation(fields: [lts_task_type_id], references: [id])
|
|
|
|
|
schedules lts_task_schedule[]
|
|
|
|
|
executions lts_task_execution[]
|
|
|
|
|
|
|
|
|
|
@@map("lts_task")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Task schedule definitions
|
|
|
|
|
model lts_task_schedule {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
lts_task_id String
|
|
|
|
|
schedule_type String // cron, interval, daily, weekly, monthly
|
|
|
|
|
schedule_value String // cron expression or interval value
|
|
|
|
|
timezone String @default("UTC")
|
|
|
|
|
is_active Boolean @default(true)
|
|
|
|
|
next_run_at DateTime?
|
|
|
|
|
created_at DateTime @default(now())
|
|
|
|
|
updated_at DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
task lts_task @relation(fields: [lts_task_id], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([lts_task_id])
|
|
|
|
|
@@index([next_run_at])
|
|
|
|
|
@@map("lts_task_schedule")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Task execution log
|
|
|
|
|
model lts_task_execution {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
lts_task_id String
|
|
|
|
|
started_at DateTime @default(now())
|
|
|
|
|
completed_at DateTime?
|
|
|
|
|
status String @default("running") // running, success, failed
|
|
|
|
|
output String?
|
|
|
|
|
error_message String?
|
|
|
|
|
exit_code Int?
|
|
|
|
|
|
|
|
|
|
task lts_task @relation(fields: [lts_task_id], references: [id])
|
|
|
|
|
|
|
|
|
|
@@index([lts_task_id])
|
|
|
|
|
@@index([started_at])
|
|
|
|
|
@@index([status])
|
|
|
|
|
@@map("lts_task_execution")
|
|
|
|
|
}
|