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
}
};
export default
},
{
// 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.