Practical Prisma query patterns for retrieving and working with tasks assigned to a user. Optimized for AI assistant usage.

Prisma — user.tasksAssigned Examples

These examples demonstrate idiomatic Prisma queries using the user.tasksAssigned relation introduced in our schema. They cover common patterns such as filtering, pagination, counting, and eager-loading related records.

Import the shared Prisma client:

import { prisma } from "@/lib/prisma";

Basic: load tasks assigned to a user

export async function getUserTasks(userId: string) {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    select: {
      id: true,
      name: true,
      tasksAssigned: true,
    },
  });
  return user?.tasksAssigned ?? [];
}

Filter and sort: only open tasks ordered by sortIndex

export async function getOpenTasks(userId: string) {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    select: {
      tasksAssigned: {
        where: { status: "open" },
        orderBy: [{ sortIndex: "asc" }, { createdAt: "asc" }],
      },
    },
  });
  return user?.tasksAssigned ?? [];
}
export async function getTasksWithTicket(userId: string) {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    select: {
      tasksAssigned: {
        include: {
          ticket: {
            select: {
              id: true,
              title: true,
              status: true,
              priority: true,
              project: { select: { id: true, name: true } },
            },
          },
        },
      },
    },
  });
  return user?.tasksAssigned ?? [];
}

Pagination with cursor

interface GetUserTasksPageParams {
  userId: string;
  limit?: number;
  cursor?: string; // task.id
  status?: string; // e.g. "open", "closed"
}

export async function getUserTasksPage(params: GetUserTasksPageParams) {
  const { userId, limit = 20, cursor, status } = params;
  const tasks = await prisma.task.findMany({
    where: { assigneeId: userId, ...(status ? { status } : {}) },
    include: {
      ticket: { select: { id: true, title: true, status: true, projectId: true } },
    },
    take: limit + 1,
    ...(cursor ? { cursor: { id: cursor }, skip: 1 } : {}),
    orderBy: [{ sortIndex: "asc" }, { createdAt: "desc" }],
  });

  const hasMore = tasks.length > limit;
  const items = hasMore ? tasks.slice(0, -1) : tasks;
  const nextCursor = hasMore ? items[items.length - 1]?.id : undefined;
  return { items, nextCursor } as const;
}

Count tasks per status (groupBy)

export async function getTaskStatusCounts(userId: string) {
  const grouped = await prisma.task.groupBy({
    by: ["status"],
    where: { assigneeId: userId },
    _count: { _all: true },
  });

  return grouped.map(g => ({ status: g.status, count: g._count._all }));
}

Filter by Project (or Organization) and date window

interface GetUserProjectTasksParams {
  userId: string;
  projectId?: string;
  organizationId?: string;
  from?: Date;
  to?: Date;
}

export async function getUserProjectTasks(params: GetUserProjectTasksParams) {
  const { userId, projectId, organizationId, from, to } = params;
  return prisma.task.findMany({
    where: {
      assigneeId: userId,
      ...(from || to ? { createdAt: { gte: from, lte: to } } : {}),
      ...(projectId ? { ticket: { projectId } } : {}),
      ...(organizationId ? { ticket: { organizationId } } : {}),
    },
    include: { ticket: { select: { id: true, title: true, projectId: true } } },
    orderBy: { createdAt: "desc" },
  });
}

Create a Task for a Ticket and assign it to a User

interface CreateTaskParams {
  ticketId: string;
  title: string;
  assigneeId?: string;
}

export async function createTask(params: CreateTaskParams) {
  const { ticketId, title, assigneeId } = params;
  return prisma.task.create({
    data: {
      ticketId,
      title,
      ...(assigneeId ? { assignee: { connect: { id: assigneeId } } } : {}),
    },
    include: { ticket: true, assignee: true },
  });
}

Reassign a Task to another User

export async function reassignTask(taskId: string, newAssigneeId: string) {
  return prisma.task.update({
    where: { id: taskId },
    data: { assigneeId: newAssigneeId },
    select: { id: true, assigneeId: true },
  });
}

Tasks with Workflow Runs (latest first)

export async function getTasksWithRuns(userId: string) {
  return prisma.task.findMany({
    where: { assigneeId: userId },
    include: {
      runs: {
        orderBy: { updatedAt: "desc" },
        select: { id: true, status: true, currentStep: true, updatedAt: true },
      },
      ticket: { select: { id: true, title: true } },
    },
    orderBy: [{ sortIndex: "asc" }, { createdAt: "desc" }],
  });
}

Load User with a trimmed tasksAssigned slice for dashboards

export async function getUserWithPreviewTasks(userId: string) {
  return prisma.user.findUnique({
    where: { id: userId },
    select: {
      id: true,
      name: true,
      tasksAssigned: {
        take: 5,
        orderBy: [{ sortIndex: "asc" }, { createdAt: "desc" }],
        include: { ticket: { select: { id: true, title: true, status: true } } },
      },
    },
  });
}

Example: Minimal API route using validateUserSession()

// File: src/app/api/user/tasks/route.ts
import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { validateUserSession } from "@/lib/permissions";

export async function GET() {
  const session = await validateUserSession();
  if (!session?.user?.id) {
    return NextResponse.json({ error: { code: "UNAUTHORIZED" } }, { status: 401 });
  }

  const tasks = await prisma.task.findMany({
    where: { assigneeId: session.user.id },
    include: { ticket: { select: { id: true, title: true, status: true } } },
    orderBy: [{ sortIndex: "asc" }, { createdAt: "desc" }],
    take: 50,
  });

  return NextResponse.json({ data: tasks });
}

Tips

  • Select only the fields you need; avoid include: true for large nested shapes.
  • For lists, use stable ordering (sortIndex, then createdAt) to prevent cursor drift.
  • Prefer cursor-based pagination for long lists; include an index on the order columns.
  • Use groupBy for aggregated counts and pair with a separate list fetch for items.
  • For AI use, provide concise shapes (ids, titles, statuses) to reduce token/JSON size.