feat: enable assignee selection when creating tickets
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
parent
fe7025d433
commit
be27dcfd15
4 changed files with 182 additions and 16 deletions
|
|
@ -5,6 +5,8 @@ import { Id, type Doc } from "./_generated/dataModel";
|
|||
|
||||
import { requireCustomer, requireStaff, requireUser } from "./rbac";
|
||||
|
||||
const STAFF_ROLES = new Set(["ADMIN", "MANAGER", "AGENT", "COLLABORATOR"]);
|
||||
|
||||
const QUEUE_RENAME_LOOKUP: Record<string, string> = {
|
||||
"Suporte N1": "Chamados",
|
||||
"suporte-n1": "Chamados",
|
||||
|
|
@ -459,6 +461,7 @@ export const create = mutation({
|
|||
channel: v.string(),
|
||||
queueId: v.optional(v.id("queues")),
|
||||
requesterId: v.id("users"),
|
||||
assigneeId: v.optional(v.id("users")),
|
||||
categoryId: v.id("ticketCategories"),
|
||||
subcategoryId: v.id("ticketSubcategories"),
|
||||
customFields: v.optional(
|
||||
|
|
@ -471,11 +474,34 @@ export const create = mutation({
|
|||
),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const { role } = await requireUser(ctx, args.actorId, args.tenantId)
|
||||
const { user: actorUser, role } = await requireUser(ctx, args.actorId, args.tenantId)
|
||||
if (role === "CUSTOMER" && args.requesterId !== args.actorId) {
|
||||
throw new ConvexError("Clientes só podem abrir chamados para si mesmos")
|
||||
}
|
||||
|
||||
if (args.assigneeId && (!role || !STAFF_ROLES.has(role))) {
|
||||
throw new ConvexError("Somente a equipe interna pode definir o responsável")
|
||||
}
|
||||
|
||||
let initialAssigneeId: Id<"users"> | undefined
|
||||
let initialAssignee: Doc<"users"> | null = null
|
||||
|
||||
if (args.assigneeId) {
|
||||
const assignee = (await ctx.db.get(args.assigneeId)) as Doc<"users"> | null
|
||||
if (!assignee || assignee.tenantId !== args.tenantId) {
|
||||
throw new ConvexError("Responsável inválido")
|
||||
}
|
||||
const normalizedAssigneeRole = (assignee.role ?? "AGENT").toUpperCase()
|
||||
if (!STAFF_ROLES.has(normalizedAssigneeRole)) {
|
||||
throw new ConvexError("Responsável inválido")
|
||||
}
|
||||
initialAssigneeId = assignee._id
|
||||
initialAssignee = assignee
|
||||
} else if (role && STAFF_ROLES.has(role)) {
|
||||
initialAssigneeId = actorUser._id
|
||||
initialAssignee = actorUser
|
||||
}
|
||||
|
||||
const subject = args.subject.trim();
|
||||
if (subject.length < 3) {
|
||||
throw new ConvexError("Informe um assunto com pelo menos 3 caracteres");
|
||||
|
|
@ -510,7 +536,7 @@ export const create = mutation({
|
|||
categoryId: args.categoryId,
|
||||
subcategoryId: args.subcategoryId,
|
||||
requesterId: args.requesterId,
|
||||
assigneeId: undefined,
|
||||
assigneeId: initialAssigneeId,
|
||||
working: false,
|
||||
activeSessionId: undefined,
|
||||
totalWorkedMs: 0,
|
||||
|
|
@ -531,6 +557,16 @@ export const create = mutation({
|
|||
payload: { requesterId: args.requesterId, requesterName: requester?.name, requesterAvatar: requester?.avatarUrl },
|
||||
createdAt: now,
|
||||
});
|
||||
|
||||
if (initialAssigneeId && initialAssignee) {
|
||||
await ctx.db.insert("ticketEvents", {
|
||||
ticketId: id,
|
||||
type: "ASSIGNEE_CHANGED",
|
||||
payload: { assigneeId: initialAssigneeId, assigneeName: initialAssignee.name, actorId: args.actorId },
|
||||
createdAt: now,
|
||||
})
|
||||
}
|
||||
|
||||
return id;
|
||||
},
|
||||
});
|
||||
|
|
@ -558,10 +594,23 @@ export const addComment = mutation({
|
|||
throw new ConvexError("Ticket não encontrado")
|
||||
}
|
||||
|
||||
const author = (await ctx.db.get(args.authorId)) as Doc<"users"> | null
|
||||
if (!author || author.tenantId !== ticket.tenantId) {
|
||||
throw new ConvexError("Autor do comentário inválido")
|
||||
}
|
||||
|
||||
const normalizedRole = (author.role ?? "AGENT").toUpperCase()
|
||||
|
||||
if (ticket.requesterId === args.authorId) {
|
||||
await requireCustomer(ctx, args.authorId, ticket.tenantId)
|
||||
if (args.visibility !== "PUBLIC") {
|
||||
throw new ConvexError("Clientes só podem registrar comentários públicos")
|
||||
if (normalizedRole === "CUSTOMER") {
|
||||
await requireCustomer(ctx, args.authorId, ticket.tenantId)
|
||||
if (args.visibility !== "PUBLIC") {
|
||||
throw new ConvexError("Clientes só podem registrar comentários públicos")
|
||||
}
|
||||
} else if (STAFF_ROLES.has(normalizedRole)) {
|
||||
await requireStaff(ctx, args.authorId, ticket.tenantId)
|
||||
} else {
|
||||
throw new ConvexError("Autor não possui permissão para comentar")
|
||||
}
|
||||
} else {
|
||||
await requireStaff(ctx, args.authorId, ticket.tenantId)
|
||||
|
|
@ -577,11 +626,10 @@ export const addComment = mutation({
|
|||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
const author = await ctx.db.get(args.authorId);
|
||||
await ctx.db.insert("ticketEvents", {
|
||||
ticketId: args.ticketId,
|
||||
type: "COMMENT_ADDED",
|
||||
payload: { authorId: args.authorId, authorName: author?.name, authorAvatar: author?.avatarUrl },
|
||||
payload: { authorId: args.authorId, authorName: author.name, authorAvatar: author.avatarUrl },
|
||||
createdAt: now,
|
||||
});
|
||||
// bump ticket updatedAt
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue