@horizon-modules/arbo-crm-to-property-v2
Version:
Conversor de dados do Arbo CRM para o formato Property Model V2
688 lines (682 loc) • 19.8 kB
JavaScript
// src/discoverers/discoverType.ts
function discoverType(arbo) {
const tipoImovel = arbo.tipo_imovel?.toLowerCase() || "";
const categoria = arbo.categoria?.toLowerCase() || "";
const typeMap = {
"casa": { type: "Casa", subtype: "Casa padr\xE3o" },
"casa t\xE9rrea": { type: "Casa", subtype: "Casa padr\xE3o" },
"sobrado": { type: "Casa", subtype: "Sobrado" },
"apartamento": { type: "Apartamento", subtype: "Apartamento" },
"cobertura": { type: "Apartamento", subtype: "Cobertura" },
"duplex": { type: "Apartamento", subtype: "Duplex" },
"triplex": { type: "Apartamento", subtype: "Triplex" },
"kitnet": { type: "Apartamento", subtype: "Kitnet" },
"studio": { type: "Apartamento", subtype: "Studio" },
"flat": { type: "Apartamento", subtype: "Flat" },
"loft": { type: "Apartamento", subtype: "Loft" },
"terreno": { type: "Terreno/Lote", subtype: "Terreno" },
"lote": { type: "Terreno/Lote", subtype: "Lote" },
"ch\xE1cara": { type: "Rural", subtype: "Ch\xE1cara" },
"s\xEDtio": { type: "Rural", subtype: "S\xEDtio" },
"fazenda": { type: "Rural", subtype: "Fazenda" },
"sala comercial": { type: "Comercial", subtype: "Sala comercial" },
"loja": { type: "Comercial", subtype: "Loja" },
"galp\xE3o": { type: "Barrac\xE3o/Armaz\xE9m", subtype: "Barrac\xE3o" },
"barrac\xE3o": { type: "Barrac\xE3o/Armaz\xE9m", subtype: "Barrac\xE3o" },
"armaz\xE9m": { type: "Barrac\xE3o/Armaz\xE9m", subtype: "Armaz\xE9m" },
"pr\xE9dio": { type: "Comercial", subtype: "Pr\xE9dio comercial" },
"ponto comercial": { type: "Comercial", subtype: "Ponto comercial" }
};
for (const [key, value] of Object.entries(typeMap)) {
if (tipoImovel.includes(key) || categoria.includes(key)) {
return value;
}
}
if (categoria.includes("comercial")) {
return { type: "Comercial", subtype: "Im\xF3vel comercial" };
}
if (categoria.includes("residencial")) {
return { type: "Casa", subtype: "Casa padr\xE3o" };
}
return { type: "Outros", subtype: "Outros" };
}
// src/discoverers/discoverOperation.ts
function discoverOperation(arbo) {
const finalidade = arbo.finalidade?.toLowerCase() || "";
if (finalidade.includes("venda") || finalidade.includes("vender")) {
return "sale";
}
if (finalidade.includes("aluguel") || finalidade.includes("alugar") || finalidade.includes("loca\xE7\xE3o")) {
return "rent";
}
if (finalidade.includes("temporada")) {
return "season";
}
if (arbo.valor_venda && arbo.valor_venda > 0) {
return "sale";
}
if (arbo.valor_aluguel && arbo.valor_aluguel > 0) {
return "rent";
}
return "sale";
}
// src/discoverers/discoverAttributes.ts
function discoverAttributes(arbo, operation, type, subtype, options = {}) {
const attributes = [];
if (arbo.qtd_quartos && arbo.qtd_quartos > 0) {
attributes.push({
key: "bedrooms",
ref: "bedroom",
type: "amount",
label: "Quarto(s)",
value: arbo.qtd_quartos,
section: "rooms"
});
}
if (arbo.qtd_banheiro && arbo.qtd_banheiro > 0) {
attributes.push({
key: "bathrooms",
ref: "bathroom",
type: "amount",
label: "Banheiro(s)",
value: arbo.qtd_banheiro,
section: "rooms"
});
}
if (arbo.qtd_suites && arbo.qtd_suites > 0) {
attributes.push({
key: "suites",
ref: "suites",
tags: ["has-suite"],
type: "amount",
label: "Su\xEDte(s)",
value: arbo.qtd_suites,
section: "rooms"
});
}
if (arbo.area_total && arbo.area_total > 0) {
attributes.push({
key: "total-area",
ref: "total-area",
type: "area",
label: "\xC1rea total - m\xB2",
value: arbo.area_total.toString(),
section: "feature"
});
}
if (arbo.area_privativa && arbo.area_privativa > 0) {
attributes.push({
key: "util-area",
type: "number",
label: "\xC1rea \xFAtil - m\xB2",
value: arbo.area_privativa.toString(),
section: "feature"
});
}
if (arbo.qtd_vagas && arbo.qtd_vagas > 0) {
attributes.push({
key: "garage",
ref: "garage",
type: "amount",
label: "Vaga(s) na garagem",
value: arbo.qtd_vagas,
section: "feature"
});
}
if (arbo.caracteristicas && arbo.caracteristicas.length > 0) {
const charMap = {
"cozinha": {
key: "kitchen",
type: "bool",
label: "Cozinha",
value: true,
section: "rooms"
},
"sala de estar": {
key: "living-room",
type: "bool",
label: "Sala de estar",
value: true,
section: "rooms"
},
"sala de jantar": {
key: "dinner-room",
type: "bool",
label: "Sala de jantar",
value: true,
section: "rooms"
},
"\xE1rea de servi\xE7o": {
key: "service-area",
type: "bool",
label: "\xC1rea de servi\xE7o",
value: true,
section: "rooms"
},
"lavanderia": {
key: "service-area",
type: "bool",
label: "\xC1rea de servi\xE7o",
value: true,
section: "rooms"
},
"closet": {
key: "closet ",
type: "bool",
label: "Closet ",
value: true,
section: "rooms"
},
"sala de tv": {
key: "tv-room",
type: "bool",
label: "Sala de TV",
value: true,
section: "rooms"
},
"escrit\xF3rio": {
key: "office",
type: "bool",
label: "Escrit\xF3rio",
value: true,
section: "rooms"
},
"espa\xE7o gourmet": {
key: "gourmet-space",
type: "bool",
label: "Espa\xE7o Gourmet",
value: true,
section: "rooms"
},
"\xE1rea gourmet": {
key: "gourmet-space",
type: "bool",
label: "Espa\xE7o Gourmet",
value: true,
section: "rooms"
},
"varanda": {
key: "balcony",
tags: ["balcony"],
type: "text",
label: "Sacada",
value: "padrao",
section: "rooms",
"value.label": "Padr\xE3o"
},
"sacada": {
key: "balcony",
tags: ["balcony"],
type: "text",
label: "Sacada",
value: "padrao",
section: "rooms",
"value.label": "Padr\xE3o"
},
"su\xEDte master": {
key: "master-suite",
tags: ["suite"],
type: "bool",
label: "Su\xEDte Master",
value: true,
section: "rooms"
},
"piscina": {
key: "pool",
type: "bool",
label: "Piscina",
value: true,
section: "improvement"
},
"churrasqueira": {
key: "barbecue",
tags: ["bbq"],
type: "bool",
label: "Churrasqueira",
value: true,
section: "improvement"
},
"\xE1rea de lazer": {
key: "recreation-area",
type: "bool",
label: "\xC1rea de lazer",
value: true,
section: "improvement"
},
"playground": {
key: "playground",
type: "bool",
label: "Parquinho",
value: true,
section: "improvement"
},
"seguran\xE7a 24h": {
key: "security-guard",
tags: ["security"],
type: "bool",
label: "Seguran\xE7a 24h",
value: true,
section: "improvement"
},
"portaria 24h": {
key: "security-guard",
tags: ["security"],
type: "bool",
label: "Seguran\xE7a 24h",
value: true,
section: "improvement"
}
};
const addedKeys = /* @__PURE__ */ new Set();
for (const char of arbo.caracteristicas) {
const charLower = char.toLowerCase();
for (const [key, attr] of Object.entries(charMap)) {
if (charLower.includes(key) && !addedKeys.has(attr.key)) {
attributes.push(attr);
addedKeys.add(attr.key);
}
}
}
}
if (arbo.end_condominio || arbo.valor_condominio && arbo.valor_condominio > 0) {
attributes.push({
key: "in-condominium",
tags: ["in-condominium"],
type: "bool",
label: "Em condom\xEDnio",
value: true,
section: "improvement"
});
attributes.push({
key: "em-condominio",
value: true
});
}
if (options.agentId) {
attributes.push({
key: "agent",
value: options.agentId
});
}
if (arbo.latitude && arbo.longitude) {
attributes.push({
key: "position",
value: `${arbo.latitude},${arbo.longitude}`
});
}
const city = arbo.end_cidade && arbo.end_estado ? `${arbo.end_cidade} - ${arbo.end_estado}` : arbo.end_cidade || "";
if (city) {
attributes.push({
key: "city",
value: city
});
}
attributes.push(
{ key: "description", value: arbo.descricao || "" },
{ key: "type", value: type },
{ key: "title", value: arbo.titulo || "" },
{ key: "objective", value: "Residencial" },
{ key: "reference", value: arbo.codigo || "" }
);
if (options.clientId) {
attributes.push({
key: "client",
value: options.clientId
});
}
attributes.push(
{ key: "model", value: `${subtype.toLowerCase().replace(/ /g, "-")}@1.0` },
{ key: "id", value: `ppt_${generateId()}` },
{ key: "modified_at", value: (/* @__PURE__ */ new Date()).toISOString() }
);
if (arbo.end_logradouro) {
attributes.push({
key: "address-street",
value: arbo.end_logradouro
});
}
if (operation === "sale" && arbo.valor_venda) {
attributes.push(
{ key: "value", value: arbo.valor_venda },
{
key: "sale-value",
ref: "sale-value",
type: "currency",
value: arbo.valor_venda
}
);
} else if (operation === "rent" && arbo.valor_aluguel) {
attributes.push(
{ key: "value", value: arbo.valor_aluguel },
{
key: "rent-value",
ref: "rent-value",
type: "currency",
value: arbo.valor_aluguel
}
);
}
attributes.push(
{ key: "published", value: false },
{ key: "postal-code", value: arbo.end_cep || "" },
{ key: "friendly-url", value: arbo.codigo?.toLowerCase() || "" }
);
if (arbo.end_complemento) {
attributes.push({
key: "address-complement",
value: arbo.end_complemento
});
}
if (arbo.end_bairro) {
attributes.push({
key: "district",
value: arbo.end_bairro
});
}
attributes.push(
{ key: "operation", value: operation },
{
key: "integrations",
value: [
{ key: "imovelweb", title: "Im\xF3vel Web" },
{ key: "chavesnamao", title: "Chaves na m\xE3o" },
{ key: "procure-imovel", title: "Procure Im\xF3vel" },
{ key: "vivareal", title: "Viva Real" },
{ key: "zapimoveis", title: "Zap Im\xF3veis" },
{ key: "olx", title: "OLX" }
]
}
);
const fullAddress = buildFullAddress(arbo);
if (fullAddress) {
attributes.push({
key: "full-address",
ref: "address",
type: "address",
value: fullAddress,
section: "location"
});
}
attributes.push({
key: "subtype",
value: subtype
});
return attributes;
}
function buildFullAddress(arbo) {
const parts = [];
if (arbo.end_logradouro) {
parts.push(arbo.end_logradouro);
if (arbo.end_numero) {
parts[parts.length - 1] += `, ${arbo.end_numero}`;
}
}
if (arbo.end_complemento) {
parts.push(arbo.end_complemento);
}
if (arbo.end_bairro) {
parts.push(arbo.end_bairro);
}
const cityState = [];
if (arbo.end_cidade) cityState.push(arbo.end_cidade);
if (arbo.end_estado) cityState.push(arbo.end_estado);
if (cityState.length > 0) {
parts.push(cityState.join(" - "));
}
return parts.join(" - ");
}
function generateId() {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = "";
for (let i = 0; i < 28; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// src/discoverers/discoverMedia.ts
function discoverMedia(arbo) {
const media = {
videos: [],
tour360: [],
pictures: []
};
if (arbo.fotos && arbo.fotos.length > 0) {
const sortedPhotos = [...arbo.fotos].sort((a, b) => {
if (a.principal && !b.principal) return -1;
if (!a.principal && b.principal) return 1;
return (a.ordem || 999) - (b.ordem || 999);
});
media.pictures = sortedPhotos.map((foto, index) => ({
id: generatePhotoId(),
src: foto.url,
name: extractFileName(foto.url) || `foto_${index + 1}.jpg`,
label: extractFileName(foto.url) || `foto_${index + 1}.jpg`
}));
}
if (arbo.url_video) {
media.videos.push({
url: arbo.url_video,
type: "youtube"
});
}
if (arbo.url_tour) {
media.tour360.push({
url: arbo.url_tour,
type: "external"
});
}
return media;
}
function generatePhotoId() {
return Math.random().toString().slice(2, 20);
}
function extractFileName(url) {
try {
const urlParts = url.split("/");
const fileName = urlParts[urlParts.length - 1];
return fileName.split("?")[0];
} catch {
return "";
}
}
function discoverThumbnails(arbo, media) {
if (media.pictures.length > 0) {
return media.pictures[0].src;
}
if (arbo.fotos && arbo.fotos.length > 0) {
const mainPhoto = arbo.fotos.find((f) => f.principal);
if (mainPhoto) return mainPhoto.url;
return arbo.fotos[0].url;
}
return "";
}
// src/discoverers/discoverTags.ts
function discoverTags(arbo, attributes, operation) {
const tags = /* @__PURE__ */ new Set();
tags.add(operation);
for (const attr of attributes) {
if (attr.tags) {
attr.tags.forEach((tag) => tags.add(tag));
}
}
if (arbo.caracteristicas) {
const tagMap = {
"piscina": "pool",
"churrasqueira": "bbq",
"seguran\xE7a": "security",
"portaria": "security",
"\xE1rea de lazer": "recreation",
"playground": "playground",
"academia": "gym",
"sal\xE3o de festas": "party-room",
"quadra": "court",
"jardim": "garden",
"pet place": "pet-friendly",
"pet": "pet-friendly",
"mobiliado": "furnished",
"semi mobiliado": "semi-furnished"
};
for (const char of arbo.caracteristicas) {
const charLower = char.toLowerCase();
for (const [key, tag] of Object.entries(tagMap)) {
if (charLower.includes(key)) {
tags.add(tag);
}
}
}
}
const tipo = arbo.tipo_imovel?.toLowerCase() || "";
if (tipo.includes("cobertura")) tags.add("penthouse");
if (tipo.includes("duplex")) tags.add("duplex");
if (tipo.includes("triplex")) tags.add("triplex");
if (tipo.includes("loft")) tags.add("loft");
const categoria = arbo.categoria?.toLowerCase() || "";
if (categoria.includes("residencial")) tags.add("residencial");
if (categoria.includes("comercial")) tags.add("comercial");
if (arbo.mobiliado) tags.add("furnished");
if (arbo.permuta) tags.add("exchange");
if (arbo.financiamento) tags.add("financing");
return Array.from(tags).join(" ");
}
function discoverKeywords(arbo, attributes) {
const keywords = /* @__PURE__ */ new Set();
if (arbo.codigo) keywords.add(arbo.codigo.toLowerCase());
if (arbo.tipo_imovel) keywords.add(arbo.tipo_imovel.toLowerCase());
if (arbo.categoria) keywords.add(arbo.categoria.toLowerCase());
const titleWords = (arbo.titulo || "").toLowerCase().split(/\s+/);
const descWords = (arbo.descricao || "").toLowerCase().split(/\s+/);
const allWords = [...titleWords, ...descWords];
allWords.forEach((word) => {
const cleanWord = word.replace(/[^\w]/g, "");
if (cleanWord.length > 2) {
keywords.add(cleanWord);
}
});
if (arbo.end_cidade) keywords.add(arbo.end_cidade.toLowerCase());
if (arbo.end_bairro) keywords.add(arbo.end_bairro.toLowerCase());
if (arbo.end_estado) keywords.add(arbo.end_estado.toLowerCase());
if (arbo.caracteristicas) {
arbo.caracteristicas.forEach((char) => {
const words = char.toLowerCase().split(/\s+/);
words.forEach((word) => {
const cleanWord = word.replace(/[^\w]/g, "");
if (cleanWord.length > 2) {
keywords.add(cleanWord);
}
});
});
}
attributes.forEach((attr) => {
if (attr.key) keywords.add(attr.key.replace(/[^a-z0-9]/gi, "-"));
if (typeof attr.value === "string" && attr.value.length > 2) {
keywords.add(attr.value.toLowerCase().replace(/[^\w]/g, ""));
}
});
return Array.from(keywords).join(" ");
}
// src/discoverers/discoverSearch.ts
function discoverPropertySearch(arbo, id, title, reference, type, subtype, operation, price, tags, keywords, description, attributes) {
const city = arbo.end_cidade && arbo.end_estado ? `${arbo.end_cidade} - ${arbo.end_estado}` : arbo.end_cidade || "";
const bedrooms = arbo.qtd_quartos || 0;
const bathrooms = arbo.qtd_banheiro || 0;
const garage = arbo.qtd_vagas || 0;
const area = arbo.area_total || arbo.area_privativa || 0;
const cleanDescription = description.toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
return {
id,
title,
reference,
type,
subtype,
operation,
price,
tags,
keywords,
description: cleanDescription,
highlighted_date: null,
state: arbo.end_estado || null,
city,
district: arbo.end_bairro || "",
lat: arbo.latitude || 0,
lon: arbo.longitude || 0,
created_at: (/* @__PURE__ */ new Date()).toISOString(),
modified_at: null,
updated_at: null,
bed: bedrooms,
bath: bathrooms,
garage,
area
};
}
// src/converter.ts
function convertArboToPropertyV2(arbo, options = {}) {
const { type, subtype } = discoverType(arbo);
const operation = discoverOperation(arbo);
const attributes = discoverAttributes(arbo, operation, type, subtype, options);
const media = discoverMedia(arbo);
const thumbnails = discoverThumbnails(arbo, media);
const tags = options.generateTags !== false ? discoverTags(arbo, attributes, operation) : "";
const keywords = options.generateKeywords !== false ? discoverKeywords(arbo, attributes) : "";
const title = arbo.titulo || "";
const description = arbo.descricao || "";
const reference = arbo.codigo || "";
const price = operation === "sale" ? arbo.valor_venda || 0 : arbo.valor_aluguel || 0;
const id = arbo.ref_id;
const now = (/* @__PURE__ */ new Date()).toISOString();
const propertySearch = discoverPropertySearch(
arbo,
id,
title,
reference,
type,
subtype,
operation,
price,
tags,
keywords,
description,
attributes
);
const propertyV2 = {
id,
source_id: arbo.ref_id,
reference,
title,
description,
type,
subtype,
operation,
attributes,
media,
tags,
keywords,
thumbnails: options.defaultThumbnail || thumbnails,
web_code: null,
provider: "arbo-crm",
index: null,
seo: null,
visibility: null,
preview: null,
created_at: arbo.created_at || now,
modified_at: arbo.updated_at || now,
updated_at: now,
property_search: [propertySearch]
};
return propertyV2;
}
function convertMultipleArboToPropertyV2(arboProperties, options = {}) {
return arboProperties.map((arbo) => convertArboToPropertyV2(arbo, options));
}
export {
convertArboToPropertyV2,
convertMultipleArboToPropertyV2,
discoverAttributes,
discoverKeywords,
discoverMedia,
discoverOperation,
discoverPropertySearch,
discoverTags,
discoverThumbnails,
discoverType
};
//# sourceMappingURL=index.mjs.map