Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> git-subtree-dir: maquina-comercial-pessoal git-subtree-mainline:f5af038e19git-subtree-split:a9ef4d776d
92 lines
3.9 KiB
JavaScript
92 lines
3.9 KiB
JavaScript
export function normalizePhone(value = '') {
|
|
return String(value).replace(/\D/g, '');
|
|
}
|
|
|
|
export function equivalentPhoneNumbers(value = '') {
|
|
const digits = normalizePhone(value);
|
|
const numbers = digits ? [digits] : [];
|
|
if (!digits.startsWith('55')) return numbers;
|
|
const prefix = digits.slice(0, 4);
|
|
const local = digits.slice(4);
|
|
if (local.length === 9 && local.startsWith('9')) numbers.push(`${prefix}${local.slice(1)}`);
|
|
if (local.length === 8 && /^[6-9]/.test(local)) numbers.push(`${prefix}9${local}`);
|
|
return [...new Set(numbers)];
|
|
}
|
|
|
|
// equivalentPhoneNumbers NAO e simetrica: ela so gera a variante de 8 digitos a
|
|
// partir de um celular de 9 digitos quando o local comeca com 6-9. Um numero
|
|
// como 557533334444 (local '33334444') nao volta para 5575933334444, embora o
|
|
// caminho inverso exista — o que fazia um lado do par ser bloqueado e o outro
|
|
// nao, e escondia o grupo da tela de revisao.
|
|
//
|
|
// canonicalPhoneKey resolve isso reduzindo SEMPRE o celular brasileiro de 13
|
|
// digitos com nono digito para a forma de 12 digitos (mesma regra de remocao ja
|
|
// usada por equivalentPhoneNumbers). Dois numeros pertencem a mesma linha
|
|
// quando compartilham a chave canonica — uma relacao simetrica por construcao.
|
|
export function canonicalPhoneKey(value = '') {
|
|
const digits = normalizePhone(value);
|
|
if (!digits.startsWith('55')) return digits;
|
|
const prefix = digits.slice(0, 4);
|
|
const local = digits.slice(4);
|
|
if (local.length === 9 && local.startsWith('9')) return `${prefix}${local.slice(1)}`;
|
|
return digits;
|
|
}
|
|
|
|
// Todas as formas que um numero pode ter armazenado e que reduzem a mesma chave
|
|
// canonica. O numero informado vem sempre primeiro (o override guarda esse
|
|
// valor). Usado para casar contra a coluna crua `leads.whatsapp`.
|
|
export function canonicalPhoneVariants(value = '') {
|
|
const digits = normalizePhone(value);
|
|
if (!digits) return [];
|
|
const key = canonicalPhoneKey(digits);
|
|
const variants = new Set([digits, key]);
|
|
if (key.startsWith('55') && key.length === 12) {
|
|
variants.add(`${key.slice(0, 4)}9${key.slice(4)}`);
|
|
}
|
|
return [...variants];
|
|
}
|
|
|
|
// Fragmentos SQL equivalentes as funcoes JS acima. Ficam neste modulo para que
|
|
// exista uma unica origem da regra 8/9 digitos — tests/phone.test.mjs prova que
|
|
// as duas implementacoes concordam.
|
|
export function normalizedSql(column) {
|
|
return `replace(replace(replace(replace(replace(${column}, '+', ''), ' ', ''), '-', ''), '(', ''), ')', '')`;
|
|
}
|
|
|
|
// Espelha equivalentPhoneNumbers: alterna entre as duas variantes brasileiras.
|
|
export function equivalentSql(column) {
|
|
const number = normalizedSql(column);
|
|
return `CASE
|
|
WHEN substr(${number}, 1, 2) = '55' AND length(${number}) = 13 AND substr(${number}, 5, 1) = '9'
|
|
THEN substr(${number}, 1, 4) || substr(${number}, 6)
|
|
WHEN substr(${number}, 1, 2) = '55' AND length(${number}) = 12 AND substr(${number}, 5, 1) BETWEEN '6' AND '9'
|
|
THEN substr(${number}, 1, 4) || '9' || substr(${number}, 5)
|
|
ELSE ${number}
|
|
END`;
|
|
}
|
|
|
|
// Espelha canonicalPhoneKey.
|
|
export function canonicalKeySql(column) {
|
|
const number = normalizedSql(column);
|
|
return `CASE
|
|
WHEN substr(${number}, 1, 2) = '55' AND length(${number}) = 13 AND substr(${number}, 5, 1) = '9'
|
|
THEN substr(${number}, 1, 4) || substr(${number}, 6)
|
|
ELSE ${number}
|
|
END`;
|
|
}
|
|
|
|
// A outra forma da mesma chave canonica (a de 13 digitos). Junto com
|
|
// canonicalKeySql cobre as duas formas possiveis de armazenamento, permitindo
|
|
// `outra.whatsapp IN (chave, variante)` — comparacao contra a coluna crua, que
|
|
// mantem o uso de idx_leads_whatsapp.
|
|
export function canonicalVariantSql(column) {
|
|
const number = normalizedSql(column);
|
|
return `CASE
|
|
WHEN substr(${number}, 1, 2) = '55' AND length(${number}) = 13 AND substr(${number}, 5, 1) = '9'
|
|
THEN ${number}
|
|
WHEN substr(${number}, 1, 2) = '55' AND length(${number}) = 12
|
|
THEN substr(${number}, 1, 4) || '9' || substr(${number}, 5)
|
|
ELSE ${number}
|
|
END`;
|
|
}
|