DocumentaçãoDocumentationDocumentaciónOne Conecta
ÍndiceIndexÍndice
Baixar .mdDownload .mdBajar .md
Você está vendo esta documentação online. No topo você também pode baixar o PDF (mesmo conteúdo desta página, no idioma e modo atuais) e o Markdown (Funcional ou Técnica).You are viewing this documentation online. At the top you can also download the PDF (same content as this page, in the current language and mode) and the Markdown (Functional or Technical).Está viendo esta documentación en línea. Arriba también puede bajar el PDF (mismo contenido de esta página, en el idioma y modo actuales) y el Markdown (Funcional o Técnica).
Transação gRPC · DispatchergRPC transaction · DispatcherTransacción gRPC · Dispatcher

Verificação de preçoProduct price checkVerificación de precio

A transação de escrita que envia os preços de venda observados no varejo para o backend. Durante uma visita, o representante de vendas registra, produto a produto, por quanto o item é vendido (por maço e por unidade); ao concluir, este envio manda toda a coleta de uma vez. O payload é uma lista de linhas de preço — uma por produto verificado. É uma transação leve: reenviá-la é seguro, pois o backend apenas re-registra a mesma coleta. Toda a construção do contrato wire vive no builder. The write transaction that sends the selling prices observed at the retail to the backend. During a visit, the sales rep records, product by product, how much the item sells for (per pack and per stick); on finishing, this send pushes the whole collection at once. The payload is a list of price lines — one per checked product. It's a lightweight transaction: resending it is safe, since the backend just re-records the same collection. All wire-contract shaping lives in the builder. La transacción de escritura que envía los precios de venta observados en el punto de venta al backend. Durante una visita, el representante de ventas registra, producto por producto, a cuánto se vende el ítem (por paquete y por unidad); al terminar, este envío manda toda la recolección de una vez. El payload es una lista de líneas de precio — una por producto verificado. Es una transacción liviana: reenviarla es seguro, pues el backend solo re-registra la misma recolección. Toda la construcción del contrato wire vive en el builder.

PúblicoAudiencePúblico
QA · Suporte · Produto · DevQA · Support · Product · DevQA · Soporte · Producto · Dev
CamadaLayerCapa
Escrita · DispatcherWrite · DispatcherEscritura · Dispatcher
RelacionadoRelatedRelacionado
AtualizadoUpdatedActualizado
18/08/20262026-08-18
Disponível emAvailable inDisponible en ZA
01

O que é e quando aconteceWhat it is and when it happensQué es y cuándo ocurre

Durante a visita a um varejo, o representante de vendas pode verificar por quanto os produtos estão sendo vendidos na loja — uma checagem de preço de prateleira. O rep percorre a lista de produtos e anota, para cada um, o preço de venda observado por maço e por unidade. Quando termina, o app envia essa coleta ao backend por esta transação, para acompanhamento comercial dos preços praticados no ponto de venda. During a visit to a retail, the sales rep can check how much products are being sold for at the store — a shelf-price check. The rep goes through the product list and notes, for each one, the observed selling price per pack and per stick. When done, the app sends that collection to the backend through this transaction, for commercial tracking of the prices charged at the point of sale. Durante la visita a un punto de venta, el representante de ventas puede verificar a cuánto se están vendiendo los productos en la tienda — un chequeo de precio de góndola. El rep recorre la lista de productos y anota, para cada uno, el precio de venta observado por paquete y por unidad. Cuando termina, la app envía esa recolección al backend por esta transacción, para seguimiento comercial de los precios practicados en el punto de venta.

Só o que foi preenchidoOnly what was filledSolo lo que se completó O rep não precisa preencher todos os produtos: só os itens com pelo menos um preço informado (maço ou unidade) entram no envio. Produtos deixados em branco são simplesmente ignorados. The rep doesn't have to fill every product: only items with at least one price entered (pack or stick) go in the send. Products left blank are simply skipped. El rep no tiene que completar todos los productos: solo los ítems con al menos un precio informado (paquete o unidad) entran en el envío. Los productos dejados en blanco se ignoran.

02

Fluxo de telas que disparaScreen flow that fires itFlujo de pantallas que lo dispara

A transação é o último passo da verificação de preço. As telas do caminho pertencem à feature de Verificação de preço; aqui só situamos onde o envio acontece:The transaction is the last step of the price check. The screens along the way belong to the Price check feature; here we only place where the send happens:La transacción es el último paso de la verificación de precio. Las pantallas del camino pertenecen a la feature de Verificación de precio; aquí solo situamos dónde ocurre el envío:

  1. Detalhe da visita → ferramenta Price CheckVisit detail → Price Check toolDetalle de la visita → herramienta Price CheckDentro de uma visita, o rep abre a ferramenta de verificação de preço na grade de ferramentas.Inside a visit, the rep opens the price-check tool from the tools grid.Dentro de una visita, el rep abre la herramienta de verificación de precio en la grilla de herramientas.
  2. Lista de produtosProduct listLista de productosVê os produtos elegíveis e informa, por produto, o preço de venda por maço e por unidade.Sees the eligible products and enters, per product, the selling price per pack and per stick.Ve los productos elegibles e informa, por producto, el precio de venta por paquete y por unidad.
  3. Rodapé de resumoSummary footerPie de resumenUm rodapé mostra quantos produtos foram preenchidos; ao tocar, abre o resumo da coleta.A footer shows how many products were filled; tapping it opens the collection summary.Un pie muestra cuántos productos se completaron; al tocar, abre el resumen de la recolección.
  4. Confirmar e enviar → esta transaçãoConfirm and send → this transactionConfirmar y enviar → esta transacciónO rep confirma o envio no diálogo de confirmação. É este toque que dispara a Verificação de preço.The rep confirms the send in the confirmation dialog. This tap is what fires Product price check.El rep confirma el envío en el diálogo de confirmación. Este toque es lo que dispara la Verificación de precio.

Um envio por coletaOne send per collectionUn envío por recolección Toda a coleta de preços da visita vai num único envio, com uma linha por produto preenchido — não há um envio por produto. The whole price collection of the visit goes in a single send, with one line per filled product — there's no per-product send. Toda la recolección de precios de la visita va en un único envío, con una línea por producto completado — no hay un envío por producto.

03

Depois do envioAfter sendingDespués del envío

Confirmação ao repConfirmation to the repConfirmación al rep
Quando o backend aceita, o app confirma o envio e o rep volta da tela de verificação. A coleta de preços fica registrada no sistema para acompanhamento comercial.When the backend accepts it, the app confirms the send and the rep leaves the check screen. The price collection is recorded in the system for commercial tracking.Cuando el backend lo acepta, la app confirma el envío y el rep sale de la pantalla de verificación. La recolección de precios queda registrada en el sistema para seguimiento comercial.
Se o envio falha / sem internetIf the send fails / offlineSi el envío falla / sin internet
Se o backend não aceita (erro ou sem conexão), o app avisa o rep e a coleta continua na tela — nada é perdido. O rep pode tentar enviar de novo. Não há fila de reenvio automático para este tipo.If the backend doesn't accept it (error or no connection), the app warns the rep and the collection stays on the screen — nothing is lost. The rep can try to send again. There's no automatic resend queue for this type.Si el backend no lo acepta (error o sin conexión), la app avisa al rep y la recolección queda en la pantalla — nada se pierde. El rep puede intentar enviar de nuevo. No hay cola de reenvío automático para este tipo.
Reenvio é seguroResending is safeReenviar es seguro
Por ser uma transação leve, mandar de novo a mesma coleta não causa efeito duplicado — o backend apenas re-registra os mesmos preços. Tentar enviar mais de uma vez é inofensivo.Being a lightweight transaction, sending the same collection again causes no duplicated effect — the backend just re-records the same prices. Trying to send more than once is harmless.Al ser una transacción liviana, enviar de nuevo la misma recolección no causa efecto duplicado — el backend solo re-registra los mismos precios. Intentar enviar más de una vez es inofensivo.
Acompanhar o envioTracking the sendSeguir el envío
O status técnico do despacho (enviado, com erro) pode ser acompanhado na central de dados / tracking de despachos do app — útil para suporte investigar um envio.The dispatch's technical status (sent, errored) can be followed in the app's data center / dispatch tracking — useful for support to investigate a send.El estado técnico del despacho (enviado, con error) puede seguirse en el centro de datos / tracking de despachos de la app — útil para que soporte investigue un envío.
04

Visão técnicaTechnical overviewVisión técnica

Verificação de preço é a transação de saída que persiste no backend os preços de venda coletados na visita. É disparada pelo PriceCheckNotifier.submit quando o rep confirma a coleta. Uma única variante, um único serviceName (ProductPriceCheck), sem prefixo Promo_. Está no conjunto leve (resendMayDuplicate == false) e o destino é o batch API (DispatcherDestination.batchApi → endpoint sfbatchapi). Product price check is the outbound transaction that persists in the backend the selling prices collected during the visit. It's fired by PriceCheckNotifier.submit when the rep confirms the collection. A single variant, a single serviceName (ProductPriceCheck), no Promo_ prefix. It's in the lightweight set (resendMayDuplicate == false) and the destination is the batch API (DispatcherDestination.batchApi → endpoint sfbatchapi). Verificación de precio es la transacción de salida que persiste en el backend los precios de venta recolectados en la visita. La dispara PriceCheckNotifier.submit cuando el rep confirma la recolección. Una única variante, un único serviceName (ProductPriceCheck), sin prefijo Promo_. Está en el conjunto liviano (resendMayDuplicate == false) y el destino es el batch API (DispatcherDestination.batchApi → endpoint sfbatchapi).

Payload em listaList payloadPayload en lista

Um único array ProductPriceCheck, uma linha por produto verificado; cada linha tem 7 folhas (conta, produto, preços, data). Nenhum cálculo monetário.A single ProductPriceCheck array, one line per checked product; each line has 7 leaves (account, product, prices, date). No monetary computation.Un único array ProductPriceCheck, una línea por producto verificado; cada línea tiene 7 hojas (cuenta, producto, precios, fecha). Sin cálculo monetario.

RPC genéricoGeneric RPCRPC genérico

Passa pelo mesmo sendTransaction de todas as transações, com o JSON no campo message e ProductPriceCheck como serviceName discriminador; endpoint sfbatchapi.Goes through the same sendTransaction as every transaction, with the JSON in the message field and ProductPriceCheck as the discriminating serviceName; endpoint sfbatchapi.Pasa por el mismo sendTransaction de todas las transacciones, con el JSON en el campo message y ProductPriceCheck como serviceName discriminador; endpoint sfbatchapi.

Leve / idempotenteLightweight / idempotentLiviana / idempotente

No conjunto {notificationRead, answerTask, priceCheck}: reenviar a mesma coleta não duplica efeito. Falha volta como Failure à UI, sem fila de reenvio.In the {notificationRead, answerTask, priceCheck} set: resending the same collection duplicates nothing. Failure returns as Failure to the UI, with no resend queue.En el conjunto {notificationRead, answerTask, priceCheck}: reenviar la misma recolección no duplica efecto. La falla vuelve como Failure a la UI, sin cola de reenvío.

FontesSourcesFuentes BuildProductPriceCheckDispatcherPayloadUseCase + ProductPriceCheckDispatcherPayloadInput + DispatcherType.priceCheck + DispatcherConectaRep.proto. O input carrega dado como existe no domínio (entities de entrada e catálogo cruas + o relógio); o build() constrói todo o wire (CLAUDE.md §36). BuildProductPriceCheckDispatcherPayloadUseCase + ProductPriceCheckDispatcherPayloadInput + DispatcherType.priceCheck + DispatcherConectaRep.proto. The input carries data as it exists in the domain (raw entry and catalog entities + the clock); build() constructs the entire wire (CLAUDE.md §36). BuildProductPriceCheckDispatcherPayloadUseCase + ProductPriceCheckDispatcherPayloadInput + DispatcherType.priceCheck + DispatcherConectaRep.proto. El input lleva el dato como existe en el dominio (entities de entrada y catálogo crudas + el reloj); el build() construye todo el wire (CLAUDE.md §36).

05

Transporte gRPCgRPC transportTransporte gRPC

DispatcherConectaRep.proto · proto3 · package mn.bat.conectarep.dispatcher. O serviço expõe um único RPC genérico — não existe mensagem por transação. TODA transação de escrita do app usa este mesmo sendTransaction; o que muda é o serviceName (discriminador), o endpoint (destino) e o JSON dentro de message.The service exposes a single generic RPC — there's no per-transaction message. EVERY write transaction in the app uses this same sendTransaction; what changes is the serviceName (discriminator), the endpoint (destination) and the JSON inside message.El servicio expone un único RPC genérico — no existe mensaje por transacción. TODA transacción de escritura de la app usa este mismo sendTransaction; lo que cambia es el serviceName (discriminador), el endpoint (destino) y el JSON dentro de message.

sendTransactionunary
MétodoMethodMétodo

rpc sendTransaction(InboxTransactionRequest) returns (InboxTransactionReply)

path /mn.bat.conectarep.dispatcher.DispatcherConectaRepService/sendTransaction

Request · InboxTransactionRequest
endpoint
string · #1 · sfbatchapitype.destination.value (destino batchApi)sfbatchapitype.destination.value (batchApi destination)sfbatchapitype.destination.value (destino batchApi)
serviceName
string · #2 · discriminador — sempre ProductPriceCheck (sem prefixo Promo_)discriminator — always ProductPriceCheck (no Promo_ prefix)discriminador — siempre ProductPriceCheck (sin prefijo Promo_)
dateReference
string · #3 · AAAA-MM-DD do envio (formatDate(submittedAt))YYYY-MM-DD of the submission (formatDate(submittedAt))AAAA-MM-DD del envío (formatDate(submittedAt))
transactionReference
string · #4 · o sfid da conta (correlação; = input.accountSfid)the account sfid (correlation; = input.accountSfid)el sfid de la cuenta (correlación; = input.accountSfid)
username
string · #5
message
string · #6 · o payload JSON serializado (a tabela da seção 07)the JSON payload serialized (the table in section 07)el payload JSON serializado (la tabla de la sección 07)
manufacturer · model · deviceUuid · deviceVersion
string · #7–#10 · dados do dispositivo (preenchidos pelo gateway)device data (filled by the gateway)datos del dispositivo (completados por el gateway)
tid
int64 · #11 · id de transação para idempotência/replaytransaction id for idempotency/replayid de transacción para idempotencia/replay
Reply · InboxTransactionReply
status
int32 · #1 · status do ack (0 = sucesso)ack status (0 = success)status del ack (0 = éxito)
message
string · #2 · mensagem do backendbackend messagemensaje del backend
transactionId
int32 · #3 · id atribuído pelo backend (correlação)backend-assigned id (correlation)id asignado por el backend (correlación)

Envelope → Request O builder devolve um DispatcherEnvelope (type, serviceName, payload, account, transactionReference, dateReference). O DispatcherGateway serializa payload em JSON para message (jsonEncode(envelope.payload)), copia serviceName/dateReference/transactionReference, resolve endpoint a partir de type.destination.value (aqui sfbatchapi), preenche os campos de dispositivo e o bearer token de auth, e chama o RPC. The builder returns a DispatcherEnvelope (type, serviceName, payload, account, transactionReference, dateReference). The DispatcherGateway serializes payload to JSON into message (jsonEncode(envelope.payload)), copies serviceName/dateReference/transactionReference, resolves endpoint from type.destination.value (here sfbatchapi), fills in the device fields and the auth bearer token, and calls the RPC. El builder devuelve un DispatcherEnvelope (type, serviceName, payload, account, transactionReference, dateReference). El DispatcherGateway serializa payload a JSON en message (jsonEncode(envelope.payload)), copia serviceName/dateReference/transactionReference, resuelve endpoint desde type.destination.value (aquí sfbatchapi), completa los campos del dispositivo y el bearer token de auth, y llama al RPC.

Esta transação está no conjunto leveresendMayDuplicate == false: um reenvio (ex.: o rep tocar enviar de novo após erro) não duplica efeito, pois re-registrar a mesma coleta de preços é idempotente no backend.This transaction is in the lightweight setresendMayDuplicate == false: a resend (e.g. the rep tapping send again after an error) does not duplicate any effect, since re-recording the same price collection is idempotent on the backend.Esta transacción está en el conjunto livianoresendMayDuplicate == false: un reenvío (p. ej. el rep tocando enviar de nuevo tras un error) no duplica efecto, pues re-registrar la misma recolección de precios es idempotente en el backend.

06

Como é disparadoHow it's firedCómo se dispara

A transação é disparada pelo PriceCheckNotifier.submit (remote-first, §36) quando o rep confirma a coleta. O notifier apenas reúne entities cruas (entradas de preço + produtos do catálogo) e o relógio; o builder é o dono único do join, do rename e da formatação de data. A cascata:The transaction is fired by PriceCheckNotifier.submit (remote-first, §36) when the rep confirms the collection. The notifier only gathers raw entities (price entries + catalog products) and the clock; the builder is the sole owner of the join, rename and date formatting. The cascade:La transacción la dispara PriceCheckNotifier.submit (remote-first, §36) cuando el rep confirma la recolección. El notifier solo reúne entities crudas (entradas de precio + productos del catálogo) y el reloj; el builder es el dueño único del join, del rename y del formateo de fecha. La cascada:

  • PriceCheckNotifier.submitconfirmação da coletacollection confirmationconfirmación de la recolección
    • ProductPriceCheckDispatcherPayloadInputBuildProductPriceCheckDispatcherPayloadUseCasemonta o wireassembles the wirearma el wire
      • devolvereturnsdevuelveDispatcherEnvelope
        • SubmitProductPriceCheckUseCaseDispatcherOrchestrator.dispatch
          • sendDispatcherRepository
            • jsonEncode + authjsonEncode + authjsonEncode + authDispatcherGateway
              • sendTransactionBackendgRPC

Gate de disparo no notifierFire gate in the notifierGate de disparo en el notifier submit retorna cedo (UnknownFailure) se não há estado ou se !hasAnyEntry — nunca envia coleta vazia. Marca isSubmitting: true, monta o input com submittedAt: DateTimeUtils.now(), chama build() e despacha via SubmitProductPriceCheckUseCase. Em Success, seta submitSucceeded: true e retorna null; em Error, desliga isSubmitting e retorna o Failure à UI (que mantém a coleta na tela). Não há gravação local nem fila de reenvio. submit returns early (UnknownFailure) if there's no state or if !hasAnyEntry — it never sends an empty collection. It marks isSubmitting: true, builds the input with submittedAt: DateTimeUtils.now(), calls build() and dispatches via SubmitProductPriceCheckUseCase. On Success, it sets submitSucceeded: true and returns null; on Error, it clears isSubmitting and returns the Failure to the UI (which keeps the collection on screen). There's no local persist nor resend queue. submit retorna temprano (UnknownFailure) si no hay estado o si !hasAnyEntry — nunca envía recolección vacía. Marca isSubmitting: true, arma el input con submittedAt: DateTimeUtils.now(), llama a build() y despacha vía SubmitProductPriceCheckUseCase. En Success, setea submitSucceeded: true y retorna null; en Error, apaga isSubmitting y retorna el Failure a la UI (que mantiene la recolección en pantalla). No hay persistencia local ni cola de reenvío.

O input (entities cruas)The input (raw entities)El input (entities crudas)

ProductPriceCheckDispatcherPayloadInput (Freezed). Carrega o dado como existe no domínio; nada de formato wire. O relógio chega como submittedAt (via DateTimeUtils.now() no notifier).ProductPriceCheckDispatcherPayloadInput (Freezed). Carries data as it exists in the domain; no wire shaping. The clock arrives as submittedAt (via DateTimeUtils.now() in the notifier).ProductPriceCheckDispatcherPayloadInput (Freezed). Lleva el dato como existe en el dominio; nada de formato wire. El reloj llega como submittedAt (vía DateTimeUtils.now() en el notifier).

CampoFieldCampoTipoTypeTipoPapelRoleRol
accountSfidStringsfid do varejo da visita → cada linha (accountSfid) + transactionReferencesfid of the visit's retail → each line (accountSfid) + transactionReferencesfid del punto de venta de la visita → cada línea (accountSfid) + transactionReference
accountCodeStringcódigo SAP do varejo → cada linha (accountCode)retail's SAP code → each line (accountCode)código SAP del punto de venta → cada línea (accountCode)
entriesList<PriceCheckEntryEntity>preços informados (por productSfid: packPrice?/stickPrice?) — o builder as indexa num map por productSfidentered prices (by productSfid: packPrice?/stickPrice?) — the builder indexes them into a map by productSfidprecios informados (por productSfid: packPrice?/stickPrice?) — el builder los indexa en un map por productSfid
productsList<ProductEntity>catálogo elegível — dirige o loop (uma linha por produto com entrada) e fornece productSfid + nameeligible catalog — drives the loop (one line per product with an entry) and provides productSfid + namecatálogo elegible — dirige el loop (una línea por producto con entrada) y provee productSfid + name
submittedAtDateTimerelógio do envio (DateTimeUtils.now()) → dateReference + priceCheckDate de cada linhasubmission clock (DateTimeUtils.now()) → dateReference + each line's priceCheckDatereloj del envío (DateTimeUtils.now()) → dateReference + priceCheckDate de cada línea
07

Payload (message)

O JSON serializado no campo message do request. A tabela tem 4 colunasCampo JSON · Tipo · Origem do Dado · Regra — e lista todas as 8 chaves que o build() emite (1 array-envelope ProductPriceCheck + 7 folhas por item). Campo, Tipo e Origem são código cru; só a Regra é prosa. Um exemplo completo (ZA) está em transaction_example.json, ao lado deste doc.The JSON serialized into the request's message field. The table has 4 columnsJSON field · Type · Data source · Rule — and lists all 8 keys that build() emits (1 ProductPriceCheck array wrapper + 7 leaves per item). Field, Type and Source are raw code; only Rule is prose. A full example (ZA) sits in transaction_example.json, next to this doc.El JSON serializado en el campo message del request. La tabla tiene 4 columnasCampo JSON · Tipo · Origen del Dato · Regla — y lista las 8 claves que build() emite (1 array-envoltorio ProductPriceCheck + 7 hojas por ítem). Campo, Tipo y Origen son código crudo; solo la Regla es prosa. Un ejemplo completo (ZA) está en transaction_example.json, junto a este doc.

Campo JSONJSON fieldCampo JSON TipoTypeTipo Origem do DadoData sourceOrigen del Dato RegraRuleRegla
ProductPriceCheckList<Map>Fixo (envelope)Fixed (wrapper)Fijo (envoltorio)array com uma linha por produto verificado — o builder itera input.products e, para cada produto que tem uma entrada com ao menos um preço, adiciona um objeto. Produtos sem entrada, ou entradas sem preço, não geram linha (pode ser vazio na teoria, mas o notifier bloqueia envio vazio).array with one line per checked product — the builder iterates input.products and, for each product having an entry with at least one price, adds an object. Products with no entry, or entries with no price, produce no line (could be empty in theory, but the notifier blocks an empty send).array con una línea por producto verificado — el builder itera input.products y, para cada producto que tiene una entrada con al menos un precio, agrega un objeto. Productos sin entrada, o entradas sin precio, no generan línea (podría ser vacío en teoría, pero el notifier bloquea el envío vacío).
ProductPriceCheck[].accountSfidStringinput.accountSfidsfid do varejo da visita, repetido em cada linha. É a mesma string do transactionReference do envelope.the visit retail's sfid, repeated on every line. Same string as the envelope's transactionReference.sfid del punto de venta de la visita, repetido en cada línea. Es la misma string del transactionReference del envelope.
ProductPriceCheck[].accountCodeStringinput.accountCodecódigo SAP do varejo, repetido em cada linha.the retail's SAP code, repeated on every line.código SAP del punto de venta, repetido en cada línea.
ProductPriceCheck[].productSfidStringproduct.productSfidsfid do produto verificado (do ProductEntity do catálogo, não da entrada). É a chave usada para casar a entrada de preço.sfid of the checked product (from the catalog ProductEntity, not the entry). It's the key used to match the price entry.sfid del producto verificado (del ProductEntity del catálogo, no de la entrada). Es la clave usada para casar la entrada de precio.
ProductPriceCheck[].productNameStringproduct.namenome do produto vindo do catálogo (não digitado pelo rep).product name from the catalog (not typed by the rep).nombre del producto del catálogo (no tipeado por el rep).
ProductPriceCheck[].packsSellingPricedoubleentry.packPrice ?? 0.0preço de venda por maço informado pelo rep; 0.0 quando não preenchido (o rep pode ter informado só o de unidade). Passa cru, sem arredondamento nem prefixo de moeda.the pack selling price entered by the rep; 0.0 when unfilled (the rep may have entered only the stick one). Passes raw — no rounding, no currency prefix.el precio de venta por paquete informado por el rep; 0.0 cuando no se completó (el rep pudo informar solo el de unidad). Pasa crudo — sin redondeo ni prefijo de moneda.
ProductPriceCheck[].sticksSellingPricedoubleentry.stickPrice ?? 0.0preço de venda por unidade informado pelo rep; 0.0 quando não preenchido. Passa cru, sem arredondamento nem prefixo de moeda.the stick selling price entered by the rep; 0.0 when unfilled. Passes raw — no rounding, no currency prefix.el precio de venta por unidad informado por el rep; 0.0 cuando no se completó. Pasa crudo — sin redondeo ni prefijo de moneda.
ProductPriceCheck[].priceCheckDateStringformatDate(input.submittedAt)AAAA-MM-DD do envio, o mesmo dateReference do envelope, repetido em cada linha.YYYY-MM-DD of the send, the same dateReference as the envelope, repeated on every line.AAAA-MM-DD del envío, el mismo dateReference del envelope, repetido en cada línea.
08

Regras de negócioBusiness rulesReglas de negocio

O que o builder decideWhat the builder decidesLo que el builder decide

  • Índice por produto: o build() monta entriesByProductSfid (map productSfid → PriceCheckEntryEntity) a partir de input.entries, e depois itera input.products — o catálogo dirige a ordem, não a lista de entradas.Index by product: build() assembles entriesByProductSfid (map productSfid → PriceCheckEntryEntity) from input.entries, then iterates input.products — the catalog drives the order, not the entry list.Índice por producto: build() arma entriesByProductSfid (map productSfid → PriceCheckEntryEntity) a partir de input.entries, y luego itera input.products — el catálogo dirige el orden, no la lista de entradas.
  • Dois filtros de linha: um produto é pulado se (a) não há entrada para o seu productSfid (entry == null → continue); ou (b) a entrada existe mas packPrice == null && stickPrice == null. Só produtos com ao menos um preço geram linha.Two line filters: a product is skipped if (a) there's no entry for its productSfid (entry == null → continue); or (b) the entry exists but packPrice == null && stickPrice == null. Only products with at least one price produce a line.Dos filtros de línea: un producto se omite si (a) no hay entrada para su productSfid (entry == null → continue); o (b) la entrada existe pero packPrice == null && stickPrice == null. Solo productos con al menos un precio generan línea.
  • Coalescência para 0.0: preço ausente vira 0.0 no payload (packPrice ?? 0.0, stickPrice ?? 0.0) — o wire não distingue "não informado" de "preço zero".Coalesce to 0.0: a missing price becomes 0.0 in the payload (packPrice ?? 0.0, stickPrice ?? 0.0) — the wire doesn't distinguish "not entered" from "zero price".Coalescencia a 0.0: un precio ausente pasa a 0.0 en el payload (packPrice ?? 0.0, stickPrice ?? 0.0) — el wire no distingue "no informado" de "precio cero".
  • Sem cálculo monetário: os preços passam crus, sem arredondamento (CurrencyUtils), sem separador nem prefixo de moeda; o nome do produto vem do catálogo.No monetary computation: prices pass raw — no rounding (CurrencyUtils), no separator or currency prefix; the product name comes from the catalog.Sin cálculo monetario: los precios pasan crudos — sin redondeo (CurrencyUtils), sin separador ni prefijo de moneda; el nombre del producto viene del catálogo.
  • serviceName sem prefixo: type.resolveServiceName(hasPromotion: false) — chamado com false fixo, então nunca há Promo_. O resultado é sempre ProductPriceCheck.serviceName without prefix: type.resolveServiceName(hasPromotion: false) — called with a fixed false, so there's never a Promo_. The result is always ProductPriceCheck.serviceName sin prefijo: type.resolveServiceName(hasPromotion: false) — llamado con false fijo, así que nunca hay Promo_. El resultado es siempre ProductPriceCheck.
  • dateReference único: DateTimeUtils.formatDate(dateTime: input.submittedAt)AAAA-MM-DD, calculado uma vez e reusado no envelope e em priceCheckDate de cada linha.Single dateReference: DateTimeUtils.formatDate(dateTime: input.submittedAt)YYYY-MM-DD, computed once and reused on the envelope and in each line's priceCheckDate.dateReference único: DateTimeUtils.formatDate(dateTime: input.submittedAt)AAAA-MM-DD, calculado una vez y reusado en el envelope y en priceCheckDate de cada línea.
  • Leve / idempotente: resendMayDuplicate == false (conjunto {notificationRead, answerTask, priceCheck}). Reenviar a mesma coleta não duplica efeito no backend.Lightweight / idempotent: resendMayDuplicate == false (set {notificationRead, answerTask, priceCheck}). Resending the same collection duplicates nothing on the backend.Liviana / idempotente: resendMayDuplicate == false (conjunto {notificationRead, answerTask, priceCheck}). Reenviar la misma recolección no duplica efecto en el backend.
09

Pendências / roadmapPending / roadmapPendientes / roadmap

O que o builder/fluxo envia inerte ou fixo, documentado fiel ao estado atual do código (nunca descrito como se já existisse):What the builder/flow ships inert or fixed, documented faithfully to the current code state (never described as already existing):Lo que el builder/flujo envía inerte o fijo, documentado fiel al estado actual del código (nunca descrito como si ya existiera):

Fixo / pendenteFixed / pendingFijo / pendiente

  • Preço ausente ambíguo: packsSellingPrice/sticksSellingPrice caem para 0.0 quando não preenchidos, então o backend não consegue distinguir "não coletado" de um preço legítimo de 0. Um produto com só o preço de maço envia sticksSellingPrice: 0.0.Ambiguous missing price: packsSellingPrice/sticksSellingPrice fall to 0.0 when unfilled, so the backend can't tell "not collected" from a legitimate 0 price. A product with only a pack price sends sticksSellingPrice: 0.0.Precio ausente ambiguo: packsSellingPrice/sticksSellingPrice caen a 0.0 cuando no se completan, así que el backend no puede distinguir "no recolectado" de un precio legítimo de 0. Un producto con solo el precio de paquete envía sticksSellingPrice: 0.0.
  • Sem moeda/UoM no payload: os preços vão como double crus, sem código de moeda nem unidade — o mercado (ZA) é implícito no contexto do envio, não um campo.No currency/UoM in the payload: prices go as raw double, with no currency code or unit — the market (ZA) is implicit in the send context, not a field.Sin moneda/UoM en el payload: los precios van como double crudos, sin código de moneda ni unidad — el mercado (ZA) es implícito en el contexto del envío, no un campo.
  • Sem fila offline para este tipo: uma falha/offline volta como Failure à UI e a coleta fica na tela; não há registro pendente nem reenvio automático (o rep reenvia manualmente). Roadmap: incluir os tipos leves no reenvio (o efeito é idempotente, então seria seguro).No offline queue for this type: a failure/offline returns as Failure to the UI and the collection stays on screen; there's no pending record nor automatic resend (the rep resends manually). Roadmap: include the lightweight types in the resend (the effect is idempotent, so it would be safe).Sin cola offline para este tipo: una falla/offline vuelve como Failure a la UI y la recolección queda en pantalla; no hay registro pendiente ni reenvío automático (el rep reenvía manualmente). Roadmap: incluir los tipos livianos en el reenvío (el efecto es idempotente, así que sería seguro).
  • Transporte: deviceUuid vai como literal provisório no gateway (pendência conhecida do Dispatcher, comum a todas as transações).Transport: deviceUuid ships as a provisional literal in the gateway (known Dispatcher pending item, common to all transactions).Transporte: deviceUuid va como literal provisional en el gateway (pendiente conocido del Dispatcher, común a todas las transacciones).

Feature relacionadaRelated featureFeature relacionada A tela e a lógica de coleta (lista de produtos, inputs de preço, rodapé, resumo) estão documentadas em Verificação de preço. Esta transação é o único ponto de escrita dessa feature. The collection screen and logic (product list, price inputs, footer, summary) are documented in Price check. This transaction is that feature's only write point. La pantalla y la lógica de recolección (lista de productos, inputs de precio, pie, resumen) están documentadas en Verificación de precio. Esta transacción es el único punto de escritura de esa feature.

MercadosMarketsMercados

A disponibilidade da transação vem do DispatcherType.priceCheck.enabledMarkets = só ZA (África do Sul). É a mesma cobertura da feature de Verificação de preço. BR/CL/AR/PY/PE não disparam esta transação.Transaction availability comes from DispatcherType.priceCheck.enabledMarkets = ZA only (South Africa). It's the same coverage as the Price check feature. BR/CL/AR/PY/PE don't fire this transaction.La disponibilidad de la transacción viene de DispatcherType.priceCheck.enabledMarkets = solo ZA (Sudáfrica). Es la misma cobertura de la feature de Verificación de precio. BR/CL/AR/PY/PE no disparan esta transacción.

BR CL ZAx AR PY PE
disponívelavailabledisponible presente, desligadopresent, offpresente, apagado ausenteabsentausente
ZA

Só na África do SulSouth Africa onlySolo Sudáfrica A verificação de preço de prateleira (por maço e por unidade) é uma prática só da África do Sul; nenhum outro mercado lista priceCheck em enabledMarkets. Preços por maço/unidade refletem o modelo de venda de tabaco local. Shelf price checking (per pack and per stick) is a South Africa-only practice; no other market lists priceCheck in enabledMarkets. Pack/stick prices reflect the local tobacco selling model. La verificación de precio de góndola (por paquete y por unidad) es una práctica solo de Sudáfrica; ningún otro mercado lista priceCheck en enabledMarkets. Los precios por paquete/unidad reflejan el modelo de venta de tabaco local.

BR · CL · AR · PY · PE Existem como mercados do app, mas não têm a transação de verificação de preço — enabledMarkets lista só ZA. A coleta de preços não é disparada nesses mercados. They exist as app markets, but have no price-check transaction — enabledMarkets lists only ZA. Price collection is not fired in these markets. Existen como mercados de la app, pero no tienen la transacción de verificación de precio — enabledMarkets lista solo ZA. La recolección de precios no se dispara en estos mercados.