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

Envio de resultado de pesquisaSurvey result uploadEnvío de resultado de encuesta

A transação de escrita que envia ao backend as respostas de uma pesquisa respondida pelo representante de vendas dentro de uma visita. Um único builder monta o payload JSON com o cabeçalho do resultado, o detalhe pergunta-a-pergunta e as evidências em foto/documento. Quando há muitas evidências, o envio é fatiado em vários envelopes (até três evidências por envelope), disparados em paralelo. The write transaction that sends to the backend the answers of a survey filled in by the sales rep during a visit. A single builder assembles the JSON payload with the result header, the question-by-question detail and the photo/document evidences. When there are many evidences, the send is split into several envelopes (up to three evidences each), fired in parallel. La transacción de escritura que envía al backend las respuestas de una encuesta respondida por el representante de ventas dentro de una visita. Un único builder arma el payload JSON con el encabezado del resultado, el detalle pregunta por pregunta y las evidencias en foto/documento. Cuando hay muchas evidencias, el envío se divide en varios envelopes (hasta tres evidencias cada uno), disparados en paralelo.

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 BR CL ZA
01

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

Durante uma visita, o representante de vendas pode responder uma pesquisa sobre aquele varejo — um censo de concorrência, um checklist de encerramento, uma auditoria de preço, uma pesquisa de satisfação. Quando ele finaliza a resposta, o app envia esse resultado ao backend por esta transação. É o momento em que as respostas saem do dispositivo e passam a existir no sistema. During a visit, the sales rep can answer a survey about that retail — a competition census, a closing checklist, a price audit, a satisfaction survey. When they finish the answers, the app sends that result to the backend through this transaction. It's the moment the answers leave the device and start to exist in the system. Durante una visita, el representante de ventas puede responder una encuesta sobre ese punto de venta — un censo de competencia, un checklist de cierre, una auditoría de precio, una encuesta de satisfacción. Cuando termina las respuestas, la app envía ese resultado al backend por esta transacción. Es el momento en que las respuestas salen del dispositivo y pasan a existir en el sistema.

As respostasThe answersLas respuestas

Cada pergunta respondida vira uma linha do resultado — a opção escolhida, o texto digitado, o número ou a data.Each answered question becomes a result line — the chosen option, the typed text, the number or the date.Cada pregunta respondida se vuelve una línea del resultado — la opción elegida, el texto escrito, el número o la fecha.

As evidênciasThe evidencesLas evidencias

Algumas perguntas exigem foto ou documento. As evidências vão junto com o resultado, em blocos de até três arquivos.Some questions require a photo or document. Evidences go along with the result, in blocks of up to three files.Algunas preguntas exigen foto o documento. Las evidencias van junto con el resultado, en bloques de hasta tres archivos.

Completa ou em andamentoComplete or in progressCompleta o en curso

O resultado é marcado como concluído ou em andamento conforme a configuração da pesquisa — algumas fecham no primeiro envio, outras admitem envios parciais.The result is marked complete or in progress per the survey config — some close on the first send, others accept partial sends.El resultado se marca como completo o en curso según la config de la encuesta — algunas cierran en el primer envío, otras admiten envíos parciales.

Sempre dentro de uma visitaAlways inside a visitSiempre dentro de una visita Não existe pesquisa "solta": ela é sempre respondida a partir de uma visita, e o varejo vem dela. Enviar um pedido não está envolvido aqui — esta transação é só sobre pesquisas. There's no standalone survey: it's always answered from within a visit, and the retail comes from it. Sending an order isn't involved here — this transaction is only about surveys. No existe encuesta "suelta": siempre se responde a partir de una visita, y el punto de venta viene de ella. Enviar un pedido no está involucrado aquí — esta transacción es solo sobre encuestas.

02

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

A transação é o último passo do fluxo de resposta de pesquisa. As telas do caminho pertencem à feature de Pesquisas; aqui só situamos onde o envio acontece:The transaction is the last step of the survey-answering flow. The screens along the way belong to the Surveys feature; here we only place where the send happens:La transacción es el último paso del flujo de respuesta de encuesta. Las pantallas del camino pertenecen a la feature de Encuestas; aquí solo situamos dónde ocurre el envío:

  1. Detalhe da visitaVisit detailDetalle de la visitaCom a visita iniciada, o rep abre a grade de ferramentas e toca em Pesquisas (no Brasil, também por Ações de concorrência ou pelas pendências de encerramento).With the visit started, the rep opens the tools grid and taps Surveys (in Brazil, also via Competition actions or the closing pending items).Con la visita iniciada, el rep abre la grilla de herramientas y toca Encuestas (en Brasil, también por Acciones de competencia o los pendientes de cierre).
  2. Lista de pesquisasSurvey listLista de encuestasMostra as pesquisas que se aplicam àquele varejo. O rep toca num card para abrir a resposta.Shows the surveys that apply to that retail. The rep taps a card to open the answering flow.Muestra las encuestas que aplican a ese punto de venta. El rep toca una tarjeta para abrir la respuesta.
  3. Fluxo de respostaAnswering flowFlujo de respuestaUma pergunta por página. Escolher uma opção pode revelar perguntas dependentes; algumas perguntas exigem foto ou documento.One question per page. Choosing an option may reveal dependent questions; some questions require a photo or document.Una pregunta por página. Elegir una opción puede revelar preguntas dependientes; algunas preguntas exigen foto o documento.
  4. Finalizar → esta transaçãoFinish → this transactionFinalizar → esta transacciónAo tocar em finalizar/enviar na última pergunta, o app dispara o Envio de resultado de pesquisa. É este toque que aciona a transação.Tapping finish/send on the last question fires the Survey result upload. This tap is what triggers the transaction.Al tocar finalizar/enviar en la última pregunta, la app dispara el Envío de resultado de encuesta. Este toque es lo que activa la transacción.
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 em tela. Uma pesquisa de resposta única só desaparece da lista quando a próxima sincronização traz o varejo atualizado — o envio em si não marca a pesquisa como respondida no dispositivo.When the backend accepts it, the app confirms the send on screen. A single-answer survey only leaves the list when the next sync brings the retail updated — the send itself does not mark the survey as answered on the device.Cuando el backend lo acepta, la app confirma el envío en pantalla. Una encuesta de respuesta única solo desaparece de la lista cuando la próxima sincronización trae el punto de venta actualizado — el envío en sí no marca la encuesta como respondida en el dispositivo.
Muitas evidênciasMany evidencesMuchas evidencias
Se a pesquisa tem muitas fotos/documentos, o envio é dividido em vários blocos (até três arquivos por bloco), enviados em paralelo. O rep não percebe a divisão — para ele é um único envio.If the survey has many photos/documents, the send is split into several blocks (up to three files each), sent in parallel. The rep doesn't notice the split — to them it's a single send.Si la encuesta tiene muchas fotos/documentos, el envío se divide en varios bloques (hasta tres archivos cada uno), enviados en paralelo. El rep no percibe la división — para él es un único envío.
Sem internetOfflineSin internet
O envio exige conexão; sem rede, o app bloqueia o despacho e avisa. O status técnico do despacho (enviado, com erro) pode ser acompanhado na central de dados / tracking de despachos — útil para suporte investigar um envio.The send requires a connection; offline, the app blocks the dispatch and warns. The dispatch's technical status (sent, errored) can be followed in the data center / dispatch tracking — useful for support to investigate a send.El envío exige conexión; sin red, la app bloquea el despacho y avisa. El estado técnico del despacho (enviado, con error) puede seguirse en el centro de datos / tracking de despachos — útil para que soporte investigue un envío.
04

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

Envio de resultado de pesquisa é a transação de saída que persiste no backend as respostas de uma pesquisa. É disparada pelo SurveyAnswerNotifier quando o representante de vendas finaliza o fluxo de resposta. A leitura das pesquisas é cache-only (proto getSurveys); a escrita não usa esse proto — o resultado vai como JSON pelo Dispatcher. As respostas do rep vivem num sealed class escrito à mão (SurveyAnswerValue) e são convertidas direto em JSON no builder. Survey result upload is the outbound transaction that persists a survey's answers in the backend. It's fired by SurveyAnswerNotifier when the sales rep finishes the answering flow. Reading surveys is cache-only (proto getSurveys); the write does not use that proto — the result goes as JSON through the Dispatcher. The rep's answers live in a hand-written sealed class (SurveyAnswerValue) and are converted straight to JSON in the builder. Envío de resultado de encuesta es la transacción de salida que persiste en el backend las respuestas de una encuesta. La dispara SurveyAnswerNotifier cuando el representante de ventas finaliza el flujo de respuesta. La lectura de encuestas es cache-only (proto getSurveys); la escritura no usa ese proto — el resultado va como JSON por el Dispatcher. Las respuestas del rep viven en un sealed class escrito a mano (SurveyAnswerValue) y se convierten directo a JSON en el builder.

Três blocos de payloadThree payload blocksTres bloques de payload

O JSON tem surveyResult (cabeçalho), surveyResultdetails (uma linha por resposta) e evidenceList (arquivos). O builder é o dono único da montagem.The JSON has surveyResult (header), surveyResultdetails (one line per answer) and evidenceList (files). The builder is the sole owner of the assembly.El JSON tiene surveyResult (encabezado), surveyResultdetails (una línea por respuesta) y evidenceList (archivos). El builder es el dueño único del armado.

Split por evidênciasSplit by evidencesSplit por evidencias

buildAll fatia as evidências em blocos de três e devolve um DispatcherEnvelope por bloco — cabeçalho e detalhes repetidos em todos. Sem evidências (ou até três): um envelope só.buildAll slices evidences into blocks of three and returns one DispatcherEnvelope per block — header and details repeated in all. No evidences (or up to three): a single envelope.buildAll corta las evidencias en bloques de tres y devuelve un DispatcherEnvelope por bloque — encabezado y detalles repetidos en todos. Sin evidencias (o hasta tres): un solo envelope.

RPC genéricoGeneric RPCRPC genérico

Não há RPC por pesquisa: tudo passa pelo mesmo sendTransaction, com o JSON no campo message e serviceName = SurveyResultUploadAPI como discriminador.There's no per-survey RPC: everything goes through the same sendTransaction, with the JSON in the message field and serviceName = SurveyResultUploadAPI as the discriminator.No hay RPC por encuesta: todo pasa por el mismo sendTransaction, con el JSON en el campo message y serviceName = SurveyResultUploadAPI como discriminador.

FontesSourcesFuentes BuildSurveyResultUploadDispatcherPayloadUseCase + SurveyResultUploadDispatcherPayloadInput + DispatcherType.survey + DispatcherConectaRep.proto. O input carrega entities cruas de domínio (CLAUDE.md §36) — SurveyEntity e VisitEntity inteiras; o build() constrói todo o wire. BuildSurveyResultUploadDispatcherPayloadUseCase + SurveyResultUploadDispatcherPayloadInput + DispatcherType.survey + DispatcherConectaRep.proto. The input carries raw domain entities (CLAUDE.md §36) — whole SurveyEntity and VisitEntity; build() constructs the entire wire. BuildSurveyResultUploadDispatcherPayloadUseCase + SurveyResultUploadDispatcherPayloadInput + DispatcherType.survey + DispatcherConectaRep.proto. El input lleva entities crudas de dominio (CLAUDE.md §36) — SurveyEntity y VisitEntity enteras; build() construye todo el wire.

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 (pedido, price check, survey, etc.) usa este mesmo sendTransaction; o que muda é o serviceName (discriminador) 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 (order, price check, survey, etc.) uses this same sendTransaction; what changes is the serviceName (discriminator) 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 (pedido, price check, survey, etc.) usa este mismo sendTransaction; lo que cambia es el serviceName (discriminador) 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 · endpoint alvo (config de ambiente)target endpoint (environment config)endpoint destino (config de ambiente)
serviceName
string · #2 · discriminadorSurveyResultUploadAPIdiscriminatorSurveyResultUploadAPIdiscriminadorSurveyResultUploadAPI
dateReference
string · #3 · AAAA-MM-DD do envio (submittedAt)YYYY-MM-DD of the submission (submittedAt)AAAA-MM-DD del envío (submittedAt)
transactionReference
string · #4 · o surveyCode (correlação)the surveyCode (correlation)el surveyCode (correlación)
username
string · #5
message
string · #6 · o payload JSON serializado (a tabela da seção 08)the JSON payload serialized (the table in section 08)el payload JSON serializado (la tabla de la sección 08)
manufacturer
string · #7 · dado do dispositivodevice datadato del dispositivo
model
string · #8 · dado do dispositivodevice datadato del dispositivo
deviceUuid
string · #9 · literal "REP" hoje (ver Pendências)"REP" literal today (see Pending)literal "REP" hoy (ver Pendientes)
deviceVersion
string · #10
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 (ou vários) DispatcherEnvelope (type, serviceName, payload, account, transactionReference, dateReference). O DispatcherGateway serializa payload em JSON para message (jsonEncode), copia serviceName/dateReference/transactionReference, preenche os campos de dispositivo e o bearer token de auth, e chama o RPC. The builder returns one (or several) DispatcherEnvelope (type, serviceName, payload, account, transactionReference, dateReference). The DispatcherGateway serializes payload to JSON into message (jsonEncode), copies serviceName/dateReference/transactionReference, fills in the device fields and the auth bearer token, and calls the RPC. El builder devuelve uno (o varios) DispatcherEnvelope (type, serviceName, payload, account, transactionReference, dateReference). El DispatcherGateway serializa payload a JSON en message (jsonEncode), copia serviceName/dateReference/transactionReference, completa los campos del dispositivo y el bearer token de auth, y llama al RPC.

Para survey, resendMayDuplicate == true: um reenvio (ex.: recuperação de fila offline) pode duplicar o resultado no backend; a idempotência via tid é o que mitiga isso.For survey, resendMayDuplicate == true: a resend (e.g. offline-queue recovery) may duplicate the result on the backend; idempotency via tid is what mitigates it.Para survey, resendMayDuplicate == true: un reenvío (p. ej. recuperación de cola offline) puede duplicar el resultado en el backend; la idempotencia vía tid es lo que lo mitiga.

06

serviceName e splitsserviceName & splitsserviceName y splits

Uma única transação, sem variantes de tipo: o builder sempre emite DispatcherType.survey. O que se ramifica é o número de envelopes (por evidências) e o status do resultado (concluído vs. em andamento).A single transaction, with no type variants: the builder always emits DispatcherType.survey. What branches is the number of envelopes (by evidences) and the result status (complete vs. in progress).Una única transacción, sin variantes de tipo: el builder siempre emite DispatcherType.survey. Lo que se ramifica es el número de envelopes (por evidencias) y el status del resultado (completo vs. en curso).

DispatcherType serviceName MercadosMarketsMercados DestinoDestinationDestino
surveySurveyResultUploadAPIBR · CL · ZAsalesforce

Prefixo Promo_ não usadoPromo_ prefix unusedPrefijo Promo_ no usado O serviceName vem de type.resolveServiceName(hasPromotion: false) — o builder passa false hardcoded. Portanto o prefixo Promo_ (existente para transações com promoção) nunca é anexado aqui: o serviço é sempre SurveyResultUploadAPI. Ver Pendências. The serviceName comes from type.resolveServiceName(hasPromotion: false) — the builder passes false hardcoded. So the Promo_ prefix (which exists for promotion transactions) is never prepended here: the service is always SurveyResultUploadAPI. See Pending. El serviceName viene de type.resolveServiceName(hasPromotion: false) — el builder pasa false hardcoded. Por eso el prefijo Promo_ (existente para transacciones con promoción) nunca se antepone aquí: el servicio es siempre SurveyResultUploadAPI. Ver Pendientes.

Split multi-envelopeMulti-envelope splitSplit multi-envelope buildAll(input) compara input.evidences.length com _maxEvidencesPerEnvelope = 3. Até três (inclusive zero) → um envelope (build(input)). Acima de três → um envelope por bloco de três, cada um via build(input.copyWith(evidences: sublist)). Cabeçalho e detalhes são repetidos em todos os envelopes; só a evidenceList difere. O SubmitSurveyResultUploadUseCase despacha os envelopes em paralelo (índice-alinhado); o Notifier trata a primeira falha como falha do envio inteiro. buildAll(input) compares input.evidences.length against _maxEvidencesPerEnvelope = 3. Up to three (including zero) → one envelope (build(input)). Above three → one envelope per block of three, each via build(input.copyWith(evidences: sublist)). Header and details are repeated across all envelopes; only evidenceList differs. SubmitSurveyResultUploadUseCase dispatches the envelopes in parallel (index-aligned); the Notifier treats the first failure as failure of the whole send. buildAll(input) compara input.evidences.length con _maxEvidencesPerEnvelope = 3. Hasta tres (incluido cero) → un envelope (build(input)). Más de tres → un envelope por bloque de tres, cada uno vía build(input.copyWith(evidences: sublist)). Encabezado y detalles se repiten en todos los envelopes; solo evidenceList difiere. SubmitSurveyResultUploadUseCase despacha los envelopes en paralelo (índice-alineado); el Notifier trata la primera falla como falla de todo el envío.

07

Como é disparadoHow it's firedCómo se dispara

A transação é orquestrada pelo fluxo de resposta de pesquisa (remote-first, §36). O notifier apenas reúne entities cruas e valores injetados; o builder é o dono único de todo join, rename, formatação de data e derivação wire. A cascata:The transaction is orchestrated by the survey-answering flow (remote-first, §36). The notifier only gathers raw entities and injected values; the builder is the sole owner of every join, rename, date formatting and wire derivation. The cascade:La transacción se orquesta desde el flujo de respuesta de encuesta (remote-first, §36). El notifier solo reúne entities crudas y valores inyectados; el builder es el dueño único de todo join, rename, formateo de fecha y derivación wire. La cascada:

  • SurveyAnswerNotifiersubmit()
    • reúne entities cruas + injetadosgathers raw entities + injectedreúne entities crudas + inyectadosSurveyResultUploadDispatcherPayloadInput
      • buildAll()BuildSurveyResultUploadDispatcherPayloadUseCasemonta o wireassembles the wirearma el wire
        • devolve ≤3 evid./envelopereturns ≤3 evid./envelopedevuelve ≤3 evid./envelopeList<DispatcherEnvelope>
          • SubmitSurveyResultUploadUseCaseDispatcherOrchestrator
            • serializa + authserialize + authserializa + authDispatcherGateway
              • sendTransactionBackendgRPC

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

SurveyResultUploadDispatcherPayloadInput (Freezed). Carrega o dado como existe no domínio; nada de formato wire. O relógio chega como submittedAt (via DateTimeUtils.now()); as evidências chegam com o arquivo já lido em base64.SurveyResultUploadDispatcherPayloadInput (Freezed). Carries data as it exists in the domain; no wire shaping. The clock arrives as submittedAt (via DateTimeUtils.now()); evidences arrive with the file already read as base64.SurveyResultUploadDispatcherPayloadInput (Freezed). Lleva el dato como existe en el dominio; nada de formato wire. El reloj llega como submittedAt (vía DateTimeUtils.now()); las evidencias llegan con el archivo ya leído en base64.

CampoFieldCampoTipoTypeTipoPapelRoleRol
surveySurveyEntitypesquisa respondida (crua). O builder lê survey.sfidsurveyID e percorre a árvore questions → answerOptions → dependentQuestion para resolver o questionAnswerOption de cada respostaanswered survey (raw). The builder reads survey.sfidsurveyID and walks the questions → answerOptions → dependentQuestion tree to resolve each answer's questionAnswerOptionencuesta respondida (cruda). El builder lee survey.sfidsurveyID y recorre el árbol questions → answerOptions → dependentQuestion para resolver el questionAnswerOption de cada respuesta
visitVisitEntityvisita anfitriã (crua). O builder deriva storeID (visit.accountData.sfid), visitID (visit.sfid) e o account do envelope (sfid/sapCode/name)host visit (raw). The builder derives storeID (visit.accountData.sfid), visitID (visit.sfid) and the envelope's account (sfid/sapCode/name)visita anfitriona (cruda). El builder deriva storeID (visit.accountData.sfid), visitID (visit.sfid) y el account del envelope (sfid/sapCode/name)
answersMap<String, SurveyAnswerValue>questionSfid → resposta tipada (SurveyOptionAnswer / SurveyTextAnswer / SurveyNumericAnswer / SurveyDateAnswer). Uma ou mais linhas de surveyResultdetails por entradaquestionSfid → typed answer (SurveyOptionAnswer / SurveyTextAnswer / SurveyNumericAnswer / SurveyDateAnswer). One or more surveyResultdetails rows per entryquestionSfid → respuesta tipada (SurveyOptionAnswer / SurveyTextAnswer / SurveyNumericAnswer / SurveyDateAnswer). Una o más filas de surveyResultdetails por entrada
evidencesList<SurveyResultUploadEvidence>fotos/documentos anexados (questionSfid, base64, fileName). Alimenta a evidenceList e o split de envelopesattached photos/documents (questionSfid, base64, fileName). Feeds evidenceList and the envelope splitfotos/documentos adjuntos (questionSfid, base64, fileName). Alimenta la evidenceList y el split de envelopes
completesResultOnUploadboolseleciona o surveyStatus: trueComplete; falseIn Progressselects surveyStatus: trueComplete; falseIn Progressselecciona el surveyStatus: trueComplete; falseIn Progress
surveyCodeStringcódigo do resultado → surveyCode (raiz e cada detalhe) e transactionReference do enveloperesult code → surveyCode (header and each detail) and the envelope's transactionReferencecódigo del resultado → surveyCode (encabezado y cada detalle) y transactionReference del envelope
submittedAtDateTimerelógio → dateReference do envelope em yyyy-MM-ddclock → the envelope's dateReference in yyyy-MM-ddreloj → dateReference del envelope en yyyy-MM-dd

SurveyResultUploadEvidence (Freezed, aninhado): questionSfid · base64 · fileName — todos String.SurveyResultUploadEvidence (Freezed, nested): questionSfid · base64 · fileName — all String.SurveyResultUploadEvidence (Freezed, anidado): questionSfid · base64 · fileName — todos String.

08

Payload (message)

O JSON serializado no campo message do request. Cada tabela abaixo tem 4 colunasCampo JSON · Tipo · Origem do Dado · Regra — e lista toda chave que o build() emite (17 no total: 3 na raiz + 5 + 6 + 3). Campo, Tipo e Origem são código cru; só a Regra é prosa. Um exemplo completo está em transaction_example.json, ao lado deste doc.The JSON serialized into the request's message field. Each table below has 4 columnsJSON field · Type · Data source · Rule — and lists every key that build() emits (17 total: 3 root + 5 + 6 + 3). Field, Type and Source are raw code; only Rule is prose. A full example sits in transaction_example.json, next to this doc.El JSON serializado en el campo message del request. Cada tabla abajo tiene 4 columnasCampo JSON · Tipo · Origen del Dato · Regla — y lista toda clave que build() emite (17 en total: 3 raíz + 5 + 6 + 3). Campo, Tipo y Origen son código crudo; solo la Regla es prosa. Un ejemplo completo está en transaction_example.json, junto a este doc.

Raiz do payloadPayload rootRaíz del payload

Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
surveyResultarrayinlineinlineinlinearray de um único objeto (cabeçalho do resultado)single-element array (result header)array de un solo objeto (encabezado del resultado)
surveyResultdetailsarray_buildDetailsuma ou mais entradas por resposta (ver Regras)one or more entries per answer (see Rules)una o más entradas por respuesta (ver Reglas)
evidenceListarrayinput.evidencesuma entrada por evidência do envelope (≤ 3)one entry per envelope evidence (≤ 3)una entrada por evidencia del envelope (≤ 3)
  • surveyResult objeto únicosingle objectobjeto único 5 camposfieldscampos
    Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
    surveyCodestringinput.surveyCode
    surveyIDstringinput.survey.sfid
    storeIDstringinput.visit.accountData.sfidsfid do varejo da visitavisit retail's sfidsfid del punto de venta de la visita
    visitIDstringinput.visit.sfid
    surveyStatusstringstatus.valuecompletesResultOnUpload ? "Complete" : "In Progress"completesResultOnUpload ? "Complete" : "In Progress"completesResultOnUpload ? "Complete" : "In Progress"
    • surveyResultdetails por respostaper answerpor respuesta 6 camposfieldscampos

      Uma entrada por resposta em input.answersexceto SurveyOptionAnswer, que gera uma entrada por opção selecionada. Todas as entradas vêm de _detailRow.One entry per answer in input.answersexcept SurveyOptionAnswer, which yields one entry per selected option. All entries come from _detailRow.Una entrada por respuesta en input.answersexcepto SurveyOptionAnswer, que genera una entrada por opción seleccionada. Todas las entradas vienen de _detailRow.

      Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
      surveyCodestringinput.surveyCode
      surveyQuestionstringquestionSfida chave da entrada em input.answersthe entry key in input.answersla clave de la entrada en input.answers
      questionAnswerOptionstringCalculadoopção → optionsBySfid[optionSfid].questionAnswerOptionSfid ?? ""; texto/número/data → _firstOptionSfid (1ª opção da pergunta) (ver Regras)option → optionsBySfid[optionSfid].questionAnswerOptionSfid ?? ""; text/number/date → _firstOptionSfid (question's 1st option) (see Rules)opción → optionsBySfid[optionSfid].questionAnswerOptionSfid ?? ""; texto/número/fecha → _firstOptionSfid (1ª opción de la pregunta) (ver Reglas)
      scorestringFixo: "0"contrato · inertecontract · inertcontrato · inerte
      surveyResultstringFixo: ""contrato · inertecontract · inertcontrato · inerte
      actualAnswerstringCalculadoopção → ""; texto → answer.text; número → answer.value.toString(); data → answer.date em dd/MM/yyyyoption → ""; text → answer.text; number → answer.value.toString(); date → answer.date as dd/MM/yyyyopción → ""; texto → answer.text; número → answer.value.toString(); fecha → answer.date en dd/MM/yyyy
    • evidenceList por evidênciaper evidencepor evidencia 3 camposfieldscampos

      Uma entrada por SurveyResultUploadEvidence em input.evidences (já fatiado em ≤ 3 pelo buildAll).One entry per SurveyResultUploadEvidence in input.evidences (already sliced to ≤ 3 by buildAll).Una entrada por SurveyResultUploadEvidence en input.evidences (ya cortado a ≤ 3 por buildAll).

      Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
      base64stringevidence.base64arquivo (foto/documento) já lido em base64 pelo notifierfile (photo/document) already read as base64 by the notifierarchivo (foto/documento) ya leído en base64 por el notifier
      questionSfidstringevidence.questionSfidpergunta a que a evidência pertencequestion the evidence belongs topregunta a la que pertenece la evidencia
      fileNamestringevidence.fileName.replaceAll("'", "") — apóstrofos removidos do nome.replaceAll("'", "") — apostrophes stripped from the name.replaceAll("'", "") — apóstrofos removidos del nombre
09

Regras de negócioBusiness rulesReglas de negocio

Status do resultadoResult statusStatus del resultado SurveyResultUploadStatus

status = completesResultOnUpload ? SurveyResultUploadStatus.complete : SurveyResultUploadStatus.inProgress. O surveyStatus emitido é o .value:status = completesResultOnUpload ? SurveyResultUploadStatus.complete : SurveyResultUploadStatus.inProgress. The emitted surveyStatus is the .value:status = completesResultOnUpload ? SurveyResultUploadStatus.complete : SurveyResultUploadStatus.inProgress. El surveyStatus emitido es el .value:

SurveyResultUploadStatus.valueQuandoWhenCuándo
completeCompletecompletesResultOnUpload == true
inProgressIn ProgresscompletesResultOnUpload == false
Uma resposta → N linhas de detalheOne answer → N detail rowsUna respuesta → N filas de detalle _buildDetails · SurveyAnswerValue

Cada entrada de input.answers (questionSfid → SurveyAnswerValue) é convertida por tipo de resposta:Each input.answers entry (questionSfid → SurveyAnswerValue) is converted by answer type:Cada entrada de input.answers (questionSfid → SurveyAnswerValue) se convierte por tipo de respuesta:

SurveyAnswerValueLinhasRowsFilasquestionAnswerOptionactualAnswer
SurveyOptionAnsweruma por selectedOptionSfidsone per selectedOptionSfidsuna por selectedOptionSfidsoptionsBySfid[optionSfid]?.questionAnswerOptionSfid ?? """"
SurveyTextAnswer1_firstOptionSfid(questionSfid)answer.text
SurveyNumericAnswer1_firstOptionSfid(questionSfid)answer.value.toString()
SurveyDateAnswer1_firstOptionSfid(questionSfid)answer.date · dd/MM/yyyy

Opção única e múltipla escolha compartilham SurveyOptionAnswer: múltipla simplesmente traz mais de um selectedOptionSfid, logo mais de uma linha.Single- and multi-choice share SurveyOptionAnswer: multi simply carries more than one selectedOptionSfid, hence more than one row.Opción única y opción múltiple comparten SurveyOptionAnswer: la múltiple simplemente trae más de un selectedOptionSfid, por eso más de una fila.

Resolução de questionAnswerOptionquestionAnswerOption resolutionResolución de questionAnswerOption _indexOptions · _firstOptionSfid
  • Antes de montar os detalhes, o builder indexa recursivamente todas as opções da pesquisa: optionsBySfid (opção pelo seu sfid) e optionsByQuestionSfid (opções por pergunta), descendo por option.dependentQuestion.answerOptions (perguntas dependentes).Before building the details, the builder recursively indexes all survey options: optionsBySfid (option by its sfid) and optionsByQuestionSfid (options per question), descending through option.dependentQuestion.answerOptions (dependent questions).Antes de armar los detalles, el builder indexa recursivamente todas las opciones de la encuesta: optionsBySfid (opción por su sfid) y optionsByQuestionSfid (opciones por pregunta), bajando por option.dependentQuestion.answerOptions (preguntas dependientes).
  • Resposta de opção: o questionAnswerOption emitido é o questionAnswerOptionSfid da opção selecionada (não o sfid da opção). Se a opção não é encontrada no índice → "".Option answer: the emitted questionAnswerOption is the selected option's questionAnswerOptionSfid (not the option's sfid). If the option isn't found in the index → "".Respuesta de opción: el questionAnswerOption emitido es el questionAnswerOptionSfid de la opción seleccionada (no el sfid de la opción). Si la opción no se encuentra en el índice → "".
  • Resposta de texto/número/data: como não há opção escolhida, usa-se o questionAnswerOptionSfid da primeira opção da pergunta (_firstOptionSfid); se a pergunta não tem opções → "".Text/number/date answer: with no chosen option, it uses the question's first option's questionAnswerOptionSfid (_firstOptionSfid); if the question has no options → "".Respuesta de texto/número/fecha: al no haber opción elegida, usa el questionAnswerOptionSfid de la primera opción de la pregunta (_firstOptionSfid); si la pregunta no tiene opciones → "".
Split de evidênciasEvidence splitSplit de evidencias buildAll · _maxEvidencesPerEnvelope = 3
  • input.evidences.length <= 3 (inclui zero) → um envelope, [build(input)].input.evidences.length <= 3 (includes zero) → one envelope, [build(input)].input.evidences.length <= 3 (incluye cero) → un envelope, [build(input)].
  • Acima de 3 → loop em passos de 3 sobre evidences, cada bloco via build(input.copyWith(evidences: sublist)). Cada envelope carrega o mesmo surveyResult e surveyResultdetails; só a evidenceList muda.Above 3 → loop in steps of 3 over evidences, each block via build(input.copyWith(evidences: sublist)). Each envelope carries the same surveyResult and surveyResultdetails; only evidenceList changes.Más de 3 → loop en pasos de 3 sobre evidences, cada bloque vía build(input.copyWith(evidences: sublist)). Cada envelope lleva el mismo surveyResult y surveyResultdetails; solo cambia la evidenceList.
  • SubmitSurveyResultUploadUseCase.submit({envelopes}) despacha em paralelo pelo DispatcherOrchestrator, resultado índice-alinhado; o Notifier trata a primeira falha como falha do envio inteiro.SubmitSurveyResultUploadUseCase.submit({envelopes}) dispatches in parallel via DispatcherOrchestrator, index-aligned result; the Notifier treats the first failure as failure of the whole send.SubmitSurveyResultUploadUseCase.submit({envelopes}) despacha en paralelo por DispatcherOrchestrator, resultado índice-alineado; el Notifier trata la primera falla como falla de todo el envío.
Datas e formatosDates & formatsFechas y formatos dateReference vs actualAnswer
  • Envelope dateReference: DateTimeUtils.formatDate(dateTime: submittedAt) — formato default isoDate = yyyy-MM-dd.Envelope dateReference: DateTimeUtils.formatDate(dateTime: submittedAt) — default isoDate format = yyyy-MM-dd.Envelope dateReference: DateTimeUtils.formatDate(dateTime: submittedAt) — formato default isoDate = yyyy-MM-dd.
  • Resposta de data (actualAnswer): DateFormatType.dayMonthYearSlash = dd/MM/yyyy — formato diferente do dateReference.Date answer (actualAnswer): DateFormatType.dayMonthYearSlash = dd/MM/yyyy — different format from dateReference.Respuesta de fecha (actualAnswer): DateFormatType.dayMonthYearSlash = dd/MM/yyyy — formato distinto del dateReference.
Conta do envelopeEnvelope accountCuenta del envelope DispatchAccountEntity

Fora do payload JSON, o envelope leva um account (usado pelo Dispatcher/tracking): sfid = visit.accountData.sfid, sapCode = visit.accountData.customerCode, name = visit.accountData.name. Também: transactionReference = surveyCode.Outside the JSON payload, the envelope carries an account (used by Dispatcher/tracking): sfid = visit.accountData.sfid, sapCode = visit.accountData.customerCode, name = visit.accountData.name. Also: transactionReference = surveyCode.Fuera del payload JSON, el envelope lleva un account (usado por Dispatcher/tracking): sfid = visit.accountData.sfid, sapCode = visit.accountData.customerCode, name = visit.accountData.name. También: transactionReference = surveyCode.

10

Pendências / roadmapPending / roadmapPendientes / roadmap

O que o builder ainda não preenche ou envia inerte, documentado fiel ao estado atual do código (nunca descrito como se já existisse):What the builder does not yet fill, or ships inert, documented faithfully to the current code state (never described as already existing):Lo que el builder aún no completa, o envía inerte, documentado fiel al estado actual del código (nunca descrito como si ya existiera):

Não portado / pendenteNot ported / pendingNo portado / pendiente

  • serviceName: o builder chama resolveServiceName(hasPromotion: false) com false hardcoded. Se uma pesquisa vier a fazer parte de um contexto promocional, o prefixo Promo_ não seria anexado — hoje não há caminho que passe true.serviceName: the builder calls resolveServiceName(hasPromotion: false) with a hardcoded false. If a survey were to belong to a promotional context, the Promo_ prefix would not be prepended — there's no path passing true today.serviceName: el builder llama resolveServiceName(hasPromotion: false) con false hardcoded. Si una encuesta llegara a formar parte de un contexto promocional, el prefijo Promo_ no se antepondría — hoy no hay camino que pase true.
  • score ("0") e surveyResult ("") do detalhe: placeholders inertes fixos do contrato — o app não calcula pontuação de pesquisa.score ("0") and surveyResult ("") in the detail: fixed inert contract placeholders — the app computes no survey score.score ("0") y surveyResult ("") del detalle: placeholders inertes fijos del contrato — la app no calcula puntuación de encuesta.
  • questionAnswerOption em respostas de texto/número/data cai na primeira opção da pergunta (_firstOptionSfid) — heurística; perguntas dessas naturezas normalmente não têm opção real associada, então o valor pode ser "".questionAnswerOption for text/number/date answers falls back to the question's first option (_firstOptionSfid) — a heuristic; questions of those kinds usually have no real option, so the value may be "".questionAnswerOption en respuestas de texto/número/fecha cae en la primera opción de la pregunta (_firstOptionSfid) — heurística; preguntas de esas naturalezas normalmente no tienen opción real, así que el valor puede ser "".
  • Transporte: deviceUuid vai como literal "REP" no gateway (pendência conhecida do Dispatcher, comum a todas as transações).Transport: deviceUuid ships as the literal "REP" in the gateway (known Dispatcher pending item, shared by all transactions).Transporte: deviceUuid va como literal "REP" en el gateway (pendiente conocido del Dispatcher, común a todas las transacciones).

Feature donaOwning featureFeature dueña As telas, os UseCases de leitura, os Notifiers e o modelo de dados das pesquisas estão documentados em Surveys (feature). The screens, read UseCases, Notifiers and data model of surveys are documented in Surveys (feature). Las pantallas, los UseCases de lectura, los Notifiers y el modelo de datos de las encuestas están documentados en Surveys (feature).

MercadosMarketsMercados

A disponibilidade da transação vem do DispatcherType.survey.enabledMarkets = [BR, CL, ZA]. AR/PY/PE não têm dispatcher de survey. O payload é o mesmo nos três mercados — não há ramificação por mercado no builder.Transaction availability comes from DispatcherType.survey.enabledMarkets = [BR, CL, ZA]. AR/PY/PE have no survey dispatcher. The payload is the same across the three markets — there's no per-market branching in the builder.La disponibilidad de la transacción viene de DispatcherType.survey.enabledMarkets = [BR, CL, ZA]. AR/PY/PE no tienen dispatcher de survey. El payload es el mismo en los tres mercados — no hay ramificación por mercado en el builder.

BRx CLx ZAx AR PY PE
disponívelavailabledisponible presente, desligadopresent, offpresente, apagado ausenteabsentausente
BRCLZA

Mesmo contratoSame contractMismo contrato A transação é idêntica em BR/CL/ZA: mesmo serviceName, mesma estrutura de payload, mesmo split por evidências. O que varia por mercado é quais pesquisas se aplicam e se completam no primeiro envio (completesResultOnUpload) — isso é configuração da pesquisa/mercado, resolvida na feature, não no builder. The transaction is identical across BR/CL/ZA: same serviceName, same payload structure, same evidence split. What varies by market is which surveys apply and whether they complete on the first send (completesResultOnUpload) — that's survey/market config, resolved in the feature, not in the builder. La transacción es idéntica en BR/CL/ZA: mismo serviceName, misma estructura de payload, mismo split por evidencias. Lo que varía por mercado es cuáles encuestas aplican y si se completan en el primer envío (completesResultOnUpload) — eso es config de la encuesta/mercado, resuelta en la feature, no en el builder.

AR · PY · PE Existem como mercados do app (config PANGEA mínima), mas não têm dispatcher de surveysurvey não os lista em enabledMarkets. O envio de resultado de pesquisa não é disparado nesses mercados. They exist as app markets (minimal PANGEA config), but have no survey dispatchersurvey does not list them in enabledMarkets. Survey result upload is not fired in these markets. Existen como mercados de la app (config PANGEA mínima), pero no tienen dispatcher de surveysurvey no los lista en enabledMarkets. El envío de resultado de encuesta no se dispara en estos mercados.