# 🌐 Guia de Integração com API PraFrota ## 📋 **Informações da API** **URL Base**: `https://prafrota-be-bff-tenant-api.grupopra.tech` **Swagger UI**: [https://prafrota-be-bff-tenant-api.grupopra.tech/swagger#/](https://prafrota-be-bff-tenant-api.grupopra.tech/swagger#/) **Projeto**: PraFrota - Sistema de Gestão de Frota **Empresa**: Grupo PRA ## 🎯 **Fluxo MCP para Novos Domínios** ### **Passo 1: Consulta ao Swagger** Quando o MCP precisar implementar um novo domínio: 1. **Acessar o Swagger da API**: [https://prafrota-be-bff-tenant-api.grupopra.tech/swagger#/](https://prafrota-be-bff-tenant-api.grupopra.tech/swagger#/) 2. **Identificar endpoints** do domínio desejado 3. **Analisar schemas** de request/response 4. **Mapear operações CRUD** disponíveis ### **Passo 2: Mapeamento de Endpoints** #### **Padrão Esperado de Endpoints** ``` GET /api/{domain} # Listagem com paginação POST /api/{domain} # Criação de nova entidade GET /api/{domain}/{id} # Detalhes de uma entidade PUT /api/{domain}/{id} # Atualização completa PATCH /api/{domain}/{id} # Atualização parcial DELETE /api/{domain}/{id} # Exclusão ``` #### **Exemplos de Domínios Esperados** - `/api/vehicles` - Gestão de veículos - `/api/drivers` - Gestão de motoristas - `/api/routes` - Gestão de rotas - `/api/clients` - Gestão de clientes - `/api/companies` - Gestão de empresas - `/api/contracts` - Gestão de contratos ### **Passo 3: Implementação do Service** #### **Template Base para Services** ```typescript import { Injectable } from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Observable } from 'rxjs'; import { DomainService } from '../base-domain/base-domain.component'; @Injectable() export class {Domain}Service implements DomainService<{Entity}> { private readonly apiUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/api'; private readonly endpoint = '{domain}'; // ex: 'vehicles' constructor(private http: HttpClient) {} // ✅ Método obrigatório para BaseDomainComponent getEntities(page: number, pageSize: number, filters: any): Observable<{ data: {Entity}[]; totalCount: number; pageCount: number; currentPage: number; }> { const params = new HttpParams() .set('page', page.toString()) .set('pageSize', pageSize.toString()); // Adicionar filtros se disponíveis na API Object.keys(filters).forEach(key => { if (filters[key] !== null && filters[key] !== '') { params = params.set(key, filters[key]); } }); return this.http.get(`${this.apiUrl}/${this.endpoint}`, { params }); } // ✅ Métodos CRUD para salvamento genérico create(entity: Partial<{Entity}>): Observable<{Entity}> { return this.http.post<{Entity}>(`${this.apiUrl}/${this.endpoint}`, entity); } update(id: any, entity: Partial<{Entity}>): Observable<{Entity}> { return this.http.put<{Entity}>(`${this.apiUrl}/${this.endpoint}/${id}`, entity); } delete(id: any): Observable { return this.http.delete(`${this.apiUrl}/${this.endpoint}/${id}`); } getById(id: any): Observable<{Entity}> { return this.http.get<{Entity}>(`${this.apiUrl}/${this.endpoint}/${id}`); } // Métodos adicionais específicos do domínio conforme Swagger } ``` ### **Passo 4: Schema para Interface TypeScript** #### **Processo de Mapeamento** 1. **Localizar schema** no Swagger (seção "Schemas" ou "Definitions") 2. **Mapear tipos** do OpenAPI para TypeScript: - `string` → `string` - `integer` → `number` - `boolean` → `boolean` - `array` → `Array` - `object` → `interface` 3. **Considerar campos opcionais** (marked as required: false) 4. **Incluir enums** se definidos na API #### **Template Base para Interfaces** ```typescript // {entity}.interface.ts // ✅ Baseado no schema do Swagger da API PraFrota export interface {Entity} { // Campos obrigatórios (required: true no schema) id: string; name: string; createdAt: string; updatedAt: string; // Campos opcionais (required: false ou não listados) description?: string; status?: EntityStatus; // Relacionamentos {relation}Id?: string; {relation}?: {RelatedEntity}; } export enum EntityStatus { ACTIVE = 'ACTIVE', INACTIVE = 'INACTIVE', PENDING = 'PENDING' } // Types auxiliares se necessário export type {Entity}CreateRequest = Omit<{Entity}, 'id' | 'createdAt' | 'updatedAt'>; export type {Entity}UpdateRequest = Partial<{Entity}CreateRequest>; ``` ### **Passo 5: Configuração de Colunas** #### **Mapeamento de Campos para Tabela** ```typescript // Baseado nos campos do schema da API protected getDomainConfig(): DomainConfig { return { domain: '{domain}', title: '{Plural}', entityName: '{singular}', subTabs: ['dados', 'endereco', 'documentos'], // Conforme necessário columns: [ // ✅ Campos principais para listagem { field: 'id', header: 'ID', sortable: true, visible: false }, { field: 'name', header: 'Nome', sortable: true, filterable: true }, { field: 'status', header: 'Status', filterable: true }, { field: 'createdAt', header: 'Criado em', sortable: true, type: 'date' }, // Campos específicos do domínio baseados no schema { field: '{specific_field}', header: '{Header}', sortable: true } ] }; } ``` ## 🔧 **Orientações Específicas para o MCP** ### **Antes de Implementar um Domínio** 1. ✅ **SEMPRE consultar o Swagger primeiro** 2. ✅ **Verificar endpoints disponíveis** 3. ✅ **Analisar schema de dados** 4. ✅ **Identificar campos obrigatórios vs opcionais** 5. ✅ **Verificar relacionamentos entre entidades** ### **Durante a Implementação** 1. ✅ **Usar nomes consistentes** com a API 2. ✅ **Mapear todos os campos** do schema 3. ✅ **Incluir validações** baseadas na API 4. ✅ **Testar endpoints** antes de finalizar 5. ✅ **Documentar diferenças** se houver ### **Validação da Implementação** 1. ✅ **Listar entidades** funciona 2. ✅ **Criar nova entidade** funciona 3. ✅ **Editar entidade** funciona 4. ✅ **Excluir entidade** funciona 5. ✅ **Filtros e ordenação** funcionam ## 🎮 **Exemplo Completo: Veículos** ### **1. Endpoints Identificados no Swagger** ``` GET /api/vehicles # Listagem de veículos POST /api/vehicles # Criar veículo GET /api/vehicles/{id} # Detalhes do veículo PUT /api/vehicles/{id} # Atualizar veículo DELETE /api/vehicles/{id} # Excluir veículo ``` ### **2. Schema Extraído** ```json { "Vehicle": { "type": "object", "required": ["plate", "model", "year"], "properties": { "id": { "type": "string" }, "plate": { "type": "string" }, "model": { "type": "string" }, "year": { "type": "integer" }, "status": { "type": "string", "enum": ["ACTIVE", "INACTIVE", "MAINTENANCE", "RENTED", "STOLEN", "CRASHED", "FOR_SALE", "SCRAPPED", "RESERVED", "UNDER_REPAIR"] }, "brand": { "type": "string" }, "color": { "type": "string" } } } } ``` ### **3. Interface TypeScript** ```typescript export interface Vehicle { id: string; plate: string; // obrigatório model: string; // obrigatório year: number; // obrigatório status?: VehicleStatus; brand?: string; color?: string; createdAt?: string; updatedAt?: string; } export enum VehicleStatus { ACTIVE = 'ACTIVE', // ✅ Ativo na frota INACTIVE = 'INACTIVE', // ❌ Inativo MAINTENANCE = 'MAINTENANCE', // 🔧 Em manutenção RENTED = 'RENTED', // 🏠 Alugado STOLEN = 'STOLEN', // 🚨 Roubado CRASHED = 'CRASHED', // 💥 Sinistrado FOR_SALE = 'FOR_SALE', // 💰 Em venda SCRAPPED = 'SCRAPPED', // ♻️ Sucateado RESERVED = 'RESERVED', // 📋 Reservado UNDER_REPAIR = 'UNDER_REPAIR' // 🔨 Em reparo } ``` ### **4. Service Implementado** ```typescript @Injectable() export class VehiclesService implements DomainService { private readonly apiUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/api'; // ... implementação conforme template } ``` ### **5. Component Final** ```typescript export class VehiclesComponent extends BaseDomainComponent { protected getDomainConfig(): DomainConfig { return { domain: 'vehicle', title: 'Veículos', entityName: 'veículo', subTabs: ['dados', 'documentos', 'manutencao'], columns: [ { field: 'plate', header: 'Placa', sortable: true, filterable: true }, { field: 'model', header: 'Modelo', sortable: true, filterable: true }, { field: 'year', header: 'Ano', sortable: true }, { field: 'status', header: 'Status', filterable: true }, { field: 'brand', header: 'Marca', sortable: true } ] }; } } ``` ## 🚨 **Tratamento de Erros da API** ### **Códigos de Status Esperados** - `200 OK` - Sucesso - `201 Created` - Criado com sucesso - `400 Bad Request` - Dados inválidos - `401 Unauthorized` - Não autenticado - `403 Forbidden` - Sem permissão - `404 Not Found` - Recurso não encontrado - `409 Conflict` - Conflito (ex: duplicata) - `500 Internal Server Error` - Erro do servidor ### **Implementação de Error Handling** ```typescript import { catchError } from 'rxjs/operators'; import { throwError } from 'rxjs'; // No service create(entity: Partial): Observable { return this.http.post(`${this.apiUrl}/vehicles`, entity) .pipe( catchError(error => { console.error('Erro ao criar veículo:', error); // Transformar erro da API em mensagem amigável return throwError(() => this.handleApiError(error)); }) ); } private handleApiError(error: any): string { switch (error.status) { case 400: return 'Dados inválidos. Verifique os campos obrigatórios.'; case 409: return 'Já existe um veículo com esta placa.'; default: return 'Erro interno. Tente novamente.'; } } ``` --- ## 🔗 **Links Úteis** - **Swagger da API**: [https://prafrota-be-bff-tenant-api.grupopra.tech/swagger#/](https://prafrota-be-bff-tenant-api.grupopra.tech/swagger#/) - **Documentação do Framework**: [../src/app/shared/components/tab-system/README.md](../src/app/shared/components/tab-system/README.md) - **Base Domain Component**: [../src/app/shared/components/base-domain/base-domain.component.ts](../src/app/shared/components/base-domain/base-domain.component.ts) --- **💡 Dica para o MCP**: Sempre começar pela consulta ao Swagger para garantir implementação correta e consistente com a API PraFrota!