Real World Example

Seller Dashboard Stats

Marketplace seller panels (Meesho, Amazon Seller Central, Flipkart Seller Hub) show revenue per product and orders per day. Prisma's groupBy and aggregate handle this without raw SQL; raw SQL is still available with $queryRaw for complex reports. (This assumes Product has a sellerId field linking it to a seller.)

src/sellers/seller-stats.service.ts

import { Injectable } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class SellerStatsService {
  constructor(private readonly prisma: PrismaService) {}

  async summary(sellerId: number, from: Date) {
    const [top, totals, daily] = await Promise.all([
      this.prisma.orderItem.groupBy({
        by: ['productId'],
        where: { product: { sellerId }, order: { createdAt: { gte: from }, status: { not: 'CANCELLED' } } },
        _sum: { quantity: true },
        orderBy: { _sum: { quantity: 'desc' } },
        take: 5,
      }),
      this.prisma.order.aggregate({
        where: { items: { some: { product: { sellerId } } }, createdAt: { gte: from } },
        _count: true,
        _sum: { total: true },
      }),
      this.prisma.$queryRaw<{ day: Date; orders: bigint }[]>(Prisma.sql`
        SELECT date_trunc('day', o."createdAt") AS day, COUNT(DISTINCT o.id) AS orders
        FROM "Order" o JOIN "OrderItem" i ON i."orderId" = o.id JOIN "Product" p ON p.id = i."productId"
        WHERE p."sellerId" = ${sellerId} AND o."createdAt" >= ${from}
        GROUP BY 1 ORDER BY 1`),
    ]);
    return { top, orders: totals._count, revenue: totals._sum.total, daily: daily.map((d) => ({ ...d, orders: Number(d.orders) })) };
  }
}

Note: Prisma.sql with ${value} placeholders sends values as parameters, so it is safe from SQL injection. Never build raw SQL with string concatenation.