@horizon-modules/property-model-v3
v3.6.0
Published
Modelo de propriedades imobiliárias v3 - Sistema de atributos dinâmicos
Maintainers
Readme
@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
npm install @horizon-modules/property-model-v3
# ou
pnpm add @horizon-modules/property-model-v3🚀 Uso Básico
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
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:
// 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
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:
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
{
"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:
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:
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:
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:
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:
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:
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
# 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:allEstrutura 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.tsFluxo de Desenvolvimento
- 🔄 Download:
dev:download→ Baixa dados reais do Arbo CRM - 📊 Profiling:
dev:profile→ Analisa padrões estatísticos nos dados - 🎨 Fake Data:
dev:fake→ Gera dados fake baseados no profiling - 🧪 Mocks:
dev:mocks→ Gera mocks para testes unitários - 📋 Schema:
dev:json-schema→ Gera JSON Schema para validação externa
🏠 Modelo de Atributos
Sistema com 96 atributos pré-definidos em 8 categorias:
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
- comercial (8):
operacao,status_comercial,financiavel,aceita_permuta - valores (12):
valor_venda,valor_locacao,valor_condominio,valor_iptu - situacoes (6):
disponivel,reservado,vendido,alugado - localizacao (15):
endereco_cidade,endereco_bairro,latitude,longitude - estrutura (20):
tipo,subtipo,area_total,area_util,conservacao - dependencias (8):
dormitorios,banheiros,suites,vagas - caracteristicas (15):
mobiliado,aceita_pets,churrasqueira,piscina - corretor (12):
corretor_nome,corretor_telefone,corretor_email
🔧 Utilitários
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
# 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
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:
// 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
// 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
- Atributos: Array → Objeto chave-valor
- Media:
media→media_assetscom estrutura tipada - Validação: Zod schemas obrigatórios
- Settings: Novo campo para configurações de formato
Exemplo de Migração
// 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 para detalhes.
Desenvolvido pela Horizon Modules 🏗️
