UNPKG

@horizon-modules/property-model-v3

Version:

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

344 lines (277 loc) 8 kB
# Property Customizer Sistema de transformação de dados PropertyV3 baseado em regras configuráveis. ## 🎯 Propósito O Property Customizer permite aplicar transformações complexas em dados PropertyV3 através de regras declarativas, sem necessidade de escrever código customizado para cada transformação. ## 🚀 Instalação ```bash pnpm add @horizon-modules/property-model-v3 ``` ## 📦 Importação ```typescript import { PropertyCustomizer, propertyV3CustomMapper, type MapRules, type PropertyV3 } from '@horizon-modules/property-model-v3' ``` ## 🔧 Uso Básico ### Usando a Classe ```typescript const mapRules: MapRules = { attributesRules: [ { key: "tipo", condition: { eq: "Casa" }, rules: [ { fn: "upsertAttr", key: "tipo", value: "Casa/Sobrado" }, { fn: "upsertAttr", key: "subtipo", value: "Casa" }, ] } ] } const customizer = new PropertyCustomizer(mapRules) const result = customizer.transform(propertyV3Data) ``` ### Usando a Função Helper ```typescript const result = propertyV3CustomMapper(propertyV3Data, mapRules) ``` ## 📋 Estrutura das Regras ### Reference Rules Aplicam transformações baseadas na referência do imóvel: ```typescript const mapRules: MapRules = { referenceRules: { 'REF-123': [ { fn: 'upsertAttr', key: 'destaque', value: true }, { fn: 'addToArray', key: 'tags', value: 'premium' } ], 'REF-456': [ { fn: 'upsertAttr', key: 'promocao', value: true } ] } } ``` ### Attributes Rules Aplicam transformações baseadas em condições dos atributos: ```typescript 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: 'dormitorios', condition: { gte: 3 }, rules: [ { fn: 'addToArray', key: 'tags', value: 'muitos-quartos' } ] } ] } ``` ## 🎮 Actions Disponíveis ### upsertAttr Cria ou atualiza um atributo: ```typescript { fn: 'upsertAttr', key: 'piscina', value: true } ``` ### removeAttr Remove um atributo: ```typescript { fn: 'removeAttr', key: 'campo_antigo' } ``` ### addToArray Adiciona valor(es) a um array: ```typescript // Adicionar um valor { fn: 'addToArray', key: 'tags', value: 'nova-tag' } // Adicionar múltiplos valores { fn: 'addToArray', key: 'caracteristicas', value: ['item1', 'item2'] } ``` ### removeFromArray Remove um valor de um array: ```typescript { fn: 'removeFromArray', key: 'caracteristicas', value: 'Piscina' } ``` ## 🎯 Condições Suportadas ### Igualdade - `eq` - igual a - `not_eq` - diferente de ### Arrays - `has` - contém todos os valores - `has_any` - contém pelo menos um valor - `not_has` - não contém valor(es) ### Numéricos - `gt` - maior que - `gte` - maior ou igual - `lt` - menor que - `lte` - menor ou igual ### Texto - `contains` - contém substring (case insensitive) - `starts_with` - começa com (case insensitive) - `ends_with` - termina com (case insensitive) ### Booleanos - `is_true` - é verdadeiro (true, "true", 1) - `is_false` - é falso (false, "false", 0) ### Existência - `exists` - campo existe e não está vazio - `not_exists` - campo não existe ou está vazio ## 📝 Placeholders Use `{{value}}` para referenciar o valor do atributo atual: ```typescript { key: 'area', condition: { exists: true }, rules: [ { fn: 'upsertAttr', key: 'area_formatada', value: '{{value}} m²' } ] } ``` ## 🏷️ Tags de Description O Property Customizer processa automaticamente tags especiais na description: ### Tags Simples ```typescript const property: PropertyV3 = { description: 'Casa linda [[description-en]]Beautiful house[[/description-en]] com vista' } // Após processamento: // property.attributes.description_en = 'Beautiful house' // property.description = 'Casa linda com vista' ``` ### Custom Attributes (JSON) ```typescript const property: PropertyV3 = { description: `Imóvel especial [[custom-attributes]] { "energia_solar": true, "classificacao": "A+" } [[/custom-attributes]] Com tecnologia sustentável` } // Após processamento: // property.attributes.energia_solar = true // property.attributes.classificacao = 'A+' // property.description = 'Imóvel especial\nCom tecnologia sustentável' ``` ## 💡 Exemplos Práticos ### Transformar Características em Campos Booleanos ```typescript const mapRules: MapRules = { attributesRules: [ { key: 'caracteristicas', condition: { has_any: ['Piscina'] }, rules: [ { fn: 'removeFromArray', key: 'caracteristicas', value: 'Piscina' }, { fn: 'upsertAttr', key: 'piscina', value: true } ] }, { key: 'caracteristicas', condition: { has_any: ['Churrasqueira'] }, rules: [ { fn: 'removeFromArray', key: 'caracteristicas', value: 'Churrasqueira' }, { fn: 'upsertAttr', key: 'churrasqueira', value: true } ] } ] } ``` ### Normalizar Tipos de Imóveis ```typescript 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: 'tipo', condition: { eq: 'Apartamento Duplex' }, rules: [ { fn: 'upsertAttr', key: 'tipo', value: 'Apartamento' }, { fn: 'upsertAttr', key: 'subtipo', value: 'Duplex' } ] } ] } ``` ### Adicionar Tags Baseadas em Corretor ```typescript const mapRules: MapRules = { attributesRules: [ { key: 'tags', condition: { has_any: ['agente-elvis'] }, rules: [ { fn: 'upsertAttr', key: 'corretor_id', value: 'elvis-ghisi' }, { fn: 'upsertAttr', key: 'corretor_nome', value: 'Elvis Ghisi' }, { fn: 'addToArray', key: 'tags', value: 'corretor-premium' } ] } ] } ``` ## 🧪 Testando ```typescript import { describe, it, expect } from 'vitest' import { propertyV3CustomMapper } from '@horizon-modules/property-model-v3' describe('Minhas regras customizadas', () => { it('deve transformar corretamente', () => { const property = { attributes: { tipo: 'Casa de Condomínio' } } const result = propertyV3CustomMapper(property, mapRules) expect(result.attributes.tipo).toBe('Casa/Sobrado') expect(result.attributes.subtipo).toBe('Casa') }) }) ``` ## 📌 Notas Importantes 1. O Property Customizer **não modifica** o objeto original, sempre retorna uma cópia 2. As regras são aplicadas na ordem: description tags reference rules attribute rules 3. Para arrays, o `addToArray` automaticamente evita duplicatas usando `union` 4. Condições de texto são case-insensitive 5. Placeholders são resolvidos dinamicamente durante a execução ## 🔄 Migração de Código Legado Se você tem código customizado para transformações, pode migrar facilmente: **Antes:** ```typescript if (property.attributes.tipo === 'Casa de Condomínio') { property.attributes.tipo = 'Casa/Sobrado' property.attributes.subtipo = 'Casa' property.attributes.tags = [...(property.attributes.tags || []), 'em-condominio'] } ``` **Depois:** ```typescript 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' } ] }] } const result = propertyV3CustomMapper(property, mapRules) ```