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

Insights de concorrênciaCompetitor insightsInsights de competencia

A transação de escrita que envia ao backend um registro de ação da concorrência observada durante uma visita — empresa concorrente, atividade, período, descrição e fotos. Um único builder monta um payload JSON plano (sem variantes, sem arrays aninhados). É a única transação do app roteada para o destino competitor. Existe só na África do Sul. The write transaction that sends the backend a competitor-action record observed during a visit — competitor company, activity, period, description and photos. A single builder assembles a flat JSON payload (no variants, no nested arrays). It's the only transaction in the app routed to the competitor destination. Exists in South Africa only. La transacción de escritura que envía al backend un registro de acción de la competencia observada durante una visita — empresa competidora, actividad, período, descripción y fotos. Un único builder arma un payload JSON plano (sin variantes, sin arrays anidados). Es la única transacción de la app enrutada al destino competitor. Existe solo en Sudáfrica.

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

Quando o representante de vendas registra uma ação da concorrência dentro de uma visita, o app envia esse registro ao backend por esta transação. É o momento em que o formulário de Insights de concorrência vira um registro de verdade: sai do dispositivo e passa a existir no sistema. O rep reporta o que viu no ponto de venda — uma promoção de um concorrente, uma troca de display, um combo de preço — informando a empresa, a atividade, o período, uma descrição e de 1 a 3 fotos. When the sales rep records a competitor action inside a visit, the app sends that record to the backend through this transaction. It's the moment the Competitor insights form becomes a real record: it leaves the device and starts to exist in the system. The rep reports what was seen at the point of sale — a competitor's promotion, a display swap, a price combo — providing the company, the activity, the period, a description and 1 to 3 photos. Cuando el representante de ventas registra una acción de la competencia dentro de una visita, la app envía ese registro al backend por esta transacción. Es el momento en que el formulario de Insights de competencia se convierte en un registro real: sale del dispositivo y pasa a existir en el sistema. El rep reporta lo que vio en el punto de venta — una promoción de un competidor, un cambio de display, un combo de precio — informando la empresa, la actividad, el período, una descripción y de 1 a 3 fotos.

Não há variantes: uma única forma de envio, sempre a mesma. Cada envio é um registro independente — o app não guarda histórico na tela nem edita um registro já enviado.There are no variants: a single send shape, always the same. Each send is an independent record — the app keeps no on-screen history and does not edit an already-sent record.No hay variantes: una única forma de envío, siempre la misma. Cada envío es un registro independiente — la app no guarda historial en pantalla ni edita un registro ya enviado.

Não confundirDon't confuseNo confundir Insights de concorrência (ZA) é uma feature distinta do tile Ações de concorrência do Brasil, que abre a tela de Pesquisas filtrada e usa outra transação. Aqui trata-se só do formulário sul-africano. Competitor insights (ZA) is a distinct feature from Brazil's Competitor actions tile, which opens the filtered Surveys screen and uses a different transaction. This doc is only about the South African form. Insights de competencia (ZA) es una feature distinta del tile Acciones de competencia de Brasil, que abre la pantalla de Encuestas filtrada y usa otra transacción. Este doc trata solo del formulario sudafricano.

02

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

A transação é o último passo do registro de um insight. As telas do caminho pertencem à feature de Insights de concorrência; aqui só situamos onde o envio acontece:The transaction is the last step of recording an insight. The screens along the way belong to the Competitor insights feature; here we only place where the send happens:La transacción es el último paso del registro de un insight. Las pantallas del camino pertenecen a la feature de Insights de competencia; aquí solo situamos dónde ocurre el envío:

  1. Detalhe da visitaVisit detailDetalle de la visitaDa lista de Visitas, o rep entra no detalhe do varejo e toca no tile Competitor Insights na grade de ferramentas (só aparece na África do Sul). A visita precisa estar iniciada.From the Visits list, the rep opens the retail's detail and taps the Competitor Insights tile in the tools grid (shown only in South Africa). The visit must be started.Desde la lista de Visitas, el rep abre el detalle del punto de venta y toca el tile Competitor Insights en la grilla de herramientas (solo aparece en Sudáfrica). La visita debe estar iniciada.
  2. Formulário do insightInsight formFormulario del insightUma única tela em branco: escolhe a empresa concorrente e a atividade, define data inicial e final, escreve a descrição, captura de 1 a 3 fotos e pode marcar como Crítico.A single blank screen: picks the competitor company and the activity, sets start and end dates, writes the description, captures 1 to 3 photos and can flag it Critical.Una única pantalla en blanco: elige la empresa competidora y la actividad, define fecha inicial y final, escribe la descripción, captura de 1 a 3 fotos y puede marcarlo como Crítico.
  3. Enviar → esta transaçãoSend → this transactionEnviar → esta transacciónO botão Enviar só habilita com empresa, atividade, as duas datas, descrição não vazia e ao menos uma foto. Ao tocar, o app dispara esta transação — sem modal de confirmação.The Send button only enables with company, activity, both dates, a non-empty description and at least one photo. On tap, the app fires this transaction — with no confirmation modal.El botón Enviar solo se habilita con empresa, actividad, las dos fechas, descripción no vacía y al menos una foto. Al tocar, la app dispara esta transacción — sin modal de confirmación.
03

Depois do envioAfter sendingDespués del envío

Confirmação ao repConfirmation to the repConfirmación al rep
Quando o backend aceita, aparece um aviso verde e a tela volta automaticamente para o Detalhe da visita. Não fica histórico na tela — cada abertura é um formulário novo em branco.When the backend accepts it, a green notice appears and the screen returns automatically to the Visit detail. No on-screen history remains — each opening is a fresh blank form.Cuando el backend lo acepta, aparece un aviso verde y la pantalla vuelve automáticamente al Detalle de la visita. No queda historial en pantalla — cada apertura es un formulario nuevo en blanco.
Sem internetOfflineSin internet
Esta transação não entra na fila offline do app (que hoje só atende o envio de visita). Sem conexão, o envio falha na hora, aparece um aviso vermelho, a tela permanece com tudo preenchido e o registro fica marcado como erro — não como pendente. Não é reenviado sozinho quando a rede volta.This transaction does not enter the app's offline queue (which today serves only the visit upload). Offline, the send fails immediately, a red notice appears, the screen stays with everything filled, and the record is marked as an error — not as pending. It is not resent on its own when the connection returns.Esta transacción no entra en la cola offline de la app (que hoy solo atiende el envío de visita). Sin conexión, el envío falla al instante, aparece un aviso rojo, la pantalla queda con todo completado y el registro se marca como error — no como pendiente. No se reenvía solo cuando vuelve la red.
Acompanhar / reenviarTracking / resendingSeguir / reenviar
O status técnico do despacho (enviado, com erro) fica na Central de dados, de onde um envio com erro pode ser reenviado manualmente. O rep também pode simplesmente tocar em Enviar de novo na própria tela.The dispatch's technical status (sent, errored) lives in the Data Center, from which an errored send can be manually resent. The rep can also just tap Send again on the screen itself.El estado técnico del despacho (enviado, con error) está en el Centro de datos, desde donde un envío con error puede reenviarse manualmente. El rep también puede simplemente tocar Enviar de nuevo en la propia pantalla.
04

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

Insights de concorrência é a transação de saída que persiste um registro de ação da concorrência no backend. É disparada pelo CompetitorInsightsNotifier quando o representante de vendas conclui o formulário dentro de uma visita. A leitura (listas de empresas e atividades) é cache-only e não faz parte desta transação — aqui só documentamos a escrita. Competitor insights is the outbound transaction that persists a competitor-action record in the backend. It's fired by the CompetitorInsightsNotifier when the sales rep completes the form inside a visit. The read side (company and activity lists) is cache-only and is not part of this transaction — here we document only the write. Insights de competencia es la transacción de salida que persiste un registro de acción de la competencia en el backend. Se dispara desde el CompetitorInsightsNotifier cuando el representante de ventas completa el formulario dentro de una visita. La lectura (listas de empresas y actividades) es cache-only y no forma parte de esta transacción — aquí documentamos solo la escritura.

Destino único competitorUnique competitor destinationDestino único competitor

É a única transação do app cujo DispatcherType.destination é competitor — todas as demais usam salesforce, sfbatchapi ou none. Isso vira o campo endpoint do request.It's the only transaction whose DispatcherType.destination is competitor — all others use salesforce, sfbatchapi or none. It becomes the request's endpoint field.Es la única transacción cuyo DispatcherType.destination es competitor — las demás usan salesforce, sfbatchapi o none. Se convierte en el campo endpoint del request.

Payload planoFlat payloadPayload plano

Um único objeto de 13 chaves, sem arrays aninhados de detalhe. Fotos e ids de marca são as únicas listas — e as de marca vão vazias hoje.A single object of 13 keys, with no nested detail arrays. Photos and brand ids are the only lists — and the brand ones ship empty today.Un único objeto de 13 claves, sin arrays anidados de detalle. Fotos e ids de marca son las únicas listas — y las de marca van vacías hoy.

RPC genéricoGeneric RPCRPC genérico

Não há RPC por transação: tudo passa pelo mesmo sendTransaction, com o JSON serializado em message e o serviceName como discriminador.There's no per-transaction RPC: everything goes through the same sendTransaction, with the JSON serialized into message and serviceName as the discriminator.No hay RPC por transacción: todo pasa por el mismo sendTransaction, con el JSON serializado en message y el serviceName como discriminador.

FontesSourcesFuentes BuildCompetitorInsightsDispatcherPayloadUseCase + CompetitorInsightsDispatcherPayloadInput + DispatcherType.competitorInsights + DispatcherConectaRep.proto. O input carrega entities cruas de domínio (CLAUDE.md §36); o build() constrói todo o wire. BuildCompetitorInsightsDispatcherPayloadUseCase + CompetitorInsightsDispatcherPayloadInput + DispatcherType.competitorInsights + DispatcherConectaRep.proto. The input carries raw domain entities (CLAUDE.md §36); build() constructs the entire wire. BuildCompetitorInsightsDispatcherPayloadUseCase + CompetitorInsightsDispatcherPayloadInput + DispatcherType.competitorInsights + DispatcherConectaRep.proto. El input lleva entities crudas de dominio (CLAUDE.md §36); 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 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 · destino = type.destination.value"competitor" (exclusivo desta transação)destination = type.destination.value"competitor" (exclusive to this transaction)destino = type.destination.value"competitor" (exclusivo de esta transacción)
serviceName
string · #2 · discriminador — sempre CompetitorInsightsUploadAPI (nunca leva prefixo Promo_: hasPromotion: false)discriminator — always CompetitorInsightsUploadAPI (never carries the Promo_ prefix: hasPromotion: false)discriminador — siempre CompetitorInsightsUploadAPI (nunca lleva prefijo Promo_: hasPromotion: false)
dateReference
string · #3 · AAAA-MM-DD do envio (submittedAt, formato default isoDate)YYYY-MM-DD of the submission (submittedAt, default isoDate format)AAAA-MM-DD del envío (submittedAt, formato default isoDate)
transactionReference
string · #4 · input.accountSfid (correlação)input.accountSfid (correlation)input.accountSfid (correlación)
username
string · #5 · resource.usernameresource.usernameresource.username
message
string · #6 · o payload JSON serializado (jsonEncode(envelope.payload) — a tabela da seção 07)the JSON payload serialized (jsonEncode(envelope.payload) — the table in section 07)el payload JSON serializado (jsonEncode(envelope.payload) — la tabla de la sección 07)
manufacturer
string · #7 · dado do dispositivodevice datadato del dispositivo
model
string · #8 · dado do dispositivodevice datadato del dispositivo
deviceUuid
string · #9 · literal "REP" no gateway (ver Pendências)"REP" literal in the gateway (see Pending)literal "REP" en el gateway (ver Pendientes)
deviceVersion
string · #10 · versão do sistemasystem versionversión del sistema
tid
int64 · #11 · id de transação para idempotência/replay (envelope.tid, 0 por default)transaction id for idempotency/replay (envelope.tid, 0 by default)id de transacción para idempotencia/replay (envelope.tid, 0 por default)
Reply · InboxTransactionReply
status
int32 · #1 · status do ack — 0 ou 5 = sucesso, 1 = duplicado, demais = erroack status — 0 or 5 = success, 1 = duplicate, else = errorstatus del ack — 0 o 5 = éxito, 1 = duplicado, demás = error
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, usa type.destination.value como endpoint, copia serviceName/dateReference/transactionReference, 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, uses type.destination.value as endpoint, copies serviceName/dateReference/transactionReference, 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, usa type.destination.value como endpoint, copia serviceName/dateReference/transactionReference, completa los campos del dispositivo y el bearer token de auth, y llama al RPC.

Para esta transação, resendMayDuplicate == true: um reenvio (ex.: pela Central de dados) pode duplicar o registro no backend; a idempotência via tid é o que mitiga isso. Só notificationRead, answerTask e priceCheck são tratados como leves (sem risco de duplicação).For this transaction, resendMayDuplicate == true: a resend (e.g. from the Data Center) may duplicate the record on the backend; idempotency via tid is what mitigates it. Only notificationRead, answerTask and priceCheck are treated as lightweight (no duplication risk).Para esta transacción, resendMayDuplicate == true: un reenvío (p. ej. desde el Centro de datos) puede duplicar el registro en el backend; la idempotencia vía tid es lo que lo mitiga. Solo notificationRead, answerTask y priceCheck se tratan como livianos (sin riesgo de duplicación).

06

Como é disparadoHow it's firedCómo se dispara

A transação é orquestrada pelo CompetitorInsightsNotifier (remote-first, §36). O notifier apenas reúne entities cruas + valores injetados (resolve o accountSfid da visita e converte as fotos em base64); o builder é o dono único do rename, do trim(), da formatação de data e da derivação do repAccountId. A cascata:The transaction is orchestrated by CompetitorInsightsNotifier (remote-first, §36). The notifier only gathers raw entities + injected values (resolves the visit's accountSfid and converts photos to base64); the builder is the sole owner of the rename, the trim(), date formatting and the repAccountId derivation. The cascade:La transacción se orquesta desde el CompetitorInsightsNotifier (remote-first, §36). El notifier solo reúne entities crudas + valores inyectados (resuelve el accountSfid de la visita y convierte las fotos a base64); el builder es el dueño único del rename, del trim(), del formateo de fecha y de la derivación del repAccountId. La cascada:

  • CompetitorInsightsNotifiersubmit()
    • reúne entities cruas + injetadosgathers raw entities + injectedreúne entities crudas + inyectadosCompetitorInsightsDispatcherPayloadInput
      • build()BuildCompetitorInsightsDispatcherPayloadUseCasemonta o wireassembles the wirearma el wire
        • devolvereturnsdevuelveDispatcherEnvelope
          • SubmitCompetitorInsightsUseCaseDispatcherOrchestratordispatch()
            • _transport.sendDispatcherRepository
              • serializa + authserialize + authserializa + authDispatcherGateway
                • sendTransactionBackendgRPC

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

CompetitorInsightsDispatcherPayloadInput (Freezed). Carrega o dado como existe no domínio; nada de formato wire. O relógio chega como submittedAt (via DateTimeUtils.now()); as fotos já chegam como base64 (I/O resolvido no notifier via fileCaptureService).CompetitorInsightsDispatcherPayloadInput (Freezed). Carries data as it exists in the domain; no wire shaping. The clock arrives as submittedAt (via DateTimeUtils.now()); photos already arrive as base64 (I/O resolved in the notifier via fileCaptureService).CompetitorInsightsDispatcherPayloadInput (Freezed). Lleva el dato como existe en el dominio; nada de formato wire. El reloj llega como submittedAt (vía DateTimeUtils.now()); las fotos ya llegan como base64 (I/O resuelto en el notifier vía fileCaptureService).

CampoFieldCampoTipoTypeTipoPapelRoleRol
resourceResourceEntityrepresentante de vendas (cru — o builder deriva repAccountId)sales rep (raw — the builder derives repAccountId)representante de ventas (crudo — el builder deriva repAccountId)
accountSfidStringSFID do varejo (resolvido da visita) → retailerIdretail SFID (resolved from the visit) → retailerIdSFID del punto de venta (resuelto de la visita) → retailerId
companyCompetitorCompanyEntityempresa selecionada → companyId (.sfid)selected company → companyId (.sfid)empresa seleccionada → companyId (.sfid)
activityCompetitorActivityEntityatividade selecionada → activityId (.sfid)selected activity → activityId (.sfid)actividad seleccionada → activityId (.sfid)
descriptionStringtexto livre → description (o builder aplica .trim())free text → description (builder applies .trim())texto libre → description (el builder aplica .trim())
startDateDateTimedata inicial → startDate (dd/MM/yyyy)start date → startDate (dd/MM/yyyy)fecha inicial → startDate (dd/MM/yyyy)
endDateDateTimedata final → endDate (dd/MM/yyyy)end date → endDate (dd/MM/yyyy)fecha final → endDate (dd/MM/yyyy)
imagesBase64List<String>1 a 3 fotos já em base64 → images1 to 3 photos already in base64 → images1 a 3 fotos ya en base64 → images
isCriticalbooltoggle Crítico → isCriticalCritical toggle → isCriticaltoggle Crítico → isCritical
submittedAtDateTimerelógio (DateTimeUtils.now()) → dateReferenceclock (DateTimeUtils.now()) → dateReferencereloj (DateTimeUtils.now()) → dateReference
07

Payload (message)

O JSON serializado no campo message do request. É um objeto plano, embrulhado sob a chave-serviço CompetitorInsightsUploadAPI. A tabela tem 4 colunasCampo JSON · Tipo · Origem do Dado · Regra — e lista todas as 13 chaves que o build() emite. 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. It's a flat object, wrapped under the service key CompetitorInsightsUploadAPI. The table has 4 columnsJSON field · Type · Data source · Rule — and lists all 13 keys that build() emits. 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. Es un objeto plano, envuelto bajo la clave-servicio CompetitorInsightsUploadAPI. La tabla tiene 4 columnasCampo JSON · Tipo · Origen del Dato · Regla — y lista todas las 13 claves que build() emite. 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
CompetitorInsightsUploadAPIobjectdatachave-serviço única embrulhando o objeto de 13 campos abaixosingle service key wrapping the 13-field object belowclave-servicio única que envuelve el objeto de 13 campos abajo
  • CompetitorInsightsUploadAPI objeto únicosingle objectobjeto único 13 camposfieldscampos
    Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
    repAccountIdstringCalculadoresource.isPrimaryResource ? primaryResourceSfid : secondaryResourceSfidresource.isPrimaryResource ? primaryResourceSfid : secondaryResourceSfidresource.isPrimaryResource ? primaryResourceSfid : secondaryResourceSfid
    retailerIdstringinput.accountSfidSFID do varejo da visitathe visit's retail SFIDSFID del punto de venta de la visita
    companyIdstringinput.company.sfidempresa concorrente selecionadaselected competitor companyempresa competidora seleccionada
    activityIdstringinput.activity.sfidatividade observada selecionadaselected observed activityactividad observada seleccionada
    brandIdstringFixo: ""seleção de marca não implementada (ver Pendências)brand selection not implemented (see Pending)selección de marca no implementada (ver Pendientes)
    brandVariantIdsarrayFixo: []sempre vazio (não implementado)always empty (not implemented)siempre vacío (no implementado)
    brandVersionIdsarrayFixo: []sempre vazio (não implementado)always empty (not implemented)siempre vacío (no implementado)
    descriptionstringinput.description.trim() aplicado no builder.trim() applied in the builder.trim() aplicado en el builder
    startDatestringinput.startDateformato dd/MM/yyyy (dayMonthYearSlash)dd/MM/yyyy format (dayMonthYearSlash)formato dd/MM/yyyy (dayMonthYearSlash)
    endDatestringinput.endDateformato dd/MM/yyyy (dayMonthYearSlash)dd/MM/yyyy format (dayMonthYearSlash)formato dd/MM/yyyy (dayMonthYearSlash)
    imagesarray<string>input.imagesBase641 a 3 fotos em base64 (I/O resolvido no notifier)1 to 3 photos in base64 (I/O resolved in the notifier)1 a 3 fotos en base64 (I/O resuelto en el notifier)
    answersarrayFixo: []respostas estruturadas não implementadas (ver Pendências)structured answers not implemented (see Pending)respuestas estructuradas no implementadas (ver Pendientes)
    isCriticalboolinput.isCriticalmarcador Crítico do formuláriothe form's Critical flagmarcador Crítico del formulario
08

Regras de negócioBusiness rulesReglas de negocio

Identidade do repRep identityIdentidad del rep repAccountId
  • repAccountId não é resource.sfid: é o SFID primário (primaryResourceSfid) quando isPrimaryResource, senão o secundário (secondaryResourceSfid). A derivação mora no build() (§36), não no notifier.repAccountId is not resource.sfid: it's the primary SFID (primaryResourceSfid) when isPrimaryResource, else the secondary one (secondaryResourceSfid). The derivation lives in build() (§36), not the notifier.repAccountId no es resource.sfid: es el SFID primario (primaryResourceSfid) cuando isPrimaryResource, si no el secundario (secondaryResourceSfid). La derivación vive en build() (§36), no en el notifier.
serviceName & endpoint CompetitorInsightsUploadAPI · competitor
  • serviceName: type.resolveServiceName(hasPromotion: false) → sempre CompetitorInsightsUploadAPI. Esta transação nunca carrega promoção, então o prefixo Promo_ jamais aparece.serviceName: type.resolveServiceName(hasPromotion: false) → always CompetitorInsightsUploadAPI. This transaction never carries a promotion, so the Promo_ prefix never appears.serviceName: type.resolveServiceName(hasPromotion: false) → siempre CompetitorInsightsUploadAPI. Esta transacción nunca lleva promoción, así que el prefijo Promo_ jamás aparece.
  • endpoint = DispatcherDestination.competitor.value"competitor". É o único DispatcherType com esse destino; todos os outros roteiam para salesforce (default), sfbatchapi ou none. O destino é o que roteia a transação no gateway.endpoint = DispatcherDestination.competitor.value"competitor". It's the only DispatcherType with that destination; every other routes to salesforce (default), sfbatchapi or none. The destination is what routes the transaction in the gateway.endpoint = DispatcherDestination.competitor.value"competitor". Es el único DispatcherType con ese destino; todos los demás enrutan a salesforce (default), sfbatchapi o none. El destino es lo que enruta la transacción en el gateway.
Datas e trimDates & trimFechas y trim startDate · endDate · dateReference · description
  • startDate e endDate do payload usam dd/MM/yyyy (DateFormatType.dayMonthYearSlash).startDate and endDate in the payload use dd/MM/yyyy (DateFormatType.dayMonthYearSlash).startDate y endDate del payload usan dd/MM/yyyy (DateFormatType.dayMonthYearSlash).
  • dateReference do envelope (nível de transporte, não do payload) usa o formato default yyyy-MM-dd (isoDate), a partir de submittedAt. Mesmos dados, formatos distintos — atenção ao comparar.The envelope's dateReference (transport level, not payload) uses the default yyyy-MM-dd format (isoDate), from submittedAt. Same source, different formats — mind the comparison.El dateReference del envelope (nivel transporte, no del payload) usa el formato default yyyy-MM-dd (isoDate), a partir de submittedAt. Mismo dato, formatos distintos — atención al comparar.
  • description: o builder aplica .trim(). O formulário já garante descrição não vazia antes de habilitar o envio.description: the builder applies .trim(). The form already ensures a non-empty description before enabling the send.description: el builder aplica .trim(). El formulario ya garantiza descripción no vacía antes de habilitar el envío.
Envio, ack e offlineSend, ack & offlineEnvío, ack y offline DispatcherOrchestrator · resendMayDuplicate
  • O envio passa pelo DispatcherOrchestrator.dispatch(). A fila offline só registra DispatcherType.visit; esta transação vai direto ao transporte e, sem rede, o gateway lança NetworkExceptionNetworkFailure (falha imediata, gravada como erro no histórico).The send goes through DispatcherOrchestrator.dispatch(). The offline queue only records DispatcherType.visit; this transaction goes straight to transport and, offline, the gateway throws NetworkExceptionNetworkFailure (immediate failure, stored as an error in history).El envío pasa por DispatcherOrchestrator.dispatch(). La cola offline solo registra DispatcherType.visit; esta transacción va directo al transporte y, sin red, el gateway lanza NetworkExceptionNetworkFailure (falla inmediata, guardada como error en el historial).
  • Mapeamento do ack (_statusForAck): status 0 ou 5 → sucesso; 1 → duplicado; qualquer outro → erro.Ack mapping (_statusForAck): status 0 or 5 → success; 1 → duplicate; anything else → error.Mapeo del ack (_statusForAck): status 0 o 5 → éxito; 1 → duplicado; cualquier otro → error.
  • resendMayDuplicate == true: um reenvio manual (Central de dados) pode gerar duplicata no backend; a idempotência via tid mitiga.resendMayDuplicate == true: a manual resend (Data Center) may produce a backend duplicate; idempotency via tid mitigates it.resendMayDuplicate == true: un reenvío manual (Centro de datos) puede generar duplicado en el backend; la idempotencia vía tid lo mitiga.
09

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 implementado / pendenteNot implemented / pendingNo implementado / pendiente

  • brandId (""), brandVariantIds ([]) e brandVersionIds ([]): a seleção de marca/variante/versão não existe no formulário — o contrato wire tem os campos, mas o app nunca os popula.brandId (""), brandVariantIds ([]) and brandVersionIds ([]): brand/variant/version selection doesn't exist in the form — the wire contract has the fields, but the app never populates them.brandId (""), brandVariantIds ([]) y brandVersionIds ([]): la selección de marca/variante/versión no existe en el formulario — el contrato wire tiene los campos, pero la app nunca los completa.
  • answers: sempre [] — respostas estruturadas (questionário do insight) não implementadas.answers: always [] — structured answers (insight questionnaire) not implemented.answers: siempre [] — respuestas estructuradas (cuestionario del insight) no implementadas.
  • Fila offline: esta transação não entra na fila offline (só o envio de visita entra hoje). Sem rede, falha na hora e o reenvio é manual pela Central de dados.Offline queue: this transaction does not enter the offline queue (only the visit upload does today). Offline, it fails immediately and the resend is manual via the Data Center.Cola offline: esta transacción no entra en la cola offline (solo el envío de visita lo hace hoy). Sin red, falla al instante y el reenvío es manual por el Centro de datos.
  • Transporte: deviceUuid vai como literal "REP" no gateway (pendência conhecida do Dispatcher, compartilhada por 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, compartido por todas las transacciones).

MercadosMarketsMercados

A disponibilidade da transação vem de DispatcherType.competitorInsights.enabledMarkets = [ZA]. Existe só na África do Sul. BR, CL, AR, PY e PE não têm dispatcher de insights de concorrência.Transaction availability comes from DispatcherType.competitorInsights.enabledMarkets = [ZA]. It exists in South Africa only. BR, CL, AR, PY and PE have no competitor-insights dispatcher.La disponibilidad de la transacción viene de DispatcherType.competitorInsights.enabledMarkets = [ZA]. Existe solo en Sudáfrica. BR, CL, AR, PY y PE no tienen dispatcher de insights de competencia.

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

Só na África do SulSouth Africa onlySolo Sudáfrica O tile Competitor Insights aparece na grade de ferramentas da visita apenas na África do Sul, e a transação só é habilitada aqui. O envio é o mesmo em qualquer situação — não há variação de payload por sub-região. The Competitor Insights tile appears in the visit's tools grid only in South Africa, and the transaction is enabled only here. The send is the same in every situation — there's no per-sub-region payload variation. El tile Competitor Insights aparece en la grilla de herramientas de la visita solo en Sudáfrica, y la transacción se habilita solo aquí. El envío es el mismo en cualquier situación — no hay variación de payload por sub-región.

BR

Não confundirDon't confuseNo confundir O Brasil tem o tile Ações de concorrência (competitor_actions), que abre a tela de Pesquisas filtrada — é outra feature e outra transação, não esta. BR não dispara CompetitorInsightsUploadAPI. Brazil has the Competitor actions tile (competitor_actions), which opens the filtered Surveys screen — a different feature and transaction, not this one. BR does not fire CompetitorInsightsUploadAPI. Brasil tiene el tile Acciones de competencia (competitor_actions), que abre la pantalla de Encuestas filtrada — es otra feature y otra transacción, no esta. BR no dispara CompetitorInsightsUploadAPI.

CL · AR · PY · PE Existem como mercados do app, mas não têm dispatcher de insights de concorrênciaenabledMarkets lista só ZA. A feature não é renderizada nesses mercados. They exist as app markets, but have no competitor-insights dispatcherenabledMarkets lists only ZA. The feature is not rendered in these markets. Existen como mercados de la app, pero no tienen dispatcher de insights de competenciaenabledMarkets lista solo ZA. La feature no se renderiza en estos mercados.