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
organizerIdtextOrganizer scope
merchantIdtextTenant scope
reporterIdtextWho opened the ticket
reporterTypetext (TActorTypes)USERUSER / AGENT / SYSTEM
categorytextTicketCategory 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
assignedToAgentIdtextCurrent agent
assignedToUserIdtextAgent's user id
assignedAttimestamptz
resolvedAt / resolvedBy / resolutionNotetimestamptz / text / i18nResolution data
closedAt / closedBytimestamptz / textClosure data
sessionIdtextOriginating 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
ticketIdtextParent ticket
authorId (col sender_id)textAuthor
authorType (col sender_type)text (TActorTypes)USER/AGENT/SYSTEM
type (col message_type)text (TTicketMessageTypes)See enum
contenti18n jsonbBody { 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 / actorTypetextWho acted
oldValue / newValuetextStatus/value diff
changesjsonbStructured diff
reasontextOptional 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
ticketIdtextTicket (unique)
policyId (col sla_policy_id)textSlaPolicy
priorityinteger200Snapshot priority
firstResponseDeadlinetimestamptzResponse deadline
resolutionDeadlinetimestamptzResolution deadline
firstResponseAt / resolvedAttimestamptzActuals
firstResponseStatustext (TSlaStatuses)OKOK/WARNING/BREACHED
resolutionStatustext (TSlaStatuses)OKOK/WARNING/BREACHED
timeToFirstResponse / timeToResolutionintegerMinutes
breachedAt / breachMinutes / breachReasontimestamptz / integer / text0Breach tracking
escalationLevelinteger0Current escalation level
warningsSentjsonb[][]Warnings already dispatched
lastCheckedAttimestamptzLast 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 / newPrioritysmallintPriority 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.