feat(c3): consulta de pedidos — schema, api, web (OrdersModule + ClientDetailPage)

- Prisma: Order, OrderItem, OrderStatusHistory + migration
- Seed: 17 pedidos em 7 clientes com itens, histórico e desnorm de clientes
- @sar/api-interface: contratos Zod (OrderSummary, OrderDetail, OrderListQuery, etc.)
- API: GET /orders, GET /orders/:id, GET /clients/:id/orders (últimos 10)
- Web: OrdersPage (lista + filtro status/número + pending_approval highlighted)
- Web: ClientDetailPage (ficha completa + últimos 10 pedidos)
- Web: /pedidos e /pedidos/$id adicionados ao router; ClientDetailPage substitui placeholder

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 23:31:18 +00:00
parent 14c8350216
commit c36451dd33
15 changed files with 1494 additions and 71 deletions

View File

@@ -0,0 +1,32 @@
import { Controller, Get, Param, ParseUUIDPipe, Query } from '@nestjs/common';
import { ClsService } from 'nestjs-cls';
import { createZodDto } from 'nestjs-zod';
import {
OrderListQuerySchema,
type OrderDetail,
type OrderListQuery,
type OrderListResponse,
} from '@sar/api-interface';
import type { WorkspaceClsStore } from '../workspace/workspace.types';
import { OrdersService } from './orders.service';
class OrderListQueryDto extends createZodDto(OrderListQuerySchema) {}
@Controller({ path: 'orders' })
export class OrdersController {
constructor(
private readonly orders: OrdersService,
private readonly cls: ClsService<WorkspaceClsStore>,
) {}
@Get()
list(@Query() query: OrderListQueryDto): Promise<OrderListResponse> {
const parsed = OrderListQuerySchema.parse(query) as OrderListQuery;
return this.orders.list(parsed, this.cls.get('userId') ?? '', this.cls.get('role') ?? 'rep');
}
@Get(':id')
findOne(@Param('id', ParseUUIDPipe) id: string): Promise<OrderDetail> {
return this.orders.findOne(id, this.cls.get('userId') ?? '', this.cls.get('role') ?? 'rep');
}
}