initial push
This commit is contained in:
477
prisma/schema.prisma
Normal file
477
prisma/schema.prisma
Normal file
@@ -0,0 +1,477 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum PriorityLevel {
|
||||
LOW
|
||||
MEDIUM
|
||||
HIGH
|
||||
}
|
||||
|
||||
enum UserRole {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum ContentPageType {
|
||||
FAQ
|
||||
MANUAL
|
||||
}
|
||||
|
||||
enum OverallScoreMethod {
|
||||
EQUAL_ALL_MODULES
|
||||
EQUAL_ANSWERED_MODULES
|
||||
WEIGHTED_ANSWERED_MODULES
|
||||
}
|
||||
|
||||
enum OrganizationDocumentType {
|
||||
ACTA_CONSTITUTIVA
|
||||
}
|
||||
|
||||
enum StrategicDiagnosticEvidenceSection {
|
||||
TECHNICAL
|
||||
EXPERIENCE
|
||||
ORGANIZATION
|
||||
PUBLIC_PROCUREMENT
|
||||
}
|
||||
|
||||
enum WorkshopProgressStatus {
|
||||
NOT_STARTED
|
||||
WATCHED
|
||||
EVIDENCE_SUBMITTED
|
||||
APPROVED
|
||||
REJECTED
|
||||
SKIPPED
|
||||
}
|
||||
|
||||
enum WorkshopEvidenceValidationStatus {
|
||||
PENDING
|
||||
APPROVED
|
||||
REJECTED
|
||||
ERROR
|
||||
}
|
||||
|
||||
enum LicitationSource {
|
||||
MUNICIPAL_OPEN_PORTAL
|
||||
PNT
|
||||
MUNICIPAL_BACKUP
|
||||
}
|
||||
|
||||
enum LicitationProcedureType {
|
||||
LICITACION_PUBLICA
|
||||
INVITACION_RESTRINGIDA
|
||||
ADJUDICACION_DIRECTA
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
enum LicitationCategory {
|
||||
GOODS
|
||||
SERVICES
|
||||
WORKS
|
||||
MIXED
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
enum SyncRunStatus {
|
||||
SUCCESS
|
||||
PARTIAL
|
||||
FAILED
|
||||
}
|
||||
|
||||
enum MunicipalOpenPortalType {
|
||||
GENERIC
|
||||
SAN_PEDRO_ASPX
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
passwordHash String
|
||||
name String?
|
||||
role UserRole @default(USER)
|
||||
emailVerifiedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization?
|
||||
companyProfile CompanyProfile?
|
||||
organizationDocs OrganizationDocument[]
|
||||
strategicDiagnosticEvidenceDocs StrategicDiagnosticEvidenceDocument[]
|
||||
workshopProgresses DevelopmentWorkshopProgress[]
|
||||
workshopEvidenceDocs DevelopmentWorkshopEvidence[]
|
||||
verificationTokens EmailVerificationToken[]
|
||||
responses Response[]
|
||||
results AssessmentResult[]
|
||||
}
|
||||
|
||||
model Organization {
|
||||
id String @id @default(cuid())
|
||||
userId String @unique
|
||||
name String
|
||||
tradeName String?
|
||||
rfc String?
|
||||
legalRepresentative String?
|
||||
incorporationDate String?
|
||||
deedNumber String?
|
||||
notaryName String?
|
||||
stateOfIncorporation String?
|
||||
companyType String?
|
||||
fiscalAddress String?
|
||||
businessPurpose String?
|
||||
industry String?
|
||||
operatingState String?
|
||||
municipality String?
|
||||
companySize String?
|
||||
yearsOfOperation String?
|
||||
annualRevenueRange String?
|
||||
hasGovernmentContracts Boolean?
|
||||
country String?
|
||||
primaryObjective String?
|
||||
actaExtractedData Json?
|
||||
actaLookupDictionary Json?
|
||||
actaUploadedAt DateTime?
|
||||
onboardingCompletedAt DateTime?
|
||||
strategicDiagnosticData Json?
|
||||
strategicDiagnosticScores Json?
|
||||
strategicDiagnosticCompletedAt DateTime?
|
||||
companyProfile CompanyProfile?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
documents OrganizationDocument[]
|
||||
strategicDiagnosticEvidenceDocs StrategicDiagnosticEvidenceDocument[]
|
||||
}
|
||||
|
||||
model OrganizationDocument {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
userId String
|
||||
type OrganizationDocumentType
|
||||
fileName String
|
||||
storedFileName String
|
||||
filePath String
|
||||
mimeType String
|
||||
sizeBytes Int
|
||||
checksumSha256 String?
|
||||
extractedData Json?
|
||||
extractedTextSnippet String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([organizationId, type])
|
||||
@@unique([userId, type])
|
||||
@@index([type])
|
||||
}
|
||||
|
||||
model StrategicDiagnosticEvidenceDocument {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
userId String
|
||||
section StrategicDiagnosticEvidenceSection
|
||||
category String
|
||||
fileName String
|
||||
storedFileName String
|
||||
filePath String
|
||||
mimeType String
|
||||
sizeBytes Int
|
||||
checksumSha256 String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([organizationId, section])
|
||||
@@index([userId, section])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model DiagnosticModule {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
name String
|
||||
description String?
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
questions Question[]
|
||||
results AssessmentResult[]
|
||||
recommendations Recommendation[]
|
||||
workshops DevelopmentWorkshop[]
|
||||
}
|
||||
|
||||
model DevelopmentWorkshop {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
moduleId String
|
||||
title String
|
||||
summary String
|
||||
videoUrl String
|
||||
durationMinutes Int @default(0)
|
||||
evidenceRequired String
|
||||
learningObjectives Json?
|
||||
sortOrder Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
module DiagnosticModule @relation(fields: [moduleId], references: [id], onDelete: Cascade)
|
||||
progresses DevelopmentWorkshopProgress[]
|
||||
evidences DevelopmentWorkshopEvidence[]
|
||||
|
||||
@@index([moduleId, sortOrder])
|
||||
@@index([isActive, sortOrder])
|
||||
}
|
||||
|
||||
model DevelopmentWorkshopProgress {
|
||||
id String @id @default(cuid())
|
||||
workshopId String
|
||||
userId String
|
||||
status WorkshopProgressStatus @default(NOT_STARTED)
|
||||
watchedAt DateTime?
|
||||
skippedAt DateTime?
|
||||
completedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
workshop DevelopmentWorkshop @relation(fields: [workshopId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([workshopId, userId])
|
||||
@@index([userId, status])
|
||||
@@index([workshopId, status])
|
||||
}
|
||||
|
||||
model DevelopmentWorkshopEvidence {
|
||||
id String @id @default(cuid())
|
||||
workshopId String
|
||||
userId String
|
||||
validationStatus WorkshopEvidenceValidationStatus @default(PENDING)
|
||||
validationReason String?
|
||||
validationConfidence Float?
|
||||
validatedAt DateTime?
|
||||
fileName String
|
||||
storedFileName String
|
||||
filePath String
|
||||
mimeType String
|
||||
sizeBytes Int
|
||||
checksumSha256 String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
workshop DevelopmentWorkshop @relation(fields: [workshopId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId, workshopId, createdAt])
|
||||
@@index([workshopId, validationStatus])
|
||||
}
|
||||
|
||||
model Question {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
moduleId String
|
||||
prompt String
|
||||
helpText String?
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
module DiagnosticModule @relation(fields: [moduleId], references: [id], onDelete: Cascade)
|
||||
answerOptions AnswerOption[]
|
||||
responses Response[]
|
||||
|
||||
@@index([moduleId, sortOrder])
|
||||
}
|
||||
|
||||
model AnswerOption {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
questionId String
|
||||
label String
|
||||
weight Int
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
question Question @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
||||
responses Response[]
|
||||
|
||||
@@index([questionId, sortOrder])
|
||||
}
|
||||
|
||||
model Response {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
questionId String
|
||||
answerOptionId String
|
||||
evidence Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
question Question @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
||||
answerOption AnswerOption @relation(fields: [answerOptionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, questionId])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model AssessmentResult {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
moduleId String?
|
||||
overallScore Float?
|
||||
moduleScore Float?
|
||||
metadata Json?
|
||||
calculatedAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
module DiagnosticModule? @relation(fields: [moduleId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([userId, calculatedAt])
|
||||
@@index([moduleId])
|
||||
}
|
||||
|
||||
model Recommendation {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
moduleId String?
|
||||
title String
|
||||
description String
|
||||
priority PriorityLevel @default(MEDIUM)
|
||||
isTemplate Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
module DiagnosticModule? @relation(fields: [moduleId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([moduleId])
|
||||
}
|
||||
|
||||
model ContentPage {
|
||||
id String @id @default(cuid())
|
||||
type ContentPageType
|
||||
slug String @unique
|
||||
title String
|
||||
content String
|
||||
sortOrder Int @default(0)
|
||||
isPublished Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([type, sortOrder])
|
||||
}
|
||||
|
||||
model ScoringConfig {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
lowScoreThreshold Int @default(70)
|
||||
overallScoreMethod OverallScoreMethod @default(EQUAL_ALL_MODULES)
|
||||
moduleWeights Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model EmailVerificationToken {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
token String @unique
|
||||
expiresAt DateTime
|
||||
consumedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([expiresAt])
|
||||
}
|
||||
|
||||
model Municipality {
|
||||
id String @id @default(cuid())
|
||||
stateCode String
|
||||
stateName String
|
||||
municipalityCode String
|
||||
municipalityName String
|
||||
openPortalUrl String?
|
||||
openPortalType MunicipalOpenPortalType @default(GENERIC)
|
||||
openSyncIntervalDays Int @default(7)
|
||||
lastOpenSyncAt DateTime?
|
||||
pntSubjectId String?
|
||||
pntEntityId String?
|
||||
pntSectorId String?
|
||||
pntEntryUrl String?
|
||||
backupUrl String?
|
||||
scrapingEnabled Boolean @default(true)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
licitations Licitation[]
|
||||
syncRuns SyncRun[]
|
||||
|
||||
@@unique([stateCode, municipalityCode])
|
||||
@@index([stateCode, municipalityName])
|
||||
@@index([isActive, scrapingEnabled])
|
||||
}
|
||||
|
||||
model Licitation {
|
||||
id String @id @default(cuid())
|
||||
municipalityId String
|
||||
source LicitationSource
|
||||
sourceRecordId String
|
||||
tenderCode String?
|
||||
procedureType LicitationProcedureType @default(UNKNOWN)
|
||||
title String
|
||||
description String?
|
||||
category LicitationCategory? @default(UNKNOWN)
|
||||
isOpen Boolean @default(true)
|
||||
openingDate DateTime?
|
||||
closingDate DateTime?
|
||||
publishDate DateTime?
|
||||
eventDates Json?
|
||||
amount Decimal? @db.Decimal(14, 2)
|
||||
currency String?
|
||||
status String?
|
||||
supplierAwarded String?
|
||||
documents Json?
|
||||
rawSourceUrl String?
|
||||
rawPayload Json
|
||||
lastSeenAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
municipality Municipality @relation(fields: [municipalityId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([municipalityId, source, sourceRecordId])
|
||||
@@index([municipalityId, isOpen, closingDate])
|
||||
@@index([municipalityId, publishDate])
|
||||
@@index([procedureType, category])
|
||||
@@index([amount])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model SyncRun {
|
||||
id String @id @default(cuid())
|
||||
startedAt DateTime @default(now())
|
||||
finishedAt DateTime?
|
||||
municipalityId String?
|
||||
source LicitationSource
|
||||
status SyncRunStatus @default(SUCCESS)
|
||||
stats Json?
|
||||
error String?
|
||||
municipality Municipality? @relation(fields: [municipalityId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([municipalityId, startedAt])
|
||||
@@index([source, status, startedAt])
|
||||
}
|
||||
|
||||
model CompanyProfile {
|
||||
id String @id @default(cuid())
|
||||
userId String @unique
|
||||
organizationId String? @unique
|
||||
locations Json?
|
||||
categoriesSupported Json?
|
||||
keywords Json?
|
||||
minAmount Decimal? @db.Decimal(14, 2)
|
||||
maxAmount Decimal? @db.Decimal(14, 2)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
organization Organization? @relation(fields: [organizationId], references: [id], onDelete: SetNull)
|
||||
}
|
||||
Reference in New Issue
Block a user