# Ficha Técnica — Conversão Jetimob → Horizon

Mapeamento campo-a-campo produzido por `convertJetimobPropertyToHorizon`.
Fonte da verdade é o código (`src/services/PropertyConverter/`); este doc resume.

A conversão tem duas partes:
- **`convertBaseFields`** → os 45 campos base do `HorizonPropertySchemaBase`
- **`convertExtendedFields`** → campos extras específicos da Jetimob

E o `convertJetimobPropertyToHorizon` ainda adiciona `sync_hash` (hash determinístico
do record convertido — usado pra delta).

---

## Campos base (Jetimob → Horizon)

| Jetimob (cru) | Horizon (base) | Regra |
|---|---|---|
| — | `source_key` | Fixo: `"jetimob-api-imoveis"` |
| `codigo` | `reference` | Direto |
| `titulo_anuncio` | `title` | Fallback `"Sem título"` |
| `observacoes` | `description` | Fallback `"Sem descrição"` |
| `data_update` ?? `updated_at` | `source_updated_at` | `"YYYY-MM-DD HH:mm:ss"` → ISO 8601. **Null se ausente — nunca inventado** |
| — | `source_published_at` | Sempre `null` (Jetimob não fornece) |
| `meta_description` | `seo_description` | Direto |
| — | `currency` / `unit_area` / `unit_distance` | Fixos: `BRL` / `m2` / `meters` |
| `contrato` | `operacao` | Split por vírgula → `["venda" \| "locacao" \| "temporada"]` (Compra→venda) |
| `subtipo` | `tipo` | Direto |
| `valor_venda` + `valor_venda_visivel` | `valor_venda` | Só se visível e > 0 |
| `valor_locacao` + `valor_locacao_visivel` | `valor_locacao` | Só se visível e > 0 |
| `valor_temporada` + `valor_temporada_visivel` | `valor_diaria` (extra) | Só se visível e > 0 |
| `valor_condominio` + `valor_condominio_visivel` | `valor_condominio` | Só se visível e ≥ 0 |
| `valor_iptu` + `valor_iptu_visivel` | `valor_iptu` | Só se visível e ≥ 0 |
| `area_total` / `area_privativa` / `area_util` | idem | Só se > 0 |
| `dormitorios` / `suites` / `banheiros` | idem | Direto |
| `garagens` | `vagas_garagem` | Direto |
| `endereco_cep` | `endereco_cep` | Formatado `00000-000`. Sem flag de visibilidade na Jetimob — sempre mapeado |
| `endereco_estado/cidade/bairro/logradouro/numero/complemento/referencia` | `endereco_*` | **Só se a flag `endereco_<campo>_visivel` for truthy.** A imobiliária marca no CRM o que é privado — `falsy`/ausente = campo omitido (privacy-first) |
| `endereco_zona` | `endereco_zona` | Direto — sem flag de visibilidade na Jetimob |
| `latitude` / `longitude` | `lat` / `lng` | Só se `geoposicionamento_visivel === 1` (exato) |
| `latitude` / `longitude` | `geo_aproximado` (extra) | Se `geoposicionamento_visivel === 2` — offset ~500m |
| `destaque` | `destaque` | `true` se `"Destaque"` / `"true"` (não `"Sem destaque"`) |
| `id_corretor` | `corretor_key` | `String()` |
| `id_condominio` | `condominio_key` | `String()` |
| `condominio_nome` | `condominio_nome` | Direto |
| `tags` | `tags` (extra) | Split por vírgula |
| `numero_pessoas` | `numero_pessoas` (extra) | Só se > 0 |
| `imagens[]` | `images[]` + `main_image` | `{ full, md: link_thumb, sm: link_thumb, cover }` |
| `videos[]` | `videos[]` | Jetimob guarda só o ID do YouTube → reconstrói `https://youtube.com/watch?v={id}` |
| `tour360[]` | `virtual_tours[]` | `{ embed_url }` |

---

## Campos extras Jetimob

Campos que não existem no schema base — declarados em
`HorizonPropertySchemaByJetimobZod`.

| Jetimob (cru) | Horizon (extra) | Observação |
|---|---|---|
| `id_imovel` | `id_imovel` | ID interno Jetimob. Pareia com `getListing().ref` e o filtro `?id=`. Distinto de `reference` (que é o `codigo`) |
| `tipo` | `finalidade` | A Jetimob chama de "tipo" o que o Horizon chama de finalidade |
| `mobiliado` | `mobiliado` | `1`/`"true"` → `true` |
| `financiavel` / `exclusividade` / `permuta` / `seguro_fianca` | idem | Booleanos (`1`/`"true"` → `true`) |
| `imovel_comodidades` | `caracteristicas[]` | Split por vírgula |
| `plantas[]` | `plantas[]` | URLs |
| `valor_seguro_incendio` / `valor_taxa_limpeza` | idem | Só se ≥ 0 |
| `andar` | `andar` | **Só se `andar_visivel` truthy** (JET-009 — flag de privacidade) |
| `situacao` / `status` / `posicao` | idem | Direto (single-valor) |
| `posicao_solar` | `posicao_solar[]` | **Split por vírgula** — multi-valor ("Sul,Leste" → `["Sul","Leste"]`) |
| `distancia_mar` | `distancia_mar` | Direto |
| `calendario_temporada` | `calendario_temporada` | Normalizado pra array |
| `condominio_comodidades` | `condominio_comodidades[]` | Split por vírgula |
| `condominio_tipo` / `id_subcondominio` / `condominio_fechado` | `condominio_tipo` / `subcondominio_id` / `condominio_fechado` | — |
| `entrega_ano` / `entrega_mes` | idem | `entrega_mes` validado 1–12 (número; humanizado na exibição via `format: month`) |
| `tipo_construcao` | `tipo_construcao` | Direto |
| `tipo_piso` | `tipo_piso[]` | **Split por vírgula** — multi-valor ("Porcelanato,Mármore" → array) |
| `periodicidade_iptu` | `periodicidade_iptu` | Direto |
| `terreno_frente/fundos/esquerdo/direita/total` | `terreno_*` | Aceita string da API (JET-003), faz `Number()` |
| `rural.rural_area_aravel` / `rural.rural_sedes` / `rural.atividade_rural` | `rural_area_aravel` / `rural_sedes` / `rural_atividade` | Só se > 0 |
| — | `sync_hash` | Hash SHA-256 (64 bits) do record convertido — adicionado por `convertJetimobPropertyToHorizon` |

---

## Campos descartados (de propósito)

`*_visivel` (flags de visibilidade — usados como condição, não viram dado),
`id_estado` / `id_cidade` / `id_bairro` (IDs internos sem uso no Horizon),
`data_cadastro` / `data_atualizacao` (redundantes com `data_update`),
`origem` (sempre `"Jetimob"`), `descricao_anuncio` (redundante com `observacoes`),
`medida_terreno_total` (a unidade padrão já é `m2`).
