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).
Feature · VisitasFeature · VisitsFeature · Visitas

Lista de visitasVisit listLista de visitas

A agenda de visitas do representante de vendas: os varejos que ele precisa visitar, agrupados por tipo, com busca, setores, filtros e acesso ao detalhe. É também onde o app controla que só uma visita fica ativa por vez (check-in). Somente leitura da lista — o roteiro de dentro da visita vive no detalhe. The sales rep's visit agenda: the retails they need to visit, grouped by type, with search, sectors, filters and drill-down to detail. It's also where the app enforces that only one visit is active at a time (check-in). The list is read-only — the in-visit playbook lives in the detail. La agenda de visitas del representante de ventas: los puntos de venta que debe visitar, agrupados por tipo, con búsqueda, sectores, filtros y acceso al detalle. Es también donde la app controla que solo una visita esté activa a la vez (check-in). La lista es solo lectura — el guion dentro de la visita vive en el detalle.

PúblicoAudiencePúblico
Representante · QA · Suporte · DevRep · QA · Support · DevRepresentante · QA · Soporte · Dev
Onde ficaWhereDónde
Aba inferior → VisitasBottom tab → VisitsPestaña inferior → Visitas
RelacionadoRelatedRelacionado
Visit Detail · VisitUploadAPI
AtualizadoUpdatedActualizado
22/07/20262026-07-22
Disponível emAvailable inDisponible en BR CL ZA
01

O que é e para que serveWhat it is and what it's forQué es y para qué sirve

A Lista de visitas é a agenda do dia do representante de vendas: reúne os varejos que ele precisa atender sob a sua hierarquia de localização. Cada linha é um card de visita com os dados do varejo e indicadores. Responde três perguntas: The Visit list is the sales rep's daily agenda: it gathers the retails they must serve under their location hierarchy. Each row is a visit card with the retail's data and indicators. It answers three questions: La Lista de visitas es la agenda diaria del representante de ventas: reúne los puntos de venta que debe atender bajo su jerarquía de ubicación. Cada fila es una tarjeta de visita con los datos del punto de venta e indicadores. Responde tres preguntas:

Quem eu visito?Who do I visit?¿A quién visito?

Um card por visita, agrupado por presencial / digital, com nome, código e endereço do varejo.One card per visit, grouped by physical / digital, with the retail's name, code and address.Una tarjeta por visita, agrupada por presencial / digital, con nombre, código y dirección del punto de venta.

Qual está em andamento?Which one is in progress?¿Cuál está en curso?

O card da visita iniciada fica destacado e um botão flutuante leva direto a ela.The started visit's card is highlighted and a floating button jumps straight to it.La tarjeta de la visita iniciada queda destacada y un botón flotante lleva directo a ella.

O que fazer numa?What to do with one?¿Qué hacer en una?

Tocar num card abre o detalhe da visita, onde ficam tarefas, metas e o check-in.Tapping a card opens the visit detail, where tasks, targets and check-in live.Tocar una tarjeta abre el detalle de la visita, donde están tareas, metas y el check-in.

Escopo desta telaScope of this screenAlcance de esta pantalla Esta doc cobre a lista de visitas e o controle de visita única ativa. Tarefas, metas do dia, ferramentas e o roteiro completo de dentro da visita vivem no Detalhe da visita — a lista só navega até lá. This doc covers the visit list and the single-active-visit rule. Tasks, targets of the day, tools and the full in-visit playbook live in the Visit detail — the list only navigates there. Esta doc cubre la lista de visitas y la regla de visita única activa. Tareas, metas del día, herramientas y el guion completo dentro de la visita viven en el Detalle de la visita — la lista solo navega allí.

02

Como acessarHow to openCómo acceder

  1. Pela barra inferiorFrom the bottom barDesde la barra inferiorToque na aba Visitas na navegação inferior. É uma das telas base do app.Tap the Visits tab in the bottom navigation. It's one of the app's base screens.Toque la pestaña Visitas en la navegación inferior. Es una de las pantallas base de la app.
  2. A lista abreThe list opensLa lista abreComeça na aba Presencial (padrão). Puxe para baixo para atualizar.It starts on the Physical tab (default). Pull down to refresh.Empieza en la pestaña Presencial (por defecto). Deslice hacia abajo para actualizar.
  3. Visita em andamentoVisit in progressVisita en cursoSe você já iniciou uma visita, um botão flutuante "Em andamento" aparece — toque para rolar direto até o card dela.If you've already started a visit, an "In progress" floating button appears — tap it to scroll straight to its card.Si ya inició una visita, aparece un botón flotante "En curso" — tóquelo para desplazarse directo a su tarjeta.
03

Estrutura da telaScreen structureEstructura de la pantalla

Cada bloco abaixo aparece só quando o mercado o habilita (via End Market Configuration) — a tela é montada por configuração, não fixa.Each block below appears only when the market enables it (via End Market Configuration) — the screen is config-driven, not hardcoded.Cada bloque abajo aparece solo cuando el mercado lo habilita (vía End Market Configuration) — la pantalla se arma por configuración, no es fija.

CabeçalhoHeaderEncabezado
Título "Visitas" e a data da última sincronização dos dados."Visits" title and the last sync date of the data.Título "Visitas" y la fecha de última sincronización.
AbasTabsPestañas
Presencial / Digital (e opcionalmente Ambas). Filtram a lista pelo tipo de recurso da visita.Physical / Digital (and optionally Both). They filter the list by the visit's resource type.Presencial / Digital (y opcionalmente Ambas). Filtran la lista por el tipo de recurso de la visita.
SetorizadorSectorizerSectorizador
Chips com contador: Presencial, Digital, Duplicadas (mesmo varejo nos dois canais) e FDR (visita ad hoc).Chips with a counter: Physical, Digital, Duplicated (same retail in both channels) and FDR (ad hoc visit).Chips con contador: Presencial, Digital, Duplicadas (mismo punto de venta en ambos canales) y FDR (visita ad hoc).
BuscaSearchBúsqueda
Campo que filtra por nome, código, nome comercial e endereço do varejo.A field that filters by the retail's name, code, commercial name and address.Campo que filtra por nombre, código, nombre comercial y dirección del punto de venta.
AçõesActionsAcciones
Botões Ordenar e Filtrar (Filtrar aparece só onde há abas de filtro configuradas).Sort and Filter buttons (Filter shows only where filter tabs are configured).Botones Ordenar y Filtrar (Filtrar solo donde hay pestañas de filtro configuradas).
CardsCardsTarjetas
Um por visita, montado por seções configuráveis: dados do varejo, atividades, meta do dia, pilares comerciais e a linha inferior. O card da visita iniciada fica destacado.One per visit, assembled from configurable sections: retail data, activities, target of the day, commercial pillars and the bottom row. The started visit's card is highlighted.Una por visita, armada con secciones configurables: datos del punto de venta, actividades, meta del día, pilares comerciales y la fila inferior. La tarjeta de la visita iniciada queda destacada.
Contador "X de Y""X of Y" counterContador "X de Y"
Mostra quantas visitas estão visíveis do total filtrado; a lista carrega mais ao rolar.Shows how many visits are visible out of the filtered total; the list loads more as you scroll.Muestra cuántas visitas están visibles del total filtrado; la lista carga más al desplazar.
Botão flutuanteFloating buttonBotón flotante
"Em andamento" — só aparece quando existe uma visita iniciada; leva o scroll até o card dela."In progress" — appears only when a visit is started; scrolls to its card."En curso" — aparece solo cuando hay una visita iniciada; desplaza hasta su tarjeta.
04

Status e check-inStatus & check-inEstado y check-in

Cada visita tem um status, refletido na cor do avatar do card (a lista completa está na seção técnica Enums):Each visit has a status, shown by the card avatar's color (the full list is in the technical Enums section):Cada visita tiene un estado, reflejado en el color del avatar de la tarjeta (la lista completa está en la sección técnica Enums):

ConcluídaCompletedCompletada Em andamento (iniciada)In progress (started)En curso (iniciada) CanceladaCancelledCancelada Agendada / não iniciadaScheduled / not startedAgendada / no iniciada

Só uma visita ativa por vezOne active visit at a timeSolo una visita activa a la vez Iniciar (check-in) e finalizar uma visita acontece no detalhe. A lista protege essa regra: se você já tem uma visita em andamento e toca em outro card, o app pergunta se quer finalizar a atual antes de abrir a nova. Ao confirmar, a visita atual é finalizada em segundo plano e o app avisa se o envio foi enviado, enfileirado (offline) ou falhou. Starting (check-in) and finishing a visit happen in the detail. The list guards this rule: if you already have a visit in progress and tap another card, the app asks whether to finish the current one before opening the new. On confirm, the current visit is finished in the background and the app reports whether the upload was sent, queued (offline) or failed. Iniciar (check-in) y finalizar una visita ocurren en el detalle. La lista protege esa regla: si ya tiene una visita en curso y toca otra tarjeta, la app pregunta si desea finalizar la actual antes de abrir la nueva. Al confirmar, la visita actual se finaliza en segundo plano y la app avisa si el envío fue enviado, encolado (offline) o falló.

05

Buscar, setorizar, filtrar e ordenarSearch, sector, filter and sortBuscar, sectorizar, filtrar y ordenar

BuscaSearchBúsqueda

Filtra enquanto você digita por nome, nome comercial, código do varejo e pelos campos de endereço (rua, bairro, cidade, estado, CEP). Vários termos separados por espaço precisam todos aparecer.Filters as you type by name, commercial name, retail code and address fields (street, neighborhood, city, state, postal code). Multiple space-separated terms must all match.Filtra mientras escribe por nombre, nombre comercial, código del punto de venta y campos de dirección (calle, barrio, ciudad, estado, código postal). Varios términos separados por espacio deben coincidir todos.

SetoresSectorsSectores

Chips que restringem a lista: Presencial, Digital, Duplicadas (o mesmo varejo aparece nos dois canais) e FDR (visitas ad hoc). Tocar no setor ativo o desmarca.Chips that narrow the list: Physical, Digital, Duplicated (same retail appears in both channels) and FDR (ad hoc visits). Tapping the active sector clears it.Chips que acotan la lista: Presencial, Digital, Duplicadas (el mismo punto de venta aparece en ambos canales) y FDR (visitas ad hoc). Tocar el sector activo lo desmarca.

FiltrosFiltersFiltros

O modal de filtros é montado por mercado: cada aba de filtro e cada critério (ex.: status do varejo, situação financeira, tipo de visita, visita planejada) vêm do End Market Configuration. Cada filtro cruza os códigos de filtro que a própria visita traz. Valem após tocar em Aplicar.The filter modal is built per market: each filter tab and criterion (e.g. retail status, financial status, visit type, planned visit) comes from End Market Configuration. Each filter matches the filter codes carried by the visit itself. They apply after you tap Apply.El modal de filtros se arma por mercado: cada pestaña de filtro y criterio (ej.: estado del punto de venta, situación financiera, tipo de visita, visita planificada) viene del End Market Configuration. Cada filtro cruza los códigos de filtro que trae la propia visita. Valen tras tocar Aplicar.

OrdenaçãoSortOrdenación

Três opções: ordem de rota (padrão, mantém a ordem que veio do backend), nome do varejo e status (por progressão da visita).Three options: route order (default, keeps the backend order), retail name and status (by visit progression).Tres opciones: orden de ruta (por defecto, mantiene el orden del backend), nombre del punto de venta y estado (por progresión de la visita).

06

Arquitetura e fluxo de dadosArchitecture & data flowArquitectura y flujo de datos

Clean Architecture + Riverpod + Freezed + gRPC + ObjectBox. A lista é somente leitura: um único RPC (getVisitList) traz a visita completa, com cache write-through (todo fetch grava no ObjectBox). O check-in (iniciar/finalizar) é um caminho separado: grava o status localmente e despacha a transação VisitUploadAPI.Clean Architecture + Riverpod + Freezed + gRPC + ObjectBox. The list is read-only: a single RPC (getVisitList) returns the full visit, with cache write-through (every fetch writes to ObjectBox). Check-in (start/finish) is a separate path: it writes the status locally and dispatches the VisitUploadAPI transaction.Clean Architecture + Riverpod + Freezed + gRPC + ObjectBox. La lista es solo lectura: un único RPC (getVisitList) trae la visita completa, con cache write-through (todo fetch graba en ObjectBox). El check-in (iniciar/finalizar) es un camino aparte: graba el estado localmente y despacha la transacción VisitUploadAPI.

Leitura da listaReading the listLectura de la lista

  • VisitReplygRPC proto
    • toVisitsDTOVisitsDTODTO · Freezed
      • toDomainVisitsEntitydomain
        • toModelVisitsModelObjectBox
          • toDomainVisitsEntitydomain · cache
            • watchVisitsNotifier + State
              • → UIVisitsPage

Check-in (iniciar / finalizar)Check-in (start / finish)Check-in (iniciar / finalizar)

Orquestrado pelo provider compartilhado VisitContext (acionado sobretudo pelo Detalhe da visita; a lista dispara apenas o finalizar, via guarda de visita única):Orchestrated by the shared VisitContext provider (triggered mainly by the Visit detail; the list only triggers finish, via the single-visit guard):Orquestado por el provider compartido VisitContext (accionado sobre todo por el Detalle de la visita; la lista dispara solo el finalizar, vía la guarda de visita única):

  • VisitContext.start/endVisitshared provider
    • saveVisitStatusObjectBoxstatus local (startedAt/endedAt)
      • build(input)BuildVisitUploadDispatcherPayloadUseCase
        • submitSubmitVisitUploadUseCaseDispatcher
          • VisitUploadAPIsent · queued · failed

Cross-linksCross-linksCross-links O payload e o contrato do envio estão em Transação · VisitUploadAPI. As telas dentro da visita, em Detalhe da visita. The upload payload and contract live in Transaction · VisitUploadAPI. The in-visit screens, in Visit detail. El payload y el contrato del envío están en Transacción · VisitUploadAPI. Las pantallas dentro de la visita, en Detalle de la visita.

07

Modelo de dadosData modelModelo de datos

A mesma visita existe em quatro representações quase idênticasProto (wire gRPC) → DTO (Freezed) → Model (ObjectBox) → Entity (domínio) — e cada fronteira é atravessada por um mapper. Os nomes dos campos se mantêm; muda pouco (enums tipados na Entity, relações no Model, e dois campos de check-in que só existem local). O fetch é write-through: todo retorno grava no ObjectBox e a UI passa a ler do cache.The same visit exists in four near-identical representationsProto (gRPC wire) → DTO (Freezed) → Model (ObjectBox) → Entity (domain) — and each boundary is crossed by a mapper. Field names stay the same; little changes (enums typed in the Entity, relations in the Model, and two check-in fields that exist only locally). Fetch is write-through: every response is written to ObjectBox and the UI reads from cache.La misma visita existe en cuatro representaciones casi idénticasProto (wire gRPC) → DTO (Freezed) → Model (ObjectBox) → Entity (dominio) — y cada frontera se cruza con un mapper. Los nombres se mantienen; cambia poco (enums tipados en la Entity, relaciones en el Model, y dos campos de check-in que solo existen local). El fetch es write-through: toda respuesta se graba en ObjectBox y la UI lee del caché.

A lista chega num container VisitsEntity (lastSyncAt gerado no mapper + visits[]); cada item é um Visit de 26 campos de wire, com muitas sub-estruturas aninhadas. Os enums só existem tipados na Entity; em Proto/DTO/Model trafegam como String. A seguir, na ordem: o proto, as estruturas de dados campo-a-campo, e os mappers.The list arrives in a VisitsEntity container (lastSyncAt generated in the mapper + visits[]); each item is a 26-wire-field Visit with many nested sub-structures. Enums are only typed in the Entity; in Proto/DTO/Model they travel as String. Next, in order: the proto, the field-by-field data structures, and the mappers.La lista llega en un container VisitsEntity (lastSyncAt generado en el mapper + visits[]); cada ítem es un Visit de 26 campos de wire, con muchas sub-estructuras anidadas. Los enums solo están tipados en la Entity; en Proto/DTO/Model viajan como String. A continuación, en orden: el proto, las estructuras de datos campo a campo, y los mappers.

Proto

VisitConectaRep.proto · proto3 · package mn.bat.conectarep.streambridge (importa KpiConectaRep e CommonConectaRep). Um serviço (VisitConectaRepService), um método unário:One service (VisitConectaRepService), a single unary method:Un servicio (VisitConectaRepService), un método unario:

getVisitListunary
MétodoMethodMétodo

rpc getVisitList(VisitRequest) returns (VisitReply)

path /mn.bat.conectarep.streambridge.VisitConectaRepService/getVisitList

Request · VisitRequest
locationHierarchySfid
string · #1 · hierarquia do representante de vendas (resolvida no repository)sales rep hierarchy (resolved in the repository)jerarquía del representante de ventas (resuelta en el repository)
dateReference
string · #2 · optional
lastModifiedDate
string · #3 · optional (não usado hoje)optional (not used today)optional (no usado hoy)
Reply · VisitReply

repeated Visit visitLista lista de visitas. Os campos de Visit estão detalhados nas Estruturas de dados abaixo.the list of visits. Visit's fields are detailed in Data structures below.la lista de visitas. Los campos de Visit están detallados en Estructuras de datos abajo.

Estruturas de dadosData structuresEstructuras de datos

Colunas Proto · DTO · Model · Entity, uma linha por campo, tipo repetido nas 4 colunas. O delta (texto azul) marca onde o tipo primeiro muda: relação ToMany/ToOne no Model, enum na Entity, parse de data no Model. ¹ = optional no proto. startedAt/endedAt só existem no Model/Entity (gravados no check-in local).Columns Proto · DTO · Model · Entity, one row per field, type repeated across the 4 columns. The delta (blue text) marks where the type first changes: ToMany/ToOne relation in the Model, enum in the Entity, date parse in the Model. ¹ = optional in the proto. startedAt/endedAt exist only in Model/Entity (written on local check-in).Columnas Proto · DTO · Model · Entity, una fila por campo, tipo repetido en las 4 columnas. El delta (texto azul) marca dónde primero cambia el tipo: relación ToMany/ToOne en el Model, enum en la Entity, parse de fecha en el Model. ¹ = optional en el proto. startedAt/endedAt solo existen en Model/Entity (grabados en el check-in local).

  • Visit raiz 26 + 2 camposfieldscampos
    CampoProtoDTOModelEntity
    sfidstringStringStringString
    visitResourceTypestringStringStringResourceType
    accountDataAccount…DTOToOne<…Model>AccountDataEntity
    statusstringStringStringVisitStatus
    isTelesalesboolboolboolbool
    previousVisitDatestringString?String?String?
    nextVisitDatestringString?String?String?
    hasSmartInvestmentbool¹boolboolbool
    hasDeliverybool¹boolboolbool
    labelsrepeated LabelList<…DTO>ToMany<…Model>List<…Entity>
    kpisrepeated KpiInfoList<…DTO>ToMany<…Model>List<VisitKpiEntity>
    sellableCategoriesIndicatorrepeated CategoryIndicatorList<…DTO>ToMany<…Model>List<…Entity>
    salesCategoriesIndicatorrepeated SalesCategoryIndicatorList<…DTO>ToMany<…Model>List<…Entity>
    commercialPillarsrepeated PillarsKpiList<…DTO>ToMany<…Model>List<CommercialPillarEntity>
    filtersFilter…DTO?ToOne<…Model>VisitFiltersEntity?
    monthlyVolumerepeated MonthlyVolumeList<…DTO>ToMany<…Model>List<…Entity>
    monthlyTargetMonthlyTarget¹…DTO?ToOne<…Model>…Entity?
    targetsOfTheDayrepeated TargetOfTheDayList<…DTO>ToMany<…Model>List<…Entity>
    deliveryTrackingrepeated DeliveryTrackingList<…DTO>ToMany<…Model>List<…Entity>
    dashboardsDashboards…DTO?ToOne<…Model>VisitDashboardsEntity?
    competitorChecksrepeated CompetitorCheckList<…DTO>ToMany<…Model>List<…Entity>
    shelfWatchShelfWatch¹…DTO?ToOne<…Model>…Entity?
    typestringStringStringString
    visitDatestringString?String?String?
    visitResourcestringStringStringString
    boostPlanScriptstring¹String?String?String?
    startedAtDateTime?DateTime?
    endedAtDateTime?DateTime?
    • AccountData Visit.accountData · proto Account 42 camposfieldscampos
      CampoProtoDTOModelEntity
      sfidstringStringStringString
      namestringStringStringString
      customerCodestringStringStringString
      addressAddress…DTO?ToOne<…Model>AddressEntity?
      taxCodestringString?String?String?
      stateRegistrationstringString?String?String?
      commercialNamestringString?String?String?
      totalStaffint32int?int?int?
      contactNamestringString?String?String?
      contactPhonestringString?String?String?
      latitudedoubledouble?double?double?
      longitudedoubledouble?double?double?
      operatingDaysrepeated stringList<String>List<String>List<String>
      openingTimestringString?String?String?
      closingTimestringString?String?String?
      categoriesSoldrepeated stringList<String>List<String>List<CategoryForSale>
      outletSubtypeSfidNamePair…DTO?ToOne<…Model>SfidNamePairEntity?
      bannerNamestringString?String?String?
      keyAccountTypestringString?String?String?
      volumeRangestringString?String?String?
      merchandisingClassstringString?String?String?
      localClassificationLocalClassification…DTO?ToOne<…Model>…Entity?
      routeInfoRouteInfo…DTO?ToOne<…Model>RouteInfoEntity?
      supplierDataSupplier¹…DTO?ToOne<…Model>SupplierDataEntity?
      creditLimitdoubledouble?double?double?
      baseCreditLimitdoubledouble?double?double?
      creditDaysint32int?int?int?
      paymentMethodsrepeated stringList<String>List<String>List<String>
      overdueAmountdoubledouble?double?double?
      statusAccount → statusstringStringStringString
      isB2Bboolbool?bool?bool?
      isOverdueboolbool?bool?bool?
      isBlockedToSalesboolbool?bool?bool?
      hasCompetitionboolbool?bool?bool?
      hasIllegalProductsboolbool?bool?bool?
      deactivationDatestringString?String?String?
      reactivationDatestringString?String?String?
      girostringString?String?String?
      canalstringString?String?String?
      faxstringString?String?String?
      distributorBadDebtPendingboolboolboolbool
      staffStaff…DTOToOne<…Model>StaffEntity
      • Address AccountData.address 7 camposfieldscampos
        CampoProtoDTOModelEntity
        fullAddressstringString?String?String?
        streetstringString?String?String?
        streetComplementstringString?String?String?
        neighborhoodstringString?String?String?
        postalCodestringString?String?String?
        citySfidNamePair…DTO?ToOne<…Model>SfidNamePairEntity?
        stateSfidNamePair…DTO?ToOne<…Model>SfidNamePairEntity?
    • Label Visit.labels[] 3 camposfieldscampos
      CampoProtoDTOModelEntity
      labelstringStringStringString
      backgroundColorstringStringStringString
      textColorstringStringStringString
    • VisitKpi Visit.kpis[] · proto KpiInfo 2 camposfieldscampos
      CampoProtoDTOModelEntity
      kpiNamestringStringStringString
      valuedoubledoubledoubledouble
    • CategoryIndicator Visit.sellableCategoriesIndicator[] 2 camposfieldscampos
      CampoProtoDTOModelEntity
      categoryNamestringStringStringString
      hasTargetboolboolboolbool
    • SalesCategoryIndicator Visit.salesCategoriesIndicator[] 2 camposfieldscampos
      CampoProtoDTOModelEntity
      categoryNamestringStringStringString
      statusstringStringStringString
    • CommercialPillar Visit.commercialPillars[] · proto PillarsKpi 6 camposfieldscampos
      CampoProtoDTOModelEntity
      kpiNamestringStringStringString
      targetdoubledoubledoubledouble
      realizeddoubledoubledoubledouble
      differencedoubledoubledoubledouble
      percentagedoubledoubledoubledouble
      isAchievedbool¹bool?bool?bool?
    • Filter Visit.filters 2 listaslistslistas
      CampoProtoDTOModelEntity
      normalFiltersrepeated FilterInfoList<…DTO>ToMany<…Model>List<FilterItemEntity>
      commercialPillarsFilterrepeated FilterInfoList<…DTO>ToMany<…Model>List<FilterItemEntity>
      • FilterInfo Filter.*[] · = FilterItemEntity 2 camposfieldscampos
        CampoProtoDTOModelEntity
        filterCodestringStringStringString
        valuesrepeated stringList<String>List<String>List<String>
    • MonthlyVolume Visit.monthlyVolume[] 5 camposfieldscampos
      CampoProtoDTOModelEntity
      categorystringStringStringString
      realizeddoubledoubledoubledouble
      targetdoubledoubledoubledouble
      differencedoubledoubledoubledouble
      percentagedoubledoubledoubledouble
    • TargetOfTheDay Visit.targetsOfTheDay[] 6 + details
      CampoProtoDTOModelEntity
      categorystringStringStringString
      realizeddoubledoubledoubledouble
      targetdoubledoubledoubledouble
      differencedoubledoubledoubledouble
      percentagedoubledoubledoubledouble
      unitOfMeasurementstring¹String?String?String?
      detailsrepeated TargetDetailList<…DTO>ToMany<…Model>List<TargetDetailEntity>
      • TargetDetail TargetOfTheDay.details[] 5 camposfieldscampos
        CampoProtoDTOModelEntity
        detailNamestringStringStringString
        realizeddoubledoubledoubledouble
        targetdoubledoubledoubledouble
        differencedoubledoubledoubledouble
        percentagedoubledoubledoubledouble

Estruturas só do detalheDetail-only structuresEstructuras solo del detalle O Visit ainda carrega sub-árvores que a lista não renderizaMonthlyTarget (categorias → itens → períodos), os 7 Dashboards (campaign, partnership, conectaVoce, conectaNegocios, conectaAMPM, boostPlan, smartInvestment), DeliveryTracking, CompetitorCheck, ShelfWatch e AccountData.staff (contacts/clerks). São wire da mesma resposta, mas consumidas na tela de detalhe — documentadas lá campo-a-campo. The Visit also carries sub-trees the list doesn't renderMonthlyTarget (categories → items → periods), the 7 Dashboards (campaign, partnership, conectaVoce, conectaNegocios, conectaAMPM, boostPlan, smartInvestment), DeliveryTracking, CompetitorCheck, ShelfWatch and AccountData.staff (contacts/clerks). They're wire of the same response, but consumed on the detail screen — documented there field-by-field. El Visit también carga sub-árboles que la lista no renderizaMonthlyTarget (categorías → ítems → períodos), los 7 Dashboards (campaign, partnership, conectaVoce, conectaNegocios, conectaAMPM, boostPlan, smartInvestment), DeliveryTracking, CompetitorCheck, ShelfWatch y AccountData.staff (contacts/clerks). Son wire de la misma respuesta, pero se consumen en la pantalla de detalle — documentados allí campo a campo.

Mappers

As conversões entre as camadas, todas como extension (5 direções por tipo):The conversions between layers, all as extensions (5 directions per type):Las conversiones entre capas, todas como extension (5 direcciones por tipo):

DireçãoDirectionDirecciónMétodoMethodMétodo
JSON → DTOstatic fromMap(Map)
Proto → DTOtoDTO()
DTO → EntitytoDomain() (resolve enums: ResourceType.fromString, VisitStatus.fromString…)(resolves enums: ResourceType.fromString, VisitStatus.fromString…)(resuelve enums: ResourceType.fromString, VisitStatus.fromString…)
Entity → ModeltoModel() (enums → .value; popula ToMany/ToOne; carrega startedAt/endedAt)(enums → .value; fills relations; carries startedAt/endedAt)(enums → .value; llena relaciones; carga startedAt/endedAt)
Model → EntitytoDomain()

Os únicos deltasThe only deltasLos únicos deltas

  • visitResourceTypeResourceType, statusVisitStatus tipados só na Entitytyped only in the Entitytipados solo en la Entity
  • AccountData.categoriesSold List<String>List<CategoryForSale> na Entityin the Entityen la Entity
  • startedAt/endedAt só no Model/Entity — gravados no check-in, ausentes no wireModel/Entity only — written on check-in, absent from the wiresolo en Model/Entity — grabados en el check-in, ausentes del wire
  • relações viram ToMany/ToOne no Modelrelations become ToMany/ToOne in the Modelrelaciones pasan a ToMany/ToOne en el Model
  • type vazio no proto vira "unknown" já no DTOempty in the proto becomes "unknown" at the DTOvacío en el proto pasa a "unknown" ya en el DTO
  • lastSyncAt gerado no mapper com DateTimeUtils.now()generated in the mapper with DateTimeUtils.now()generado en el mapper con DateTimeUtils.now()
08

Repository

VisitRepositoryImpl implementaimplementsimplementa VisitRepositoryInterface e injeta os 3 datasources (mock/local/remote) + ConnectivityService + a flag useMockData + Ref. Método a método:and injects the 3 datasources (mock/local/remote) + ConnectivityService + the useMockData flag + Ref. Method by method:e inyecta los 3 datasources (mock/local/remote) + ConnectivityService + la flag useMockData + Ref. Método a método:

getVisits({source}) mock / local / remote

RetornaReturnsDevuelve Result<VisitsEntity?, Failure>

Ponto de entrada da lista: decide a fonte pela source + flags, mapeia e grava no cache (write-through). Chamado pelo VisitsNotifier.List entry point: picks the source from source + flags, maps and writes to cache (write-through). Called by VisitsNotifier.Punto de entrada de la lista: elige la fuente por source + flags, mapea y graba en caché (write-through). Llamado por VisitsNotifier.

Árvore de decisão de fonteSource decision treeÁrbol de decisión de fuente

  1. useMockData == true ouoro source == mock_fetchFromMock(): lê o mock, mapeia, grava no cache. A flag global tem precedência máxima._fetchFromMock(): reads the mock, maps, writes to cache. The global flag has top precedence._fetchFromMock(): lee el mock, mapea, graba en caché. La flag global tiene máxima precedencia.
  2. source == local ou offlineor offlineu offlinegetCachedVisits() (sem rede).getCachedVisits() (no network).getCachedVisits() (sin red).
  3. senão (remoto + conectado)otherwise (remote + connected)si no (remoto + conectado)_fetchFromRemoteWithFallback(): lê currentResourceProvider; se null cai pro cache; senão chama o remoto com resource.locationHierarchyId, mapeia, grava no cache; em erro, fallback pro cache._fetchFromRemoteWithFallback(): reads currentResourceProvider; if null falls back to cache; else calls remote with resource.locationHierarchyId, maps, writes to cache; on error, falls back to cache._fetchFromRemoteWithFallback(): lee currentResourceProvider; si null cae al caché; si no llama al remoto con resource.locationHierarchyId, mapea, graba en caché; en error, fallback al caché.
getCachedVisits() local

RetornaReturnsDevuelve Result<VisitsEntity?, Failure>

Só cache. null vira Success(null), não erro — quem chama trata "sem dados" sem falha.Cache only. null becomes Success(null), not an error — callers handle "no data" without a failure.Solo caché. null es Success(null), no error — quien llama trata "sin datos" sin fallo.

getCachedVisitsLastSyncAt() local

RetornaReturnsDevuelve DateTime? (sem Result)(no Result)(sin Result)

Timestamp da última sincronização do container, para o DataLoadInfo.The container's last-sync timestamp, for DataLoadInfo.Timestamp de última sincronización del container, para DataLoadInfo.

getCachedVisitBySfid({visitSfid}) local

RetornaReturnsDevuelve Result<VisitEntity, Failure>

Busca 1 visita no cache pelo sfid; ausente → Error(CacheFailure). Alimenta o Visit Detail (§28 cat. A) — nunca dispara remoto.Fetches 1 visit from cache by sfid; missing → Error(CacheFailure). Feeds Visit Detail (§28 cat. A) — never triggers remote.Busca 1 visita en caché por sfid; ausente → Error(CacheFailure). Alimenta el Visit Detail (§28 cat. A) — nunca dispara remoto.

getCachedVisitByAccountSfid({accountSfid}) local

RetornaReturnsDevuelve Result<VisitEntity?, Failure>

Varre o cache e devolve a primeira visita cujo accountData.sfid bate; sem match → Success(null). Usado por quem parte do varejo (ex.: retail detail) para achar a visita.Scans the cache and returns the first visit whose accountData.sfid matches; no match → Success(null). Used by callers starting from the retail (e.g. retail detail) to find the visit.Recorre el caché y devuelve la primera visita cuyo accountData.sfid coincide; sin match → Success(null). Usado por quien parte del punto de venta (ej.: retail detail) para hallar la visita.

saveVisits({entity}) local

RetornaReturnsDevuelve Result<void, Failure>

Destrutivo: limpa e regrava tudo (cascata das boxes filhas), reaplicando o progresso client-side (status/started/ended da visita iniciada) por cima do dado fresco. É o cache-writer chamado após cada fetch bem-sucedido.Destructive: clears and rewrites everything (child boxes cascade), re-applying client-side progress (started visit's status/started/ended) on top of the fresh data. It's the cache-writer called after each successful fetch.Destructivo: limpia y regraba todo (cascada de boxes hijas), reaplicando el progreso client-side (status/started/ended de la visita iniciada) sobre el dato fresco. Es el cache-writer llamado tras cada fetch exitoso.

saveVisitStatus({visitSfid, status, startedAt?, endedAt?}) local · check-inlocal · check-inlocal · check-in

RetornaReturnsDevuelve Result<void, Failure>

Grava o novo status da visita somente no cache local (updateVisitStatusInVisit), sem rede. O envio remoto do check-in é separado, feito pelo VisitContext via VisitUploadAPI (ver seção 06).Writes the visit's new status to the local cache only (updateVisitStatusInVisit), no network. The remote check-in upload is separate, done by VisitContext via VisitUploadAPI (see section 06).Graba el nuevo estado de la visita solo en el caché local (updateVisitStatusInVisit), sin red. El envío remoto del check-in es separado, hecho por VisitContext vía VisitUploadAPI (ver sección 06).

09

Datasources

Um card por datasource (dropdown). No corpo: método, envio, retorno, fluxo de uso e tratamento de erro.One card per datasource (dropdown). In the body: method, what it sends, return, usage flow and error handling.Un card por datasource (dropdown). En el cuerpo: método, envío, retorno, flujo de uso y manejo de errores.

Remote VisitRemoteDataSource gRPC
getVisits({locationHierarchySfid, dateReference?})
EnvioSendsEnvío
monta VisitRequest e chama _client.getVisitList(request) no VisitConectaRepServiceClient (via visitServiceClientProvider).builds VisitRequest and calls _client.getVisitList(request) on VisitConectaRepServiceClient (via visitServiceClientProvider).arma VisitRequest y llama _client.getVisitList(request) en VisitConectaRepServiceClient (vía visitServiceClientProvider).
RetornoReturnRetorno
VisitsDTO (via response.toVisitsDTO())(via response.toVisitsDTO())(vía response.toVisitsDTO())
Fluxo de usoUsage flowFlujo de uso
chamado pelo caminho remoto do repository (_fetchFromRemoteWithFallback), quando online e sem mock; o resultado é gravado no cache.called by the repository's remote path (_fetchFromRemoteWithFallback), when online and not mocking; the result is written to cache.llamado por el camino remoto del repository (_fetchFromRemoteWithFallback), online y sin mock; el resultado se graba en caché.
Tratamento de erroError handlingManejo de errores
GrpcErrorGrpcExceptionHandler; outros → ServerException. Em erro, o repository faz fallback pro cache.GrpcErrorGrpcExceptionHandler; others → ServerException. On error, the repository falls back to cache.GrpcErrorGrpcExceptionHandler; otros → ServerException. En error, el repository hace fallback al caché.
Local VisitLocalDataSource ObjectBox

Envio / fluxo: persistência local via ObjectBox (boxes VisitsModel e VisitModel) — sem rede. Alimenta os caminhos cache do repository. Erro: falhas de persistência propagam como exceção (não engolidas). Além dos métodos da lista abaixo, expõe mutações usadas pelo detalhe/staff (updateAccountInVisit, upsert/removeContactInVisit, upsertClerkInVisit, mergeAdhocVisits).Sends / flow: local persistence via ObjectBox (VisitsModel and VisitModel boxes) — no network. Feeds the repository's cache paths. Error: persistence failures propagate as exceptions (not swallowed). Beyond the list methods below, it exposes mutations used by detail/staff (updateAccountInVisit, upsert/removeContactInVisit, upsertClerkInVisit, mergeAdhocVisits).Envío / flujo: persistencia local vía ObjectBox (boxes VisitsModel y VisitModel) — sin red. Alimenta los caminos caché del repository. Error: fallos de persistencia propagan como excepción (no tragados). Además de los métodos de la lista abajo, expone mutaciones usadas por el detalle/staff (updateAccountInVisit, upsert/removeContactInVisit, upsertClerkInVisit, mergeAdhocVisits).

getVisits()
RetornoReturnRetorno
VisitsEntity?
ComportamentoBehaviorComportamiento
o agregado único do cache, ou null se vazio.the single cached aggregate, or null if empty.el agregado único del caché, o null si está vacío.
getVisitsLastSyncAt()
RetornoReturnRetorno
DateTime?
ComportamentoBehaviorComportamiento
timestamp da última sync do container.the container's last-sync timestamp.timestamp de última sincronización del container.
getVisitBySfid({visitSfid})
RetornoReturnRetorno
VisitEntity?
ComportamentoBehaviorComportamiento
busca 1 visita pelo sfid. É o método que alimenta o Visit Detail.fetches 1 visit by sfid. This is the method feeding Visit Detail.busca 1 visita por sfid. Es el método que alimenta el Visit Detail.
saveVisits({entity})
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
destrutivo: limpa e regrava tudo, reaplicando o progresso client-side da visita iniciada. Cache-writer após cada fetch.destructive: clears and rewrites everything, re-applying the started visit's client-side progress. Cache-writer after each fetch.destructivo: limpia y regraba todo, reaplicando el progreso client-side de la visita iniciada. Cache-writer tras cada fetch.
updateVisitStatusInVisit({visitSfid, status, startedAt?, endedAt?})
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
grava status + startedAt/endedAt da visita no cache (o dado de check-in). Chamado pelo saveVisitStatus.writes the visit's status + startedAt/endedAt to the cache (the check-in data). Called by saveVisitStatus.graba status + startedAt/endedAt de la visita en el caché (el dato de check-in). Llamado por saveVisitStatus.
clearVisits()
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
limpa todas as boxes na ordem filhas→raízes.clears all boxes children→roots.limpia todas las boxes hijas→raíces.
Mock VisitMockDataSource JSON
getVisits()
EnvioSendsEnvío
carrega o asset JSON visits/visits (por mercado, real vs sintético via useRealMockData) — sem rede.loads the JSON asset visits/visits (per market, real vs synthetic via useRealMockData) — no network.carga el asset JSON visits/visits (por mercado, real vs sintético vía useRealMockData) — sin red.
RetornoReturnRetorno
VisitsDTO (via VisitsDTOJsonMapper.fromMap)(via VisitsDTOJsonMapper.fromMap)(vía VisitsDTOJsonMapper.fromMap)
Fluxo de usoUsage flowFlujo de uso
usado quando useMockData está ligado ou source == mock; grava no cache como um fetch normal.used when useMockData is on or source == mock; writes to cache like a normal fetch.usado cuando useMockData está activo o source == mock; graba en caché como un fetch normal.
Tratamento de erroError handlingManejo de errores
asset ausente ou JSON inválido → CacheException (sem rede envolvida).missing asset or invalid JSON → CacheException (no network involved).asset ausente o JSON inválido → CacheException (sin red involucrada).
10

Enums e labelsEnums & labelsEnums y labels

Os enums só existem tipados na camada Entity; em DTO/Model/Proto trafegam como String. Enums de wire (status, tipos) são exibidos crus, sem tradução (decisão de produto). Lista completa dos enums da lista:Enums are only typed in the Entity layer; in DTO/Model/Proto they travel as String. Wire enums (status, types) are shown raw, untranslated (product decision). Full list of the list's enums:Los enums solo están tipados en la Entity; en DTO/Model/Proto viajan como String. Los enums de wire (estado, tipos) se muestran crudos, sin traducir (decisión de producto). Lista completa de los enums de la lista:

VisitStatus 6 · cor do avatar6 · avatar color6 · color del avatar
casevaluecor avataravatar colorcolor avatar
scheduled"scheduled"divider
notStarted"not_started"divider
started"started"warning
completed"completed"success
cancelled"cancelled"error
unknown"unknown"divider
ResourceType 4
casevalueitemsitemsitems
physical"physical"preSalesRep · promptSalesRep · universalRep · deliveryRep
digital"digital"webAgentDirect
telesales"telesales"telesalesAnalyst
unknown"unknown"
VisitType 3
casevalue
planned"planned"
adhoc"adhoc"
unknown"unknown"
VisitSector 4
casevaluenotanotenota
physical"physical"recurso presencialphysical resourcerecurso presencial
digital"digital"digital + telesalesdigital + telesalesdigital + telesales
duplicated"duplicated"varejo nos dois canaisretail in both channelspunto de venta en ambos canales
fdr"fdr"visita ad hoc (type == adhoc)ad hoc visit (type == adhoc)visita ad hoc (type == adhoc)
VisitSort 3
casenotanotenota
routeOrderpadrão · ordem do backend (sem reordenar)default · backend order (no reorder)por defecto · orden del backend (sin reordenar)
customerNamenome do varejoretail namenombre del punto de venta
statuspor progressão (depois nome)by progression (then name)por progresión (luego nombre)
VisitsTabFilter 3
case
physical
digital
both
VisitFilterGroup 2
casevalue
defaultFilters"default"
commercialPillars"commercial_pillars"
FilterSelectionMode 2
casevalue
single"single"
multi"multi"
CommercialPillarName 8
casevalue
effectiveness"effectiveness"
primeCompliance"prime_compliance"
productivity"productivity"
capilarity"capilarity"
overdue"overdue"
positivationPartnership"positivation_partnership"
fatPartnership"fat_partnership"
unknown""
VisitKpiName 6
casevalue
targetOfTheDay"target_of_the_day"
targetOfTheDayNc"target_of_the_day_nc"
realizedOfTheDay"realized_of_the_day"
realizedOfTheDayNc"realized_of_the_day_nc"
realizedOfTheWeek"realized_of_the_week"
targetOfTheWeek"target_of_the_week"
AccountStatus 5
casevalue
active"active"
temporarilyDeactivated"temporarily_deactivated"
permanentDeactivationRequest"permanent_deactivation_request"
disablePermanent"disable_permanent"
unknown"unknown"
FinancialStatus 2
casevalue
compliant"compliant"
overdue"overdue"
VisitStatusUpdateOutcome 3 · resultado do check-in3 · check-in result3 · resultado del check-in
casenotanotenota
sentenviado ao backendsent to backendenviado al backend
queuedoffline · enfileirado no Dispatcheroffline · queued in the Dispatcheroffline · encolado en el Dispatcher
failedfalhou · status revertidofailed · status revertedfalló · estado revertido

Enums do detalheDetail enumsEnums del detalle AccountData.categoriesSold é tipado como CategoryForSale (enum de reference_data, definido fora de Visitas). Os enums de staff (ContactRole, B2bPortalStatus, ContactDesignation, LanguagePreference, ClerkProgramLayer, ClerkStatus…) pertencem ao Detalhe da visita. AccountData.categoriesSold is typed as CategoryForSale (a reference_data enum, defined outside Visits). The staff enums (ContactRole, B2bPortalStatus, ContactDesignation, LanguagePreference, ClerkProgramLayer, ClerkStatus…) belong to the Visit detail. AccountData.categoriesSold se tipa como CategoryForSale (enum de reference_data, definido fuera de Visitas). Los enums de staff (ContactRole, B2bPortalStatus, ContactDesignation, LanguagePreference, ClerkProgramLayer, ClerkStatus…) pertenecen al Detalle de la visita.

11

UseCases

Um dropdown por UseCase; dentro, cada método com assinatura, o que retorna e uso. Delegam ao repository (sem lógica extra) e seus providers são keepAlive.One dropdown per UseCase; inside, each method with its signature, what it returns and use. They delegate to the repository (no extra logic) and their providers are keepAlive.Un dropdown por UseCase; dentro, cada método con su firma, qué devuelve y uso. Delegan al repository (sin lógica extra) y sus providers son keepAlive.

GetVisitsUseCase 5 · a listathe listla lista
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
execute({source})Result<VisitsEntity?, Failure>Ponto de entrada da lista. Roteia por sourcerepository.getVisits. Chamado pelo VisitsNotifier.List entry point. Routes by sourcerepository.getVisits. Called by VisitsNotifier.Punto de entrada de la lista. Rutea por sourcerepository.getVisits. Llamado por VisitsNotifier.
getCached()Result<VisitsEntity?, Failure>Só cache; null vira Success(null). Usado no refresh(local).Cache only; null becomes Success(null). Used on refresh(local).Solo caché; null es Success(null). Usado en refresh(local).
getCachedLastSyncAt()DateTime?Timestamp da última sincronização. Alimenta o DataLoadInfo.Last-sync timestamp. Feeds DataLoadInfo.Timestamp de última sincronización. Alimenta DataLoadInfo.
getCachedBySfid({visitSfid})Result<VisitEntity, Failure>1 visita do cache (ausente → Error(CacheFailure)). Alimenta o Visit Detail e o VisitContext (§28 cat. A).1 visit from cache (missing → Error(CacheFailure)). Feeds Visit Detail and VisitContext (§28 cat. A).1 visita del caché (ausente → Error(CacheFailure)). Alimenta el Visit Detail y el VisitContext (§28 cat. A).
getCachedByAccountSfid({accountSfid})Result<VisitEntity?, Failure>Acha a visita de um varejo pelo accountSfid (cache). Usado por telas que partem do varejo.Finds a retail's visit by accountSfid (cache). Used by screens starting from the retail.Halla la visita de un punto de venta por accountSfid (caché). Usado por pantallas que parten del punto de venta.
SaveVisitStatusUseCase 1 · check-in1 · check-in1 · check-in
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
execute({visitSfid, status, startedAt?, endedAt?})Result<void, Failure>Persiste o status da visita só no cache local. Chamado pelo VisitContext (shared) no check-in; o envio remoto é separado (VisitUploadAPI).Persists the visit status to the local cache only. Called by VisitContext (shared) on check-in; the remote upload is separate (VisitUploadAPI).Persiste el estado de la visita solo en el caché local. Llamado por VisitContext (shared) en el check-in; el envío remoto es separado (VisitUploadAPI).

Check-in — UseCases do envioCheck-in — upload UseCasesCheck-in — UseCases del envío O envio remoto do check-in usa BuildVisitUploadDispatcherPayloadUseCase (monta o payload) + SubmitVisitUploadUseCase (despacha via Dispatcher). Ambos vivem no fluxo do VisitContext — detalhados em VisitUploadAPI. The remote check-in upload uses BuildVisitUploadDispatcherPayloadUseCase (builds the payload) + SubmitVisitUploadUseCase (dispatches via the Dispatcher). Both live in the VisitContext flow — detailed in VisitUploadAPI. El envío remoto del check-in usa BuildVisitUploadDispatcherPayloadUseCase (arma el payload) + SubmitVisitUploadUseCase (despacha vía Dispatcher). Ambos viven en el flujo del VisitContext — detallados en VisitUploadAPI.

12

Notifier & State

O VisitsNotifier (@riverpod, with AsyncGuard<VisitsState>) é o cérebro da tela. O build() observa o GetVisitsUseCase, escuta DataSyncType.visits (→ refresh(local) quando a sync em background grava) e retorna _load(). O State (VisitsState, Freezed) é a fonte única de verdade da page: guarda as visitas, os módulos habilitados (EMC) e todo o estado de cliente (aba, setor, busca, filtros, sort, paginação). Toda filtragem/ordenação/paginação é client-side, em getters do State.The VisitsNotifier (@riverpod, with AsyncGuard<VisitsState>) is the screen's brain. build() watches GetVisitsUseCase, listens to DataSyncType.visits (→ refresh(local) when background sync writes) and returns _load(). The State (VisitsState, Freezed) is the page's single source of truth: it holds the visits, the enabled modules (EMC) and all client state (tab, sector, search, filters, sort, pagination). All filtering/sorting/pagination is client-side, in State getters.El VisitsNotifier (@riverpod, with AsyncGuard<VisitsState>) es el cerebro de la pantalla. El build() observa GetVisitsUseCase, escucha DataSyncType.visits (→ refresh(local) cuando la sync en background graba) y retorna _load(). El State (VisitsState, Freezed) es la fuente única de verdad de la page: guarda las visitas, los módulos habilitados (EMC) y todo el estado de cliente (pestaña, sector, búsqueda, filtros, sort, paginación). Todo filtrado/orden/paginación es client-side, en getters del State.

MétodosMethodsMétodos

_load({source}) private

RetornoReturnRetorno Future<VisitsState>

Dono único da montagem do State: busca EMC config + visitas em paralelo e monta visits, lastSyncAt, visibleModules (só isVisible) e filterTabs. Chamado pelo build() e pelo refresh().Sole owner of building the State: fetches EMC config + visits in parallel and assembles visits, lastSyncAt, visibleModules (isVisible only) and filterTabs. Called by build() and refresh().Dueño único del armado del State: busca EMC config + visitas en paralelo y arma visits, lastSyncAt, visibleModules (solo isVisible) y filterTabs. Llamado por build() y refresh().

refresh({source = remote}) pull-to-refresh

RetornoReturnRetorno Future<void>

Recarrega via _load() (dentro de runGuarded) e preserva o estado de cliente: aba, setor, busca, filtros e sort. Não seta AsyncValue.loading (o pull-to-refresh tem indicador próprio).Reloads via _load() (inside runGuarded) and preserves client state: tab, sector, search, filters and sort. Doesn't set AsyncValue.loading (pull-to-refresh has its own indicator).Recarga vía _load() (dentro de runGuarded) y preserva el estado de cliente: pestaña, sector, búsqueda, filtros y sort. No setea AsyncValue.loading (pull-to-refresh tiene su propio indicador).

selectTab({tab})

RetornoReturnRetorno void

Fixa a aba (Presencial/Digital/Ambas). Reseta visibleCount.Sets the tab (Physical/Digital/Both). Resets visibleCount.Fija la pestaña (Presencial/Digital/Ambas). Resetea visibleCount.

selectSector({sector})

RetornoReturnRetorno void

Liga/desliga o setor (tocar no ativo desmarca). Reseta visibleCount.Toggles the sector (tapping the active one clears it). Resets visibleCount.Alterna el sector (tocar el activo lo desmarca). Resetea visibleCount.

setSearchQuery({query})

RetornoReturnRetorno void

Atualiza o termo de busca (nome/código/endereço). Reseta visibleCount; a filtragem acontece nos getters.Updates the search term (name/code/address). Resets visibleCount; filtering happens in the getters.Actualiza el término de búsqueda (nombre/código/dirección). Resetea visibleCount; el filtrado ocurre en los getters.

applyModalFilters({selectedFilters})

RetornoReturnRetorno void

Aplica os filtros do modal (Map<String, Set<String>> por código de filtro). Reseta visibleCount.Applies the modal filters (Map<String, Set<String>> by filter code). Resets visibleCount.Aplica los filtros del modal (Map<String, Set<String>> por código de filtro). Resetea visibleCount.

clearModalFilters()

RetornoReturnRetorno void

Limpa todos os filtros do modal. Reseta visibleCount.Clears all modal filters. Resets visibleCount.Limpia todos los filtros del modal. Resetea visibleCount.

setSort({sort})

RetornoReturnRetorno void

Define a ordenação (VisitSort). Reseta visibleCount.Sets the sort (VisitSort). Resets visibleCount.Define la ordenación (VisitSort). Resetea visibleCount.

revealInProgressVisit() visita ativaactive visitvisita activa

RetornoReturnRetorno void

Ajusta filtros (aba pelo tipo, sem setor/busca) para revelar a visita iniciada e amplia visibleCount até incluí-la. Acionado pelo botão flutuante "Em andamento".Adjusts filters (tab by type, no sector/search) to reveal the started visit and grows visibleCount until it's included. Triggered by the "In progress" floating button.Ajusta filtros (pestaña por tipo, sin sector/búsqueda) para revelar la visita iniciada y amplía visibleCount hasta incluirla. Accionado por el botón flotante "En curso".

loadMore()

RetornoReturnRetorno void

Incrementa visibleCount em 20 (paginação apenas visual — os dados já estão em memória).Increments visibleCount by 20 (visual-only pagination — data is already in memory).Incrementa visibleCount en 20 (paginación solo visual — los datos ya están en memoria).

State disponível para a PageState available to the PageState disponible para la Page

VisitsState campos + gettersfields + getterscampos + getters
campotipodefault
visitsList<VisitEntity>[]
lastSyncAtDateTime?null
visibleModulesList<ModuleConfig>[]
filterTabsList<FilterTabConfig>[]
selectedTabVisitsTabFilterphysical
selectedSectorVisitSector?null
searchQueryString""
selectedFiltersMap<String, Set<String>>{}
sortVisitSortrouteOrder
visibleCountint20

Getters: filteredVisits (filtro + sort), visibleVisits (recorte), totalFilteredVisits, hasMoreToLoad, inProgressVisit, sectorCount, getModule, showsSearchBar, showsSectorizer, showsFilter, showsListActions, hasActiveSort, hasActiveModalFilters, hasAnyActiveFilter, e os toggles de card via EMC showsCardRetailData/Activities/Daily/DailyNc/CommercialPillars/Insights/Sales + allowedSalesCategories/visibleSalesCategories. O filtro combina aba + setor + busca (multi-token em nome/comercial/endereço) + filtros do modal (cruzando os filterCode da visita).Getters: filteredVisits (filter + sort), visibleVisits (slice), totalFilteredVisits, hasMoreToLoad, inProgressVisit, sectorCount, getModule, showsSearchBar, showsSectorizer, showsFilter, showsListActions, hasActiveSort, hasActiveModalFilters, hasAnyActiveFilter, plus the EMC card toggles showsCardRetailData/Activities/Daily/DailyNc/CommercialPillars/Insights/Sales + allowedSalesCategories/visibleSalesCategories. Filtering combines tab + sector + search (multi-token over name/commercial/address) + modal filters (matching the visit's filterCode).Getters: filteredVisits, visibleVisits, totalFilteredVisits, hasMoreToLoad, inProgressVisit, sectorCount, getModule, showsSearchBar, showsSectorizer, showsFilter, showsListActions, hasActiveSort, hasActiveModalFilters, hasAnyActiveFilter, y los toggles de card vía EMC showsCardRetailData/Activities/Daily/DailyNc/CommercialPillars/Insights/Sales + allowedSalesCategories/visibleSalesCategories. El filtro combina pestaña + sector + búsqueda (multi-token en nombre/comercial/dirección) + filtros del modal (cruzando los filterCode de la visita).

13

Page e widgetsPage & widgetsPage y widgets

A VisitsPage (ConsumerWidget) observa o visitsProvider. Loading e erro são globais (visitsAsync.when); o conteúdo (_VisitsBody, um Stack) existe só no ramo data. O botão flutuante "Em andamento" fica sobreposto. Árvore de composição:VisitsPage (ConsumerWidget) watches visitsProvider. Loading and error are global (visitsAsync.when); content (_VisitsBody, a Stack) exists only in the data branch. The "In progress" floating button is overlaid. Composition tree:VisitsPage (ConsumerWidget) observa visitsProvider. Loading y error son globales (visitsAsync.when); el contenido (_VisitsBody, un Stack) existe solo en la rama data. El botón flotante "En curso" queda superpuesto. Árbol de composición:

  • VisitsPage
    • AppPageShell drawer · connectivity · search · notifications
      • CustomLoadingIndicator loading
      • FailureStateView error → invalidate
      • _VisitsBody · Stack data
        • CustomPullToRefresh → refresh()
          • VisitsHeaderWidget DataLoadInfo + título
          • VisitsTabBarWidget Presencial/Digital → selectTab
          • VisitsSectorizerWidget chips + contador → selectSector
          • CustomInput busca → setSearchQuery (se showsSearchBar)
          • VisitsActionsWidget ConectaSortButton · ConectaFilterButton
            • VisitsSortModalContent modal · VisitSort.selectable → setSort
            • VisitsFiltersModalContent modal · filterTabs (EMC) · single/multi → applyModalFilters / clearModalFilters
          • VisitsListSectionWidget
            • CustomEmptyState vazio
            • InfiniteScrollListView scroll → loadMore()
              • VisitCardWidget KeyedSubtree p/ visita ativa · onTap → ActiveVisitGuard → goToVisitDetail
                • VisitCardRetailDataWidget avatar (VisitAvatarWidget) + dados do varejo
                • VisitCardActivitiesWidget
                • VisitCardDailyWidget
                • VisitCardCommercialPillarsWidget
                • VisitCardBottomRowWidget
              • VisitInProgressModalContent modal (via ActiveVisitGuard) · "finalizar visita atual?" → endVisit()
            • PaginationCountIndicator X de Y
        • InProgressIndicatorWidget Positioned · flutuante · isActive = inProgressVisit != null → revealInProgressVisit + scroll

Cada seção do card aparece só quando o mercado a habilita (showsCard* via EMC). O ActiveVisitGuard intercepta o toque: se há outra visita iniciada, abre o VisitInProgressModalContent; ao confirmar, finaliza a atual em segundo plano (VisitContext.endVisit) e navega. Iniciar/finalizar a visita em si mora no Detalhe da visita.Each card section shows only when the market enables it (showsCard* via EMC). ActiveVisitGuard intercepts the tap: if another visit is started, it opens VisitInProgressModalContent; on confirm it finishes the current one in the background (VisitContext.endVisit) and navigates. Starting/finishing the visit itself lives in the Visit detail.Cada sección de la tarjeta aparece solo cuando el mercado la habilita (showsCard* vía EMC). El ActiveVisitGuard intercepta el toque: si hay otra visita iniciada, abre el VisitInProgressModalContent; al confirmar finaliza la actual en segundo plano (VisitContext.endVisit) y navega. Iniciar/finalizar la visita en sí vive en el Detalle de la visita.

Notas por mercadoMarket notesNotas por mercado

Visitas é dirigido por configuração de mercado (End Market Configuration): a presença do visitsConfig habilita a tela, e cada módulo/aba de filtro/seção de card é declarado por mercado. Está habilitado em três mercados — os mesmos do envio de check-in (VisitUploadAPI, DispatcherType.visit.enabledMarkets):Visits is driven by market configuration (End Market Configuration): the presence of visitsConfig enables the screen, and each module/filter tab/card section is declared per market. It's enabled in three markets — the same as the check-in upload (VisitUploadAPI, DispatcherType.visit.enabledMarkets):Visitas se rige por configuración de mercado (End Market Configuration): la presencia del visitsConfig habilita la pantalla, y cada módulo/pestaña de filtro/sección de tarjeta se declara por mercado. Está habilitado en tres mercados — los mismos del envío de check-in (VisitUploadAPI, DispatcherType.visit.enabledMarkets):

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

Base estruturalStructural baseBase estructural ZA é a base do EMC: BR/CL recebem só as features que têm. Módulos exclusivos de ZA (ex.: metas mensais no detalhe) não entram em BR/CL — mas a lista em si é equivalente nos três. ZA is the EMC base: BR/CL only get the features they have. ZA-exclusive modules (e.g. monthly targets in the detail) don't reach BR/CL — but the list itself is equivalent across all three. ZA es la base del EMC: BR/CL reciben solo las features que tienen. Módulos exclusivos de ZA (ej.: metas mensuales en el detalle) no llegan a BR/CL — pero la lista en sí es equivalente en los tres.

BRCL

Setores e filtrosSectors & filtersSectores y filtros As abas de filtro (status do varejo, situação financeira, tipo de visita, visita planejada) e os setores são declarados por mercado no visitsConfig — o conteúdo pode variar entre BR e CL. Filter tabs (retail status, financial status, visit type, planned visit) and sectors are declared per market in visitsConfig — the content can differ between BR and CL. Las pestañas de filtro (estado del punto de venta, situación financiera, tipo de visita, visita planificada) y los sectores se declaran por mercado en visitsConfig — el contenido puede variar entre BR y CL.

AR · PY · PE Existem como mercados do app, mas não têm visitsConfig no End Market Configuration — a tela de Visitas não é renderizada (config PANGEA mínima). Também não estão em DispatcherType.visit.enabledMarkets. They exist as app markets, but have no visitsConfig in End Market Configuration — the Visits screen isn't rendered (minimal PANGEA config). They're also not in DispatcherType.visit.enabledMarkets. Existen como mercados de la app, pero no tienen visitsConfig en End Market Configuration — la pantalla de Visitas no se renderiza (config PANGEA mínima). Tampoco están en DispatcherType.visit.enabledMarkets.