chore: import maquina-comercial-pessoal history via subtree

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

git-subtree-dir: maquina-comercial-pessoal
git-subtree-mainline: f5af038e19
git-subtree-split: a9ef4d776d
This commit is contained in:
Gustavo
2026-09-28 15:50:17 -03:00
co-authored by Claude Sonnet 5
150 changed files with 33449 additions and 0 deletions
@@ -0,0 +1,211 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {
managementFocus,
naturalBusinessName,
renderCampaignMessage,
variantForLead
} from '../src/outreach/campaign-messages.mjs';
const refusal = 'Se nao fizer sentido para sua empresa, e so me avisar que nao volto a entrar em contato.';
const approvedCases = [
{
segment: 'restaurantes',
template: `Ola, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Hoje voces controlam {foco_gestao} em um unico sistema? ${refusal}`,
expected: `Ola, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Hoje voces controlam vendas, estoque, comandas e emissão fiscal em um unico sistema? ${refusal}`
},
{
segment: 'restaurantes',
template: `Ola! Aqui e Gustavo, do Grupo GTI. Trabalhamos com gestao para empresas de Santo Antonio de Jesus e regiao. Como voces organizam hoje {foco_gestao}? ${refusal}`,
expected: `Ola! Aqui e Gustavo, do Grupo GTI. Trabalhamos com gestao para empresas de Santo Antonio de Jesus e regiao. Como voces organizam hoje vendas, estoque, comandas e emissão fiscal? ${refusal}`
},
{
segment: 'restaurantes',
template: `Ola, tudo bem? Sou Gustavo, do Grupo GTI. Ha mais de 7 anos atendemos empresas da regiao e ja temos mais de 100 clientes. Voces utilizam algum sistema para {foco_gestao}? ${refusal}`,
expected: `Ola, tudo bem? Sou Gustavo, do Grupo GTI. Ha mais de 7 anos atendemos empresas da regiao e ja temos mais de 100 clientes. Voces utilizam algum sistema para vendas, estoque, comandas e emissão fiscal? ${refusal}`
},
{
segment: 'pizzarias',
template: `Ola, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Queria entender como voces recebem os pedidos de delivery hoje: possuem um canal proprio ou dependem de aplicativos que cobram comissao? ${refusal}`,
expected: `Ola, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Queria entender como voces recebem os pedidos de delivery hoje: possuem um canal proprio ou dependem de aplicativos que cobram comissao? ${refusal}`
},
{
segment: 'pizzarias',
template: `Ola! Aqui e Gustavo, do Grupo GTI. Voces ja possuem um link proprio para receber pedidos, sem pagar comissao por venda a aplicativos? ${refusal}`,
expected: `Ola! Aqui e Gustavo, do Grupo GTI. Voces ja possuem um link proprio para receber pedidos, sem pagar comissao por venda a aplicativos? ${refusal}`
},
{
segment: 'pizzarias',
template: `Ola, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Trabalho com uma solucao de pedidos online por canal proprio e queria primeiro entender como funciona o delivery de voces hoje. ${refusal}`,
expected: `Ola, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Trabalho com uma solucao de pedidos online por canal proprio e queria primeiro entender como funciona o delivery de voces hoje. ${refusal}`
}
];
test('nome natural aceita marcas curtas com pelo menos duas letras', () => {
assert.equal(naturalBusinessName({ empresa: 'OX' }), 'OX');
assert.equal(naturalBusinessName({ empresa: 'BR2' }), 'BR2');
assert.equal(naturalBusinessName({ empresa: 'Pizzaria Central' }), 'Pizzaria Central');
});
test('nome natural rejeita identificadores, nomes legais, controles, placeholders e ruido generico', () => {
const rejected = [
'',
'7',
'7 Mares',
'61.590.668 A ARAUJO',
'12.345.678/0001-90',
'A ARAUJO LTDA',
'Loja Sol MEI',
'Loja Sol ME',
'Loja Sol EPP',
'Loja Sol EIRELI',
'Loja Sol S/A',
'Loja\nSol',
'Loja\u0000Sol',
'Loja\u200bSol',
'Loja {nome}',
'Loja {{nome}}',
'Empresa',
'Nome Fantasia',
'Nao informado',
'Comercio',
'Pizzaria Central com um nome comercial excessivamente longo para uma saudacao natural e segura'
];
for (const empresa of rejected) {
assert.equal(naturalBusinessName({ empresa, legal_name: 'A ARAUJO LTDA' }), '', empresa);
}
});
test('foco de gestao segue os quatro grupos aprovados', () => {
assert.equal(managementFocus('restaurantes'), 'vendas, estoque, comandas e emissão fiscal');
assert.equal(managementFocus('mercados_de_bairro'), 'vendas, estoque e emissão fiscal');
assert.equal(managementFocus('oficinas_mecanicas'), 'ordens de serviço, estoque e financeiro');
assert.equal(managementFocus('lojas_de_roupa'), 'vendas, estoque, financeiro e notas fiscais');
});
test('variante permanece estavel e considera apenas variantes ativas', () => {
const variants = [{ code: 'A', ativo: 1 }, { code: 'B', ativo: 1 }, { code: 'C', ativo: 1 }];
assert.equal(variantForLead(variants, 4).code, 'B');
assert.equal(variantForLead(variants, 4).code, 'B');
assert.equal(variantForLead([{ code: 'A', ativo: 0 }, ...variants.slice(1)], 4).code, 'B');
assert.throws(() => variantForLead([], 4), /variante ativa/i);
});
test('variante usa a ordem ativa mesmo com ids nao contiguos', () => {
const variants = [
{ id: 8, code: 'A', ativo: 1 },
{ id: 37, code: 'B', ativo: 1 },
{ id: 104, code: 'C', ativo: 1 }
];
assert.equal(variantForLead(variants, 4), variants[1]);
});
test('variante rejeita array nao vazio quando todas estao inativas', () => {
assert.throws(() => variantForLead([
{ id: 8, code: 'A', ativo: 0 },
{ id: 37, code: 'B', ativo: false }
], 4), /variante ativa/i);
});
test('renderizacao preserva os seis textos aprovados fora das substituicoes permitidas', () => {
for (const { segment, template, expected } of approvedCases) {
assert.equal(renderCampaignMessage(template, {
empresa: '61.590.668 A ARAUJO',
legal_name: 'A ARAUJO LTDA',
segmento: segment
}), expected);
}
});
test('renderizacao personaliza somente a saudacao inicial com nome natural', () => {
const template = approvedCases[0].template;
const rendered = renderCampaignMessage(template, {
empresa: 'Pizzaria Central',
segmento: 'restaurantes'
});
assert.equal(rendered, `Olá, pessoal da Pizzaria Central, tudo bem? Sou Gustavo, representante comercial do Grupo GTI. Hoje voces controlam vendas, estoque, comandas e emissão fiscal em um unico sistema? ${refusal}`);
});
test('validacao aceita texto portugues legitimo sem remover diacriticos', () => {
const template = `Olá, tudo bem? Sou Gustavo, do Grupo GTI. Gestão ágil para comércio. Se não fizer sentido para sua empresa, é só me avisar que não volto a entrar em contato.`;
assert.equal(renderCampaignMessage(template, { empresa: '', segmento: 'lojas_de_roupa' }), template);
const punctuation = `Olá, tudo bem? Sou Gustavo, do Grupo GTI. Gestão simples (vendas/estoque), ágil e segura. Se não fizer sentido para sua empresa, é só me avisar que não volto a entrar em contato.`;
assert.equal(renderCampaignMessage(punctuation, { empresa: '' }), punctuation);
});
test('validacao rejeita placeholders simples ou duplos que restarem no texto', () => {
const safe = `Ola, tudo bem? Sou Gustavo, do Grupo GTI. ${refusal}`;
const placeholders = [
'{produto}',
'{{produto_2}}',
'{ produto }',
'{produto-nome}',
'{123}',
'{{ produto }}',
'{{produto-nome}}',
'{{123}}'
];
for (const placeholder of placeholders) {
const template = safe.replace('Grupo GTI.', `Grupo GTI. ${placeholder}`);
assert.throws(() => renderCampaignMessage(template, {}), /mensagem inicial insegura/i, placeholder);
}
});
test('validacao de placeholders preserva portugues normal sem chaves', () => {
const template = `Olá, tudo bem? Sou Gustavo, do Grupo GTI. Produto 123 - nome e gestão simples. Se não fizer sentido para sua empresa, é só me avisar que não volto a entrar em contato.`;
assert.equal(renderCampaignMessage(template, {}), template);
});
test('validacao rejeita localhost, enderecos IP e caminhos absolutos', () => {
const safe = `Ola, tudo bem? Sou Gustavo, do Grupo GTI. ${refusal}`;
const addresses = [
'localhost',
'localhost:3000/agenda',
'127.0.0.1',
'192.168.0.1:8080/agenda',
'[::1]',
'[2001:db8::1]:8080/agenda',
'2001:db8::1',
'/agenda/demonstracao'
];
for (const address of addresses) {
const template = safe.replace('Grupo GTI.', `Grupo GTI. ${address}`);
assert.throws(() => renderCampaignMessage(template, {}), /mensagem inicial insegura/i, address);
}
});
test('renderizacao e selecao nao alteram os objetos de entrada', () => {
const template = { mensagem: approvedCases[0].template };
const lead = { empresa: 'Pizzaria Central', segmento: 'restaurantes' };
const variants = [{ id: 8, code: 'A', ativo: 0 }, { id: 37, code: 'B', ativo: 1 }];
const before = structuredClone({ template, lead, variants });
renderCampaignMessage(template, lead);
variantForLead(variants, 7);
assert.deepEqual({ template, lead, variants }, before);
});
test('validacao rejeita URL, CNPJ, preco e requisitos obrigatorios ausentes', () => {
const safe = `Ola, tudo bem? Sou Gustavo, do Grupo GTI. ${refusal}`;
const unsafe = [
safe.replace('Grupo GTI.', 'Grupo GTI. https://gti.example'),
safe.replace('Grupo GTI.', 'Grupo GTI. gti.com.br'),
safe.replace('Grupo GTI.', 'Grupo GTI. 12.345.678/0001-90'),
safe.replace('Grupo GTI.', 'Grupo GTI. 12345678000190'),
safe.replace('Grupo GTI.', 'Grupo GTI. R$ 99'),
safe.replace('Gustavo', 'Consultor'),
safe.replace('Grupo GTI', 'nossa empresa'),
safe.replace(` ${refusal}`, '')
];
for (const template of unsafe) {
assert.throws(() => renderCampaignMessage(template, { empresa: '' }), /mensagem inicial insegura/i);
}
});