Skip to content

Regras de Lojas & Aliases

Estrutura de lojas

Cada organização tem várias lojas/filiais. Uma loja pode ter:

  • Número de WhatsApp associado (StoreWhatsappNumber)
  • Caixa no Chatwoot (chatwootInboxId)
  • Horários de funcionamento (businessHours)
  • Flag de e-commerce (isEcommerce)
  • Código do ERP (code)

Hierarquia de aliases

Lojas podem ser agrupadas em hierarquia de principal/alias:

Loja Principal (primaryStoreId = null)
  ├─ Alias 1 (primaryStoreId = Loja Principal)
  └─ Alias 2 (primaryStoreId = Loja Principal)

Uso: Franquias ou filiais que reportam métricas consolidadas para a loja principal.

Regras:

  • Sem chains: A → B, mas B não pode apontar para C
  • Sem auto-referência
  • Alias herda dados de relatório da principal

Endpoints: /config/store-aliases (permissão: app:store-aliases)

Loja e-commerce

A loja marcada com isEcommerce = true é o fallback padrão quando:

  • Cliente não tem loja preferida E não responde ao menu
  • Loja preferida não tem instância Evolution conectada
  • Roteamento WABA sem caixa específica configurada

Somente uma loja por organização pode ser e-commerce (toggle PATCH /settings/stores/:id/ecommerce).

Resolução de alias

O StoreAliasResolverService tem cache de 60s e oferece:

MétodoDescrição
expandStoreIds(ids)Expande array de IDs de lojas para incluir seus aliases
resolvePrimary(storeId)Retorna o ID da loja principal para um alias
getPrimaryMap()Mapa completo de alias → principal

Útil para queries de analytics — buscar dados de todas as filiais ao consultar a principal.

Loja preferida do cliente

Customer.preferredStoreId é atribuído de três formas:

  1. Pelo roteador: quando o cliente seleciona no menu
  2. Pelo sync ERP: via PreferredAssignmentService (loja do vendedor que mais vendeu para o cliente)
  3. Manualmente: via PATCH /erp/customers/:id/preferences

Horários de funcionamento

Estrutura salva em Store.businessHours (campo JSON):

json
{
  "schedule": {
    "monday":    { "active": true,  "open": "09:00", "close": "18:00" },
    "tuesday":   { "active": true,  "open": "09:00", "close": "18:00" },
    "wednesday": { "active": true,  "open": "09:00", "close": "18:00" },
    "thursday":  { "active": true,  "open": "09:00", "close": "18:00" },
    "friday":    { "active": true,  "open": "09:00", "close": "17:00" },
    "saturday":  { "active": true,  "open": "09:00", "close": "13:00" },
    "sunday":    { "active": false, "open": "00:00", "close": "00:00" }
  }
}

Timezone: BRT (UTC-3) — hardcoded, sem DST desde 2019.

Loja sem configuração = sempre aberta.

Turno overnight: Suportado (ex: "open": "23:40", "close": "00:30").

Ao salvar: Flags Redis de business hours são limpas imediatamente para reprocessamento.

Cálculos de horário

O BusinessHoursService oferece:

MétodoRetorno
isOpen(businessHours)boolean — loja aberta agora?
minutesUntilClose(businessHours)number? — minutos até fechar
minutesSinceClose(businessHours)number? — minutos desde o fechamento
todayCloseTime(businessHours)string? — horário de fechamento hoje (HH:MM)
formatHours(businessHours)string — texto legível (ex: "Seg 09:00–18:00")

Instâncias WhatsApp por loja

StoreWhatsappNumber vincula uma loja a um número de WhatsApp:

CampoDescrição
phoneNumberIdID do número no Meta (WABA mode)
wabaIdID da conta WABA
accessTokenToken de acesso Meta (criptografado)
providerevolution ou meta_cloud
evolutionInstanceNameNome da instância Evolution (se provider = evolution)
chatwootInboxIdID da caixa no Chatwoot
messagingLimitTierTier atual de envio
qualityScoreScore de qualidade da conta Meta
isDefaultSe é a instância padrão da loja