store.business_day_closed dispara quando o pipeline automatizado de fechamento de dia do Fire termina de construir o snapshot imutável do dia operacional de uma loja. O payload é uma projeção direta desse snapshot mais o bloco store canônico v4 — os consumers (Kinesis, ERP, BI) montam seu próprio shape sem precisar fazer queries de volta ao Fire.
Diferente dos eventos de pedido, este é um evento a nível loja: um por loja fechada, não um por pedido. O snapshot contém métricas agregadas, breakdowns por canal/forma de pagamento, detalhe de pedidos force-closed e detalhe de cancelamentos do dia.
Condição de disparo
O Fire emitestore.business_day_closed uma vez por snapshot (storeId, businessDayDate), na primeira vez em que todas estas condições se cumprem:
- A loja tinha um dia operacional aberto (
isBusinessDayOpen === true) para a data a fechar - O pipeline de fechamento (
CloseBusinessDayService.execute()) completou os 9 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)
| Cobertura | Universal — todos os países. Diferente de fiscal.*.br, sem gating por país. |
| Chave de idempotência | event.id (também trigger.data.snapshotId) |
| Dispara mais de uma vez | Não, salvo retry. Um snapshot por (storeId, data). |
| Origem | Pipeline cron (v1). O path de fechamento manual ainda não emite. |
| Latência vs fechamento real | Síncrono — o evento é enfileirado imediatamente após saveSnapshot() retornar. |
O que está em trigger.data
O V4StoreDayClosedSnapshot completo — 17 keys top-level cobrindo identidade, o bloco store canônico, agregados de sales/metrics/summary, breakdowns por canal e por forma de pagamento, detalhe de pedidos force-closed, detalhe de cancelamentos, e metadata extensível.
Exemplo — payload real (sanitizado)
Referência de data.*
Identidade & temporal
UUID do snapshot persistido no DB do Fire. Também exposto como
_meta.triggerEntityId. Use como chave de idempotência do seu lado — re-entregas do mesmo fechamento compartilham o mesmo snapshotId.Data calendário que o fechamento representa, no timezone da loja (ex.
"2026-03-31"). Não é a data UTC em que o evento disparou.Timezone IANA da loja (ex.
"America/Sao_Paulo"). Use para interpretar businessDayDate e os timestamps metrics.*_order_at.Sempre
"CLOSED" para este evento. O campo existe por paridade com o shape do row do snapshot; não há outro valor possível aqui.Timestamp ISO 8601 UTC de quando o dia foi aberto. Pode ser
null para lojas que nunca abriram explicitamente (data legacy); para lojas fechadas pelo cron v1 sempre está presente.Timestamp ISO 8601 UTC de quando o pipeline persistiu o snapshot. Use isto para medir SLI/SLO em vez de
event.createdAt (que é o tempo de dispatch da fila).closedBy — identidade do operador
Identidade do operador já resolvida. Nenhum lookup runtime necessário downstream.
store — bloco store canônico
Mesmo shape que em order.completed — ver order.completed para a referência de campos. Pontos-chave:
store.externalIdé o identificador controlado pelo Fire desdesettings.externalId, não o que algum sistema POS tenha injetado. Use como chave de reconciliação do lado partner.store.storeFiscalConfigviaja completo (CNPJ, IE,storeCode3S, etc. para BR; campos análogos para outros países). Credenciais nunca são incluídas.store.vendor.nameestore.account.namesão populados desde o metadata de account do Fire.descriptioneloyaltyPlanpodem virnull/falseaqui mesmo quando populados em eventos de pedido — esses campos vêm do payload POS injetado em eventos de pedido e não são parte do metadata de account do Fire hoje.
summary, sales, metrics
Breakdown de contagem de pedidos do dia.
Agregados de receita. Inclui apenas pedidos
COMPLETED + SUCCEEDED na moeda dominante.Indicadores de performance.
Breakdowns
Sales por canal (APP, KIOSK, POS, WEB, …). Cada entrada inclui um sub-breakdown
by_fulfillment (DELIVERY, PICKUP, DINE_IN, etc.). Apenas pedidos COMPLETED + SUCCEEDED.Sales por processador de pagamento (
CASH, CARD, PIX, …). Agregado desde payment_methods[].processor através dos pedidos pagos.Anomalias
Detalhe de pedidos que estavam ainda
OPEN no momento do fechamento. Cada entrada inclui order_id, order_uid, payment_status, total, o snapshot original de payment_methods[], e um closure_reason classificando por que o pedido não completou naturalmente.Valores possíveis de closure_reason: ABANDONED, PAYMENT_PENDING, PAYMENT_FAILED, PARTIAL_PAYMENT, INTEGRATION_ERROR.Stats agregados de force-close — contagem por razão e total de receita não cobrada (soma de
forceClosedOrders[].total).Detalhe por pedido de cancelamentos (
order_id, order_uid, order_code, cancelled_at, cancellation_reason, cancellation_source de "adapter" ou "backoffice", total, currency). Para snapshots criados antes de este campo existir (data legacy), este array é [].Bucket extensível. Hoje carrega
cash_reconciliation_summary (sempre, mesmo se vazio) e opcionalmente currency_anomaly (quando mais de uma moeda foi detectada no dia). Pode crescer com o tempo sem quebrar o contrato — trate chaves desconhecidas como forward-compatíveis.Exemplo de handler
Pontos de atenção
closedBy.uidpode ser o nil UUID"00000000-0000-0000-0000-000000000000"— para fechamentos system onde o account não configurou um system user custom. UseclosedBy.type === "system"para detectar fechamentos system em vez de parsearuid.sales.currencypode sernullquando a loja fechou sem pedidos pagos. Não assuma um default — bifurque sobre o null.- As keys de
closureStats.by_reasonestão sempre presentes, mesmo quando zero. Não filtre por presença; some/compare sobre os valores. metrics.first_order_at/last_order_at/peak_hour*estão ausentes (nãonull, ausentes) quando a loja não teve pedidos. Use optional chaining.cancelledOrdersé[]para snapshots criados antes do detalhe por-pedido de cancelamentos ser adicionado. Se precisar disso em data histórica, consulte diretamente a API de snapshots do Fire — snapshots antigos não são backfilleados retroativamente.store.vendor.descriptionestore.vendor.loyaltyPlanpodem virnull/falseaqui mesmo quando populados em eventos a nível de pedido. Esses campos vêm do payload POS injetado em eventos de pedido e não são armazenados no metadata de account do Fire hoje.
Eventos relacionados
order.completed
Dispara por cada pedido individual ao completar.
store.business_day_closed agrega muitos eventos order.completed.order.cancelled
Evento por cancelamento individual. Cada cancelamento também aparece em
cancelledOrders[] do fechamento do dia.
