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

Odômetro da jornadaJourney odometerOdómetro de la jornada

A transação de escrita que registra a quilometragem do veículo no início e no fim da jornada de trabalho do representante de vendas, junto com o horário e a posição GPS de cada ponta. É a mesma transação em dois momentos: abertura (com a leitura inicial) e fechamento (com a leitura final). Toda a construção do contrato wire vive no builder. The write transaction that records the vehicle's mileage at the start and end of the sales rep's work journey, together with the time and GPS position at each end. It's the same transaction at two moments: opening (with the initial reading) and closing (with the final reading). All wire-contract construction lives in the builder. La transacción de escritura que registra el kilometraje del vehículo al inicio y al final de la jornada de trabajo del representante de ventas, junto con la hora y la posición GPS de cada punta. Es la misma transacción en dos momentos: apertura (con la lectura inicial) y cierre (con la lectura final). 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 BR CL ZA
01

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

No início do dia de trabalho, o representante de vendas registra a quilometragem do veículo (a leitura do odômetro) antes de sair para as visitas. No fim do dia, ao encerrar a jornada, registra a quilometragem final. Cada um desses dois momentos envia esta transação ao backend — é assim que a empresa acompanha o deslocamento diário de cada representante. At the start of the work day, the sales rep records the vehicle's mileage (the odometer reading) before heading out for visits. At the end of the day, when ending the journey, they record the final mileage. Each of these two moments sends this transaction to the backend — this is how the company tracks each rep's daily travel. Al inicio del día de trabajo, el representante de ventas registra el kilometraje del vehículo (la lectura del odómetro) antes de salir a las visitas. Al final del día, al cerrar la jornada, registra el kilometraje final. Cada uno de esos dos momentos envía esta transacción al backend — así la empresa sigue el desplazamiento diario de cada representante.

São dois envios da mesma jornada, ligados por um identificador comum:There are two sends of the same journey, linked by a common identifier:Son dos envíos de la misma jornada, unidos por un identificador común:

Abertura da jornadaJourney openingApertura de la jornada

O rep informa a leitura inicial do odômetro. O app captura o horário e a posição GPS e envia a jornada como aberta.The rep enters the initial odometer reading. The app captures the time and GPS position and sends the journey as open.El rep informa la lectura inicial del odómetro. La app captura la hora y la posición GPS y envía la jornada como abierta.

Fechamento da jornadaJourney closingCierre de la jornada

Ao encerrar o dia, o rep informa a leitura final. O app acrescenta o horário e a posição de chegada e envia a jornada como fechada.When ending the day, the rep enters the final reading. The app adds the arrival time and position and sends the journey as closed.Al cerrar el día, el rep informa la lectura final. La app agrega la hora y la posición de llegada y envía la jornada como cerrada.

Placa junto na aberturaPlate alongside on openingPlaca junto en la apertura Onde o mercado exige, a mesma tela de abertura também pede a placa do veículo, que segue numa transação própria — ver Placa do veículo. Para o rep, é um único gesto de "começar o dia". Where the market requires it, the same opening screen also asks for the vehicle plate, which goes in its own transaction — see Car license plate. For the rep, it's a single "start the day" gesture. Donde el mercado lo exige, la misma pantalla de apertura también pide la placa del vehículo, que va en su propia transacción — ver Placa del vehículo. Para el rep, es un único gesto de "empezar el día".

02

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

As telas de abertura e encerramento pertencem à feature de Jornada; aqui só situamos onde cada envio acontece:The opening and closing screens belong to the Journey feature; here we only place where each send happens:Las pantallas de apertura y cierre pertenecen a la feature de Jornada; aquí solo situamos dónde ocurre cada envío:

  1. Login / abertura do appLogin / app openingLogin / apertura de la appApós entrar, se não há uma jornada aberta o app leva o rep direto à tela de Jornada.After signing in, if there's no open journey the app takes the rep straight to the Journey screen.Tras ingresar, si no hay una jornada abierta la app lleva al rep directo a la pantalla de Jornada.
  2. Tela de Jornada → aberturaJourney screen → openingPantalla de Jornada → aperturaO rep digita a leitura do odômetro (e a placa, se pedida) e toca em iniciar. Esse toque dispara o envio de abertura desta transação; só depois o rep chega às telas do dia.The rep types the odometer reading (and the plate, if asked) and taps start. That tap fires this transaction's opening send; only then does the rep reach the day's screens.El rep escribe la lectura del odómetro (y la placa, si se pide) y toca iniciar. Ese toque dispara el envío de apertura de esta transacción; solo después el rep llega a las pantallas del día.
  3. Trabalho do diaDay's workTrabajo del díaVisitas, pedidos e demais tarefas seguem normalmente, com a jornada aberta em segundo plano.Visits, orders and other tasks proceed as usual, with the journey open in the background.Visitas, pedidos y demás tareas siguen normalmente, con la jornada abierta en segundo plano.
  4. Encerrar jornada → fechamentoEnd journey → closingCerrar jornada → cierrePelo menu, o rep abre "Encerrar jornada", digita a leitura final e confirma. Esse toque dispara o envio de fechamento — a mesma transação, agora com os dados de chegada.From the menu, the rep opens "End journey", types the final reading and confirms. That tap fires the closing send — the same transaction, now with the arrival data.Desde el menú, el rep abre "Cerrar jornada", escribe la lectura final y confirma. Ese toque dispara el envío de cierre — la misma transacción, ahora con los datos de llegada.
03

Depois do envioAfter sendingDespués del envío

Confirmação ao repConfirmation to the repConfirmación al rep
Quando o backend aceita a abertura, o rep segue para o dia de trabalho; quando aceita o fechamento, a jornada é encerrada. Se o envio falha, a ação não avança e o rep pode tentar de novo.When the backend accepts the opening, the rep moves on to the work day; when it accepts the closing, the journey ends. If the send fails, the action doesn't proceed and the rep can try again.Cuando el backend acepta la apertura, el rep sigue al día de trabajo; cuando acepta el cierre, la jornada se cierra. Si el envío falla, la acción no avanza y el rep puede intentar de nuevo.
Sem internetOfflineSin internet
Como todas as transações do Dispatcher, o envio pode entrar em fila e ser reenviado quando a conexão volta. Um identificador de transação evita registros duplicados no reenvio.Like all Dispatcher transactions, the send may be queued and retried when the connection returns. A transaction id avoids duplicate records on retry.Como todas las transacciones del Dispatcher, el envío puede quedar en cola y reintentarse cuando vuelve la conexión. Un identificador de transacción evita registros duplicados en el reenvío.
Acompanhar o envioTracking the sendSeguir el envío
O status técnico do despacho (enviado, em fila, com erro) pode ser acompanhado na central de dados / tracking de despachos do app — útil para o suporte investigar uma jornada.The dispatch's technical status (sent, queued, errored) can be followed in the app's data center / dispatch tracking — useful for support to investigate a journey.El estado técnico del despacho (enviado, en cola, con error) puede seguirse en el centro de datos / tracking de despachos de la app — útil para que soporte investigue una jornada.
04

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

Odômetro da jornada é a transação de saída que persiste a quilometragem de uma jornada de trabalho. Ela é disparada duas vezes por jornada: na abertura (StartOdometerJourneyUseCase) e no fechamento (FinishOdometerJourneyUseCase). Os dois envios usam o mesmo builder, o mesmo serviceName e o mesmo uid/ReconId; divergem apenas nos campos de fim e no Status/isNew. Journey odometer is the outbound transaction that persists a work journey's mileage. It's fired twice per journey: on opening (StartOdometerJourneyUseCase) and on closing (FinishOdometerJourneyUseCase). Both sends use the same builder, the same serviceName and the same uid/ReconId; they diverge only in the end fields and in Status/isNew. Odómetro de la jornada es la transacción de salida que persiste el kilometraje de una jornada de trabajo. Se dispara dos veces por jornada: en la apertura (StartOdometerJourneyUseCase) y en el cierre (FinishOdometerJourneyUseCase). Ambos envíos usan el mismo builder, el mismo serviceName y el mismo uid/ReconId; divergen solo en los campos de fin y en Status/isNew.

Payload enxutoLean payloadPayload conciso

Duas listas de um objeto — Odometer (leituras, tempo, GPS) e ReconStatus (id de reconciliação, status, van). 14 chaves no total.Two single-object arrays — Odometer (readings, time, GPS) and ReconStatus (recon id, status, van). 14 keys in total.Dos listas de un objeto — Odometer (lecturas, tiempo, GPS) y ReconStatus (id de reconciliación, estado, van). 14 claves en total.

Abertura ⇄ fechamentoOpen ⇄ closeApertura ⇄ cierre

Não há campo de "modo" no input: a variação vem do próprio estado da OdometerJourneyEntity (status, campos de fim nulos ou não).There's no "mode" field on the input: the variation comes from the OdometerJourneyEntity's own state (status, end fields null or not).No hay campo de "modo" en el input: la variación viene del propio estado de la OdometerJourneyEntity (status, campos de fin nulos o no).

RPC genéricoGeneric RPCRPC genérico

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

FontesSourcesFuentes BuildOdometerJourneyDispatcherPayloadUseCase + OdometerJourneyDispatcherPayloadInput + DispatcherType.odometerJourney + DispatcherConectaRep.proto. O input carrega entities cruas (OdometerJourneyEntity + ResourceEntity, CLAUDE.md §36); o build() constrói todo o wire. BuildOdometerJourneyDispatcherPayloadUseCase + OdometerJourneyDispatcherPayloadInput + DispatcherType.odometerJourney + DispatcherConectaRep.proto. The input carries raw entities (OdometerJourneyEntity + ResourceEntity, CLAUDE.md §36); build() constructs the entire wire. BuildOdometerJourneyDispatcherPayloadUseCase + OdometerJourneyDispatcherPayloadInput + DispatcherType.odometerJourney + DispatcherConectaRep.proto. El input lleva entities crudas (OdometerJourneyEntity + ResourceEntity, 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) 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) 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) 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 · discriminador — sempre OdometerAPI (sem prefixo Promo_: hasPromotion: false)discriminator — always OdometerAPI (no Promo_ prefix: hasPromotion: false)discriminador — siempre OdometerAPI (sin prefijo Promo_: hasPromotion: false)
dateReference
string · #3 · AAAA-MM-DDformatDate(journey.startedAt) (formato isoDate)YYYY-MM-DDformatDate(journey.startedAt) (isoDate format)AAAA-MM-DDformatDate(journey.startedAt) (formato isoDate)
transactionReference
string · #4 · journey.uuid (correlação abertura ⇄ fechamento)journey.uuid (opening ⇄ closing correlation)journey.uuid (correlación apertura ⇄ cierre)
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 provisório hoje (ver Pendências)provisional literal today (see Pending)literal provisional 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 DispatcherEnvelope (type, serviceName, payload, transactionReference, dateReferencesem account). O DispatcherGateway serializa payload em JSON para message, copia serviceName/dateReference/transactionReference, preenche os campos de dispositivo e o bearer token de auth, e chama o RPC. O destino da transação é DispatcherDestination.salesforce. The builder returns a DispatcherEnvelope (type, serviceName, payload, transactionReference, dateReferenceno account). The DispatcherGateway serializes payload to JSON into message, copies serviceName/dateReference/transactionReference, fills in the device fields and the auth bearer token, and calls the RPC. The transaction destination is DispatcherDestination.salesforce. El builder devuelve un DispatcherEnvelope (type, serviceName, payload, transactionReference, dateReferencesin account). El DispatcherGateway serializa payload a JSON en message, copia serviceName/dateReference/transactionReference, completa los campos del dispositivo y el bearer token de auth, y llama al RPC. El destino de la transacción es DispatcherDestination.salesforce.

06

Os dois envios e serviceNameThe two sends & serviceNameLos dos envíos y serviceName

Um único DispatcherType (odometerJourney) e um único serviceName (OdometerAPI) cobrem os dois envios. Não há campo de tipo no input — o envio de fechamento se distingue pelo próprio estado da OdometerJourneyEntity: no StartOdometerJourneyUseCase a entity nasce status: open com os campos de fim nulos; no FinishOdometerJourneyUseCase ela é copiada para status: closed com odometerEnd/endedAt/endLatitude/endLongitude preenchidos.A single DispatcherType (odometerJourney) and a single serviceName (OdometerAPI) cover both sends. There's no type field on the input — the closing send is distinguished by the OdometerJourneyEntity's own state: in StartOdometerJourneyUseCase the entity is born status: open with null end fields; in FinishOdometerJourneyUseCase it's copied to status: closed with odometerEnd/endedAt/endLatitude/endLongitude filled.Un único DispatcherType (odometerJourney) y un único serviceName (OdometerAPI) cubren ambos envíos. No hay campo de tipo en el input — el envío de cierre se distingue por el propio estado de la OdometerJourneyEntity: en StartOdometerJourneyUseCase la entity nace status: open con los campos de fin nulos; en FinishOdometerJourneyUseCase se copia a status: closed con odometerEnd/endedAt/endLatitude/endLongitude completados.

EnvioSendEnvío serviceName Status · isNew Campos de fimEnd fieldsCampos de fin
AberturaOpeningApertura (start)OdometerAPIOpen · "1"OdameterEnd, endtime, endlatitude, endlongitude = "" (entity com fins nulos)OdameterEnd, endtime, endlatitude, endlongitude = "" (entity with null ends)OdameterEnd, endtime, endlatitude, endlongitude = "" (entity con fines nulos)
FechamentoClosingCierre (finish)OdometerAPIClosed · "0"todos preenchidos a partir da leitura/posição de chegadaall filled from the arrival reading/positiontodos completados desde la lectura/posición de llegada

isNew · Status isNew é derivado de journey.isClosed ? "0" : "1" e Status de journey.status.wireValue (Open/Closed). Como uid, ReconId e SubmissionDate são os mesmos nos dois envios, o backend reconcilia a jornada por esse par. isNew is derived from journey.isClosed ? "0" : "1" and Status from journey.status.wireValue (Open/Closed). Since uid, ReconId and SubmissionDate are the same across both sends, the backend reconciles the journey by that pair. isNew se deriva de journey.isClosed ? "0" : "1" y Status de journey.status.wireValue (Open/Closed). Como uid, ReconId y SubmissionDate son los mismos en ambos envíos, el backend reconcilia la jornada por ese par.

07

Como é disparadoHow it's firedCómo se dispara

A transação é orquestrada pelo fluxo de jornada (remote-first, §36). O JourneyNotifier (abertura) e o fluxo de encerramento chamam os use cases, que montam a entity crua e a passam ao builder. O builder é o dono único da formatação de data e da derivação wire. A cascata:The transaction is orchestrated by the journey flow (remote-first, §36). The JourneyNotifier (opening) and the end-journey flow call the use cases, which assemble the raw entity and pass it to the builder. The builder is the sole owner of date formatting and wire derivation. The cascade:La transacción se orquesta desde el flujo de jornada (remote-first, §36). El JourneyNotifier (apertura) y el flujo de cierre llaman a los use cases, que arman la entity cruda y la pasan al builder. El builder es el dueño único del formateo de fecha y la derivación wire. La cascada:

  • Journey / End journeynotifier
    • gera uuid/reconId, define statusgenerates uuid/reconId, sets statusgenera uuid/reconId, define statusStart / Finish OdometerJourneyUseCase
      • entity cruaraw entityentity crudaOdometerJourneyDispatcherPayloadInput
        • build()BuildOdometerJourneyDispatcherPayloadUseCasemonta o wireassembles the wirearma el wire
          • devolvereturnsdevuelveDispatcherEnvelope
            • SubmitOdometerJourneyUseCaseDispatcherOrchestrator
              • serializa + authserialize + authserializa + authDispatcherGateway
                • sendTransactionBackendgRPC

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

OdometerJourneyDispatcherPayloadInput (Freezed). Carrega o dado como existe no domínio; nada de formato wire. O relógio, o GPS, o uuid e o reconId já chegam resolvidos dentro da OdometerJourneyEntity (montada nos use cases de start/finish).OdometerJourneyDispatcherPayloadInput (Freezed). Carries data as it exists in the domain; no wire shaping. The clock, GPS, uuid and reconId arrive already resolved inside the OdometerJourneyEntity (assembled in the start/finish use cases).OdometerJourneyDispatcherPayloadInput (Freezed). Lleva el dato como existe en el dominio; nada de formato wire. El reloj, el GPS, el uuid y el reconId ya llegan resueltos dentro de la OdometerJourneyEntity (armada en los use cases de start/finish).

CampoFieldCampoTipoTypeTipoPapelRoleRol
journeyOdometerJourneyEntitya jornada crua: uuid, reconId, status, odometerStart/End, startedAt/endedAt, GPS de início/fimthe raw journey: uuid, reconId, status, odometerStart/End, startedAt/endedAt, start/end GPSla jornada cruda: uuid, reconId, status, odometerStart/End, startedAt/endedAt, GPS de inicio/fin
resourceResourceEntityrepresentante de vendas (cru — o builder deriva vanId = resource.locationSfid)sales rep (raw — the builder derives vanId = resource.locationSfid)representante de ventas (crudo — el builder deriva vanId = resource.locationSfid)
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 (14 no total). Campo, Tipo e Origem são código cru; só a Regra é prosa. Um exemplo completo (envio de fechamento) 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 (14 in total). Field, Type and Source are raw code; only Rule is prose. A full example (closing send) 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 (14 en total). Campo, Tipo y Origen son código crudo; solo la Regla es prosa. Un ejemplo completo (envío de cierre) está en transaction_example.json, junto a este doc.

Raiz do payloadPayload rootRaíz del payload

Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
Odometerarrayjourneyarray de um único objeto (leituras + tempo + GPS)single-element array (readings + time + GPS)array de un solo objeto (lecturas + tiempo + GPS)
ReconStatusarrayjourney + resourcearray de um único objeto (reconciliação + status + van)single-element array (reconciliation + status + van)array de un solo objeto (reconciliación + estado + van)
  • Odometer objeto únicosingle objectobjeto único 10 camposfieldscampos
    Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
    uidstringjourney.uuidid da jornada (SLREP-<uuid v4>); igual nos dois enviosjourney id (SLREP-<uuid v4>); same across both sendsid de la jornada (SLREP-<uuid v4>); igual en ambos envíos
    OdameterStartstringjourney.odometerStart.toString()leitura inicial; chave com typo mantida verbatim (contrato)initial reading; misspelled key kept verbatim (contract)lectura inicial; clave con typo mantenida verbatim (contrato)
    OdameterEndstringjourney.odometerEnd?.toString() ?? ""leitura final; "" na abertura; typo mantido verbatimfinal reading; "" on opening; typo kept verbatimlectura final; "" en la apertura; typo mantenido verbatim
    starttimestringjourney.startedAtformato yyyy/MM/dd HH:mm:ssyyyy/MM/dd HH:mm:ss formatformato yyyy/MM/dd HH:mm:ss
    endtimestringjourney.endedAt"" na abertura; senão yyyy/MM/dd HH:mm:ss"" on opening; else yyyy/MM/dd HH:mm:ss"" en la apertura; si no yyyy/MM/dd HH:mm:ss
    startlatitudestringjourney.startLatitude.toString()GPS na abertura (0.0 quando indisponível)GPS on opening (0.0 when unavailable)GPS en la apertura (0.0 cuando no disponible)
    startlongitudestringjourney.startLongitude.toString()GPS na abertura (0.0 quando indisponível)GPS on opening (0.0 when unavailable)GPS en la apertura (0.0 cuando no disponible)
    endlatitudestringjourney.endLatitude?.toString() ?? """" na abertura; GPS de chegada no fechamento"" on opening; arrival GPS on closing"" en la apertura; GPS de llegada en el cierre
    endlongitudestringjourney.endLongitude?.toString() ?? """" na abertura; GPS de chegada no fechamento"" on opening; arrival GPS on closing"" en la apertura; GPS de llegada en el cierre
    SubmissionDatestringjourney.startedAtformato yyyy/MM/dd; sempre a data de abertura (igual nos dois envios)yyyy/MM/dd format; always the opening date (same across both sends)formato yyyy/MM/dd; siempre la fecha de apertura (igual en ambos envíos)
  • ReconStatus objeto únicosingle objectobjeto único 4 camposfieldscampos
    Campo JSONTipoTypeTipoOrigem do DadoData sourceOrigen del DatoRegraRuleRegla
    ReconIdstringjourney.reconId{uuid}_{yyyy.MM.dd da abertura} — composto no use case de start; igual nos dois envios{uuid}_{opening yyyy.MM.dd} — composed in the start use case; same across both sends{uuid}_{yyyy.MM.dd de apertura} — compuesto en el use case de start; igual en ambos envíos
    Statusstringjourney.status.wireValue"Open" na abertura, "Closed" no fechamento"Open" on opening, "Closed" on closing"Open" en la apertura, "Closed" en el cierre
    isNewstringjourney.isClosed ? "0" : "1""1" na abertura, "0" no fechamento"1" on opening, "0" on closing"1" en la apertura, "0" en el cierre
    vanIdstringresource.locationSfidSFID da localização/van do rep (derivado da ResourceEntity crua)rep's location/van SFID (derived from the raw ResourceEntity)SFID de la ubicación/van del rep (derivado de la ResourceEntity cruda)
Formatação de dataDate formattingFormateo de fecha DateTimeUtils · DateFormatType
  • starttime/endtime: DateFormatType.slashYearMonthDayWithTimeyyyy/MM/dd HH:mm:ss.starttime/endtime: DateFormatType.slashYearMonthDayWithTimeyyyy/MM/dd HH:mm:ss.starttime/endtime: DateFormatType.slashYearMonthDayWithTimeyyyy/MM/dd HH:mm:ss.
  • SubmissionDate: DateFormatType.slashYearMonthDayyyyy/MM/dd (sempre sobre startedAt).SubmissionDate: DateFormatType.slashYearMonthDayyyyy/MM/dd (always over startedAt).SubmissionDate: DateFormatType.slashYearMonthDayyyyy/MM/dd (siempre sobre startedAt).
  • dateReference do envelope: DateTimeUtils.formatDate(dateTime: journey.startedAt) com o default isoDateyyyy-MM-dd (traço, não barra).envelope dateReference: DateTimeUtils.formatDate(dateTime: journey.startedAt) with the isoDate default → yyyy-MM-dd (dash, not slash).dateReference del envelope: DateTimeUtils.formatDate(dateTime: journey.startedAt) con el default isoDateyyyy-MM-dd (guion, no barra).
  • ReconId usa DateFormatType.dotYearMonthDayyyyy.MM.dd (composto no StartOdometerJourneyUseCase, não no builder).ReconId uses DateFormatType.dotYearMonthDayyyyy.MM.dd (composed in StartOdometerJourneyUseCase, not in the builder).ReconId usa DateFormatType.dotYearMonthDayyyyy.MM.dd (compuesto en StartOdometerJourneyUseCase, no en el builder).
09

Regras de negócioBusiness rulesReglas de negocio

Só os deltasOnly the deltasSolo los deltas

  • Um único par abertura/fechamento por jornada. O uid, o ReconId e o SubmissionDate são idênticos nos dois envios — é o par de correlação que o backend usa para casar a leitura inicial com a final.One opening/closing pair per journey. The uid, ReconId and SubmissionDate are identical across both sends — the correlation pair the backend uses to match the initial reading with the final one.Un único par apertura/cierre por jornada. El uid, el ReconId y el SubmissionDate son idénticos en ambos envíos — es el par de correlación que el backend usa para casar la lectura inicial con la final.
  • Remote-first. Tanto StartOdometerJourneyUseCase quanto FinishOdometerJourneyUseCase só gravam a jornada no local (repository.saveJourney) após o envio remoto ser aceito; se o envio falha, a entity não é persistida e a ação não avança.Remote-first. Both StartOdometerJourneyUseCase and FinishOdometerJourneyUseCase only persist the journey locally (repository.saveJourney) after the remote send is accepted; if the send fails, the entity isn't persisted and the action doesn't proceed.Remote-first. Tanto StartOdometerJourneyUseCase como FinishOdometerJourneyUseCase solo persisten la jornada localmente (repository.saveJourney) tras aceptarse el envío remoto; si el envío falla, la entity no se persiste y la acción no avanza.
  • Odômetro > 0. O JourneyNotifier rejeita leitura <= 0 (JourneyActionResult.invalidOdometer) antes de disparar o envio — o builder recebe sempre um valor válido.Odometer > 0. The JourneyNotifier rejects a <= 0 reading (JourneyActionResult.invalidOdometer) before firing the send — the builder always receives a valid value.Odómetro > 0. El JourneyNotifier rechaza lectura <= 0 (JourneyActionResult.invalidOdometer) antes de disparar el envío — el builder siempre recibe un valor válido.
  • Sem prefixo Promo_. type.resolveServiceName(hasPromotion: false) — a jornada nunca carrega promoção, então o serviceName é sempre OdometerAPI.No Promo_ prefix. type.resolveServiceName(hasPromotion: false) — a journey never carries a promotion, so the serviceName is always OdometerAPI.Sin prefijo Promo_. type.resolveServiceName(hasPromotion: false) — la jornada nunca lleva promoción, así que el serviceName es siempre OdometerAPI.
  • Números como string. Odômetro, latitude e longitude vão como String (.toString()) — o contrato wire trata tudo como texto. GPS indisponível vira "0.0".Numbers as strings. Odometer, latitude and longitude go as String (.toString()) — the wire contract treats everything as text. Unavailable GPS becomes "0.0".Números como string. Odómetro, latitud y longitud van como String (.toString()) — el contrato wire trata todo como texto. GPS no disponible se vuelve "0.0".
10

Pendências / roadmapPending / roadmapPendientes / roadmap

O que o builder envia com particularidade ou fora do ideal, documentado fiel ao estado atual do código (nunca descrito como se já estivesse corrigido):What the builder ships with a quirk or below the ideal, documented faithfully to the current code state (never described as already fixed):Lo que el builder envía con particularidad o fuera del ideal, documentado fiel al estado actual del código (nunca descrito como si ya estuviera corregido):

Particularidades / pendenteQuirks / pendingParticularidades / pendiente

  • OdameterStart / OdameterEnd: chaves com typo ("Odameter" em vez de "Odometer") mantidas verbatim — é o contrato do backend, não um bug a corrigir no app.OdameterStart / OdameterEnd: misspelled keys ("Odameter" instead of "Odometer") kept verbatim — it's the backend contract, not an app bug to fix.OdameterStart / OdameterEnd: claves con typo ("Odameter" en vez de "Odometer") mantenidas verbatim — es el contrato del backend, no un bug a corregir en la app.
  • GPS indisponível: latitude/longitude caem para 0.0 no JourneyNotifier (position?.latitude ?? 0.0) e chegam ao payload como "0.0" — não há re-tentativa de captura de posição.Unavailable GPS: latitude/longitude fall back to 0.0 in the JourneyNotifier (position?.latitude ?? 0.0) and reach the payload as "0.0" — there's no position-capture retry.GPS no disponible: latitude/longitude caen a 0.0 en el JourneyNotifier (position?.latitude ?? 0.0) y llegan al payload como "0.0" — no hay reintento de captura de posición.
  • 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).

Transação irmãSister transactionTransacción hermana A abertura da jornada, onde o mercado exige, dispara junto a transação de placa do veículo (CarLicensePlate, só BR) — documentada em 30 · Placa do veículo (doc separado). São transações distintas, com serviceName e mercados diferentes. Journey opening, where the market requires it, fires the vehicle-plate transaction alongside (CarLicensePlate, BR only) — documented in 30 · Car license plate (separate doc). They're distinct transactions, with different serviceName and markets. La apertura de la jornada, donde el mercado lo exige, dispara junto la transacción de placa del vehículo (CarLicensePlate, solo BR) — documentada en 30 · Placa del vehículo (doc separado). Son transacciones distintas, con serviceName y mercados diferentes.

MercadosMarketsMercados

A disponibilidade da transação vem de DispatcherType.odometerJourney.enabledMarkets = [BR, CL, ZA]. AR/PY/PE existem como mercados do app (config PANGEA mínima), mas não têm dispatcher de odômetro.Transaction availability comes from DispatcherType.odometerJourney.enabledMarkets = [BR, CL, ZA]. AR/PY/PE exist as app markets (minimal PANGEA config), but have no odometer dispatcher.La disponibilidad de la transacción viene de DispatcherType.odometerJourney.enabledMarkets = [BR, CL, ZA]. AR/PY/PE existen como mercados de la app (config PANGEA mínima), pero no tienen dispatcher de odómetro.

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

Mesmo payloadSame payloadMismo payload Nos três mercados a transação é idêntica: mesmo serviceName, mesmas 14 chaves e o mesmo par abertura/fechamento. O builder não ramifica por mercado. In all three markets the transaction is identical: same serviceName, same 14 keys and the same opening/closing pair. The builder doesn't branch by market. En los tres mercados la transacción es idéntica: mismo serviceName, mismas 14 claves y el mismo par apertura/cierre. El builder no ramifica por mercado.

BR

Placa juntoPlate alongsidePlaca junto A transação de placa do veículo (CarLicensePlate), disparada na mesma abertura, é só BR — o odômetro vai além (BR/CL/ZA). A visibilidade do campo de placa na tela vem do EMC (journeyConfig). The vehicle-plate transaction (CarLicensePlate), fired on the same opening, is BR only — the odometer goes further (BR/CL/ZA). The plate field's visibility on screen comes from the EMC (journeyConfig). La transacción de placa del vehículo (CarLicensePlate), disparada en la misma apertura, es solo BR — el odómetro va más allá (BR/CL/ZA). La visibilidad del campo de placa en pantalla viene del EMC (journeyConfig).

AR · PY · PE Existem como mercados do app (config PANGEA mínima), mas não têm dispatcher de odômetro — não estão em enabledMarkets. A jornada com odômetro não é disparada nesses mercados. They exist as app markets (minimal PANGEA config), but have no odometer dispatcher — they're not in enabledMarkets. The odometer journey isn't fired in these markets. Existen como mercados de la app (config PANGEA mínima), pero no tienen dispatcher de odómetro — no están en enabledMarkets. La jornada con odómetro no se dispara en estos mercados.