Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
H
hrsystem
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
hrsystem
Commits
ff7f1d41
Commit
ff7f1d41
authored
Apr 02, 2026
by
Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update prisma/schema.prisma via Son of Anton
parent
0f56e115
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
852 additions
and
1463 deletions
+852
-1463
schema.prisma
prisma/schema.prisma
+852
-1463
No files found.
prisma/schema.prisma
View file @
ff7f1d41
//
============================================================
//
This
is
your
main
Prisma
schema
file
.
//
AL
-
ARCADE
HR
PLATFORM
v3
.0
—
"THE GRIND"
//
Since
we
're using multi-file schemas, ensure your package.json
//
Complete
Prisma
Schema
—
ALL
modules
,
ALL
phases
// has the correct prisma configuration.
//
============================================================
generator client {
generator client {
provider = "prisma-client-js"
provider = "prisma-client-js"
previewFeatures
=
[
"
fullTextSearch"
,
"fullTextIndex
"
]
previewFeatures = ["
multiSchema", "prismaSchemaFolder
"]
}
}
datasource db {
datasource db {
...
@@ -13,51 +12,34 @@ datasource db {
...
@@ -13,51 +12,34 @@ datasource db {
url = env("DATABASE_URL")
url = env("DATABASE_URL")
}
}
//
============================================
================
// ============================================
// ENUMS
// ENUMS
//
============================================
================
// ============================================
enum Role {
enum Role {
SUPER_ADMIN
SUPER_ADMIN
ADMIN
ADMIN
TEAM_LEAD
PROJECT_LEADER
CONTRACTOR
CONTRACTOR
}
}
enum ContractorType {
enum ContractorType {
FULL_TIME
FULL_TIME
PART_TIME
INTERN
PROJECT_BASED
}
}
enum
UserStatus
{
enum ContractorStatus {
INVITED
ONBOARDING
ONBOARDING
ACTIVE
ACTIVE
ON_PIP
ON_PIP
SUSPENDED
SUSPENDED
OFFBOARDING
OFFBOARDED
OFFBOARDED
}
}
enum
InviteStatus
{
enum DayType {
PENDING
IN_OFFICE
ACCEPTED
REMOTE
EXPIRED
OFF
REVOKED
}
enum
BoardVisibility
{
PUBLIC
PRIVATE
TEAM
}
enum
BoardMemberRole
{
OWNER
ADMIN
MEMBER
VIEWER
}
}
enum CardPriority {
enum CardPriority {
...
@@ -68,163 +50,137 @@ enum CardPriority {
...
@@ -68,163 +50,137 @@ enum CardPriority {
NONE
NONE
}
}
enum
DeductionType
{
enum ColumnType {
MANUAL
BACKLOG
AUTO_LATE_REPORT
TODO
AUTO_MISSED_REPORT
DOING
AUTO_PIP
FROZEN
PRESET
IN_REVIEW
}
DONE
CUSTOM
enum
DeductionStatus
{
PENDING
APPROVED
REJECTED
APPEALED
REVERSED
}
enum
AdjustmentType
{
ADVANCE
REIMBURSEMENT
BONUS
CORRECTION
OTHER
}
}
enum
AdjustmentStatus
{
enum DeductionCategory {
PENDING
A
APPROVED
B
REJECTED
C
D
}
}
enum
BountyStatus
{
enum DeductionStatus {
PENDING
DRAFT
EARNED
PENDING_ADMIN_REVIEW
PAID
PENDING_ACKNOWLEDGMENT
PENDING_RESPONSE
UPHELD
REDUCED
DISMISSED
AUTO_APPLIED
CANCELLED
CANCELLED
}
}
enum
Payroll
Status
{
enum
Report
Status {
DRAFT
DRAFT
CALCULATING
SUBMITTED
REVIEW
LATE
APPROVED
APPROVED
PAID
AUTO_APPROVED
CANCELLED
FLAGGED_VAGUE
}
FLAGGED_INCONSISTENT
REVISION_REQUESTED
enum
NotificationType
{
AMENDED
PASSIVE
UNREPORTED
IMPORTANT
BLOCKING
}
enum
NotificationCategory
{
CARD
BOARD
SALARY
DEDUCTION
BOUNTY
ADJUSTMENT
PAYROLL
REPORT
EVALUATION
PIP
MESSAGE
MEETING
NOTICE
POLICY
ONBOARDING
UNAVAILABILITY
SCHEDULE
SYSTEM
}
enum
ConversationType
{
DIRECT
GROUP
}
enum
MessageType
{
TEXT
FILE
SYSTEM
}
}
enum
ReportStatus
{
enum PayrollStatus {
DRAFT
PENDING_CALCULATION
CALCULATED
UNDER_REVIEW
SUBMITTED
SUBMITTED
APPROVED
APPROVED
REJECTED
REJECTED
AMENDMENT_REQUESTED
PROCESSING
PAID
}
}
enum EvaluationStatus {
enum EvaluationStatus {
DRAFT
PENDING_TECHNICAL
IN_PROGRESS
PENDING_PROFESSIONAL
COMP
LET
ED
COMP
IL
ED
ACKNOWLEDGED
ACKNOWLEDGED
RESPONDED
}
}
enum
P
IP
Status
{
enum P
ip
Status {
ACTIVE
ACTIVE
PASSED
PASSED
FAILED
FAILED
EXTENDED
CANCELLED
CANCELLED
}
}
enum LearningGoalStatus {
enum LearningGoalStatus {
NOT_STARTED
ACTIVE
IN_PROGRESS
OVERDUE
COMPLETED
PASSED
CANCELLED
FAILED
EXTENDED
}
}
enum
UnavailabilityType
{
enum NotificationType {
VACATION
BLOCKING
SICK
IMPORTANT
PERSONAL
INFORMATIONAL
EMERGENCY
}
enum NoticeType {
GENERAL_ANNOUNCEMENT
OFFICIAL_WARNING
POLICY_UPDATE
CUSTOM
}
enum AdjustmentType {
POSITIVE
NEGATIVE
}
enum AdjustmentCategory {
ADVANCE
REIMBURSEMENT
BONUS
CORRECTION
LOAN
OTHER
OTHER
}
}
enum
Reques
tStatus
{
enum
Adjustmen
tStatus {
PENDING
PENDING
_APPROVAL
APPROVED
APPROVED
REJECTED
REJECTED
CANCELLED
}
enum
MeetingStatus
{
SCHEDULED
IN_PROGRESS
COMPLETED
CANCELLED
}
}
enum
ContractStatus
{
enum InviteStatus {
DRAFT
ACTIVE
ACTIVE
USED
EXPIRED
EXPIRED
TERMINAT
ED
REVOK
ED
}
}
enum
OffboardingStatus
{
enum MeetingStatus {
PENDING
SCHEDULED
IN_PROGRESS
COMPLETED
COMPLETED
CANCELLED
CANCELLED
}
}
enum
WebhookStatus
{
enum UnavailabilityReason {
ACTIVE
PERSONAL
INACTIVE
MEDICAL
FAILED
RELIGIOUS
EMERGENCY
OTHER
}
}
enum
Recurrence
Pattern
{
enum Recurrence
Type
{
DAILY
DAILY
WEEKLY
WEEKLY
BIWEEKLY
BIWEEKLY
...
@@ -232,357 +188,219 @@ enum RecurrencePattern {
...
@@ -232,357 +188,219 @@ enum RecurrencePattern {
CUSTOM
CUSTOM
}
}
enum
AuditAction
{
enum LabelScope {
CREATE
ORGANIZATION
UPDATE
BOARD
DELETE
}
ARCHIVE
RESTORE
enum ApiKeyScope {
LOGIN
READ_ONLY
LOGOUT
READ_WRITE
PASSWORD_RESET
ADMIN
PASSWORD_CHANGE
}
ROLE_CHANGE
STATUS_CHANGE
enum ConversationType {
APPROVE
DIRECT
REJECT
GROUP
SUBMIT
}
MOVE
ASSIGN
enum TerminationType {
UNASSIGN
VOLUNTARY
LOCK
FOR_CAUSE
UNLOCK
MUTUAL
ACKNOWLEDGE
CONTRACT_EXPIRY
BULK_ACTION
}
EXPORT
IMPORT
// ============================================
SETTINGS_CHANGE
// CORE MODELS
GENERATE
// ============================================
SEND
}
//
============================================================
//
AUTH
&
USERS
//
============================================================
model User {
model User {
id String @id @default(uuid())
id String @id @default(uuid())
email
String
@
unique
username String @unique
username String @unique
passwordHash String
passwordHash String
firstName String
firstName String
lastName String
lastName String
displayName
String
?
nameArabic String?
nationalId String? @unique
dateOfBirth DateTime?
phone String?
phoneSecondary String?
address String?
avatar String?
avatar String?
role Role @default(CONTRACTOR)
role Role @default(CONTRACTOR)
contractorType ContractorType?
contractorType ContractorType?
status
UserStatus
@
default
(
INVITED
)
status ContractorStatus @default(ONBOARDING)
department
String
?
weeklySchedule Json?
title
String
?
baseSalaryPiasters Int?
phone
String
?
actualSalaryPiasters Int?
timezone
String
@
default
(
"Africa/Cairo"
)
bankName String?
bio
String
?
bankAccountNumber String?
dateOfBirth
DateTime
?
bankAccountHolderName String?
startDate
DateTime
?
emergencyContactName String?
emergencyContactPhone String?
emergencyContactRelationship String?
currentStreak Int @default(0)
bestStreak Int @default(0)
forcePasswordChange Boolean @default(false)
activatedAt DateTime?
contractSignedAt DateTime?
lastLoginAt DateTime?
lastLoginAt DateTime?
isOnline
Boolean
@
default
(
false
)
loginAttempts Int @default(0)
lockedUntil DateTime?
deletedAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
//
Relations
—
Auth
&
Sessions
sessions
Session
[]
passwordResetTokens
PasswordResetToken
[]
//
Relations
—
Onboarding
sentInvites
Invite
[]
@
relation
(
"InviteSender"
)
receivedInvite
Invite
?
@
relation
(
"InviteRecipient"
)
onboardingProgress
ContractorOnboarding
?
//
Relations
—
Boards
&
Cards
// Relations
ownedBoards
Board
[]
@
relation
(
"BoardCreator"
)
boards BoardMember[]
boardMemberships
BoardMember
[]
assignedCards CardAssignee[]
watchedCards CardWatcher[]
createdCards Card[] @relation("CardCreator")
createdCards Card[] @relation("CardCreator")
cardAssignments
CardAssignee
[]
comments Comment[]
cardWatches
CardWatcher
[]
attachments Attachment[]
cardComments
CardComment
[]
reports DailyReport[] @relation("ReportAuthor")
cardActivities
CardActivity
[]
@
relation
(
"CardActivityActor"
)
reviewedReports DailyReport[] @relation("ReportReviewer")
lockedCards
Card
[]
@
relation
(
"CardLocker"
)
deductions Deduction[] @relation("DeductionTarget")
initiatedDeductions Deduction[] @relation("DeductionInitiator")
//
Relations
—
Financial
reviewedDeductions Deduction[] @relation("DeductionReviewer")
contractorSalaries
ContractorSalary
[]
@
relation
(
"SalaryContractor"
)
bountyPayouts BountyPayout[]
createdSalaries
ContractorSalary
[]
@
relation
(
"SalaryCreator"
)
adjustments Adjustment[] @relation("AdjustmentTarget")
earnedBounties
Bounty
[]
@
relation
(
"BountyContractor"
)
createdAdjustments Adjustment[] @relation("AdjustmentCreator")
createdBounties
Bounty
[]
@
relation
(
"BountyCreator"
)
reviewedAdjustments Adjustment[] @relation("AdjustmentReviewer")
receivedDeductions
Deduction
[]
@
relation
(
"DeductionContractor"
)
evaluations Evaluation[] @relation("EvaluationTarget")
createdDeductions
Deduction
[]
@
relation
(
"DeductionCreator"
)
techEvaluator Evaluation[] @relation("TechEvaluator")
approvedDeductions
Deduction
[]
@
relation
(
"DeductionApprover"
)
profEvaluator Evaluation[] @relation("ProfEvaluator")
reversedDeductions
Deduction
[]
@
relation
(
"DeductionReverser"
)
pips Pip[] @relation("PipTarget")
receivedAdjustments
SalaryAdjustment
[]
@
relation
(
"AdjustmentContractor"
)
createdPips Pip[] @relation("PipCreator")
createdAdjustments
SalaryAdjustment
[]
@
relation
(
"AdjustmentCreator"
)
learningGoals LearningGoal[] @relation("GoalTarget")
approvedAdjustments
SalaryAdjustment
[]
@
relation
(
"AdjustmentApprover"
)
createdGoals LearningGoal[] @relation("GoalCreator")
payrollItems
PayrollItem
[]
unavailability Unavailability[]
generatedPayrolls
PayrollPeriod
[]
@
relation
(
"PayrollGenerator"
)
scheduleRequests ScheduleChangeRequest[] @relation("ScheduleRequester")
approvedPayrolls
PayrollPeriod
[]
@
relation
(
"PayrollApprover"
)
reviewedSchedules ScheduleChangeRequest[] @relation("ScheduleReviewer")
conversations ConversationParticipant[]
//
Relations
—
Communication
conversationParticipations
ConversationParticipant
[]
sentMessages Message[]
sentMessages Message[]
createdNotices
Notice
[]
@
relation
(
"NoticeCreator"
)
createdPolicies
Policy
[]
@
relation
(
"PolicyCreator"
)
policyAcknowledgments
PolicyAcknowledgment
[]
//
Relations
—
Notifications
notifications Notification[]
notifications Notification[]
notificationPreferences
NotificationPreference
[]
noticeAcknowledgments NoticeAcknowledgment[]
policyAcknowledgments PolicyAcknowledgment[]
//
Relations
—
Reports
dailyReports
DailyReport
[]
@
relation
(
"ReportContractor"
)
reviewedReports
DailyReport
[]
@
relation
(
"ReportReviewer"
)
//
Relations
—
Performance
evaluationsReceived
Evaluation
[]
@
relation
(
"EvaluationContractor"
)
evaluationsGiven
Evaluation
[]
@
relation
(
"EvaluationEvaluator"
)
createdEvalTemplates
EvaluationTemplate
[]
pipsReceived
PIP
[]
@
relation
(
"PIPContractor"
)
pipsManaged
PIP
[]
@
relation
(
"PIPManager"
)
learningGoals
LearningGoal
[]
competencyAssessments
CompetencyAssessment
[]
@
relation
(
"AssessmentContractor"
)
givenAssessments
CompetencyAssessment
[]
@
relation
(
"AssessmentAssessor"
)
//
Relations
—
Time
&
Scheduling
unavailabilityRequests
UnavailabilityRequest
[]
@
relation
(
"UnavailabilityContractor"
)
reviewedUnavailabilities
UnavailabilityRequest
[]
@
relation
(
"UnavailabilityReviewer"
)
scheduleChangeRequests
ScheduleChangeRequest
[]
@
relation
(
"ScheduleChangeContractor"
)
reviewedScheduleChanges
ScheduleChangeRequest
[]
@
relation
(
"ScheduleChangeReviewer"
)
workSchedule
WorkSchedule
?
//
Relations
—
Meetings
createdMeetings
Meeting
[]
@
relation
(
"MeetingCreator"
)
meetingParticipations
MeetingParticipant
[]
//
Relations
—
Contracts
&
Offboarding
contracts Contract[]
contracts Contract[]
offboardingProcesses
OffboardingProcess
[]
@
relation
(
"OffboardingContractor"
)
meetings MeetingInvitee[]
initiatedOffboardings
OffboardingProcess
[]
@
relation
(
"OffboardingInitiator"
)
createdMeetings Meeting[] @relation("MeetingCreator")
invites Invite[]
//
Relations
—
Admin
refreshTokens RefreshToken[]
apiKeys
ApiKey
[]
payrollLines PayrollLine[]
createdWebhooks
Webhook
[]
createdNotices Notice[]
sessions Session[]
//
Relations
—
Notes
&
Activity
privateNotesAbout
PrivateNote
[]
@
relation
(
"NoteSubject"
)
privateNotesAuthored
PrivateNote
[]
@
relation
(
"NoteAuthor"
)
activityFeedItems
ActivityFeedItem
[]
@
relation
(
"ActivityActor"
)
uploadedFiles
File
[]
//
Relations
—
Templates
createdBoardTemplates
BoardTemplate
[]
createdCardTemplates
CardTemplate
[]
@@
index
([
email
])
@@index([username])
@@index([username])
@@
index
([
role
])
@@index([status])
@@index([status])
@@index([role])
@@index([contractorType])
@@index([deletedAt])
@@index([deletedAt])
@@
index
([
department
])
@@
map
(
"users"
)
}
}
model
Sessio
n
{
model
RefreshToke
n {
id String @id @default(uuid())
id String @id @default(uuid())
token String @unique
userId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
token
String
@
unique
refreshToken
String
@
unique
ipAddress
String
?
userAgent
String
?
expiresAt DateTime
expiresAt DateTime
lastActiveAt
DateTime
@
default
(
now
())
createdAt DateTime @default(now())
createdAt DateTime @default(now())
@@index([userId])
@@index([userId])
@@
index
([
token
])
@@index([expiresAt])
@@index([expiresAt])
@@
map
(
"sessions"
)
}
}
model
PasswordResetToke
n
{
model
Sessio
n {
id String @id @default(uuid())
id String @id @default(uuid())
userId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
token
String
@
unique
ipAddress String?
expiresAt
DateTime
userAgent String?
usedAt
DateTime
?
lastActivity DateTime @default(now())
createdAt DateTime @default(now())
createdAt DateTime @default(now())
@@
index
([
token
])
@@index([userId])
@@index([userId])
@@
map
(
"password_reset_tokens"
)
}
}
//
============================================================
model Setting {
//
SYSTEM
SETTINGS
//
============================================================
model
SystemSetting
{
id String @id @default(uuid())
id String @id @default(uuid())
key String @unique
key String @unique
value Json
value Json
description String?
description String?
category
String
@
default
(
"general"
)
createdAt
DateTime
@
default
(
now
())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
createdAt DateTime @default(now())
@@index([key])
@@index([key])
@@
index
([
category
])
@@
map
(
"system_settings"
)
}
}
//
============================================================
model AuditTrail {
//
AUDIT
TRAIL
(
IMMUTABLE
)
//
============================================================
model
AuditLog
{
id String @id @default(uuid())
id String @id @default(uuid())
userId String?
userId String?
action
AuditAction
action
String
entityType String
entityType String
entityId String?
entityId String?
oldValue
Json
?
method String?
newValue
Json
?
url String?
metadata
Json
?
before Json?
after Json?
ipAddress String?
ipAddress String?
userAgent String?
userAgent String?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
//
NO
updatedAt
.
NO
deletedAt
.
IMMUTABLE
.
@@index([userId])
@@index([userId])
@@
index
([
entityType
,
entityId
])
@@index([entityType])
@@index([action])
@@index([action])
@@index([createdAt])
@@index([createdAt])
@@
map
(
"audit_logs"
)
}
}
//
============================================================
// ============================================
//
ONBOARDING
// BOARDS & KANBAN
//
============================================================
// ============================================
model
Invite
{
id
String
@
id
@
default
(
uuid
())
email
String
role
Role
@
default
(
CONTRACTOR
)
senderId
String
sender
User
@
relation
(
"InviteSender"
,
fields
:
[
senderId
],
references
:
[
id
])
recipientId
String
?
@
unique
recipient
User
?
@
relation
(
"InviteRecipient"
,
fields
:
[
recipientId
],
references
:
[
id
])
token
String
@
unique
status
InviteStatus
@
default
(
PENDING
)
message
String
?
expiresAt
DateTime
acceptedAt
DateTime
?
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
index
([
email
])
@@
index
([
token
])
@@
index
([
status
])
@@
map
(
"invites"
)
}
model
OnboardingChecklist
{
model
Board
{
id String @id @default(uuid())
id String @id @default(uuid())
name String
name String
description String?
description String?
role
Role
@
default
(
CONTRACTOR
)
key String @unique
isActive
Boolean
@
default
(
true
)
visibility String @default("PRIVATE")
items
OnboardingChecklistItem
[]
icon String?
contractors
ContractorOnboarding
[]
color String?
createdAt
DateTime
@
default
(
now
())
allowContractorCreation Boolean @default(true)
updatedAt
DateTime
@
updatedAt
autoArchiveDoneCardsDays Int @default(30)
isArchived Boolean @default(false)
nextCardNumber Int @default(1)
deletedAt DateTime?
deletedAt DateTime?
@@
map
(
"onboarding_checklists"
)
}
model
OnboardingChecklistItem
{
id
String
@
id
@
default
(
uuid
())
checklistId
String
checklist
OnboardingChecklist
@
relation
(
fields
:
[
checklistId
],
references
:
[
id
],
onDelete
:
Cascade
)
title
String
description
String
?
order
Int
isRequired
Boolean
@
default
(
true
)
progressItems
ContractorOnboardingItem
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
index
([
checklistId
])
@@
map
(
"onboarding_checklist_items"
)
}
model
ContractorOnboarding
{
id
String
@
id
@
default
(
uuid
())
contractorId
String
@
unique
contractor
User
@
relation
(
fields
:
[
contractorId
],
references
:
[
id
],
onDelete
:
Cascade
)
checklistId
String
checklist
OnboardingChecklist
@
relation
(
fields
:
[
checklistId
],
references
:
[
id
])
completedAt
DateTime
?
items
ContractorOnboardingItem
[]
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contractorId
])
columns BoardColumn[]
@@
map
(
"contractor_onboardings"
)
members BoardMember[]
}
cards Card[]
labels Label[] @relation("BoardLabels")
model
ContractorOnboardingItem
{
savedFilters SavedFilter[]
id
String
@
id
@
default
(
uuid
())
onboardingId
String
onboarding
ContractorOnboarding
@
relation
(
fields
:
[
onboardingId
],
references
:
[
id
],
onDelete
:
Cascade
)
checklistItemId
String
checklistItem
OnboardingChecklistItem
@
relation
(
fields
:
[
checklistItemId
],
references
:
[
id
])
isCompleted
Boolean
@
default
(
false
)
completedAt
DateTime
?
notes
String
?
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
unique
([
onboardingId
,
checklistItemId
])
@@index([key])
@@
map
(
"contractor_onboarding_items"
)
@@index([isArchived])
@@index([deletedAt])
}
}
//
============================================================
model BoardColumn {
//
BOARDS
&
KANBAN
//
============================================================
model
Board
{
id String @id @default(uuid())
id String @id @default(uuid())
boardId String
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
name String
name String
description
String
?
type ColumnType
visibility
BoardVisibility
@
default
(
TEAM
)
createdById
String
createdBy
User
@
relation
(
"BoardCreator"
,
fields
:
[
createdById
],
references
:
[
id
])
prefix
String
?
color
String
?
icon String?
icon String?
isArchived
Boolean
@
default
(
false
)
position Int
archivedAt
DateTime
?
wipLimit Int?
columns
Column
[]
members
BoardMember
[]
labels
Label
[]
cards
Card
[]
savedFilters
SavedFilter
[]
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
index
([
createdById
])
cards Card[]
@@
index
([
visibility
])
@@
index
([
deletedAt
])
@@index([boardId])
@@
index
([
isArchived
])
@@index([type])
@@
map
(
"boards"
)
}
}
model BoardMember {
model BoardMember {
...
@@ -591,116 +409,74 @@ model BoardMember {
...
@@ -591,116 +409,74 @@ model BoardMember {
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
userId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role
BoardMemberRole
@
default
(
MEMBER
)
role
String @default("MEMBER"
)
joinedAt
DateTime
@
default
(
now
())
createdAt DateTime
@default(now())
@@unique([boardId, userId])
@@unique([boardId, userId])
@@index([boardId])
@@index([userId])
@@index([userId])
@@
map
(
"board_members"
)
}
}
model
BoardTemplate
{
model
Label
{
id String @id @default(uuid())
id String @id @default(uuid())
name String
name String
description
String
?
color String
structure
Json
//
{
columns
:
[...],
labels
:
[...]
}
textColor String @default("#FFFFFF")
createdById
String
scope LabelScope @default(ORGANIZATION)
createdBy
User
@
relation
(
fields
:
[
createdById
],
references
:
[
id
])
boardId String?
isPublic
Boolean
@
default
(
fals
e
)
board Board? @relation("BoardLabels", fields: [boardId], references: [id], onDelete: Cascad
e)
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
map
(
"board_templates"
)
}
model
Column
{
cards CardLabel[]
id
String
@
id
@
default
(
uuid
())
boardId
String
board
Board
@
relation
(
fields
:
[
boardId
],
references
:
[
id
],
onDelete
:
Cascade
)
name
String
position
Float
color
String
?
wipLimit
Int
?
isDone
Boolean
@
default
(
false
)
cards
Card
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@index([scope])
@@index([boardId])
@@index([boardId])
@@
index
([
boardId
,
position
])
@@
map
(
"columns"
)
}
}
model
Label
{
model
Card
{
id String @id @default(uuid())
id String @id @default(uuid())
boardId String
boardId String
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
name
String
columnId String
color
String
column BoardColumn @relation(fields: [columnId], references: [id], onDelete: Cascade)
cards
CardLabel
[]
cardNumber String
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
index
([
boardId
])
@@
map
(
"labels"
)
}
//
============================================================
//
CARDS
//
============================================================
model
Card
{
id
String
@
id
@
default
(
uuid
())
title String
title String
description String?
description String?
boardId
String
board
Board
@
relation
(
fields
:
[
boardId
],
references
:
[
id
],
onDelete
:
Cascade
)
columnId
String
column
Column
@
relation
(
fields
:
[
columnId
],
references
:
[
id
])
position
Float
priority CardPriority @default(NONE)
priority CardPriority @default(NONE)
position Float @default(0)
dueDate DateTime?
dueDate DateTime?
startDate
DateTime
?
estimatedHours Float?
estimatedHours Float?
actualHours
Float
?
bountyPiasters Int @default(0)
bountyPiasters Int @default(0)
coverImage
String
?
bountyPaidOut Boolean @default(false)
isLocked
Boolean
@
default
(
false
)
frozenReason String?
lockedById
String
?
version Int @default(1)
lockedBy
User
?
@
relation
(
"CardLocker"
,
fields
:
[
lockedById
],
references
:
[
id
])
isArchived Boolean @default(false)
lockedAt
DateTime
?
completedAt DateTime?
parentCardId
String
?
firstDoingAt DateTime?
parentCard
Card
?
@
relation
(
"CardSubtasks"
,
fields
:
[
parentCardId
],
references
:
[
id
])
totalFrozenMs Int @default(0)
subtasks
Card
[]
@
relation
(
"CardSubtasks"
)
createdById String
createdById String
createdBy User @relation("CardCreator", fields: [createdById], references: [id])
createdBy User @relation("CardCreator", fields: [createdById], references: [id])
completedAt
DateTime
?
deletedAt DateTime?
archivedAt
DateTime
?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
//
Relations
assignees CardAssignee[]
assignees CardAssignee[]
watchers CardWatcher[]
watchers CardWatcher[]
labels CardLabel[]
labels CardLabel[]
comments
CardComment
[]
comments Comment[]
attachments Attachment[]
checklists Checklist[]
checklists Checklist[]
attachments
CardAttachment
[]
bountyPayouts BountyPayout[]
activities
CardActivity
[]
deductions Deduction[]
bounties
Bounty
[]
reportEntries
DailyReportEntry
[]
@@index([boardId])
@@index([boardId])
@@index([columnId])
@@index([columnId])
@@
index
([
c
reatedById
])
@@index([c
ardNumber
])
@@
index
([
priority
])
@@index([
isArchived
])
@@index([dueDate])
@@index([dueDate])
@@index([deletedAt])
@@index([deletedAt])
@@
index
([
boardId
,
columnId
,
position
])
@@index([createdById])
@@
index
([
parentCardId
])
@@
map
(
"cards"
)
}
}
model CardAssignee {
model CardAssignee {
...
@@ -709,11 +485,11 @@ model CardAssignee {
...
@@ -709,11 +485,11 @@ model CardAssignee {
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
userId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
assign
edAt
DateTime
@
default
(
now
())
creat
edAt DateTime @default(now())
@@unique([cardId, userId])
@@unique([cardId, userId])
@@index([cardId])
@@index([userId])
@@index([userId])
@@
map
(
"card_assignees"
)
}
}
model CardWatcher {
model CardWatcher {
...
@@ -722,11 +498,11 @@ model CardWatcher {
...
@@ -722,11 +498,11 @@ model CardWatcher {
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
userId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
addedAt
DateTime
@
default
(
now
())
createdAt
DateTime @default(now())
@@unique([cardId, userId])
@@unique([cardId, userId])
@@index([cardId])
@@index([userId])
@@index([userId])
@@
map
(
"card_watchers"
)
}
}
model CardLabel {
model CardLabel {
...
@@ -737,843 +513,489 @@ model CardLabel {
...
@@ -737,843 +513,489 @@ model CardLabel {
label Label @relation(fields: [labelId], references: [id], onDelete: Cascade)
label Label @relation(fields: [labelId], references: [id], onDelete: Cascade)
@@unique([cardId, labelId])
@@unique([cardId, labelId])
@@
map
(
"card_labels"
)
@@index([cardId])
@@index([labelId])
}
}
model
CardComment
{
// ============================================
// COMMENTS, CHECKLISTS, ATTACHMENTS
// ============================================
model Comment {
id String @id @default(uuid())
id String @id @default(uuid())
cardId String
cardId String
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
authorId String
authorId String
author User @relation(fields: [authorId], references: [id])
author User @relation(fields: [authorId], references: [id])
content String
content String
isEdited
Boolean
@
default
(
false
)
editedAt DateTime?
parentId
String
?
editableUntil DateTime?
parent
CardComment
?
@
relation
(
"CommentReplies"
,
fields
:
[
parentId
],
references
:
[
id
])
deletedAt DateTime?
replies
CardComment
[]
@
relation
(
"CommentReplies"
)
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@index([cardId])
@@index([cardId])
@@index([authorId])
@@index([authorId])
@@
index
([
parentId
])
@@
map
(
"card_comments"
)
}
}
model Checklist {
model Checklist {
id String @id @default(uuid())
id String @id @default(uuid())
cardId String
cardId String
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
card Card @relation(fields: [cardId], references: [id], onDelete: Cascade)
title
String
name String
position
Float
position Int @default(0)
items
ChecklistItem
[]
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
items ChecklistItem[]
@@index([cardId])
@@index([cardId])
@@
map
(
"checklists"
)
}
}
model ChecklistItem {
model ChecklistItem {
id String @id @default(uuid())
id String @id @default(uuid())
checklistId String
checklistId String
checklist Checklist @relation(fields: [checklistId], references: [id], onDelete: Cascade)
checklist Checklist @relation(fields: [checklistId], references: [id], onDelete: Cascade)
title
String
text String
isCompleted
Boolean
@
default
(
false
)
isChecked Boolean @default(false)
completedAt
DateTime
?
position Int @default(0)
assigneeId
String
?
checkedAt DateTime?
position
Float
dueDate
DateTime
?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@index([checklistId])
@@index([checklistId])
@@
map
(
"checklist_items"
)
}
}
model
Card
Attachment
{
model Attachment {
id String @id @default(uuid())
id String @id @default(uuid())
cardId
String
cardId String?
card
Card
@
relation
(
fields
:
[
cardId
],
references
:
[
id
],
onDelete
:
Cascade
)
card Card? @relation(fields: [cardId], references: [id], onDelete: Cascade)
fileId
String
uploadedById String
file
File
@
relation
(
fields
:
[
fileId
],
references
:
[
id
])
uploadedBy User @relation(fields: [uploadedById], references: [id])
createdAt
DateTime
@
default
(
now
())
fileName String
fileSize Int
@@
index
([
cardId
])
mimeType String
@@
map
(
"card_attachments"
)
storagePath String
}
entityType String @default("card")
entityId String?
model
CardActivity
{
id
String
@
id
@
default
(
uuid
())
cardId
String
card
Card
@
relation
(
fields
:
[
cardId
],
references
:
[
id
],
onDelete
:
Cascade
)
actorId
String
actor
User
@
relation
(
"CardActivityActor"
,
fields
:
[
actorId
],
references
:
[
id
])
action
String
//
"moved"
,
"assigned"
,
"commented"
,
"priority_changed"
,
etc
.
details
Json
?
//
{
from
:
"To Do"
,
to
:
"In Progress"
}
createdAt DateTime @default(now())
createdAt DateTime @default(now())
@@index([cardId])
@@index([cardId])
@@
index
([
cardId
,
createdAt
])
@@index([entityType, entityId])
@@
map
(
"card_activities"
)
}
model
CardTemplate
{
id
String
@
id
@
default
(
uuid
())
name
String
description
String
?
boardId
String
?
defaultColumn
String
?
priority
CardPriority
@
default
(
NONE
)
bountyPiasters
Int
@
default
(
0
)
templateData
Json
//
{
checklists
:
[...],
labels
:
[...],
description
:
"..."
}
createdById
String
createdBy
User
@
relation
(
fields
:
[
createdById
],
references
:
[
id
])
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
recurringCards
RecurringCard
[]
@@
map
(
"card_templates"
)
}
}
model
RecurringCard
{
// ============================================
id
String
@
id
@
default
(
uuid
())
// FINANCIAL
templateId
String
// ============================================
template
CardTemplate
@
relation
(
fields
:
[
templateId
],
references
:
[
id
])
boardId
String
columnId
String
pattern
RecurrencePattern
cronExpression
String
?
customDays
Json
?
//
[
1
,
3
,
5
]
for
Mon
/
Wed
/
Fri
nextRunAt
DateTime
lastRunAt
DateTime
?
isActive
Boolean
@
default
(
true
)
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
index
([
isActive
,
nextRunAt
])
model Deduction {
@@
map
(
"recurring_cards"
)
}
model
SavedFilter
{
id String @id @default(uuid())
id String @id @default(uuid())
boardId
String
board
Board
@
relation
(
fields
:
[
boardId
],
references
:
[
id
],
onDelete
:
Cascade
)
userId String
userId String
name
String
user User @relation("DeductionTarget", fields: [userId], references: [id])
filters
Json
//
{
priority
:
[...],
assignees
:
[...],
labels
:
[...],
dueDate
:
...
}
initiatedById String?
isDefault
Boolean
@
default
(
false
)
initiatedBy User? @relation("DeductionInitiator", fields: [initiatedById], references: [id])
createdAt
DateTime
@
default
(
now
())
reviewedById String?
updatedAt
DateTime
@
updatedAt
reviewedBy User? @relation("DeductionReviewer", fields: [reviewedById], references: [id])
cardId String?
@@
index
([
boardId
,
userId
])
card Card? @relation(fields: [cardId], references: [id], onDelete: SetNull)
@@
map
(
"saved_filters"
)
category DeductionCategory
}
subCategory String
status DeductionStatus @default(DRAFT)
//
============================================================
amountPiasters Int
//
FINANCIAL
—
SALARY
appliedAmountPiasters Int?
//
============================================================
description String
evidence Json?
model
ContractorSalary
{
violationDate DateTime?
id
String
@
id
@
default
(
uuid
())
acknowledgedAt DateTime?
contractorId
String
contractorResponse String?
contractor
User
@
relation
(
"SalaryContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
respondedAt DateTime?
baseSalaryPiasters
Int
reviewNotes String?
contractorType
ContractorType
reviewedAt DateTime?
effectiveDate
DateTime
payrollMonth Int?
endDate
DateTime
?
payrollYear Int?
workDaysPerWeek
Int
@
default
(
5
)
hoursPerDay
Float
@
default
(
8
)
isActive
Boolean
@
default
(
true
)
notes
String
?
createdById
String
createdBy
User
@
relation
(
"SalaryCreator"
,
fields
:
[
createdById
],
references
:
[
id
])
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contractorId
])
@@index([userId])
@@
index
([
contractorId
,
isActive
])
@@index([status])
@@
index
([
effectiveDate
])
@@index([category])
@@
map
(
"contractor_salaries"
)
@@index([payrollMonth, payrollYear])
@@index([createdAt])
}
}
//
============================================================
model BountyPayout {
//
FINANCIAL
—
BOUNTIES
//
============================================================
model
Bounty
{
id String @id @default(uuid())
id String @id @default(uuid())
cardId String
cardId String
card Card @relation(fields: [cardId], references: [id])
card Card @relation(fields: [cardId], references: [id])
contractorId
String
userId
String
contractor
User
@
relation
(
"BountyContractor"
,
fields
:
[
contracto
rId
],
references
:
[
id
])
user User @relation(fields: [use
rId], references: [id])
amountPiasters Int
amountPiasters Int
status
BountyStatus
@
default
(
PENDING
)
splitPercentage Float @default(100)
earnedAt
DateTime
?
payrollMonth Int
payrollItemId
String
?
payrollYear Int
payrollItem
PayrollItem
?
@
relation
(
fields
:
[
payrollItemId
],
references
:
[
id
])
paidAt DateTime @default(now())
createdById
String
createdBy
User
@
relation
(
"BountyCreator"
,
fields
:
[
createdById
],
references
:
[
id
])
month
Int
year
Int
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt
DateTime
@
updatedAt
@@
index
([
contractorId
])
@@index([userId])
@@
index
([
contractorId
,
month
,
year
])
@@index([cardId])
@@index([cardId])
@@
index
([
status
])
@@index([payrollMonth, payrollYear])
@@
map
(
"bounties"
)
}
//
============================================================
//
FINANCIAL
—
DEDUCTIONS
//
============================================================
model
DeductionPreset
{
id
String
@
id
@
default
(
uuid
())
name
String
description
String
?
amountPiasters
Int
type
DeductionType
isActive
Boolean
@
default
(
true
)
deductions
Deduction
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
@@
map
(
"deduction_presets"
)
}
model
Deduction
{
id
String
@
id
@
default
(
uuid
())
contractorId
String
contractor
User
@
relation
(
"DeductionContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
amountPiasters
Int
type
DeductionType
reason
String
presetId
String
?
preset
DeductionPreset
?
@
relation
(
fields
:
[
presetId
],
references
:
[
id
])
triggerCardId
String
?
triggerReportId
String
?
status
DeductionStatus
@
default
(
PENDING
)
approvedById
String
?
approvedBy
User
?
@
relation
(
"DeductionApprover"
,
fields
:
[
approvedById
],
references
:
[
id
])
approvedAt
DateTime
?
appealReason
String
?
appealedAt
DateTime
?
reversedById
String
?
reversedBy
User
?
@
relation
(
"DeductionReverser"
,
fields
:
[
reversedById
],
references
:
[
id
])
reversedAt
DateTime
?
reversalReason
String
?
month
Int
year
Int
payrollItemId
String
?
payrollItem
PayrollItem
?
@
relation
(
fields
:
[
payrollItemId
],
references
:
[
id
])
createdById
String
createdBy
User
@
relation
(
"DeductionCreator"
,
fields
:
[
createdById
],
references
:
[
id
])
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
@@
index
([
contractorId
])
@@
index
([
contractorId
,
month
,
year
])
@@
index
([
status
])
@@
index
([
type
])
@@
index
([
deletedAt
])
@@
map
(
"deductions"
)
}
}
//
============================================================
model Adjustment {
//
FINANCIAL
—
SALARY
ADJUSTMENTS
//
============================================================
model
SalaryAdjustment
{
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
userId String
contractor
User
@
relation
(
"AdjustmentContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
user User @relation("AdjustmentTarget", fields: [userId], references: [id])
amountPiasters
Int
type
AdjustmentType
reason
String
status
AdjustmentStatus
@
default
(
PENDING
)
approvedById
String
?
approvedBy
User
?
@
relation
(
"AdjustmentApprover"
,
fields
:
[
approvedById
],
references
:
[
id
])
approvedAt
DateTime
?
month
Int
year
Int
payrollItemId
String
?
payrollItem
PayrollItem
?
@
relation
(
fields
:
[
payrollItemId
],
references
:
[
id
])
createdById String
createdById String
createdBy User @relation("AdjustmentCreator", fields: [createdById], references: [id])
createdBy User @relation("AdjustmentCreator", fields: [createdById], references: [id])
reviewedById String?
reviewedBy User? @relation("AdjustmentReviewer", fields: [reviewedById], references: [id])
type AdjustmentType
category AdjustmentCategory
amountPiasters Int
description String
status AdjustmentStatus @default(PENDING_APPROVAL)
effectiveMonth Int
effectiveYear Int
reviewNotes String?
reviewedAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
index
([
contractorId
])
@@index([userId])
@@
index
([
contractorId
,
month
,
year
])
@@index([status])
@@index([status])
@@
map
(
"salary_adjustments"
)
@@
index([effectiveMonth, effectiveYear]
)
}
}
//
============================================================
model Payroll {
//
FINANCIAL
—
PAYROLL
//
============================================================
model
PayrollPeriod
{
id String @id @default(uuid())
id String @id @default(uuid())
month Int
month Int
year Int
year Int
status
PayrollStatus
@
default
(
DRAFT
)
status
PayrollStatus @default(PENDING_CALCULATION
)
totalGrossPiasters Int @default(0)
totalGrossPiasters Int @default(0)
totalDeductionsPiasters
Int
@
default
(
0
)
totalBountiesPiasters
Int
@
default
(
0
)
totalAdjustmentsPiasters
Int
@
default
(
0
)
totalNetPiasters Int @default(0)
totalNetPiasters Int @default(0)
contractorCount Int @default(0)
contractorCount Int @default(0)
generatedById
String
?
calculatedAt DateTime?
generatedBy
User
?
@
relation
(
"PayrollGenerator"
,
fields
:
[
generatedById
],
references
:
[
id
])
submittedAt DateTime?
approvedById
String
?
approvedBy
User
?
@
relation
(
"PayrollApprover"
,
fields
:
[
approvedById
],
references
:
[
id
])
approvedAt DateTime?
approvedAt DateTime?
paidAt DateTime?
paidAt DateTime?
notes String?
notes String?
items
PayrollItem
[]
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
lines PayrollLine[]
@@unique([month, year])
@@unique([month, year])
@@index([status])
@@index([status])
@@
map
(
"payroll_periods"
)
}
}
model
Payroll
Item
{
model Payroll
Line
{
id String @id @default(uuid())
id String @id @default(uuid())
payroll
PeriodId
String
payroll
Id
String
payroll
Period
PayrollPeriod
@
relation
(
fields
:
[
payrollPeriod
Id
],
references
:
[
id
],
onDelete
:
Cascade
)
payroll
Payroll @relation(fields: [payroll
Id], references: [id], onDelete: Cascade)
contractorId
String
userId
String
contractor
User
@
relation
(
fields
:
[
contracto
rId
],
references
:
[
id
])
user User @relation(fields: [use
rId], references: [id])
baseSalaryPiasters
Int
actualSalaryPiasters
Int
totalBountiesPiasters Int @default(0)
totalBountiesPiasters Int @default(0)
totalAdjustmentsPiasters
Int
@
default
(
0
)
totalDeductionsPiasters Int @default(0)
totalDeductionsPiasters Int @default(0)
netSalaryPiasters
Int
totalAdjustmentsPiasters Int @default(0)
breakdown
Json
?
//
detailed
breakdown
netPayablePiasters Int @default(0)
bounties
Bounty
[]
breakdown Json?
deductions
Deduction
[]
adjustments
SalaryAdjustment
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
unique
([
payrollPeriodId
,
contractorId
])
@@
index
([
contractorId
])
@@
map
(
"payroll_items"
)
}
//
============================================================
//
COMMUNICATION
—
CONVERSATIONS
&
MESSAGES
//
============================================================
model
Conversation
{
id
String
@
id
@
default
(
uuid
())
type
ConversationType
name
String
?
avatar
String
?
lastMessageAt
DateTime
?
participants
ConversationParticipant
[]
messages
Message
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
index
([
type
])
@@
index
([
lastMessageAt
])
@@
map
(
"conversations"
)
}
model
ConversationParticipant
{
id
String
@
id
@
default
(
uuid
())
conversationId
String
conversation
Conversation
@
relation
(
fields
:
[
conversationId
],
references
:
[
id
],
onDelete
:
Cascade
)
userId
String
user
User
@
relation
(
fields
:
[
userId
],
references
:
[
id
],
onDelete
:
Cascade
)
isAdmin
Boolean
@
default
(
false
)
isMuted
Boolean
@
default
(
false
)
lastReadAt
DateTime
?
joinedAt
DateTime
@
default
(
now
())
leftAt
DateTime
?
@@
unique
([
conversationId
,
userId
])
@@
index
([
userId
])
@@
map
(
"conversation_participants"
)
}
model
Message
{
id
String
@
id
@
default
(
uuid
())
conversationId
String
conversation
Conversation
@
relation
(
fields
:
[
conversationId
],
references
:
[
id
],
onDelete
:
Cascade
)
senderId
String
sender
User
@
relation
(
fields
:
[
senderId
],
references
:
[
id
])
type
MessageType
@
default
(
TEXT
)
content
String
?
fileId
String
?
file
File
?
@
relation
(
fields
:
[
fileId
],
references
:
[
id
])
replyToId
String
?
replyTo
Message
?
@
relation
(
"MessageReplies"
,
fields
:
[
replyToId
],
references
:
[
id
])
replies
Message
[]
@
relation
(
"MessageReplies"
)
isEdited
Boolean
@
default
(
false
)
isPinned
Boolean
@
default
(
false
)
readBy
MessageRead
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
@@
index
([
conversationId
])
@@
index
([
conversationId
,
createdAt
])
@@
index
([
senderId
])
@@
map
(
"messages"
)
}
model
MessageRead
{
id
String
@
id
@
default
(
uuid
())
messageId
String
message
Message
@
relation
(
fields
:
[
messageId
],
references
:
[
id
],
onDelete
:
Cascade
)
userId
String
readAt
DateTime
@
default
(
now
())
@@
unique
([
messageId
,
userId
])
@@
map
(
"message_reads"
)
}
//
============================================================
//
COMMUNICATION
—
NOTICES
&
POLICIES
//
============================================================
model
Notice
{
id
String
@
id
@
default
(
uuid
())
title
String
content
String
priority
NotificationType
@
default
(
IMPORTANT
)
isPinned
Boolean
@
default
(
false
)
targetRoles
Role
[]
publishedAt
DateTime
?
expiresAt
DateTime
?
createdById
String
createdBy
User
@
relation
(
"NoticeCreator"
,
fields
:
[
createdById
],
references
:
[
id
])
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
@@
index
([
publishedAt
])
@@
index
([
deletedAt
])
@@
map
(
"notices"
)
}
model
Policy
{
id
String
@
id
@
default
(
uuid
())
title
String
content
String
version
Int
@
default
(
1
)
requiresAck
Boolean
@
default
(
true
)
targetRoles
Role
[]
effectiveDate
DateTime
createdById
String
createdBy
User
@
relation
(
"PolicyCreator"
,
fields
:
[
createdById
],
references
:
[
id
])
acknowledgments
PolicyAcknowledgment
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
@@
index
([
effectiveDate
])
@@
index
([
deletedAt
])
@@
map
(
"policies"
)
}
model
PolicyAcknowledgment
{
id
String
@
id
@
default
(
uuid
())
policyId
String
policy
Policy
@
relation
(
fields
:
[
policyId
],
references
:
[
id
],
onDelete
:
Cascade
)
userId
String
user
User
@
relation
(
fields
:
[
userId
],
references
:
[
id
],
onDelete
:
Cascade
)
acknowledgedAt
DateTime
@
default
(
now
())
@@
unique
([
policyId
,
userId
])
@@
map
(
"policy_acknowledgments"
)
}
//
============================================================
//
NOTIFICATIONS
//
============================================================
model
Notification
{
id
String
@
id
@
default
(
uuid
())
userId
String
user
User
@
relation
(
fields
:
[
userId
],
references
:
[
id
],
onDelete
:
Cascade
)
type
NotificationType
@
default
(
PASSIVE
)
category
NotificationCategory
title
String
message
String
actionUrl
String
?
metadata
Json
?
isRead
Boolean
@
default
(
false
)
readAt
DateTime
?
acknowledgedAt
DateTime
?
expiresAt
DateTime
?
createdAt
DateTime
@
default
(
now
())
@@
index
([
userId
])
@@
index
([
userId
,
isRead
])
@@
index
([
userId
,
category
])
@@
index
([
createdAt
])
@@
map
(
"notifications"
)
}
model
NotificationPreference
{
id
String
@
id
@
default
(
uuid
())
userId
String
user
User
@
relation
(
fields
:
[
userId
],
references
:
[
id
],
onDelete
:
Cascade
)
category
NotificationCategory
inApp
Boolean
@
default
(
true
)
sound
Boolean
@
default
(
true
)
enabled
Boolean
@
default
(
true
)
@@
unique
([
userId
,
category
])
@@
map
(
"notification_preferences"
)
}
//
============================================================
//
DAILY
REPORTS
//
============================================================
model
DailyReport
{
id
String
@
id
@
default
(
uuid
())
contractorId
String
contractor
User
@
relation
(
"ReportContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
date
DateTime
@
db
.
Date
status
ReportStatus
@
default
(
DRAFT
)
summary
String
?
submittedAt
DateTime
?
reviewedById
String
?
reviewedBy
User
?
@
relation
(
"ReportReviewer"
,
fields
:
[
reviewedById
],
references
:
[
id
])
reviewedAt
DateTime
?
reviewNotes
String
?
isLate
Boolean
@
default
(
false
)
entries
DailyReportEntry
[]
amendments
ReportAmendment
[]
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
unique
([
contractorId
,
date
])
@@
index
([
contractorId
])
@@
index
([
contractorId
,
date
])
@@
index
([
status
])
@@
index
([
date
])
@@
map
(
"daily_reports"
)
}
model
DailyReportEntry
{
id
String
@
id
@
default
(
uuid
())
reportId
String
report
DailyReport
@
relation
(
fields
:
[
reportId
],
references
:
[
id
],
onDelete
:
Cascade
)
description
String
hoursSpent
Float
cardId
String
?
card
Card
?
@
relation
(
fields
:
[
cardId
],
references
:
[
id
])
createdAt
DateTime
@
default
(
now
())
updatedAt
DateTime
@
updatedAt
@@
index
([
reportId
])
@@
index
([
cardId
])
@@
map
(
"daily_report_entries"
)
}
model
ReportAmendment
{
id
String
@
id
@
default
(
uuid
())
reportId
String
report
DailyReport
@
relation
(
fields
:
[
reportId
],
references
:
[
id
],
onDelete
:
Cascade
)
content
String
requestedAt
DateTime
@
default
(
now
())
resolvedAt
DateTime
?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
@@
index
([
report
Id
])
@@index([
payroll
Id])
@@
map
(
"report_amendments"
)
@@
index([userId]
)
}
}
//
============================================
================
// ============================================
//
PERFORMANCE
—
EVALUATION
S
//
REPORT
S
//
============================================
================
// ============================================
model
EvaluationTemplate
{
model
DailyReport
{
id String @id @default(uuid())
id String @id @default(uuid())
name
String
userId String
description
String
?
user User @relation("ReportAuthor", fields: [userId], references: [id])
criteria
EvaluationCriteria
[]
reviewedById String?
evaluations
Evaluation
[]
reviewedBy User? @relation("ReportReviewer", fields: [reviewedById], references: [id])
isActive
Boolean
@
default
(
true
)
reportDate DateTime
createdById
String
status ReportStatus @default(DRAFT)
createdBy
User
@
relation
(
fields
:
[
createdById
],
references
:
[
id
])
taskEntries Json?
blockers String?
additionalNotes String?
mood String?
totalHours Float?
submittedAt DateTime?
reviewedAt DateTime?
reviewNotes String?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
map
(
"evaluation_templates"
)
amendments ReportAmendment[]
@@index([userId])
@@index([reportDate])
@@index([status])
}
}
model
EvaluationCriteria
{
model
ReportAmendment
{
id String @id @default(uuid())
id String @id @default(uuid())
templateId
String
reportId String
template
EvaluationTemplate
@
relation
(
fields
:
[
templateId
],
references
:
[
id
],
onDelete
:
Cascade
)
report DailyReport @relation(fields: [reportId], references: [id], onDelete: Cascade)
name
String
reason String
description
String
?
content Json
weight
Float
//
percentage
(
0
-
100
)
status String @default("PENDING")
maxScore
Int
@
default
(
5
)
reviewNotes String?
order
Int
scores
EvaluationScore
[]
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
templateId
])
@@index([reportId])
@@
map
(
"evaluation_criteria"
)
}
}
// ============================================
// EVALUATIONS & PERFORMANCE
// ============================================
model Evaluation {
model Evaluation {
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
userId String
contractor
User
@
relation
(
"EvaluationContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
user User @relation("EvaluationTarget", fields: [userId], references: [id])
evaluatorId
String
techEvaluatorId String?
evaluator
User
@
relation
(
"EvaluationEvaluator"
,
fields
:
[
evaluatorId
],
references
:
[
id
])
techEvaluator User? @relation("TechEvaluator", fields: [techEvaluatorId], references: [id])
templateId
String
?
profEvaluatorId String?
template
EvaluationTemplate
?
@
relation
(
fields
:
[
templateId
],
references
:
[
id
])
profEvaluator User? @relation("ProfEvaluator", fields: [profEvaluatorId], references: [id])
period
String
//
"2024-Q1"
,
"2024-01"
,
etc
.
month Int
month Int
year Int
year Int
status
EvaluationStatus
@
default
(
DRAFT
)
status EvaluationStatus @default(PENDING_TECHNICAL)
technicalScores Json?
technicalScore Float?
technicalNotes String?
professionalScores Json?
professionalScore Float?
professionalNotes String?
autoMetrics Json?
overallScore Float?
overallScore Float?
overallComments
String
?
rating
String?
autoMetrics
Json
?
//
snapshot
of
computed
metrics
contractorResponse String?
acknowledgedAt DateTime?
acknowledgedAt DateTime?
scores
EvaluationScore
[]
respondedAt DateTime?
compiledAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contractorId
])
@@unique([userId, month, year])
@@
index
([
evaluatorId
])
@@index([userId])
@@
index
([
contractorId
,
month
,
year
])
@@index([status])
@@index([status])
@@
map
(
"evaluations"
)
@@
index([month, year]
)
}
}
model
EvaluationScore
{
model
Pip
{
id String @id @default(uuid())
id String @id @default(uuid())
evaluationId
String
userId String
evaluation
Evaluation
@
relation
(
fields
:
[
evaluationId
],
references
:
[
id
],
onDelete
:
Cascade
)
user User @relation("PipTarget", fields: [userId], references: [id])
criteriaId
String
createdById String
criteria
EvaluationCriteria
@
relation
(
fields
:
[
criteriaId
],
references
:
[
id
])
createdBy User @relation("PipCreator", fields: [createdById], references: [id])
score
Float
status PipStatus @default(ACTIVE)
comments
String
?
durationDays Int
startDate DateTime @default(now())
endDate DateTime
specificIssues String
improvementTargets String
successCriteria String
consequenceOfFailure String @default("Termination of engagement.")
checkInSchedule String @default("WEEKLY")
checkIns Json?
resultNotes String?
acknowledgedAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
unique
([
evaluationId
,
criteria
Id
])
@@
index([user
Id])
@@
map
(
"evaluation_scores"
)
@@
index([status]
)
}
}
//
============================================================
model LearningGoal {
//
PERFORMANCE
—
PIPs
//
============================================================
model
PIP
{
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
userId String
contractor
User
@
relation
(
"PIPContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
user User @relation("GoalTarget", fields: [userId], references: [id])
managerId
String
createdById String
manager
User
@
relation
(
"PIPManager"
,
fields
:
[
managerId
],
references
:
[
id
])
createdBy User @relation("GoalCreator", fields: [createdById], references: [id])
reason
String
title String
status
PIPStatus
@
default
(
ACTIVE
)
description String
startDate
DateTime
competencyAreaId String?
endDate
DateTime
competencyArea CompetencyArea? @relation(fields: [competencyAreaId], references: [id])
extendedDate
DateTime
?
deadline DateTime
goals
PIPGoal
[]
status LearningGoalStatus @default(ACTIVE)
checkIns
PIPCheckIn
[]
assessmentMethod String?
outcome
String
?
passCriteria String?
completedAt
DateTime
?
assessmentNotes String?
assessedAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contracto
rId
])
@@index([
use
rId])
@@index([status])
@@index([status])
@@
index
([
managerId
])
@@
map
(
"pips"
)
}
}
model
PIPGoal
{
model
CompetencyArea
{
id String @id @default(uuid())
id String @id @default(uuid())
pipId
String
name String
pip
PIP
@
relation
(
fields
:
[
pipId
],
references
:
[
id
],
onDelete
:
Cascade
)
title
String
description String?
description String?
targetDate
DateTime
?
position Int @default(0)
isCompleted
Boolean
@
default
(
false
)
completedAt
DateTime
?
order
Int
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
pipId
])
learningGoals LearningGoal[]
@@
map
(
"pip_goals"
)
}
}
model
PIPCheckIn
{
// ============================================
// COMMUNICATION
// ============================================
model Notification {
id String @id @default(uuid())
id String @id @default(uuid())
pipId
String
userId String
pip
PIP
@
relation
(
fields
:
[
pipId
],
references
:
[
id
],
onDelete
:
Cascade
)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
meetingId
String
?
@
unique
type NotificationType @default(INFORMATIONAL)
meeting
Meeting
?
@
relation
(
fields
:
[
meetingId
],
references
:
[
id
])
title String
notes
String
?
message String?
progress
String
?
link String?
date
DateTime
isRead Boolean @default(false)
isAcknowledged Boolean @default(false)
acknowledgedAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt
DateTime
@
updatedAt
@@
index
([
pipId
])
@@index([userId])
@@
map
(
"pip_check_ins"
)
@@index([type])
@@index([isRead])
@@index([createdAt])
}
}
//
============================================================
model Conversation {
//
PERFORMANCE
—
LEARNING
GOALS
&
COMPETENCIES
//
============================================================
model
LearningGoal
{
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
name String?
contractor
User
@
relation
(
fields
:
[
contractorId
],
references
:
[
id
])
type ConversationType @default(DIRECT)
title
String
lastMessageAt DateTime?
description
String
?
status
LearningGoalStatus
@
default
(
NOT_STARTED
)
targetDate
DateTime
?
completedAt
DateTime
?
progress
Int
@
default
(
0
)
//
0
-
100
resources
Json
?
//
[{
title
,
url
,
type
}]
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contractorId
])
participants ConversationParticipant[]
@@
index
([
status
])
messages Message[]
@@
map
(
"learning_goals"
)
@@index([lastMessageAt])
}
}
model
Co
mpetency
{
model Co
nversationParticipant
{
id String @id @default(uuid())
id String @id @default(uuid())
name
String
conversationId
String
description
String
?
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
category
String
?
userId String
levels
Json
//
[{
level
:
1
,
description
:
"..."
},
...]
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
assessments
CompetencyAssessment
[]
lastReadAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt
DateTime
@
updatedAt
deletedAt
DateTime
?
@@
map
(
"competencies"
)
@@unique([conversationId, userId])
@@index([conversationId])
@@index([userId])
}
}
model
CompetencyAssessment
{
model
Message
{
id String @id @default(uuid())
id String @id @default(uuid())
competencyId
String
conversationId String
competency
Competency
@
relation
(
fields
:
[
competencyId
],
references
:
[
id
])
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
contractorId
String
senderId String
contractor
User
@
relation
(
"AssessmentContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
sender User @relation(fields: [senderId], references: [id])
assessorId
String
content String
assessor
User
@
relation
(
"AssessmentAssessor"
,
fields
:
[
assessorId
],
references
:
[
id
])
attachments Json?
level
Int
deletedAt DateTime?
notes
String
?
assessedAt
DateTime
@
default
(
now
())
createdAt DateTime @default(now())
createdAt DateTime @default(now())
@@
index
([
con
tractor
Id
])
@@index([con
versation
Id])
@@
index
([
competencyId
,
contracto
rId
])
@@index([
sende
rId])
@@
map
(
"competency_assessments"
)
@@
index([createdAt]
)
}
}
//
============================================================
model Notice {
//
TIME
&
SCHEDULING
//
============================================================
model
WorkSchedule
{
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
@
unique
title String
cont
ractor
User
@
relation
(
fields
:
[
contractorId
],
references
:
[
id
])
cont
ent String
workDays
Json
//
[
1
,
2
,
3
,
4
,
5
]
=
Mon
-
Fri
type NoticeType @default(GENERAL_ANNOUNCEMENT)
startTime
String
//
"09:00"
isBlocking Boolean @default(false)
endTime
String
//
"17:00"
targetRoles Json?
timezone
String
@
default
(
"Africa/Cairo"
)
createdById String
effectiveDate
DateTime
createdBy User @relation(fields: [createdById], references: [id])
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
map
(
"work_schedules"
)
acknowledgments NoticeAcknowledgment[]
@@index([type])
@@index([createdAt])
}
}
model
UnavailabilityReques
t
{
model
NoticeAcknowledgmen
t {
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
noticeId String
contractor
User
@
relation
(
"UnavailabilityContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
notice Notice @relation(fields: [noticeId], references: [id], onDelete: Cascade)
type
UnavailabilityType
userId String
startDate
DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
endDate
DateTime
reason
String
?
status
RequestStatus
@
default
(
PENDING
)
reviewedById
String
?
reviewedBy
User
?
@
relation
(
"UnavailabilityReviewer"
,
fields
:
[
reviewedById
],
references
:
[
id
])
reviewedAt
DateTime
?
reviewNotes
String
?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt
DateTime
@
updatedAt
@@
index
([
contractorId
])
@@unique([noticeId, userId])
@@
index
([
status
])
@@index([noticeId])
@@
index
([
startDate
,
endDate
])
@@index([userId])
@@
map
(
"unavailability_requests"
)
}
}
// ============================================
// SCHEDULING & TIME
// ============================================
model Holiday {
model Holiday {
id String @id @default(uuid())
id String @id @default(uuid())
name String
name String
date
DateTime
@
db
.
Date
startDate DateTime
endDate DateTime
isRecurring Boolean @default(false)
isRecurring Boolean @default(false)
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([startDate])
}
model Unavailability {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
startDate DateTime
endDate DateTime
reason UnavailabilityReason @default(PERSONAL)
notes String?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
unique
([
date
])
@@
index([userId
])
@@
map
(
"holidays"
)
@@
index([startDate]
)
}
}
model ScheduleChangeRequest {
model ScheduleChangeRequest {
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
userId String
contractor
User
@
relation
(
"ScheduleChangeContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
user User @relation("ScheduleRequester", fields: [userId], references: [id])
currentData
Json
//
snapshot
of
current
schedule
requestedData
Json
//
requested
changes
reason
String
status
RequestStatus
@
default
(
PENDING
)
reviewedById String?
reviewedById String?
reviewedBy
User
?
@
relation
(
"ScheduleChang
eReviewer"
,
fields
:
[
reviewedById
],
references
:
[
id
])
reviewedBy
User? @relation("Schedul
eReviewer", fields: [reviewedById], references: [id])
reviewedAt
DateTime
?
currentSchedule Json
reviewNotes
String
?
proposedSchedule Json
effectiveDate DateTime
effectiveDate DateTime
reason String
status String @default("PENDING")
reviewNotes String?
reviewedAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contracto
rId
])
@@index([
use
rId])
@@index([status])
@@index([status])
@@
map
(
"schedule_change_requests"
)
}
}
//
============================================================
//
MEETINGS
//
============================================================
model Meeting {
model Meeting {
id String @id @default(uuid())
id String @id @default(uuid())
title String
title String
...
@@ -1581,225 +1003,192 @@ model Meeting {
...
@@ -1581,225 +1003,192 @@ model Meeting {
startTime DateTime
startTime DateTime
endTime DateTime
endTime DateTime
location String?
location String?
meetingUrl
String
?
status MeetingStatus @default(SCHEDULED)
status MeetingStatus @default(SCHEDULED)
recurrence String?
notes Json?
createdById String
createdById String
createdBy User @relation("MeetingCreator", fields: [createdById], references: [id])
createdBy User @relation("MeetingCreator", fields: [createdById], references: [id])
participants
MeetingParticipant
[]
pipCheckIn
PIPCheckIn
?
notes
String
?
agenda
String
?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
invitees MeetingInvitee[]
@@index([startTime])
@@index([startTime])
@@
index
([
createdById
])
@@index([status])
@@index([status])
@@
map
(
"meetings"
)
}
}
model
Meeting
Participant
{
model Meeting
Invitee
{
id String @id @default(uuid())
id String @id @default(uuid())
meetingId String
meetingId String
meeting Meeting @relation(fields: [meetingId], references: [id], onDelete: Cascade)
meeting Meeting @relation(fields: [meetingId], references: [id], onDelete: Cascade)
userId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
status
RequestStatus
@
default
(
PENDING
)
//
PENDING
=
invited
,
APPROVED
=
accepted
,
REJECTED
=
declined
attended Boolean @default(false)
respondedAt
DateTime
?
@@unique([meetingId, userId])
@@unique([meetingId, userId])
@@index([meetingId])
@@index([userId])
@@index([userId])
@@
map
(
"meeting_participants"
)
}
}
//
============================================
================
// ============================================
//
CONTRACTS
&
OFFBOARDING
//
DOCUMENTS
//
============================================
================
// ============================================
model Contract {
model Contract {
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
userId String
contractor
User
@
relation
(
fields
:
[
contractorId
],
references
:
[
id
])
user User @relation(fields: [userId], references: [id])
title
String
contractorType String?
content
String
?
contractText String?
fileId
String
?
scheduleSnapshot Json?
file
File
?
@
relation
(
fields
:
[
fileId
],
references
:
[
id
])
salaryAtSigning Int?
status
ContractStatus
@
default
(
DRAFT
)
startDate
DateTime
endDate
DateTime
?
salaryPiasters
Int
?
contractorType
ContractorType
?
terms
Json
?
signedAt DateTime?
signedAt DateTime?
signatureData Json?
startDate DateTime?
endDate DateTime?
status String @default("ACTIVE")
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
index
([
contracto
rId
])
@@index([
use
rId])
@@index([status])
@@index([status])
@@
map
(
"contracts"
)
}
}
model
OffboardingProcess
{
model Policy {
id String @id @default(uuid())
title String
content String
version Int @default(1)
requiresAcknowledgment Boolean @default(true)
publishedAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
acknowledgments PolicyAcknowledgment[]
@@index([title])
}
model PolicyAcknowledgment {
id String @id @default(uuid())
policyId String
policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@unique([policyId, userId])
@@index([policyId])
@@index([userId])
}
// ============================================
// OFFBOARDING
// ============================================
model Termination {
id String @id @default(uuid())
id String @id @default(uuid())
contractorId
String
userId String
contractor
User
@
relation
(
"OffboardingContractor"
,
fields
:
[
contractorId
],
references
:
[
id
])
type TerminationType
initiatedById
String
reason String
initiatedBy
User
@
relation
(
"OffboardingInitiator"
,
fields
:
[
initiatedById
],
references
:
[
id
])
status
OffboardingStatus
@
default
(
PENDING
)
reason
String
?
effectiveDate DateTime
effectiveDate DateTime
items
OffboardingItem
[]
noticeDate DateTime @default(now())
notes
String
?
finalSettlement Json?
completedAt
DateTime
?
checklistItems Json?
status String @default("INITIATED")
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@
index
([
contracto
rId
])
@@index([
use
rId])
@@index([status])
@@index([status])
@@
map
(
"offboarding_processes"
)
}
}
model
OffboardingItem
{
// ============================================
// ONBOARDING
// ============================================
model Invite {
id String @id @default(uuid())
id String @id @default(uuid())
offboardingId
String
code String @unique
offboarding
OffboardingProcess
@
relation
(
fields
:
[
offboardingId
],
references
:
[
id
],
onDelete
:
Cascade
)
contractorType ContractorType
title
String
status InviteStatus @default(ACTIVE)
description
String
?
welcomeNote String?
isCompleted
Boolean
@
default
(
false
)
expiresAt DateTime
completedAt
DateTime
?
usedAt DateTime?
order
Int
usedById String?
createdById String
createdBy User @relation(fields: [createdById], references: [id])
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt
DateTime
@
updatedAt
@@
index
([
offboardingId
])
@@index([
code
])
@@
map
(
"offboarding_items"
)
@@
index([status]
)
}
}
//
============================================
================
// ============================================
//
API
KEYS
&
WEBHOOK
S
// API
& INTEGRATION
S
//
============================================
================
// ============================================
model ApiKey {
model ApiKey {
id String @id @default(uuid())
id String @id @default(uuid())
userId
String
user
User
@
relation
(
fields
:
[
userId
],
references
:
[
id
])
name String
name String
keyHash String @unique
keyHash String @unique
keyPrefix
String
//
first
8
chars
for
identification
keyPrefix String
permissions
Json
//
[
"cards:read"
,
"cards:write"
,
...]
scope ApiKeyScope @default(READ_ONLY)
expiresAt
DateTime
?
description String?
lastUsedAt
DateTime
?
isActive Boolean @default(true)
isActive Boolean @default(true)
lastUsedAt DateTime?
expiresAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
@@index([keyHash])
@@index([keyHash])
@@
index
([
userId
])
@@index([isActive])
@@
map
(
"api_keys"
)
}
}
model Webhook {
model Webhook {
id String @id @default(uuid())
id String @id @default(uuid())
userId
String
user
User
@
relation
(
fields
:
[
userId
],
references
:
[
id
])
name
String
url String
url String
secret
String
secret
String?
events
String
[]
//
[
"card.created"
,
"card.moved"
,
...]
events
Json
status
WebhookStatus
@
default
(
ACTIVE
)
isActive Boolean @default(true
)
failCount
Int
@
default
(
0
)
lastTriggeredAt DateTime?
deliveries
WebhookDelivery
[]
failureCount Int @default(0)
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
index
([
userId
])
@@index([isActive])
@@
index
([
status
])
@@
map
(
"webhooks"
)
}
}
model
WebhookDelivery
{
model SavedFilter {
id
String
@
id
@
default
(
uuid
())
webhookId
String
webhook
Webhook
@
relation
(
fields
:
[
webhookId
],
references
:
[
id
],
onDelete
:
Cascade
)
event
String
payload
Json
responseCode
Int
?
responseBody
String
?
success
Boolean
attemptCount
Int
@
default
(
1
)
deliveredAt
DateTime
@
default
(
now
())
@@
index
([
webhookId
])
@@
index
([
webhookId
,
deliveredAt
])
@@
map
(
"webhook_deliveries"
)
}
//
============================================================
//
FILES
//
============================================================
model
File
{
id String @id @default(uuid())
id String @id @default(uuid())
originalName
String
boardId String
storagePath
String
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
storageKey
String
@
unique
userId String
mimeType
String
name String
sizeBytes
Int
filters Json
uploadedById
String
uploadedBy
User
@
relation
(
fields
:
[
uploadedById
],
references
:
[
id
])
createdAt DateTime @default(now())
createdAt DateTime @default(now())
//
Reverse
relations
@@index([boardId, userId])
cardAttachments
CardAttachment
[]
messages
Message
[]
contracts
Contract
[]
@@
index
([
uploadedById
])
@@
index
([
storageKey
])
@@
map
(
"files"
)
}
}
//
============================================================
model RecurringCardDefinition {
//
PRIVATE
NOTES
(
Admin
-
only
,
invisible
to
contractor
)
//
============================================================
model
PrivateNote
{
id String @id @default(uuid())
id String @id @default(uuid())
subjectId
String
boardId String
subject
User
@
relation
(
"NoteSubject"
,
fields
:
[
subjectId
],
references
:
[
id
])
title String
authorId
String
description String?
author
User
@
relation
(
"NoteAuthor"
,
fields
:
[
authorId
],
references
:
[
id
])
labels Json?
content
String
priority CardPriority @default(NONE)
assigneeIds Json?
checklists Json?
estimatedHours Float?
recurrenceType RecurrenceType
recurrenceConfig Json?
isActive Boolean @default(true)
nextRunAt DateTime?
lastRunAt DateTime?
createdAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime @updatedAt
deletedAt
DateTime
?
@@
index
([
subjectId
])
@@
index
([
authorId
])
@@
map
(
"private_notes"
)
}
//
============================================================
@@index([boardId])
//
ACTIVITY
FEED
@@index([isActive])
//
============================================================
model
ActivityFeedItem
{
id
String
@
id
@
default
(
uuid
())
actorId
String
actor
User
@
relation
(
"ActivityActor"
,
fields
:
[
actorId
],
references
:
[
id
])
action
String
//
"completed_card"
,
"earned_bounty"
,
"submitted_report"
,
etc
.
entityType
String
entityId
String
metadata
Json
?
//
{
cardTitle
:
"..."
,
boardName
:
"..."
,
amount
:
5000
}
visibility
String
@
default
(
"org"
)
//
"org"
,
"team"
,
"admin"
createdAt
DateTime
@
default
(
now
())
@@
index
([
actorId
])
@@
index
([
entityType
,
entityId
])
@@
index
([
createdAt
])
@@
index
([
visibility
,
createdAt
])
@@
map
(
"activity_feed_items"
)
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment