feat: add company management and manager role support
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
parent
409cbea7b9
commit
854887f499
16 changed files with 955 additions and 126 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { query } from "./_generated/server";
|
||||
import type { QueryCtx } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
import { ConvexError, v } from "convex/values";
|
||||
import type { Doc, Id } from "./_generated/dataModel";
|
||||
|
||||
import { requireStaff } from "./rbac";
|
||||
|
|
@ -42,6 +42,25 @@ async function fetchTickets(ctx: QueryCtx, tenantId: string) {
|
|||
.collect();
|
||||
}
|
||||
|
||||
async function fetchScopedTickets(
|
||||
ctx: QueryCtx,
|
||||
tenantId: string,
|
||||
viewer: Awaited<ReturnType<typeof requireStaff>>,
|
||||
) {
|
||||
if (viewer.role === "MANAGER") {
|
||||
if (!viewer.user.companyId) {
|
||||
throw new ConvexError("Gestor não possui empresa vinculada");
|
||||
}
|
||||
return ctx.db
|
||||
.query("tickets")
|
||||
.withIndex("by_tenant_company", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("companyId", viewer.user.companyId!)
|
||||
)
|
||||
.collect();
|
||||
}
|
||||
return fetchTickets(ctx, tenantId);
|
||||
}
|
||||
|
||||
async function fetchQueues(ctx: QueryCtx, tenantId: string) {
|
||||
return ctx.db
|
||||
.query("queues")
|
||||
|
|
@ -92,8 +111,8 @@ function formatDateKey(timestamp: number) {
|
|||
export const slaOverview = query({
|
||||
args: { tenantId: v.string(), viewerId: v.id("users") },
|
||||
handler: async (ctx, { tenantId, viewerId }) => {
|
||||
await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchTickets(ctx, tenantId);
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchScopedTickets(ctx, tenantId, viewer);
|
||||
const queues = await fetchQueues(ctx, tenantId);
|
||||
|
||||
const now = Date.now();
|
||||
|
|
@ -140,8 +159,8 @@ export const slaOverview = query({
|
|||
export const csatOverview = query({
|
||||
args: { tenantId: v.string(), viewerId: v.id("users") },
|
||||
handler: async (ctx, { tenantId, viewerId }) => {
|
||||
await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchTickets(ctx, tenantId);
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchScopedTickets(ctx, tenantId, viewer);
|
||||
const surveys = await collectCsatSurveys(ctx, tickets);
|
||||
|
||||
const averageScore = average(surveys.map((item) => item.score));
|
||||
|
|
@ -171,8 +190,8 @@ export const csatOverview = query({
|
|||
export const backlogOverview = query({
|
||||
args: { tenantId: v.string(), viewerId: v.id("users") },
|
||||
handler: async (ctx, { tenantId, viewerId }) => {
|
||||
await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchTickets(ctx, tenantId);
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchScopedTickets(ctx, tenantId, viewer);
|
||||
|
||||
const statusCounts = tickets.reduce<Record<string, number>>((acc, ticket) => {
|
||||
acc[ticket.status] = (acc[ticket.status] ?? 0) + 1;
|
||||
|
|
@ -218,8 +237,8 @@ export const backlogOverview = query({
|
|||
export const dashboardOverview = query({
|
||||
args: { tenantId: v.string(), viewerId: v.id("users") },
|
||||
handler: async (ctx, { tenantId, viewerId }) => {
|
||||
await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchTickets(ctx, tenantId);
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchScopedTickets(ctx, tenantId, viewer);
|
||||
const now = Date.now();
|
||||
|
||||
const lastDayStart = now - ONE_DAY_MS;
|
||||
|
|
@ -294,8 +313,8 @@ export const ticketsByChannel = query({
|
|||
range: v.optional(v.string()),
|
||||
},
|
||||
handler: async (ctx, { tenantId, viewerId, range }) => {
|
||||
await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchTickets(ctx, tenantId);
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId);
|
||||
const tickets = await fetchScopedTickets(ctx, tenantId, viewer);
|
||||
const days = range === "7d" ? 7 : range === "30d" ? 30 : 90;
|
||||
|
||||
const end = new Date();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue