@horizon-framework/website-dev-docs 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/AGENTE_FULLSTACK.md +209 -0
- package/agents/AGENTE_LAYOUT_DESIGNER.md +930 -0
- package/checklists/ADICIONAR_CAMPO.md +95 -0
- package/checklists/CRIAR_SITE_NOVO.md +163 -0
- package/checklists/PUBLICAR_SITE.md +75 -0
- package/checklists/TROCAR_CRM.md +96 -0
- package/commercial/PACOTES_PAGINAS.md +86 -0
- package/commercial/POSSIBILIDADES_VENDA.md +52 -0
- package/index.md +54 -0
- package/knowledge/API_PROPERTY.md +566 -0
- package/knowledge/ARQUITETURA_GERAL.md +169 -0
- package/knowledge/ARQUITETURA_MODULOS_WEB.md +241 -0
- package/knowledge/BATCH_TOTALS_API.md +200 -0
- package/knowledge/CAPABILITIES.md +190 -0
- package/knowledge/COMPONENTES_GLOBAIS_UI.md +407 -0
- package/knowledge/CRMS_INTEGRACOES.md +151 -0
- package/knowledge/DESIGN_AVANCADO.md +403 -0
- package/knowledge/DESIGN_SYSTEM_CATALOG.md +349 -0
- package/knowledge/DESIGN_TEMPLATES_CATALOG.md +61 -0
- package/knowledge/DOMINIO_ENTIDADES.md +328 -0
- package/knowledge/HOOKS_REGISTRY.md +127 -0
- package/knowledge/MODULE_CREATION_PATTERN.md +624 -0
- package/knowledge/NAVEGACAO_DINAMICA.md +233 -0
- package/knowledge/PAGINAS_BASICAS.md +63 -0
- package/knowledge/SEARCH_ENGINE_API.md +1038 -0
- package/knowledge/SISTEMA_MODULAR.md +109 -0
- package/knowledge/SISTEMA_SCHEMAS.md +126 -0
- package/knowledge/SSOT_SPECIFICATION_V2.md +333 -0
- package/knowledge/UI_KIT_COMPLETO.md +125 -0
- package/modules/property/MODULO_IMOBILIARIO.md +356 -0
- package/package.json +17 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
# API Property -- Stack, Arquitetura e Endpoints
|
|
2
|
+
|
|
3
|
+
> **Status:** **PRODUÇÃO PRONTA**
|
|
4
|
+
> **Versão:** 3.0.0 (Property + Broker implementados)
|
|
5
|
+
> **Data:** 23/08/2025
|
|
6
|
+
|
|
7
|
+
## **Visão Geral**
|
|
8
|
+
|
|
9
|
+
API Next.js moderna para gestão e busca de propriedades imobiliárias com arquitetura avançada, busca full-text, geolocalização PostGIS e sistema de migração completo da nomenclatura IMOVEL→PROPERTY e CORRETOR→BROKER.
|
|
10
|
+
|
|
11
|
+
### **Stack Tecnológico**
|
|
12
|
+
- **Next.js 14** (App Router)
|
|
13
|
+
- **Prisma 5.22** (ORM + Client)
|
|
14
|
+
- **PostgreSQL** (Neon Database com PostGIS)
|
|
15
|
+
- **TypeScript** (strict mode)
|
|
16
|
+
- **Zod 3.24** (validação + inferência de tipos)
|
|
17
|
+
- **Vitest** (framework de testes)
|
|
18
|
+
|
|
19
|
+
### **Principais Recursos**
|
|
20
|
+
- **SSOT v2.0** - Single Source of Truth com 90+ campos estruturados
|
|
21
|
+
- **Advanced Search Library** - Biblioteca isolada e reutilizável (8 módulos)
|
|
22
|
+
- **Type-safety completo** - Zod + TypeScript em toda stack
|
|
23
|
+
- **Prisma DMMF Introspection** - Detecção automática de tipos
|
|
24
|
+
- **API RESTful robusta** - Validação completa com Zod
|
|
25
|
+
- **PostGIS Integration** - Busca geoespacial avançada
|
|
26
|
+
- **Full-text Search** - PostgreSQL tsvector com português
|
|
27
|
+
- **Migração completa** - Sistema legacy totalmente modernizado
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## **Estrutura do Projeto**
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
/apps/api/
|
|
35
|
+
├── prisma/ # Database & Schema
|
|
36
|
+
│ ├── schema.prisma # Schema completo (Property + Broker)
|
|
37
|
+
│ └── db-setup.sql # PostGIS extensions
|
|
38
|
+
├── src/
|
|
39
|
+
│ ├── app/api/ # Next.js Routes (pontes secas)
|
|
40
|
+
│ │ └── property/ # Endpoints do módulo Property
|
|
41
|
+
│ │ ├── find/route.ts # POST - busca por criteria
|
|
42
|
+
│ │ ├── search/route.ts # POST - busca multipart
|
|
43
|
+
│ │ ├── sync/route.ts # GET/PUT - sincronização
|
|
44
|
+
│ │ └── schemas/ # GET - schemas SSOT
|
|
45
|
+
│ ├── core/
|
|
46
|
+
│ │ └── prisma.ts # Singleton Prisma Client
|
|
47
|
+
│ └── modules/property/ # Módulo principal
|
|
48
|
+
│ ├── config/
|
|
49
|
+
│ │ ├── entity-schema.ts # SSOT v2.0 (~1000 linhas)
|
|
50
|
+
│ │ ├── entity-schema.zod.ts # Schemas Zod gerados
|
|
51
|
+
│ │ └── database/
|
|
52
|
+
│ │ ├── fragment.prisma # Fragment para geração
|
|
53
|
+
│ │ └── fragment.sql # SQL índices especiais
|
|
54
|
+
│ ├── controllers/ # Controllers Next.js
|
|
55
|
+
│ │ ├── search.controller.ts # Busca multipart
|
|
56
|
+
│ │ ├── find.controller.ts # Busca por criteria
|
|
57
|
+
│ │ ├── sync.controller.ts # Sincronização batch
|
|
58
|
+
│ │ └── schemas.controller.ts # Schemas SSOT
|
|
59
|
+
│ ├── lib/advancedSearch/ # BIBLIOTECA ISOLADA
|
|
60
|
+
│ │ ├── index.ts # API principal
|
|
61
|
+
│ │ ├── types.ts # Definições tipos
|
|
62
|
+
│ │ ├── extractIds.ts # Extração IDs fulltext/geo
|
|
63
|
+
│ │ ├── executeList.ts # Busca paginada
|
|
64
|
+
│ │ ├── executeMap.ts # Busca para mapas
|
|
65
|
+
│ │ ├── executeTotal.ts # Contagem total
|
|
66
|
+
│ │ ├── executeFacets.ts # Agregações/facets
|
|
67
|
+
│ │ └── helpers.ts # DMMF Introspection
|
|
68
|
+
│ ├── services/ # Services de negócio
|
|
69
|
+
│ │ ├── search.service.ts # Service busca
|
|
70
|
+
│ │ ├── find.service.ts # Service find
|
|
71
|
+
│ │ └── sync.service.ts # Service sincronização
|
|
72
|
+
│ └── mappers/ # Transformadores dados
|
|
73
|
+
│ └── enrichPropertyData/ # Enriquecimento dados
|
|
74
|
+
├── __tests__/ # Suíte completa de testes
|
|
75
|
+
├── __dev__/ # Scripts desenvolvimento
|
|
76
|
+
│ ├── scripts/ # Scripts utilitários
|
|
77
|
+
│ └── data/ # Dados Jetimob (11 páginas)
|
|
78
|
+
└── docs/ # Documentação completa
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## **Database Schema**
|
|
84
|
+
|
|
85
|
+
### **Model Property (~90 campos)**
|
|
86
|
+
```prisma
|
|
87
|
+
model Property {
|
|
88
|
+
// BASE SYSTEM
|
|
89
|
+
id Int @id @default(autoincrement())
|
|
90
|
+
created_at DateTime @default(now())
|
|
91
|
+
|
|
92
|
+
// SPECIAL GENERATED COLUMNS
|
|
93
|
+
search_tsvector Unsupported("tsvector")? // Full-text search
|
|
94
|
+
location Unsupported("geometry")? // PostGIS Point
|
|
95
|
+
|
|
96
|
+
// CORE IDENTIFICATION
|
|
97
|
+
reference String @unique // Código único
|
|
98
|
+
title String // Título
|
|
99
|
+
description String // Descrição
|
|
100
|
+
|
|
101
|
+
// COMMERCIAL
|
|
102
|
+
operacao String[] // ["venda", "locacao", "temporada"]
|
|
103
|
+
valor_venda Float? // Preço venda
|
|
104
|
+
valor_locacao Float? // Preço aluguel
|
|
105
|
+
valor_diaria Float? // Preço diária
|
|
106
|
+
|
|
107
|
+
// STRUCTURE
|
|
108
|
+
area_total Float? // Área m²
|
|
109
|
+
dormitorios Int? // Quartos
|
|
110
|
+
banheiros Int? // Banheiros
|
|
111
|
+
vagas_garagem Int? // Vagas
|
|
112
|
+
tipo String? // casa, apartamento
|
|
113
|
+
subtipo String? // cobertura, duplex
|
|
114
|
+
|
|
115
|
+
// LOCATION
|
|
116
|
+
endereco_cidade String? // Cidade
|
|
117
|
+
endereco_bairro String? // Bairro
|
|
118
|
+
endereco_logradouro String? // Rua
|
|
119
|
+
lat Float? // Latitude
|
|
120
|
+
lng Float? // Longitude
|
|
121
|
+
|
|
122
|
+
// CHARACTERISTICS
|
|
123
|
+
caracteristicas String[] // ["piscina", "churrasqueira"]
|
|
124
|
+
tags String[] // Tags livres
|
|
125
|
+
|
|
126
|
+
// BROKER/AGENT
|
|
127
|
+
corretor_nome String? // Nome broker
|
|
128
|
+
|
|
129
|
+
// CONDOMINIUM
|
|
130
|
+
condominio_nome String? // Nome condomínio
|
|
131
|
+
condominio_comodidades String[] // ["academia", "sauna"]
|
|
132
|
+
|
|
133
|
+
// JETIMOB ESPECÍFICOS (50+ campos adicionais)
|
|
134
|
+
// ... muitos outros campos do provider
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### **Colunas Especiais Geradas**
|
|
139
|
+
```sql
|
|
140
|
+
-- Full-text search (25+ campos indexados)
|
|
141
|
+
ALTER TABLE "Property"
|
|
142
|
+
ADD COLUMN search_tsvector tsvector GENERATED ALWAYS AS (
|
|
143
|
+
immutable_to_tsvector(
|
|
144
|
+
coalesce("title",'') || ' ' ||
|
|
145
|
+
coalesce("description",'') || ' ' ||
|
|
146
|
+
coalesce("endereco_cidade",'') || ' ' ||
|
|
147
|
+
coalesce("endereco_bairro",'') || ' ' ||
|
|
148
|
+
coalesce(immutable_array_to_string("caracteristicas", ' '),'')
|
|
149
|
+
-- ... 25+ campos searchables
|
|
150
|
+
)
|
|
151
|
+
) STORED;
|
|
152
|
+
|
|
153
|
+
-- Geospatial Point (PostGIS)
|
|
154
|
+
ALTER TABLE "Property"
|
|
155
|
+
ADD COLUMN location geometry(Point, 4326) GENERATED ALWAYS AS (
|
|
156
|
+
ST_SetSRID(ST_MakePoint(lng::double precision, lat::double precision), 4326)
|
|
157
|
+
) STORED;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## **SSOT v2.0 - Single Source of Truth**
|
|
163
|
+
|
|
164
|
+
### **Arquivo:** `src/modules/property/config/entity-schema.ts`
|
|
165
|
+
|
|
166
|
+
**Sistema hierárquico** de metadados que define TODA a estrutura da entidade Property:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
interface FieldSchema {
|
|
170
|
+
key: string; // Nome campo
|
|
171
|
+
type: string; // Tipo TypeScript
|
|
172
|
+
categories: string[]; // Agrupamento
|
|
173
|
+
validation?: Record<string, any>; // Regras Zod
|
|
174
|
+
ui: {
|
|
175
|
+
label: string; // Label UI
|
|
176
|
+
description: string; // Descrição
|
|
177
|
+
searchable?: boolean; // Se é searchable
|
|
178
|
+
filterable?: boolean; // Se é filterable
|
|
179
|
+
// ... mais configs UI
|
|
180
|
+
};
|
|
181
|
+
audit: {
|
|
182
|
+
origin: string; // Origem do campo
|
|
183
|
+
};
|
|
184
|
+
enum?: Record<string, string>; // Valores enum
|
|
185
|
+
rules?: { // Regras condicionais
|
|
186
|
+
conditions?: string[];
|
|
187
|
+
parent?: string;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### **Benefícios SSOT:**
|
|
193
|
+
- **Zero hardcoding** - Tudo baseado no schema
|
|
194
|
+
- **Geração automática** - Zod schemas + TypeScript types
|
|
195
|
+
- **Documentação viva** - Schema é a documentação
|
|
196
|
+
- **Validação consistente** - Uma fonte, múltiplos usos
|
|
197
|
+
- **90+ campos estruturados** - Jetimob + Horizon + Custom
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## **Advanced Search Library**
|
|
202
|
+
|
|
203
|
+
### **8 Módulos Isolados**
|
|
204
|
+
|
|
205
|
+
| Módulo | Responsabilidade | Funcionalidade |
|
|
206
|
+
|--------|------------------|----------------|
|
|
207
|
+
| **`index.ts`** | API principal | Orquestra busca multipart |
|
|
208
|
+
| **`types.ts`** | Tipos TypeScript | SearchRequest, Response, Config |
|
|
209
|
+
| **`extractIds.ts`** | Extração IDs | Full-text + geolocalização |
|
|
210
|
+
| **`executeList.ts`** | Lista paginada | SELECT + include + pagination |
|
|
211
|
+
| **`executeMap.ts`** | Dados mapa | Lat/lng otimizado |
|
|
212
|
+
| **`executeTotal.ts`** | Contagem | COUNT queries |
|
|
213
|
+
| **`executeFacets.ts`** | Agregações | GROUP BY dinâmicos |
|
|
214
|
+
| **`helpers.ts`** | DMMF Introspection | Detecção automática tipos |
|
|
215
|
+
|
|
216
|
+
### **API Super Simples**
|
|
217
|
+
```typescript
|
|
218
|
+
// 95% automático, 5% configurado
|
|
219
|
+
const config = {
|
|
220
|
+
modelName: 'Property',
|
|
221
|
+
searchColumn: 'search_tsvector', // opcional
|
|
222
|
+
locationColumn: 'location' // opcional
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const result = await advancedSearch(prisma, request, config);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### **Funcionalidades Avançadas**
|
|
229
|
+
|
|
230
|
+
#### **1. Prisma DMMF Introspection**
|
|
231
|
+
```typescript
|
|
232
|
+
// Detecta automaticamente se campo é array ou simples
|
|
233
|
+
export function getFieldType(prisma, modelName, fieldName): 'array' | 'simple' {
|
|
234
|
+
const field = prisma.dmmf.datamodel.models
|
|
235
|
+
.find(m => m.name === modelName)
|
|
236
|
+
.fields.find(f => f.name === fieldName);
|
|
237
|
+
|
|
238
|
+
return field.isList ? 'array' : 'simple';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Usa operador correto automaticamente
|
|
242
|
+
if (Array.isArray(value)) {
|
|
243
|
+
const fieldType = getFieldType(prisma, modelName, key);
|
|
244
|
+
where[key] = fieldType === 'array'
|
|
245
|
+
? { hasSome: value } // String[] field
|
|
246
|
+
: { in: value }; // String field
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### **2. Busca Multipart**
|
|
251
|
+
```typescript
|
|
252
|
+
// Uma requisição → múltiplas respostas
|
|
253
|
+
const request = {
|
|
254
|
+
filters: { endereco_cidade: "Florianópolis" },
|
|
255
|
+
search: { value: "casa piscina" },
|
|
256
|
+
location: {
|
|
257
|
+
operation: "within",
|
|
258
|
+
geometry: { type: "bbox", bounds: {...} }
|
|
259
|
+
},
|
|
260
|
+
list: { page: 1, limit: 10 }, // Lista paginada
|
|
261
|
+
map: { fields: ["lat", "lng"] }, // Dados mapa
|
|
262
|
+
meta: { total: true }, // Contagem
|
|
263
|
+
facets: { fields: ["tipo"] } // Agregações
|
|
264
|
+
};
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## **API Endpoints**
|
|
270
|
+
|
|
271
|
+
### **Pattern "Ponte Seca"**
|
|
272
|
+
Routes em `/app/api/` apenas exportam controllers:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// /app/api/property/search/route.ts
|
|
276
|
+
export { POST } from '@/modules/property/controllers/search.controller';
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### **Endpoints Disponíveis**
|
|
280
|
+
|
|
281
|
+
| Método | Endpoint | Função | Controller |
|
|
282
|
+
|--------|----------|---------|-----------|
|
|
283
|
+
| `POST` | `/api/property/search` | Busca multipart | search.controller.ts |
|
|
284
|
+
| `POST` | `/api/property/find` | Busca criteria | find.controller.ts |
|
|
285
|
+
| `GET` | `/api/property/sync` | Listing integração | sync.controller.ts |
|
|
286
|
+
| `PUT` | `/api/property/sync` | Upsert batch | sync.controller.ts |
|
|
287
|
+
| `GET` | `/api/property/schemas/entity` | Schema SSOT | schemas.controller.ts |
|
|
288
|
+
|
|
289
|
+
### **Exemplo Busca Multipart**
|
|
290
|
+
```bash
|
|
291
|
+
curl -X POST http://localhost:5000/api/property/search \
|
|
292
|
+
-H "Content-Type: application/json" \
|
|
293
|
+
-d '{
|
|
294
|
+
"filters": {
|
|
295
|
+
"endereco_cidade": "Florianópolis",
|
|
296
|
+
"operacao": ["venda"],
|
|
297
|
+
"dormitorios": [2, 3, 4]
|
|
298
|
+
},
|
|
299
|
+
"search": {
|
|
300
|
+
"value": "apartamento com piscina"
|
|
301
|
+
},
|
|
302
|
+
"location": {
|
|
303
|
+
"operation": "within",
|
|
304
|
+
"geometry": {
|
|
305
|
+
"type": "bbox",
|
|
306
|
+
"bounds": {
|
|
307
|
+
"north": -27.5,
|
|
308
|
+
"south": -27.7,
|
|
309
|
+
"east": -48.4,
|
|
310
|
+
"west": -48.6
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
"list": {
|
|
315
|
+
"page": 1,
|
|
316
|
+
"limit": 20,
|
|
317
|
+
"select": {
|
|
318
|
+
"id": true,
|
|
319
|
+
"title": true,
|
|
320
|
+
"valor_venda": true,
|
|
321
|
+
"area_total": true,
|
|
322
|
+
"dormitorios": true
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
"map": {
|
|
326
|
+
"select": {
|
|
327
|
+
"id": true,
|
|
328
|
+
"lat": true,
|
|
329
|
+
"lng": true,
|
|
330
|
+
"valor_venda": true
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
"meta": { "total": true },
|
|
334
|
+
"facets": {
|
|
335
|
+
"fields": [
|
|
336
|
+
{ "type": "terms", "field": "tipo" },
|
|
337
|
+
{ "type": "terms", "field": "endereco_bairro" },
|
|
338
|
+
{ "type": "range", "field": "valor_venda", "buckets": [100000, 300000, 500000] }
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
}'
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Response:**
|
|
345
|
+
```json
|
|
346
|
+
{
|
|
347
|
+
"results": {
|
|
348
|
+
"list": {
|
|
349
|
+
"data": [
|
|
350
|
+
{
|
|
351
|
+
"id": 1,
|
|
352
|
+
"title": "Apartamento 3 dormitórios com piscina",
|
|
353
|
+
"valor_venda": 450000,
|
|
354
|
+
"area_total": 120.50,
|
|
355
|
+
"dormitorios": 3
|
|
356
|
+
}
|
|
357
|
+
],
|
|
358
|
+
"meta": {
|
|
359
|
+
"page": 1,
|
|
360
|
+
"limit": 20,
|
|
361
|
+
"total": 150,
|
|
362
|
+
"totalPages": 8,
|
|
363
|
+
"hasNextPage": true
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
"map": {
|
|
367
|
+
"data": [
|
|
368
|
+
{
|
|
369
|
+
"id": 1,
|
|
370
|
+
"lat": -27.5969,
|
|
371
|
+
"lng": -48.5495,
|
|
372
|
+
"valor_venda": 450000
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
"meta": { "totalWithCoordinates": 127 }
|
|
376
|
+
},
|
|
377
|
+
"meta": { "total": 150 },
|
|
378
|
+
"facets": {
|
|
379
|
+
"data": {
|
|
380
|
+
"tipo": [
|
|
381
|
+
{ "value": "apartamento", "count": 89 },
|
|
382
|
+
{ "value": "casa", "count": 61 }
|
|
383
|
+
],
|
|
384
|
+
"endereco_bairro": [
|
|
385
|
+
{ "value": "Centro", "count": 45 },
|
|
386
|
+
{ "value": "Trindade", "count": 32 }
|
|
387
|
+
],
|
|
388
|
+
"valor_venda": [
|
|
389
|
+
{ "range": "0-100000", "count": 15 },
|
|
390
|
+
{ "range": "100000-300000", "count": 67 },
|
|
391
|
+
{ "range": "300000-500000", "count": 42 },
|
|
392
|
+
{ "range": "500000+", "count": 26 }
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
"metadata": {
|
|
398
|
+
"executionTime": 89
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## **Testes Completos**
|
|
406
|
+
|
|
407
|
+
### **Suíte de Testes:** `__tests__/`
|
|
408
|
+
|
|
409
|
+
| Teste | Status | Descrição |
|
|
410
|
+
|-------|--------|-----------|
|
|
411
|
+
| `final-integration.test.ts` | | Teste integração completa API |
|
|
412
|
+
| `new-api-advanced-search.test.ts` | | API isolada biblioteca |
|
|
413
|
+
| `debug-advanced-search.test.ts` | | Debug específicos |
|
|
414
|
+
| `prisma-introspection.test.ts` | | DMMF introspection |
|
|
415
|
+
|
|
416
|
+
### **Executar Testes**
|
|
417
|
+
```bash
|
|
418
|
+
# Todos os testes
|
|
419
|
+
pnpm test
|
|
420
|
+
|
|
421
|
+
# Teste específico
|
|
422
|
+
pnpm vitest run __tests__/final-integration.test.ts
|
|
423
|
+
|
|
424
|
+
# Watch mode
|
|
425
|
+
pnpm test:watch
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## **Comandos Principais**
|
|
431
|
+
|
|
432
|
+
### **Desenvolvimento**
|
|
433
|
+
```bash
|
|
434
|
+
# Instalar dependências
|
|
435
|
+
pnpm install
|
|
436
|
+
|
|
437
|
+
# Desenvolvimento (porta 5000)
|
|
438
|
+
pnpm dev
|
|
439
|
+
|
|
440
|
+
# Build produção
|
|
441
|
+
pnpm build
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### **Database**
|
|
445
|
+
```bash
|
|
446
|
+
# Gerar Prisma Client
|
|
447
|
+
pnpm prisma:generate
|
|
448
|
+
|
|
449
|
+
# Push schema
|
|
450
|
+
pnpm prisma:push
|
|
451
|
+
|
|
452
|
+
# Executar fragment SQL
|
|
453
|
+
PGPASSWORD=$POSTGRES_PASSWORD psql $DATABASE_URL -f src/modules/property/config/database/fragment.sql
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### **Scripts Desenvolvimento**
|
|
457
|
+
```bash
|
|
458
|
+
# Upload dados Jetimob (chunks)
|
|
459
|
+
pnpm tsx __dev__/scripts/sync-properties-chunked.ts
|
|
460
|
+
|
|
461
|
+
# Geração Zod schemas
|
|
462
|
+
pnpm tsx __dev__/scripts/generate-zod.ts
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## **Migração Concluída**
|
|
468
|
+
|
|
469
|
+
### **FASE COMPLETA: IMOVEL → PROPERTY + CORRETOR → BROKER**
|
|
470
|
+
|
|
471
|
+
A aplicação passou por **migração completa** de nomenclatura e arquitetura:
|
|
472
|
+
|
|
473
|
+
- **Renomeação massiva** - 50+ arquivos atualizados
|
|
474
|
+
- **Database migration** - Tabelas Property + Broker
|
|
475
|
+
- **API endpoints** - `/api/property/*` funcionais
|
|
476
|
+
- **Type-safety** - Zero breaking changes
|
|
477
|
+
- **Backward compatibility** - Sistemas legados funcionando
|
|
478
|
+
- **Tests passing** - Suíte completa validada
|
|
479
|
+
|
|
480
|
+
### **Scripts de Migração**
|
|
481
|
+
```bash
|
|
482
|
+
# Aplicados e concluídos:
|
|
483
|
+
./__dev__/scripts/rename-imovel-to-property.sh
|
|
484
|
+
./__dev__/scripts/rename-corretor-to-broker.sh
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## **Performance & Otimizações**
|
|
490
|
+
|
|
491
|
+
### **Índices Database**
|
|
492
|
+
- **B-Tree:** reference, created_at, tipo, endereco_cidade
|
|
493
|
+
- **GIN:** search_tsvector (full-text)
|
|
494
|
+
- **GIST:** location (geospatial)
|
|
495
|
+
- **Composite:** [lat, lng], [status], [valor_venda]
|
|
496
|
+
|
|
497
|
+
### **Queries Otimizadas**
|
|
498
|
+
- **Select específico** por tipo resposta
|
|
499
|
+
- **Execução paralela** de múltiplas queries
|
|
500
|
+
- **Prepared statements** via Prisma
|
|
501
|
+
- **Paginação eficiente** com limit/offset
|
|
502
|
+
|
|
503
|
+
### **Caching**
|
|
504
|
+
- **Prisma Client** singleton
|
|
505
|
+
- **ETag** para schemas estáticos
|
|
506
|
+
- **Database connection pooling**
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## **Dados Atuais**
|
|
511
|
+
|
|
512
|
+
### **Status Database**
|
|
513
|
+
- **1.076 propriedades** Jetimob importadas
|
|
514
|
+
- **search_tsvector** populado em todas
|
|
515
|
+
- **location geometry** populado com lat/lng válidos
|
|
516
|
+
- **Índices** todos criados e funcionais
|
|
517
|
+
|
|
518
|
+
### **Coverage Campos**
|
|
519
|
+
- **90+ campos** mapeados no SSOT
|
|
520
|
+
- **25+ campos** indexados para busca full-text
|
|
521
|
+
- **Geolocalização** em 98% das propriedades
|
|
522
|
+
- **Arrays** (caracteristicas, operacao, tags) funcionais
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## **Próximos Passos**
|
|
527
|
+
|
|
528
|
+
### **Funcionalidades Futuras**
|
|
529
|
+
- [ ] **Cache avançado** (Redis)
|
|
530
|
+
- [ ] **API versioning** (v1/v2)
|
|
531
|
+
- [ ] **GraphQL endpoint** (opcional)
|
|
532
|
+
- [ ] **Webhooks** para integração
|
|
533
|
+
- [ ] **Rate limiting**
|
|
534
|
+
- [ ] **Authentication/Authorization**
|
|
535
|
+
|
|
536
|
+
### **Melhorias Técnicas**
|
|
537
|
+
- [ ] **Monitoring** (APM)
|
|
538
|
+
- [ ] **Logging estruturado**
|
|
539
|
+
- [ ] **Health checks** avançados
|
|
540
|
+
- [ ] **Docker deployment**
|
|
541
|
+
- [ ] **CI/CD pipeline**
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## **Equipe & Contato**
|
|
546
|
+
|
|
547
|
+
**Desenvolvido por:** Jefferson Rosa
|
|
548
|
+
**Versão:** 3.0.0
|
|
549
|
+
**Status:** **PRODUÇÃO PRONTA**
|
|
550
|
+
**Última Atualização:** 23/08/2025
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## **Conclusão**
|
|
555
|
+
|
|
556
|
+
Este projeto representa uma **evolução significativa** na arquitetura de APIs imobiliárias:
|
|
557
|
+
|
|
558
|
+
- **Arquitetura moderna** e escalável
|
|
559
|
+
- **Type safety** em toda stack
|
|
560
|
+
- **Biblioteca reutilizável** isolada
|
|
561
|
+
- **Performance otimizada** com PostGIS
|
|
562
|
+
- **API robusta** com validação completa
|
|
563
|
+
- **Migração completa** do sistema legacy
|
|
564
|
+
- **Testes abrangentes** garantindo qualidade
|
|
565
|
+
|
|
566
|
+
A aplicação está **pronta para produção** e serve como **base sólida** para futuras expansões no ecossistema Nova Torres.
|