Skip to content

Domain Model

All Drizzle schemas live in @nx/core under packages/core/src/models/schemas/helpdesk/ (30 table directories). Helpdesk declares repository classes only. The helpdesk PostgreSQL schema is defined by PostgresSchemas.HELPDESK = 'helpdesk'.

1. Full ERD

2. Entities

One block per primary table. Schema source root: packages/core/src/models/schemas/helpdesk/. Common columns (id, createdAt, updatedAt, deletedAt, metadata) come from generateCommonColumnDefs().

Ticket

PropertyValue
Tablehelpdesk.Ticket
Sourcehelpdesk/ticket/schema.ts
Soft-deleteyes
Owner ID columnmerchantId (+ organizerId)

Fields:

FieldTypeRequiredDefaultDescription
idtextSnowflakePK
organizerIdtext-Organizer scope
merchantIdtext-Tenant scope
reporterIdtext-Who opened the ticket
reporterTypetext (TActorTypes)USERUSER / AGENT / SYSTEM
categorytext-TicketCategory ref (soft ref)
priorityinteger (TTicketPriorities)MEDIUMLOW/MEDIUM/HIGH/URGENT/CRITICAL
statustext (TTicketStatuses)OPENSee enum below
subjecti18n jsonb-{ en, vi }
descriptioni18n jsonb-{ en, vi }
contextjsonb{}Enriched order/product context
assignedToAgentIdtext--Current agent
assignedToUserIdtext--Agent's user id
assignedAttimestamptz---
resolvedAt / resolvedBy / resolutionNotetimestamptz / text / i18n--Resolution data
closedAt / closedBytimestamptz / text--Closure data
sessionIdtext--Originating session
metadatajsonb{}Misc flags (e.g. categorySkills, tagIds)

Status enum (TicketStatuses):

ValueDescription
OPENNew, not yet assigned
ASSIGNEDAssigned to an agent
IN_PROGRESSBeing worked on
WAITING_USERAwaiting reporter reply
WAITING_AGENTAwaiting an agent
WAITING_INTERNALAwaiting another team
PENDINGHolding / uncategorized
ASSIGNMENT_FAILEDAuto-assign found no agent
ESCALATEDEscalated to higher tier
RESOLVEDAgent resolved, awaiting confirm
CLOSEDConfirmed complete
REOPENEDReopened after resolution/closure

Helper sets: ACTIVE_SET = {OPEN, IN_PROGRESS, REOPENED}, RESOLVED_SET = {RESOLVED, CLOSED}.

Indexes: IDX_Ticket_merchant_status_created_at, IDX_Ticket_assigned_to_status, IDX_Ticket_reporter_created_at, IDX_Ticket_category_priority_status, IDX_Ticket_status, IDX_Ticket_priority, IDX_Ticket_created_at.

TicketMessage

PropertyValue
Tablehelpdesk.TicketMessage
Sourcehelpdesk/ticket-message/schema.ts
Soft-deleteyes
FieldTypeRequiredDefaultDescription
ticketIdtext-Parent ticket
authorId (col sender_id)text-Author
authorType (col sender_type)text (TActorTypes)-USER/AGENT/SYSTEM
type (col message_type)text (TTicketMessageTypes)-See enum
contenti18n jsonb-Body { en, vi }
isInternalbooleanfalseHidden from reporter
attachmentIdstext[]{}Attachment refs

Message types (TicketMessageTypes): COMMENT, USER_REPLY, AGENT_REPLY, INTERNAL_NOTE, SYSTEM_MESSAGE, AUTO_REPLY.

TicketEvent (audit / event sourcing)

PropertyValue
Tablehelpdesk.TicketEvent
Sourcehelpdesk/ticket-event/schema.ts
FieldTypeRequiredDescription
ticketIdtextParent
eventTypetext (TTicketEventTypes)See enum
actorId / actorTypetext-Who acted
oldValue / newValuetext-Status/value diff
changesjsonb-Structured diff
reasontext-Optional reason

Event types (TicketEventTypes, dotted-string values, e.g. ticket.created): TICKET_CREATED, TICKET_UPDATED, TICKET_ASSIGNED, TICKET_ASSIGNMENT_FAILED, TICKET_REASSIGNED, TICKET_STATUS_CHANGED, TICKET_PRIORITY_CHANGED, TICKET_RESOLVED, TICKET_CLOSED, TICKET_REOPENED, TICKET_ESCALATED, MESSAGE_CREATED, MESSAGE_UPDATED, SLA_WARNING, SLA_BREACHED, SLA_CRITICAL_BREACH.

SlaPolicy

PropertyValue
Tablehelpdesk.SlaPolicy
Sourcehelpdesk/sla-policy/schema.ts
Soft-deleteyes

Per-priority response/resolution deadlines, warning thresholds, escalation rules, and business-hours flag. Defaults: see SLA & Escalation.

SlaTracker

PropertyValue
Tablehelpdesk.SlaTracker
Sourcehelpdesk/sla-tracker/schema.ts
Cardinality1:1 per ticket (UQ_SlaTracker_ticket_id)
FieldTypeRequiredDefaultDescription
ticketIdtext-Ticket (unique)
policyId (col sla_policy_id)text-SlaPolicy
priorityinteger20Snapshot priority
firstResponseDeadlinetimestamptz-Response deadline
resolutionDeadlinetimestamptz-Resolution deadline
firstResponseAt / resolvedAttimestamptz--Actuals
firstResponseStatustext (TSlaStatuses)OKOK/WARNING/BREACHED
resolutionStatustext (TSlaStatuses)OKOK/WARNING/BREACHED
timeToFirstResponse / timeToResolutioninteger--Minutes
breachedAt / breachMinutes / breachReasontimestamptz / integer / text-0Breach tracking
escalationLevelinteger0Current escalation level
warningsSentjsonb[][]Warnings already dispatched
lastCheckedAttimestamptz--Last monitor pass

SLA status enum (SlaStatuses): OK, WARNING, BREACHED.

SlaEscalation

PropertyValue
Tablehelpdesk.SlaEscalation
Sourcehelpdesk/sla-escalation/schema.ts
FieldTypeRequiredDescription
ticketIdtextTicket
escalationTypetext (TSlaEscalationTypes)SLA_BREACH / MANUAL / CUSTOMER_REQUEST / HIGH_IMPACT / INCIDENT_REPORT
escalationLevelsmallint (TSlaEscalationLevel)1 / 2 / 3
previousPriority / newPrioritysmallint-Priority change
escalatedBy / escalatedByIdtext✓ / -Actor
reasontextWhy
actionsjsonb[]Actions taken
escalatedAt / resolvedAttimestamptz✓ / -Timestamps

Supporting entities

TableSourcePurpose
TicketAssignmenthelpdesk/ticket-assignment/Assignment history per ticket
TicketCategoryhelpdesk/ticket-category/Categories with ticket counts
TicketTag / TicketTagMappinghelpdesk/ticket-tag*/Tags + M:N mapping, usage counts
Agent / AgentGroup / AgentGroupMemberhelpdesk/agent*/Agents, groups, membership
AssignmentRulehelpdesk/assignment-rule/Routing rules → groups/agents
Article / ArticleCategory / ArticleView / ArticleFeedbackhelpdesk/article*/Knowledge base
Survey / SurveyQuestion / SurveyResponsehelpdesk/survey*/CSAT surveys
FeatureRequest / FeatureVotehelpdesk/feature-*/Feature voting
Notification / NotificationTemplate / NotificationPreference / NotificationDeliveryLog / NotificationBatchhelpdesk/notification*/Notification engine
Compensationhelpdesk/compensation/SLA-breach compensation records
JobExecutionLoghelpdesk/job-execution-log/Worker idempotency / audit

3. Cross-entity Invariants

InvariantEnforcement
Exactly one SlaTracker per ticketUQ_SlaTracker_ticket_id unique index
Ticket status transitions follow the state machineUpdateTicketStatusUseCase (XState)
Every status change writes a TicketEventUse-cases write event in same operation
TicketCategory.ticketCount reflects ticketsTicketCreatedListener.incrementTicketCount()
TicketTag.usageCount reflects mappingsTicketCreatedListener.incrementUsageCount()
escalationLevel increases monotonicallySLA monitor + escalation worker

4. Soft-delete Behavior

BehaviorDetail
Read defaultdeletedAt IS NULL (via generateCommonColumnDefs())
Hard-deleteNot the default; soft-delete via deletedAt timestamp
RestoreClear deletedAt

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.