Saltar para o conteúdo principal
Você está vendo o contrato atual (v1) de store.business_day_closed — um payload thin: identidade do fechamento, timing, closedBy e uma store mínima. Já não carrega as métricas agregadas do dia, os breakdowns nem o detalhe de anomalias — isso você consulta por businessDayId quando precisar.
store.business_day_closed dispara quando o pipeline automático de fechamento de dia do Fire termina de construir o snapshot imutável do dia operacional de uma loja. O payload é thin: carrega a identidade do fechamento (businessDayId), o timing, quem fechou e uma ref mínima de loja — o suficiente para reagir a “o dia fechou” e fazer o match do seu lado. Os agregados pesados (vendas, métricas, breakdowns por canal/pagamento, detalhe de force-closed e cancelamentos) vivem no snapshot e são obtidos por businessDayIdnão vêm embutidos no evento. Diferente dos eventos a nível pedido, este é um evento a nível loja: um por loja fechada, não um por pedido.

Condição de disparo

O Fire emite store.business_day_closed uma vez por snapshot (storeId, businessDayDate), na primeira vez que tudo a seguir é verdadeiro:
  • A loja tinha um dia de negócio aberto (isBusinessDayOpen === true) para a data sendo fechada
  • O pipeline de fechamento (CloseBusinessDayService.execute()) completou todos os passos sem erro (force-close, cálculo de métricas, persistência do snapshot)
  • Não existe já um snapshot para esse par (storeId, businessDayDate) (guard de idempotência)
CoberturaUniversal — todos os países. Sem gating por país.
Chave de idempotênciaevent.id (também trigger.data.businessDayId)
Dispara mais de uma vezNão, salvo retentativa. Um snapshot por (storeId, data).
OrigemPipeline cron (v1). O fechamento manual ainda não emite.
Latência vs fechamento realSíncrono — o evento é enfileirado assim que saveSnapshot() retorna.

O que vem em trigger.data

Um payload thin: identidade (businessDayId, businessDayDate, timezone, status), timing (openedAt, closedAt), o closedBy resolvido, e uma ref mínima de store (uid, code, externalId, countryCode, timezone, currencyCode). Sem métricas, breakdowns nem arrays de anomalias — consulte o snapshot por businessDayId se precisar do detalhe.

Exemplo — payload real (sanitizado)

{
  "event": {
    "id": "43214dd1-e260-4245-945d-5bbdfc4a54be",
    "type": "store.business_day_closed",
    "createdAt": "2026-05-18T21:59:01.306Z"
  },
  "data": {
    "businessDayId": "2c332116-79ec-4c63-a53d-8b87fff5a654",
    "businessDayDate": "2026-03-31",
    "timezone": "America/Sao_Paulo",
    "status": "CLOSED",
    "openedAt": "2026-03-31T09:00:02.55Z",
    "closedAt": "2026-05-18T21:58:09.882Z",
    "closedBy": {
      "uid": "00000000-0000-0000-0000-000000000000",
      "name": "Cierre Automático — Sandbox",
      "type": "system"
    },
    "store": {
      "uid": "a4019cad-bbac-4269-9f8d-f29654e92c45",
      "code": "BR-SP-001",
      "externalId": "200400500",
      "countryCode": "BR",
      "timezone": "America/Sao_Paulo",
      "currencyCode": "BRL"
    }
  },
  "_meta": { "executionId": "...", "flowId": "...", "flowName": "...", "attempt": 0, "triggerEntityId": "2c332116-79ec-4c63-a53d-8b87fff5a654" }
}

Referência de data.*

Identidade e temporal

businessDayId
string
UUID do snapshot de dia de negócio persistido na base do Fire. Também aparece como _meta.triggerEntityId. Use-o como chave de idempotência do seu lado — reenvios do mesmo fechamento compartilham o mesmo businessDayId — e como chave de lookup para buscar os agregados do dia na API de snapshots do Fire quando precisar.
businessDayDate
string
Data de calendário que o fechamento representa, no fuso da loja (ex. "2026-03-31"). Não a data UTC em que o evento disparou.
timezone
string
Fuso IANA da loja (ex. "America/Sao_Paulo"). Use-o para interpretar businessDayDate.
status
string
Sempre "CLOSED" para este evento. Nenhum outro valor é possível.
openedAt
string | null
Timestamp ISO 8601 UTC de abertura do dia. Pode ser null para lojas que nunca abriram explicitamente (dados legados); para lojas fechadas por cron v1 está sempre presente.
closedAt
string
Timestamp ISO 8601 UTC em que o pipeline persistiu o snapshot. Use-o para medir SLI/SLO em vez de event.createdAt (que é o momento do dispatch da fila).

closedBy — identidade do operador

closedBy
object
Identidade do operador já resolvida. Sem lookups em runtime downstream.

store — ref mínima de loja

store
object
Uma referência mínima de loja — identidade mais país/fuso/moeda. O bloco store canônico completo (name, address, vendor, account, fiscal config) não vem aqui; se precisar, pegue-o dos eventos order.completed da mesma loja.

Exemplo de handler

async function onStoreDayClosed(data) {
  const { businessDayId, businessDayDate, timezone, store, closedBy } = data;

  // 1. Idempotência — pular se já processamos este fechamento
  const existing = await db.dayCloses.findUnique({ where: { businessDayId } });
  if (existing) return;

  // 2. Registrar o fechamento (lean — identidade + ref de loja)
  await db.dayCloses.create({
    data: {
      businessDayId,
      businessDayDate,
      timezone,
      storeExternalId: store.externalId,
      storeCode: store.code,
      countryCode: store.countryCode,
      currencyCode: store.currencyCode,
      closedByName: closedBy.name,
      closedByType: closedBy.type,
    },
  });

  // 3. Precisa dos agregados do dia (sales, metrics, anomalias)? Busque por businessDayId.
  //    NÃO estão neste evento — consulte a API de snapshots do Fire on demand.
  // const snapshot = await fire.businessDay.get(businessDayId);
}

Erros comuns

  • As métricas do dia NÃO estão neste evento. sales, metrics, byChannel, byPaymentMethod, forceClosedOrders, closureStats, cancelledOrders e metadata já não viajam inline. Se você dependia deles, busque o snapshot por businessDayId.
  • snapshotId foi renomeado para businessDayId. Se você parseava data.snapshotId, mude para data.businessDayId (mesmo valor — o id da linha do snapshot).
  • closedBy.uid pode ser o nil UUID "00000000-0000-0000-0000-000000000000" — em fechamentos system onde a conta não configurou um system user. Detecte fechamentos system com closedBy.type === "system", não parseando o uid.
  • businessDayDate é a data de calendário da loja, não UTC. Interprete-a com timezone.
  • Os campos store.* podem ser null com configuração de loja incompleta. Não assuma non-null.

Eventos relacionados

order.completed

Dispara por cada pedido ao completar. O bloco store completo vive aqui.

order.cancelled

Evento por cancelamento. Use-o para o detalhe de cancelamentos em vez do payload de fechamento.