Sistema de Pedidos com Filtros, Paginação e Joins
Vamos analisar uma das rotas mais complexas do Restaurantix: a listagem de pedidos com filtros avançados.
// src/http/routes/get-orders.ts import { auth } from "../auth"; import { UnauthorizedError } from "../errors/unauthorized-error"; import { createSelectSchema } from "drizzle-typebox"; import { t } from "elysia"; import { eq, and, ilike, count, getTableColumns, desc, sql } from "drizzle-orm"; import { db } from "@/application/infra/db/connection"; import { orders, users } from "@/application/infra/db/schema"; export const getOrders = auth.get( "/orders", async ({ getCurrentUser, query }) => { // 1. AUTENTICAÇÃO E AUTORIZAÇÃO const { restaurantId } = await getCurrentUser(); if (!restaurantId) { throw new UnauthorizedError(); } // 2. EXTRAIR PARÂMETROS DE QUERY const { customerName, orderId, status, pageIndex } = query; // 3. PREPARAR COLUNAS DA TABELA ORDERS const orderTableColumns = getTableColumns(orders); // 4. CONSTRUIR QUERY BASE COM JOINS const baseQuery = db .select({ ...orderTableColumns, customerName: users.name, }) .from(orders) .innerJoin(users, eq(users.id, orders.customerId)) .where( and( // Filtrar por restaurante do usuário logado eq(orders.restaurantId, restaurantId), // Filtros opcionais orderId ? ilike(orders.id, `%${orderId}%`) : undefined, status ? eq(orders.status, status) : undefined, customerName ? ilike(users.name, `%${customerName}%`) : undefined, ), ); // 5. EXECUTAR QUERIES EM PARALELO const [[amountOfOrders], allOrders] = await Promise.all([ // Contar total de registros db.select({ count: count() }).from(baseQuery.as("baseQuery")), // Buscar registros paginados db .select() .from(baseQuery.as("baseQuery")) .offset(pageIndex * 10) .limit(10) .orderBy((fields) => { return [ // Ordenação customizada por status sql`CASE ${fields.status} WHEN 'pending' THEN 1 WHEN 'preparing' THEN 2 WHEN 'ready' THEN 3 WHEN 'delivered' THEN 4 WHEN 'cancelled' THEN 20 END`, // Depois por data (mais recente primeiro) desc(fields.createdAt), ]; }), ]); // 6. RETORNAR DADOS COM METADADOS return { orders: allOrders, meta: { pageIndex, perPage: 10, totalCount: amountOfOrders?.count ?? 0 }, }; }, { // 7. VALIDAÇÃO DE QUERY PARAMETERS query: t.Object({ customerName: t.Optional(t.String()), orderId: t.Optional(t.String()), status: t.Optional(createSelectSchema(orders).properties.status), pageIndex: t.Numeric({ minimum: 0 }), }), }, );
Agora você tem o código real do Restaurantix! Implemente as outras rotas seguindo o mesmo padrão.
Este é o código exato usado no projeto Restaurantix em produção, com todas as funcionalidades reais de filtros, paginação e joins.