chore: reorganize project structure and ensure default queues

This commit is contained in:
Esdras Renan 2025-10-06 22:59:35 -03:00
parent 854887f499
commit 1cccb852a5
201 changed files with 417 additions and 838 deletions

View file

@ -1,220 +0,0 @@
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
users: defineTable({
tenantId: v.string(),
name: v.string(),
email: v.string(),
role: v.optional(v.string()),
avatarUrl: v.optional(v.string()),
teams: v.optional(v.array(v.string())),
companyId: v.optional(v.id("companies")),
})
.index("by_tenant_email", ["tenantId", "email"])
.index("by_tenant_role", ["tenantId", "role"])
.index("by_tenant", ["tenantId"])
.index("by_tenant_company", ["tenantId", "companyId"]),
companies: defineTable({
tenantId: v.string(),
name: v.string(),
slug: v.string(),
cnpj: v.optional(v.string()),
domain: v.optional(v.string()),
phone: v.optional(v.string()),
description: v.optional(v.string()),
address: v.optional(v.string()),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("by_tenant_slug", ["tenantId", "slug"])
.index("by_tenant", ["tenantId"]),
queues: defineTable({
tenantId: v.string(),
name: v.string(),
slug: v.string(),
teamId: v.optional(v.id("teams")),
})
.index("by_tenant_slug", ["tenantId", "slug"])
.index("by_tenant", ["tenantId"]),
teams: defineTable({
tenantId: v.string(),
name: v.string(),
description: v.optional(v.string()),
}).index("by_tenant_name", ["tenantId", "name"]),
slaPolicies: defineTable({
tenantId: v.string(),
name: v.string(),
description: v.optional(v.string()),
timeToFirstResponse: v.optional(v.number()), // minutes
timeToResolution: v.optional(v.number()), // minutes
}).index("by_tenant_name", ["tenantId", "name"]),
tickets: defineTable({
tenantId: v.string(),
reference: v.number(),
subject: v.string(),
summary: v.optional(v.string()),
description: v.optional(v.string()),
status: v.string(),
priority: v.string(),
channel: v.string(),
queueId: v.optional(v.id("queues")),
categoryId: v.optional(v.id("ticketCategories")),
subcategoryId: v.optional(v.id("ticketSubcategories")),
requesterId: v.id("users"),
assigneeId: v.optional(v.id("users")),
companyId: v.optional(v.id("companies")),
working: v.optional(v.boolean()),
slaPolicyId: v.optional(v.id("slaPolicies")),
dueAt: v.optional(v.number()), // ms since epoch
firstResponseAt: v.optional(v.number()),
resolvedAt: v.optional(v.number()),
closedAt: v.optional(v.number()),
updatedAt: v.number(),
createdAt: v.number(),
tags: v.optional(v.array(v.string())),
customFields: v.optional(
v.array(
v.object({
fieldId: v.id("ticketFields"),
fieldKey: v.string(),
label: v.string(),
type: v.string(),
value: v.any(),
displayValue: v.optional(v.string()),
})
)
),
totalWorkedMs: v.optional(v.number()),
activeSessionId: v.optional(v.id("ticketWorkSessions")),
})
.index("by_tenant_status", ["tenantId", "status"])
.index("by_tenant_queue", ["tenantId", "queueId"])
.index("by_tenant_assignee", ["tenantId", "assigneeId"])
.index("by_tenant_reference", ["tenantId", "reference"])
.index("by_tenant_company", ["tenantId", "companyId"])
.index("by_tenant", ["tenantId"]),
ticketComments: defineTable({
ticketId: v.id("tickets"),
authorId: v.id("users"),
visibility: v.string(), // PUBLIC | INTERNAL
body: v.string(),
attachments: v.optional(
v.array(
v.object({
storageId: v.id("_storage"),
name: v.string(),
size: v.optional(v.number()),
type: v.optional(v.string()),
})
)
),
createdAt: v.number(),
updatedAt: v.number(),
}).index("by_ticket", ["ticketId"]),
ticketEvents: defineTable({
ticketId: v.id("tickets"),
type: v.string(),
payload: v.optional(v.any()),
createdAt: v.number(),
}).index("by_ticket", ["ticketId"]),
commentTemplates: defineTable({
tenantId: v.string(),
title: v.string(),
body: v.string(),
createdBy: v.id("users"),
updatedBy: v.optional(v.id("users")),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("by_tenant", ["tenantId"])
.index("by_tenant_title", ["tenantId", "title"]),
ticketWorkSessions: defineTable({
ticketId: v.id("tickets"),
agentId: v.id("users"),
startedAt: v.number(),
stoppedAt: v.optional(v.number()),
durationMs: v.optional(v.number()),
})
.index("by_ticket", ["ticketId"])
.index("by_ticket_agent", ["ticketId", "agentId"]),
ticketCategories: defineTable({
tenantId: v.string(),
name: v.string(),
slug: v.string(),
description: v.optional(v.string()),
order: v.number(),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("by_tenant_slug", ["tenantId", "slug"])
.index("by_tenant_order", ["tenantId", "order"])
.index("by_tenant", ["tenantId"]),
ticketSubcategories: defineTable({
tenantId: v.string(),
categoryId: v.id("ticketCategories"),
name: v.string(),
slug: v.string(),
order: v.number(),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("by_category_order", ["categoryId", "order"])
.index("by_category_slug", ["categoryId", "slug"])
.index("by_tenant_slug", ["tenantId", "slug"]),
ticketFields: defineTable({
tenantId: v.string(),
key: v.string(),
label: v.string(),
type: v.string(),
description: v.optional(v.string()),
required: v.boolean(),
order: v.number(),
options: v.optional(
v.array(
v.object({
value: v.string(),
label: v.string(),
})
)
),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("by_tenant_key", ["tenantId", "key"])
.index("by_tenant_order", ["tenantId", "order"])
.index("by_tenant", ["tenantId"]),
userInvites: defineTable({
tenantId: v.string(),
inviteId: v.string(),
email: v.string(),
name: v.optional(v.string()),
role: v.string(),
status: v.string(),
token: v.string(),
expiresAt: v.number(),
createdAt: v.number(),
createdById: v.optional(v.string()),
acceptedAt: v.optional(v.number()),
acceptedById: v.optional(v.string()),
revokedAt: v.optional(v.number()),
revokedById: v.optional(v.string()),
revokedReason: v.optional(v.string()),
})
.index("by_tenant", ["tenantId"])
.index("by_token", ["tenantId", "token"])
.index("by_invite", ["tenantId", "inviteId"]),
});