UNPKG

@horizon-modules/property-model-v3

Version:

Modelo de propriedades imobiliárias v3 - Sistema de atributos dinâmicos

689 lines (549 loc) 19.1 kB
# @horizon-modules/property-model-v3 Sistema completo para modelagem de propriedades imobiliárias V3 com **atributos dinâmicos**, **validação Zod**, **profiling de dados** e **pipeline de desenvolvimento automatizado**. ## 📦 Instalação ```bash npm install @horizon-modules/property-model-v3 # ou pnpm add @horizon-modules/property-model-v3 ``` ## 🚀 Uso Básico ```typescript import { PropertyModel, PropertyModelSchema, validatePropertyModel, safeValidatePropertyModel, generateFakeProperty, PropertyModelJsonSchema } from '@horizon-modules/property-model-v3'; // Exemplo de propriedade V3 const property: PropertyModel = { reference: "AP001_V3", title: "Apartamento Premium - 3 qtos, 150m²", description: "Apartamento moderno com acabamentos de primeira linha...", attributes: { tipo: "Apartamento", operacao: ["venda"], dormitorios: 3, banheiros: 2, area_util: 150, valor_venda: 850000, endereco_cidade: "São Paulo", endereco_bairro: "Vila Madalena" }, media_assets: { images: [ { full: "https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=800&q=80", cover: true } ] }, settings: { currency_unit: "BRL", area_unit: "m2", exibir_no_mapa: true } }; // Validação com Zod const validProperty = validatePropertyModel(property); // Validação safe (nunca lança erro) const result = safeValidatePropertyModel(property); if (result.success) { console.log("Propriedade válida:", result.data); } else { console.log("Erros:", result.error.issues); } // Gerar dados fake const fakeProperty = generateFakeProperty("apartamento"); ``` ## 🏗️ Arquitetura PropertyModel V3 ### Estrutura Principal ```typescript interface PropertyModel { reference: string // Código único title: string // Título da propriedade description: string // Descrição detalhada attributes: Record<string, any> // Atributos dinâmicos media_assets: MediaAssets // Fotos, vídeos, tours settings?: SettingsFormat // Configurações de formato updated_at?: string // Data de atualização } ``` ### Sistema de Atributos Dinâmicos O V3 substitui o array de atributos por um **objeto chave-valor** mais flexível: ```typescript // V2 (antigo) attributes: [ { key: "dormitorios", value: 3 }, { key: "valor_venda", value: 850000, unit: "BRL" } ] // V3 (novo) attributes: { dormitorios: 3, valor_venda: 850000, endereco_cidade: "São Paulo", caracteristicas: ["Churrasqueira", "Piscina"] } ``` **Benefícios do V3:** - ✅ Acesso direto: `property.attributes.dormitorios` - ✅ Menos verboso e mais legível - ✅ Melhor performance em consultas - ✅ Compatível com NoSQL (MongoDB, DynamoDB) - ✅ Validação Zod nativa ### Media Assets ```typescript interface MediaAssets { images?: ImageMedia[] // Fotos do imóvel videos?: VideoMedia[] // Vídeos (YouTube, Vimeo) virtual_tours?: VirtualTourMedia[] // Tours 360° documents?: DocumentMedia[] // PDFs, documentos } interface ImageMedia { full: string // URL da imagem completa md?: string // Versão 640x480 sm?: string // Versão 320x240 cover?: boolean // Se é imagem principal } ``` ## 🎨 Gerador de Dados Fake Avançado Sistema baseado em **profiling de dados reais** do Arbo CRM com **20+ atributos por imóvel**: ```typescript import { generateFakeProperty, generateFakeProperties, generateFakePropertyByType, getAvailablePropertyTypes } from '@horizon-modules/property-model-v3'; // Gerar uma propriedade aleatória const property = generateFakeProperty(); // Gerar 50 propriedades const properties = generateFakeProperties(50); // Gerar tipo específico const apartamento = generateFakePropertyByType("apartamento"); const casa = generateFakePropertyByType("casa"); const terreno = generateFakePropertyByType("terreno"); // Ver tipos disponíveis console.log(getAvailablePropertyTypes()); // ["apartamento", "casa", "sobrado", "terreno", "comercial"] ``` ### Características dos Dados Fake - **📍 Localização brasileira**: 5 cidades + bairros reais - **💰 Valores realistas**: Baseados em dados reais do Arbo CRM - **🏠 Atributos contextuais**: 20-30 atributos por tipo de imóvel - **🖼️ Imagens Unsplash**: URLs funcionais categorizadas por tipo - **⚡ Performance**: Baseado em profiling estatístico ### Exemplo de Propriedade Fake Gerada ```json { "reference": "FAKE_APARTAMENTOS_001", "title": "Apartamento Premium - 3 qtos, 150m², 3 vagas", "description": "Apartamento moderno com acabamentos de primeira linha...", "attributes": { "tipo": "Apartamento", "operacao": ["venda"], "dormitorios": 3, "banheiros": 2, "suites": 1, "vagas": 3, "area_util": 150, "area_total": 180, "valor_venda": 1200000, "valor_condominio": 800, "andar": 12, "endereco_cidade": "São Paulo", "endereco_estado": "SP", "endereco_bairro": "Vila Madalena", "endereco_cep": "05414-000", "caracteristicas": ["Churrasqueira", "Piscina", "Academia"], "mobiliado": false, "aceita_pets": true, "portao_eletronico": true }, "media_assets": { "images": [ { "full": "https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=800&q=80", "cover": true } ] } } ``` ## 📊 ProfilerService - Análise de Dados Ferramenta para **análise estatística** de datasets PropertyModel: ```typescript import { ProfilerService, profileProperties } from '@horizon-modules/property-model-v3'; // Análise de arquivos const profiler = new ProfilerService({ inputDir: './data/properties', outputDir: './output', fieldConfigs: { 'attributes.endereco_cidade': { maxExamples: 50 }, 'attributes.caracteristicas': { maxExamples: 100 } } }); const report = await profiler.profile(); console.log(report); // { // "attributes.tipo": ["Casa", "Apartamento", "Terreno"], // "attributes.endereco_cidade": ["São Paulo", "Rio de Janeiro", ...], // "attributes.caracteristicas": ["Churrasqueira", "Piscina", ...] // } // Análise em memória const inMemoryReport = await profileProperties(propertyArray); ``` **Características:** - ✅ **Concatena arrays**: Arrays de strings viram lista única de valores - ✅ **Objetos aninhados**: Analisa `attributes.endereco_cidade` - ✅ **Configurável**: Controle de quantos exemplos por campo - ✅ **Genérico**: Funciona com qualquer estrutura JSON ## 🎨 Property Customizer - Transformação Baseada em Regras Sistema para aplicar transformações complexas em dados PropertyV3 através de regras declarativas: ```typescript import { PropertyCustomizer, type MapRules } from '@horizon-modules/property-model-v3'; // Definir regras de transformação const mapRules: MapRules = { attributesRules: [ { key: 'tipo', condition: { eq: 'Casa de Condomínio' }, rules: [ { fn: 'upsertAttr', key: 'tipo', value: 'Casa/Sobrado' }, { fn: 'upsertAttr', key: 'subtipo', value: 'Casa' }, { fn: 'addToArray', key: 'tags', value: 'em-condominio' } ] }, { key: 'caracteristicas', condition: { has_any: ['Piscina'] }, rules: [ { fn: 'removeFromArray', key: 'caracteristicas', value: 'Piscina' }, { fn: 'upsertAttr', key: 'piscina', value: true } ] } ] }; // Aplicar transformações const transformedProperty = PropertyCustomizer(property, mapRules); ``` ### Actions Disponíveis - **upsertAttr**: Criar/atualizar atributo - **removeAttr**: Remover atributo - **addToArray**: Adicionar valores a array - **removeFromArray**: Remover valores de array ### Condições Suportadas - **Igualdade**: `eq`, `not_eq` - **Arrays**: `has`, `has_any`, `not_has` - **Numéricos**: `gt`, `gte`, `lt`, `lte` - **Texto**: `contains`, `starts_with`, `ends_with` - **Booleanos**: `is_true`, `is_false` - **Existência**: `exists`, `not_exists` ### Tags na Description O sistema processa automaticamente tags especiais na description: ```typescript const property = { description: `Casa linda [[description-en]]Beautiful house[[/description-en]] [[custom-attributes]] { "energia_solar": true, "classificacao": "A+" } [[/custom-attributes]] Com vista para o mar` }; // Após processamento: // property.attributes.description_en = 'Beautiful house' // property.attributes.energia_solar = true // property.description = 'Casa linda Com vista para o mar' ``` ## 🌐 ApiClientService - Cliente HTTP Cliente para envio de dados PropertyModel para APIs externas: ```typescript import { ApiClientService } from '@horizon-modules/property-model-v3'; const client = new ApiClientService({ endpoint: 'https://api.imobiliaria.com/properties', headers: { 'Authorization': 'Bearer token' }, batchSize: 10 // Processa 10 por vez }); // Enviar uma propriedade await client.sendProperty(property); // Enviar múltiplas propriedades await client.sendProperties([prop1, prop2, prop3]); // Enviar de pasta com JSONs await client.sendPropertiesFromDir('./data/fake-properties'); ``` **Formatos suportados:** - Array direto: `[prop1, prop2]` - Formato data: `{ "data": [prop1, prop2] }` - Categorizado: `{ "apartamentos": [prop1], "casas": [prop2] }` ## 🔒 Validação com Zod Sistema robusto de validação em runtime: ```typescript import { PropertyModelSchema, validatePropertyModel, safeValidatePropertyModel } from '@horizon-modules/property-model-v3'; // Validação direta (lança erro se inválido) const property = validatePropertyModel(unknownData); // Validação safe (nunca lança erro) const result = safeValidatePropertyModel(unknownData); if (result.success) { console.log("✅ Válido:", result.data); } else { console.log("❌ Erros:", result.error.issues); } // Schema customizado const StrictSchema = PropertyModelSchema.extend({ reference: z.string().min(5).max(20) }); ``` ## 📋 JSON Schema Export Schemas JSON para validação externa: ```typescript import { PropertyModelJsonSchema, PropertyTypeSchemaJson } from '@horizon-modules/property-model-v3'; // Usar com validadores JSON Schema import Ajv from 'ajv'; const ajv = new Ajv(); const validate = ajv.compile(PropertyModelJsonSchema); const isValid = validate(propertyData); if (!isValid) { console.log(validate.errors); } ``` ## 🛠️ Scripts de Desenvolvimento Pipeline completo para desenvolvimento de dados: ### Scripts Principais ```bash # Baixar dados reais do Arbo CRM npm run dev:download # Baixar dados fake do pacote arbo-crm npm run dev:download-arbo-fake # Converter dados Arbo para PropertyModel V3 npm run dev:convert # Fazer profiling dos dados convertidos npm run dev:profile # Gerar dados fake baseados no profiling npm run dev:fake # Gerar mocks para testes npm run dev:mocks # Gerar JSON Schema npm run dev:json-schema # Testar JSON Schema npm run dev:test-json-schema # Pipeline completo npm run dev:all ``` ### Estrutura de Desenvolvimento ``` __dev__/ ├── data/ # Dados temporários (não commitados) │ ├── arbo-downloads/ # Dados reais do Arbo CRM │ ├── arbo-fake-data-output/ # Dados fake do arbo-crm package │ ├── property-v3-converted/ # Dados convertidos para V3 │ ├── property-v3-profiling/ # Relatórios de profiling │ ├── property-v3-fake-data-output/ # Dados fake gerados │ ├── property-v3-mock-output/ # Mocks para testes │ └── json-schema/ # JSON Schema gerado ├── scripts/ # Scripts de desenvolvimento │ ├── arbo-download-properties.ts # Baixa dados do Arbo │ ├── arbo-download-fake-data.ts # Baixa fake data do arbo-crm │ ├── arbo-convert-to-property-v3.ts # Converte para V3 │ ├── profile-properties.ts # Faz profiling │ ├── generate-fake-data.ts # Gera dados fake │ ├── generate-mocks.ts # Gera mocks │ ├── generate-json-schema.ts # Gera JSON Schema │ └── test-json-schema.ts # Testa JSON Schema ├── services/ # Serviços de desenvolvimento │ └── MockGeneratorService.ts # Gerador de mocks └── tests/ # Testes dos serviços dev └── MockGeneratorService.test.ts ``` ### Fluxo de Desenvolvimento 1. **🔄 Download**: `dev:download` → Baixa dados reais do Arbo CRM 2. **📊 Profiling**: `dev:profile` → Analisa padrões estatísticos nos dados 3. **🎨 Fake Data**: `dev:fake` → Gera dados fake baseados no profiling 4. **🧪 Mocks**: `dev:mocks` → Gera mocks para testes unitários 5. **📋 Schema**: `dev:json-schema` → Gera JSON Schema para validação externa ## 🏠 Modelo de Atributos Sistema com **96 atributos pré-definidos** em 8 categorias: ```typescript import { PropertyAttributesModel } from '@horizon-modules/property-model-v3'; // Ver todos os atributos disponíveis console.log(PropertyAttributesModel.length); // 96 // Atributos por categoria const comerciais = PropertyAttributesModel.filter(attr => attr.cat === "comercial"); const valores = PropertyAttributesModel.filter(attr => attr.cat === "valores"); const dependencias = PropertyAttributesModel.filter(attr => attr.cat === "dependencias"); // Buscar atributo específico const dormitorios = PropertyAttributesModel.find(attr => attr.key === "dormitorios"); console.log(dormitorios); // { key: "dormitorios", label: "Dormitórios", type: "Number", cat: "dependencias" } ``` ### Categorias de Atributos 1. **comercial** (8): `operacao`, `status_comercial`, `financiavel`, `aceita_permuta` 2. **valores** (12): `valor_venda`, `valor_locacao`, `valor_condominio`, `valor_iptu` 3. **situacoes** (6): `disponivel`, `reservado`, `vendido`, `alugado` 4. **localizacao** (15): `endereco_cidade`, `endereco_bairro`, `latitude`, `longitude` 5. **estrutura** (20): `tipo`, `subtipo`, `area_total`, `area_util`, `conservacao` 6. **dependencias** (8): `dormitorios`, `banheiros`, `suites`, `vagas` 7. **caracteristicas** (15): `mobiliado`, `aceita_pets`, `churrasqueira`, `piscina` 8. **corretor** (12): `corretor_nome`, `corretor_telefone`, `corretor_email` ## 🔧 Utilitários ```typescript import { verifyAttrKeyInPropertyV3Model, mergePropertyAttributesModel, sortAttributes, preparaAttrValueLabel, unitListModel, formatListModel } from '@horizon-modules/property-model-v3'; // Verificar se atributo existe const attr = verifyAttrKeyInPropertyV3Model("dormitorios"); // Mesclar modelos de atributos const customModel = mergePropertyAttributesModel( PropertyAttributesModel, [{ key: "piscina", label: "Piscina", type: "Boolean" }] ); // Formatar labels de arrays preparaAttrValueLabel(["venda", "locacao"]); // Retorna: "venda e locacao" // Unidades disponíveis console.log(unitListModel.currency); // [{ key: "BRL", label: "R$" }] console.log(unitListModel.area); // [{ key: "m2", label: "m²" }] ``` ## 🧪 Testes ```bash # Executar todos os testes npm run test # Testes com cobertura npm run test:coverage # Testes dos serviços de desenvolvimento npm run dev:test # Verificação de tipos npm run typecheck # Build npm run build ``` ## 📈 Exemplo Completo ```typescript import { generateFakeProperties, ProfilerService, ApiClientService, validatePropertyModel } from '@horizon-modules/property-model-v3'; async function exemploCompleto() { // 1. Gerar 100 propriedades fake console.log('🎨 Gerando dados fake...'); const properties = generateFakeProperties(100); // 2. Validar todas as propriedades console.log('🔍 Validando propriedades...'); const validProperties = properties.filter(prop => { try { validatePropertyModel(prop); return true; } catch { return false; } }); console.log(`✅ ${validProperties.length}/${properties.length} propriedades válidas`); // 3. Fazer profiling dos dados console.log('📊 Fazendo profiling...'); const profiler = new ProfilerService({ inputData: validProperties }); const report = await profiler.profile(); console.log('Tipos encontrados:', report['attributes.tipo']); console.log('Cidades encontradas:', report['attributes.endereco_cidade']); // 4. Enviar para API (exemplo) const client = new ApiClientService({ endpoint: 'https://api.exemplo.com/properties', batchSize: 5 }); console.log('🚀 Enviando para API...'); await client.sendProperties(validProperties.slice(0, 10)); console.log('🎉 Processo concluído!'); } exemploCompleto().catch(console.error); ``` ## 🚀 Integração com Arbo CRM O projeto integra nativamente com o `@horizon-modules/arbo-crm-integration`: ```typescript // Os scripts de desenvolvimento usam o arbo-crm-integration // para baixar dados reais e convertê-los para PropertyModel V3 // Dados reais → Profiling → Fake data realista // Este processo garante que os dados fake sejam baseados // em dados reais do mercado imobiliário brasileiro ``` ## 📦 Exports Principais ```typescript // Modelos e Tipos export type { PropertyModel, MediaAssets, SettingsFormat } // Schemas Zod export { PropertyModelSchema, validatePropertyModel, safeValidatePropertyModel } // JSON Schemas export { PropertyModelJsonSchema, PropertyTypeSchemaJson } // Gerador de Dados Fake export { generateFakeProperty, generateFakeProperties, generateFakePropertyByType } // Serviços export { ProfilerService, ApiClientService } // Property Customizer export { PropertyCustomizer } export type { PropertyV3, MapRules, AttributeRule, CustomAction } // Modelo de Atributos export { PropertyAttributesModel, unitListModel, formatListModel } // Utilitários export { verifyAttrKeyInPropertyV3Model, mergePropertyAttributesModel, sortAttributes } ``` ## 🔄 Migração do V2 para V3 ### Principais Mudanças 1. **Atributos**: Array → Objeto chave-valor 2. **Media**: `media` → `media_assets` com estrutura tipada 3. **Validação**: Zod schemas obrigatórios 4. **Settings**: Novo campo para configurações de formato ### Exemplo de Migração ```typescript // V2 const propertyV2 = { reference: "AP001", attributes: [ { key: "dormitorios", value: 3 }, { key: "valor_venda", value: 850000, unit: "BRL" } ], media: { pictures: ["foto1.jpg", "foto2.jpg"] } }; // V3 const propertyV3 = { reference: "AP001", title: "Apartamento 3 dormitórios", description: "Descrição do imóvel...", attributes: { dormitorios: 3, valor_venda: 850000 }, media_assets: { images: [ { full: "foto1.jpg", cover: true }, { full: "foto2.jpg", cover: false } ] }, settings: { currency_unit: "BRL", area_unit: "m2" } }; ``` --- ## 📄 Licença MIT - veja [LICENSE](LICENSE) para detalhes. **Desenvolvido pela Horizon Modules** 🏗️