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 · Call TaskFeature · Call TaskFeature · Call Task

Call Task

As tarefas que o representante de vendas resolve dentro de uma visita: cada call task pede uma ação (verificar ruptura de produto, criar pedido, checar merchandising, responder pesquisa) e é concluída ali. Tarefas de ruptura (OOS) pedem uma resposta por produto (disponível / em falta); qualquer tarefa pode ser reagendada. Duas telas: o módulo na Detalhe da visita (lista com checkbox) e o Call Task Detail. The tasks the sales rep resolves inside a visit: each call task asks for an action (check product out-of-stock, create an order, check merchandising, answer a survey) and is completed right there. Out-of-stock (OOS) tasks ask for a per-product answer (available / missing); any task can be rescheduled. Two screens: the module in the Visit detail (checkbox list) and the Call Task Detail. Las tareas que el representante de ventas resuelve dentro de una visita: cada call task pide una acción (verificar quiebre de producto, crear pedido, revisar merchandising, responder encuesta) y se completa ahí mismo. Las tareas de quiebre (OOS) piden una respuesta por producto (disponible / faltante); cualquier tarea puede reprogramarse. Dos pantallas: el módulo en el Detalle de la visita (lista con checkbox) y el Call Task Detail.

PúblicoAudiencePúblico
Representante · QA · Suporte · DevRep · QA · Support · DevRepresentante · QA · Soporte · Dev
Onde ficaWhereDónde
Detalhe da visita → módulo Call TasksVisit detail → Call Tasks moduleDetalle de la visita → módulo Call Tasks
AtualizadoUpdatedActualizado
12/08/20262026-08-12
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

Uma Call Task é uma tarefa vinculada a uma visita — pense num "recado" que o representante precisa executar naquele varejo durante a visita. Cada tarefa tem uma categoria (ruptura, criação de pedido, merchandising, pesquisa…), um título, uma mensagem e um prazo. O representante conclui a tarefa e, quando é uma tarefa de ruptura (OOS), responde produto a produto se está disponível ou em falta. A Call Task is a task tied to a visit — think of it as a "note" the rep must execute at that retail during the visit. Each task has a category (out-of-stock, order creation, merchandising, survey…), a title, a message and a date. The rep completes the task and, when it's an out-of-stock (OOS) task, answers product by product whether it's available or missing. Una Call Task es una tarea vinculada a una visita — piénsala como un "recado" que el representante debe ejecutar en ese punto de venta durante la visita. Cada tarea tiene una categoría (quiebre, creación de pedido, merchandising, encuesta…), un título, un mensaje y una fecha. El representante completa la tarea y, cuando es una tarea de quiebre (OOS), responde producto por producto si está disponible o faltante.

O que preciso fazer?What must I do?¿Qué debo hacer?

Cada tarefa mostra a categoria, o título e a mensagem do que executar na visita.Each task shows the category, the title and the message of what to do on the visit.Cada tarea muestra la categoría, el título y el mensaje de qué ejecutar en la visita.

Está resolvida?Is it done?¿Está resuelta?

Um checkbox conclui a tarefa; tarefas OOS pedem uma resposta por produto antes.A checkbox completes the task; OOS tasks ask for a per-product answer first.Un checkbox completa la tarea; las OOS piden una respuesta por producto antes.

Não dá hoje?Not today?¿No hoy?

A tarefa pode ser reagendada para uma data futura (até 90 dias).The task can be rescheduled to a future date (up to 90 days).La tarea puede reprogramarse a una fecha futura (hasta 90 días).

Call Task ≠ Manager TasksCall Task ≠ Manager TasksCall Task ≠ Manager Tasks Não confunda com as Manager Tasks (antes "Tarefas GTV"): aquelas vêm do gerente e abrem numa tela cheia própria. A Call Task vive dentro da visita, é ligada por visitSfid e só aparece com a visita iniciada. Don't confuse it with Manager Tasks (formerly "GTV Tasks"): those come from the manager and open in their own full screen. The Call Task lives inside the visit, is linked by visitSfid and only shows once the visit has started. No la confundas con las Manager Tasks (antes "Tareas GTV"): aquellas vienen del gerente y abren en su propia pantalla completa. La Call Task vive dentro de la visita, se vincula por visitSfid y solo aparece con la visita iniciada.

02

Como acessarHow to openCómo acceder

  1. Inicie a visitaStart the visitInicie la visitaAs Call Tasks só aparecem (e só podem ser tocadas/concluídas) com a visita iniciada — um guarda de check-in protege as duas ações.Call Tasks only show up (and can only be tapped/completed) once the visit has started — a check-in guard protects both actions.Las Call Tasks solo aparecen (y solo pueden tocarse/completarse) con la visita iniciada — un guardia de check-in protege ambas acciones.
  2. Abra o Detalhe da visitaOpen the Visit detailAbra el Detalle de la visitaRole até o módulo Call Tasks: uma lista de linhas, cada uma com ícone da categoria, título, tag de status e um checkbox.Scroll to the Call Tasks module: a list of rows, each with the category icon, title, status tag and a checkbox.Desplácese hasta el módulo Call Tasks: una lista de filas, cada una con el ícono de la categoría, título, etiqueta de estado y un checkbox.
  3. Toque numa tarefaTap a taskToque una tareaAbre o Call Task Detail — a tela cheia com a mensagem, os produtos OOS (se houver) e os botões de ação.Opens the Call Task Detail — the full screen with the message, the OOS products (if any) and the action buttons.Abre el Call Task Detail — la pantalla completa con el mensaje, los productos OOS (si hay) y los botones de acción.
03

Estrutura da telaScreen structureEstructura de la pantalla

A feature tem duas superfícies: o módulo dentro do Detalhe da visita e a tela de detalhe.The feature has two surfaces: the module inside the Visit detail and the detail screen.La feature tiene dos superficies: el módulo dentro del Detalle de la visita y la pantalla de detalle.

Módulo no Detalhe da visitaModule in the Visit detailMódulo en el Detalle de la visita

TítuloTitleTítulo
"Call Tasks". O módulo some por completo se o mercado não o habilita."Call Tasks". The whole module disappears if the market doesn't enable it."Call Tasks". El módulo entero desaparece si el mercado no lo habilita.
Linha por tarefaRow per taskFila por tarea
Ícone da categoria, título (até 2 linhas), tag de status colorida e um checkbox à direita.Category icon, title (up to 2 lines), colored status tag and a checkbox on the right.Ícono de la categoría, título (hasta 2 líneas), etiqueta de estado y un checkbox a la derecha.
Lista vaziaEmpty listLista vacía
Sem tarefas, mostra um estado vazio ("nenhuma call task").With no tasks, it shows an empty state ("no call tasks").Sin tareas, muestra un estado vacío ("ninguna call task").

Call Task Detail

CabeçalhoHeaderEncabezado
Data da última sincronização e o título "Call Task".Last sync date and the "Call Task" title.Fecha de última sincronización y el título "Call Task".
Card da tarefaTask cardTarjeta de la tarea
Ícone + nome da categoria, tag de status, título e a mensagem completa.Category icon + name, status tag, title and the full message.Ícono + nombre de la categoría, etiqueta de estado, título y el mensaje completo.
Seção OOSOOS sectionSección OOS
Só em tarefas de ruptura: um card por produto com dois botões (Disponível / Em falta) e um histórico de checagens anteriores.Only on out-of-stock tasks: one card per product with two buttons (Available / Out of stock) and a history of previous checks.Solo en tareas de quiebre: una tarjeta por producto con dos botones (Disponible / Faltante) y un historial de verificaciones anteriores.
AçõesActionsAcciones
Botão Concluir (preenchido) e botão Reagendar (contornado).Complete button (filled) and Reschedule button (outlined).Botón Completar (relleno) y botón Reprogramar (contorneado).
04

StatusStatusEstado

O status é derivado de um único sinal — se a tarefa foi respondida (isCompleted) — e aparece numa tag colorida:The status is derived from a single signal — whether the task was answered (isCompleted) — and shows in a colored tag:El estado se deriva de una única señal — si la tarea fue respondida (isCompleted) — y aparece en una etiqueta de color:

Pendente (laranja) · ainda não concluídaPending (orange) · not yet completedPendiente (naranja) · aún no completada Concluída (verde) · respondidaCompleted (green) · answeredCompletada (verde) · respondida

Concluída trava a telaCompleted locks the screenCompletada bloquea la pantalla Uma tarefa concluída abre o detalhe em modo leitura: o botão vira "Concluída", os botões de resposta OOS ficam desabilitados e o checkbox da lista aparece verde e marcado. A completed task opens the detail in read mode: the button turns "Completed", the OOS answer buttons are disabled and the list checkbox shows green and checked. Una tarea completada abre el detalle en modo lectura: el botón pasa a "Completada", los botones de respuesta OOS quedan deshabilitados y el checkbox de la lista aparece verde y marcado.

05

Ações: concluir, OOS, reagendarActions: complete, OOS, rescheduleAcciones: completar, OOS, reprogramar

ConcluirCompleteCompletar
Marca a tarefa como respondida. Pode ser feito pelo checkbox da lista (no Detalhe da visita) ou pelo botão Concluir na tela de detalhe. Numa tarefa OOS, só habilita quando todos os produtos foram respondidos.Marks the task as answered. Can be done via the list checkbox (in the Visit detail) or the Complete button on the detail screen. On an OOS task, it only enables once every product has been answered.Marca la tarea como respondida. Puede hacerse con el checkbox de la lista (en el Detalle de la visita) o con el botón Completar en la pantalla de detalle. En una tarea OOS, solo se habilita cuando todos los productos fueron respondidos.
Responder OOSAnswer OOSResponder OOS
Em tarefas de ruptura, cada produto tem dois botões: Disponível (verde) e Em falta (vermelho). A resposta é guardada por produto e enviada ao concluir.On out-of-stock tasks, each product has two buttons: Available (green) and Out of stock (red). The answer is kept per product and sent on completion.En tareas de quiebre, cada producto tiene dos botones: Disponible (verde) y Faltante (rojo). La respuesta se guarda por producto y se envía al completar.
ReagendarRescheduleReprogramar
Abre um calendário (de amanhã até +90 dias) para escolher a nova data. Disponível enquanto a tarefa não está concluída.Opens a calendar (tomorrow to +90 days) to pick the new date. Available while the task isn't completed.Abre un calendario (mañana hasta +90 días) para elegir la nueva fecha. Disponible mientras la tarea no esté completada.

Feedback do envioSubmit feedbackFeedback del envío Concluir e reagendar mostram um aviso verde de sucesso ou um aviso vermelho de erro. Concluir dispara a transação AnswerTaskAPI; reagendar dispara ReschedulingCallTaskAPI — as duas vão pelo Dispatcher. Complete and reschedule show a green success notice or a red error notice. Complete fires the AnswerTaskAPI transaction; reschedule fires ReschedulingCallTaskAPI — both go through the Dispatcher. Completar y reprogramar muestran un aviso verde de éxito o un aviso rojo de error. Completar dispara la transacción AnswerTaskAPI; reprogramar dispara ReschedulingCallTaskAPI — ambas van por el Dispatcher.

06

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

Clean Architecture + Riverpod + Freezed + gRPC + ObjectBox. Há dois fluxos distintos: a leitura (cache-first, com fallback remoto via getCallTasks) e a escrita (concluir e reagendar, cada uma via Dispatcher + uma mutação local no cache).Clean Architecture + Riverpod + Freezed + gRPC + ObjectBox. There are two distinct flows: the read (cache-first, with remote fallback via getCallTasks) and the write (complete and reschedule, each via the Dispatcher + a local cache mutation).Clean Architecture + Riverpod + Freezed + gRPC + ObjectBox. Hay dos flujos distintos: la lectura (cache-first, con fallback remoto vía getCallTasks) y la escritura (completar y reprogramar, cada una vía Dispatcher + una mutación local en el caché).

Leitura · cache-firstRead · cache-firstLectura · cache-first

A fonte default é local: o repository lê do ObjectBox; sem cache/offline, tenta o remoto (getCallTasks) e grava write-through. O Detalhe da visita filtra por visitSfid in-memory (getCallTasksForVisit); o Call Task Detail carrega o container e acha o item por id.The default source is local: the repository reads from ObjectBox; with no cache/offline it tries remote (getCallTasks) and writes through. The Visit detail filters by visitSfid in-memory (getCallTasksForVisit); the Call Task Detail loads the container and finds the item by id.La fuente por defecto es local: el repository lee de ObjectBox; sin caché/offline intenta el remoto (getCallTasks) y graba write-through. El Detalle de la visita filtra por visitSfid in-memory (getCallTasksForVisit); el Call Task Detail carga el container y encuentra el ítem por id.

  • CallTasksReplygRPC proto
    • toCallTasksDTOCallTasksDTODTO · Freezed
      • toDomainCallTasksEntitydomain
        • toModel · write-throughCallTasksModelObjectBox · cache
          • toDomainCallTaskRepositoryImplgetCallTasks / forVisit
            • executeGetCallTasks(ForVisit)UseCase
              • watchCallTaskDetailNotifier · VisitDetailNotifier
                • → UICallTaskDetailPage · VisitDetailCallTaskWidget

Escrita · concluir e reagendar via DispatcherWrite · complete and reschedule via DispatcherEscritura · completar y reprogramar vía Dispatcher

Concluir monta o AnswerCallTaskDispatcherPayloadInput (com entities cruas + submittedAt), o builder produz o envelope answerTask e o submitter despacha; após o ack, o repository marca a tarefa como respondida no cache local. Reagendar é análogo com reschedulingCallTask.Complete assembles the AnswerCallTaskDispatcherPayloadInput (raw entities + submittedAt), the builder produces the answerTask envelope and the submitter dispatches; after the ack, the repository marks the task answered in the local cache. Reschedule is analogous with reschedulingCallTask.Completar arma el AnswerCallTaskDispatcherPayloadInput (entities crudas + submittedAt), el builder produce el sobre answerTask y el submitter despacha; tras el ack, el repository marca la tarea como respondida en el caché local. Reprogramar es análogo con reschedulingCallTask.

  • CallTaskDetailActionsWidgetUI
    • complete / rescheduleCallTaskDetailNotifier
      • build(input)Build{Answer|Reschedule}CallTaskDispatcherPayloadUseCase→ DispatcherEnvelope
        • submit(envelope)Submit{Answer|Reschedule}CallTaskUseCase
          • dispatchDispatcherOrchestratorgRPC dispatcher
            • on ack → cacheMark{...}Answered / rescheduleLocallyObjectBox

Notas de implementaçãoImplementation notesNotas de implementación O CallTaskDetailNotifier é family por callTaskId. As mutações do repository (markCallTaskAnswered, rescheduleCallTaskLocally) são só de cache e sempre retornam Success — o dado real vai pelo Dispatcher. O locationHierarchySfid do remoto é resolvido no repository via currentResourceProvider (§25), nunca no notifier. CallTaskDetailNotifier is family by callTaskId. The repository mutations (markCallTaskAnswered, rescheduleCallTaskLocally) are cache-only and always return Success — the real write goes via the Dispatcher. The remote locationHierarchySfid is resolved in the repository via currentResourceProvider (§25), never in the notifier. CallTaskDetailNotifier es family por callTaskId. Las mutaciones del repository (markCallTaskAnswered, rescheduleCallTaskLocally) son solo de caché y siempre retornan Success — la escritura real va vía Dispatcher. El locationHierarchySfid del remoto se resuelve en el repository vía currentResourceProvider (§25), nunca en el notifier.

07

Modelo de dadosData modelModelo de datos

O dado existe em quatro representaçõesProto (wire gRPC) → DTO (Freezed) → Model (ObjectBox) → Entity (domínio) — ligadas por mappers, com cache write-through. Os nomes se mantêm; muda pouco (enums tipados, parse de datas, relações e o rename de id no Model).The data exists in four representationsProto (gRPC wire) → DTO (Freezed) → Model (ObjectBox) → Entity (domain) — linked by mappers, with cache write-through. Names stay the same; little changes (typed enums, date parsing, relations and the id rename in the Model).El dato existe en cuatro representacionesProto (wire gRPC) → DTO (Freezed) → Model (ObjectBox) → Entity (dominio) — unidas por mappers, con cache write-through. Los nombres se mantienen; cambia poco (enums tipados, parse de fechas, relaciones y el rename de id en el Model).

A lista chega num container CallTasks (callTasks[] + lastSyncAt gerado no mapper); cada item é uma CallTask de 11 campos, com CallTaskProduct (linhas OOS) e CallTaskOosHistory (histórico) aninhados. Os enums só existem tipados na Entity (CallTaskCode, CallTaskCategory); em Proto/DTO/Model trafegam como String. A seguir, na ordem: o proto, as estruturas de dados campo-a-campo por camada, e os mappers.The list arrives in a CallTasks container (callTasks[] + a mapper-generated lastSyncAt); each item is an 11-field CallTask, with nested CallTaskProduct (OOS rows) and CallTaskOosHistory (history). Enums are only typed in the Entity (CallTaskCode, CallTaskCategory); in Proto/DTO/Model they travel as String. Next, in order: the proto, the field-by-field data structures per layer, and the mappers.La lista llega en un container CallTasks (callTasks[] + un lastSyncAt generado en el mapper); cada ítem es una CallTask de 11 campos, con CallTaskProduct (filas OOS) y CallTaskOosHistory (historial) anidados. Los enums solo están tipados en la Entity (CallTaskCode, CallTaskCategory); en Proto/DTO/Model viajan como String. A continuación, en orden: el proto, las estructuras de datos campo a campo por capa, y los mappers.

Proto

TasksConectaRep.proto · proto3 · package mn.bat.conectarep.streambridge. O serviço TasksConectaRepService tem o método de Call Task (além do getTasksManager das Manager Tasks):The TasksConectaRepService service has the Call Task method (besides getTasksManager for Manager Tasks):El servicio TasksConectaRepService tiene el método de Call Task (además de getTasksManager de Manager Tasks):

getCallTasksunary
MétodoMethodMétodo

rpc getCallTasks(CallTasksRequest) returns (CallTasksReply)

path /mn.bat.conectarep.streambridge.TasksConectaRepService/getCallTasks

Request · CallTasksRequest
locationHierarchySfid
string · #1 · hierarquia do representante de vendassales rep hierarchyjerarquía del representante de ventas
dateReference
string · #2 · optional
lastModifiedDate
string · #3 · optional

Não há visitSfid no request — a busca é por hierarquia; o filtro por visita acontece no app.There's no visitSfid in the request — the fetch is by hierarchy; the per-visit filter happens app-side.No hay visitSfid en el request — la búsqueda es por jerarquía; el filtro por visita ocurre en la app.

Reply · CallTasksReply

repeated CallTask callTasksa lista de call tasks. Os 11 campos de cada CallTask estão nas Estruturas de dados abaixo.the list of call tasks. The 11 fields of each CallTask are in Data structures below.la lista de call tasks. Los 11 campos de cada CallTask están en Estructuras de datos abajo.

Estruturas de dadosData structuresEstructuras de datos

Um dropdown por estrutura, aninhados pela hierarquia. Cada tabela tem uma coluna por camada — Proto · DTO · Model · Entity; o texto azul marca onde o tipo (ou o nome) primeiro muda (rename de id e parse de data no Model, relação ToMany no Model, enum na Entity). ¹ = optional no proto.One dropdown per structure, nested by hierarchy. Each table has one column per layer — Proto · DTO · Model · Entity; the blue text marks where the type (or name) first changes (id rename and date parse in the Model, ToMany relation in the Model, enum in the Entity). ¹ = optional in the proto.Un dropdown por estructura, anidados por jerarquía. Cada tabla tiene una columna por capa — Proto · DTO · Model · Entity; el texto azul marca dónde primero cambia el tipo (o el nombre) (rename de id y parse de fecha en el Model, relación ToMany en el Model, enum en la Entity). ¹ = optional en el proto.

  • CallTasks container 2 camposfieldscampos
    CampoProtoDTOModelEntity
    callTasksrepeated CallTaskList<…DTO>ToMany<…Model>List<…Entity>
    lastSyncAtDateTime?DateTimeDateTime?
    • CallTask CallTasks.callTasks[] 11 camposfieldscampos
      CampoProtoDTOModelEntity
      idstringStringcallTaskIdString
      callTaskCodestringStringStringCallTaskCode
      visitSfidstringStringStringString
      categorystringStringStringCallTaskCategory
      titlestringStringStringString
      messagestringStringStringString
      urlstringStringStringString
      originalDatestringStringDateTime?DateTime?
      answerDatestringStringDateTime?DateTime?
      isCompletedboolboolboolbool
      productsrepeated CallTaskProductList<…DTO>ToMany<…Model>List<…Entity>
    • CallTaskProduct CallTask.products[] 6 camposfieldscampos
      CampoProtoDTOModelEntity
      idstringStringproductIdString
      productSfidstringStringStringString
      productNamestringStringStringString
      answerstringStringStringString
      dateReferencestringStringDateTime?DateTime?
      historyrepeated CallTaskOosHistoryList<…DTO>ToMany<…Model>List<…Entity>
    • CallTaskOosHistory CallTaskProduct.history[] 2 camposfieldscampos
      CampoProtoDTOModelEntity
      datestringStringDateTime?DateTime?
      statusint32intintint

CallTaskProduct.answer = "1" disponível / "0" em falta / "" sem resposta; CallTaskOosHistory.status = 1 disponível / 0 em falta (int, não enum).CallTaskProduct.answer = "1" available / "0" out of stock / "" unanswered; CallTaskOosHistory.status = 1 available / 0 out of stock (int, not enum).CallTaskProduct.answer = "1" disponible / "0" faltante / "" sin respuesta; CallTaskOosHistory.status = 1 disponible / 0 faltante (int, no enum).

Mappers

Todas as conversões são extension, em dois arquivos (call_tasks_mapper.dart container + call_task_mapper.dart item), nas 5 direções por tipo.All conversions are extensions, in two files (call_tasks_mapper.dart container + call_task_mapper.dart item), in 5 directions per type.Todas las conversiones son extension, en dos archivos (call_tasks_mapper.dart container + call_task_mapper.dart ítem), en 5 direcciones por tipo.

DireçãoDirectionDirecciónMétodoMethodMétodo
JSON → DTOstatic fromMap(Map) (carimba lastSyncAt com DateTimeUtils.now())(stamps lastSyncAt with DateTimeUtils.now())(sella lastSyncAt con DateTimeUtils.now())
Proto → DTOtoCallTasksDTO() / toDTO() (carimba lastSyncAt)(stamps lastSyncAt)(sella lastSyncAt)
DTO → EntitytoDomain() (resolve enums fromValue + datas DateTimeUtils.tryParse)(resolves enums fromValue + dates DateTimeUtils.tryParse)(resuelve enums fromValue + fechas DateTimeUtils.tryParse)
Entity → ModeltoModel() (enums → .value; idcallTaskId/productId; guarda StateError se lastSyncAt null)(enums → .value; idcallTaskId/productId; guards StateError if lastSyncAt null)(enums → .value; idcallTaskId/productId; guarda StateError si lastSyncAt null)
Model → EntitytoDomain() (callTaskId/productIdid; enums fromValue)(callTaskId/productIdid; enums fromValue)(callTaskId/productIdid; enums fromValue)

Os únicos deltasThe only deltasLos únicos deltas

  • enums tipados só na Entity (callTaskCodeCallTaskCode, categoryCallTaskCategory; String nas outras)enums typed only in the Entity (callTaskCodeCallTaskCode, categoryCallTaskCategory; String elsewhere)enums tipados solo en la Entity (callTaskCodeCallTaskCode, categoryCallTaskCategory; String en las demás)
  • originalDate · answerDate · dateReference · date StringDateTime? (no Model, via DateTimeUtils.tryParse)StringDateTime? (in the Model, via DateTimeUtils.tryParse)StringDateTime? (en el Model, vía DateTimeUtils.tryParse)
  • rename de id: callTaskId (CallTask) / productId (CallTaskProduct) no Model — ObjectBox reserva id como @Id intid rename: callTaskId (CallTask) / productId (CallTaskProduct) in the Model — ObjectBox reserves id as @Id intrename de id: callTaskId (CallTask) / productId (CallTaskProduct) en el Model — ObjectBox reserva id como @Id int
  • relações (callTasks, products, history) viram ToMany no Modelrelations (callTasks, products, history) become ToMany in the Modelrelaciones (callTasks, products, history) pasan a ToMany en el Model
  • lastSyncAt gerado no mapper de fronteira (JSON/Proto) com DateTimeUtils.now() — não existe no protogenerated in the boundary mapper (JSON/Proto) with DateTimeUtils.now() — absent from the protogenerado en el mapper de frontera (JSON/Proto) con DateTimeUtils.now() — no existe en el proto
08

Repository

O CallTaskRepositoryImpl (provider keepAlive) injeta os 3 datasources + connectivityService + useMock + ref. A leitura é cache-first; as duas mutações são só de cache (o backend recebe pelo Dispatcher).CallTaskRepositoryImpl (keepAlive provider) injects the 3 datasources + connectivityService + useMock + ref. The read is cache-first; both mutations are cache-only (the backend gets them via the Dispatcher).El CallTaskRepositoryImpl (provider keepAlive) inyecta los 3 datasources + connectivityService + useMock + ref. La lectura es cache-first; las dos mutaciones son solo de caché (el backend las recibe vía Dispatcher).

getCallTasks({source = local}) mock / local / remote

RetornaReturnsDevuelve Future<Result<CallTasksEntity, Failure>>

Ponto de entrada da leitura. Decisão de fonte:Read entry point. Source decision:Punto de entrada de la lectura. Decisión de fuente:

  • getCallTasks
    • _useMock || source == mock → _fetchFromMock() + cache write
    • source == local || !isConnected → _fetchFromCacheOrFail() · default
    • senãoelsesi no → _fetchFromRemoteWithFallback()

_fetchFromRemoteWithFallback resolve resource via currentResourceProvider (§25); null → cai pro cache. Chama remote.getCallTasks(locationHierarchySfid: resource.locationHierarchyId), grava no cache; erro → fallback pro cache. _fetchFromCacheOrFail: cache ausente → Error(NetworkFailure)._fetchFromRemoteWithFallback resolves resource via currentResourceProvider (§25); null → falls to cache. Calls remote.getCallTasks(locationHierarchySfid: resource.locationHierarchyId), writes cache; error → cache fallback. _fetchFromCacheOrFail: missing cache → Error(NetworkFailure)._fetchFromRemoteWithFallback resuelve resource vía currentResourceProvider (§25); null → cae al caché. Llama remote.getCallTasks(locationHierarchySfid: resource.locationHierarchyId), graba caché; error → fallback al caché. _fetchFromCacheOrFail: caché ausente → Error(NetworkFailure).

getCallTasksForVisit({visitSfid}) filtro por visitafilter by visitfiltro por visita

RetornaReturnsDevuelve Future<Result<List<CallTaskEntity>, Failure>>

visitSfid vazio → Success([]); senão chama getCallTasks() (local) e filtra in-memory por callTask.visitSfid == visitSfid. Não dispara remoto próprio. Usado pelo Detalhe da visita.Empty visitSfidSuccess([]); otherwise calls getCallTasks() (local) and filters in-memory by callTask.visitSfid == visitSfid. No remote of its own. Used by the Visit detail.visitSfid vacío → Success([]); si no llama getCallTasks() (local) y filtra in-memory por callTask.visitSfid == visitSfid. Sin remoto propio. Usado por el Detalle de la visita.

getCachedCallTasksLastSyncAt() local

RetornaReturnsDevuelve Future<DateTime?>

Delega a local.getCallTasksLastSyncAt(); erro → log + null.Delegates to local.getCallTasksLastSyncAt(); error → log + null.Delega a local.getCallTasksLastSyncAt(); error → log + null.

markCallTaskAnswered({callTaskId}) só cachecache-onlysolo caché

RetornaReturnsDevuelve Future<Result<void, Failure>>

Chama local.updateCallTaskCompleted(callTaskId:) (marca isCompleted=true, answerDate=now). try/catch só loga; sempre retorna Success(null) — o envio real vai pelo Dispatcher.Calls local.updateCallTaskCompleted(callTaskId:) (sets isCompleted=true, answerDate=now). try/catch only logs; always returns Success(null) — the real submit goes via the Dispatcher.Llama local.updateCallTaskCompleted(callTaskId:) (marca isCompleted=true, answerDate=now). try/catch solo loguea; siempre retorna Success(null) — el envío real va vía Dispatcher.

rescheduleCallTaskLocally({callTaskId, newDate}) só cachecache-onlysolo caché

RetornaReturnsDevuelve Future<Result<void, Failure>>

Chama local.updateCallTaskOriginalDate(callTaskId:, newDate:). try/catch só loga; sempre retorna Success(null) — o reagendamento real vai pelo Dispatcher.Calls local.updateCallTaskOriginalDate(callTaskId:, newDate:). try/catch only logs; always returns Success(null) — the real reschedule goes via the Dispatcher.Llama local.updateCallTaskOriginalDate(callTaskId:, newDate:). try/catch solo loguea; siempre retorna Success(null) — la reprogramación real va vía Dispatcher.

09

Datasources

Três datasources: Mock (assets por mercado), Local (ObjectBox, também dono das mutações de cache) e Remote (gRPC).Three datasources: Mock (per-market assets), Local (ObjectBox, also owner of the cache mutations) and Remote (gRPC).Tres datasources: Mock (assets por mercado), Local (ObjectBox, también dueño de las mutaciones de caché) y Remote (gRPC).

Remote CallTaskRemoteDataSource gRPC

Envio / fluxo: TasksConectaRepServiceClient. Erro: GrpcErrorGrpcExceptionHandler.handle; outros → ServerException.Sends / flow: TasksConectaRepServiceClient. Error: GrpcErrorGrpcExceptionHandler.handle; others → ServerException.Envío / flujo: TasksConectaRepServiceClient. Error: GrpcErrorGrpcExceptionHandler.handle; otros → ServerException.

getCallTasks({locationHierarchySfid, dateReference?, lastModifiedDate?})
RetornoReturnRetorno
Future<CallTasksEntity>
EnvioSendsEnvío
CallTasksRequest (locationHierarchySfid + dateReference? + lastModifiedDate? quando não-vazios)
FluxoFlowFlujo
stub getCallTasks; reply.toCallTasksDTO().toDomain().stub getCallTasks; reply.toCallTasksDTO().toDomain().stub getCallTasks; reply.toCallTasksDTO().toDomain().
Local CallTaskLocalDataSource ObjectBox

CRUD sobre 4 boxes (CallTasksModel + CallTaskModel + CallTaskProductModel + CallTaskOosHistoryModel). Erros viram CacheException.CRUD over 4 boxes (CallTasksModel + CallTaskModel + CallTaskProductModel + CallTaskOosHistoryModel). Errors become CacheException.CRUD sobre 4 boxes (CallTasksModel + CallTaskModel + CallTaskProductModel + CallTaskOosHistoryModel). Errores viran CacheException.

getCachedCallTasks()
RetornoReturnRetorno
CallTasksEntity?
ComportamentoBehaviorComportamiento
primeira linha do box → toDomain(); null se vazio.first row of the box → toDomain(); null if empty.primera fila del box → toDomain(); null si vacío.
getCallTasksLastSyncAt()
RetornoReturnRetorno
DateTime?
ComportamentoBehaviorComportamiento
só o timestamp da primeira linha.just the first row's timestamp.solo el timestamp de la primera fila.
saveCallTasks({entity})
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
clearCallTasks() + put(entity.toModel()) (substitui tudo).clearCallTasks() + put(entity.toModel()) (replaces all).clearCallTasks() + put(entity.toModel()) (reemplaza todo).
updateCallTaskCompleted({callTaskId})
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
acha por callTaskId, seta isCompleted=true + answerDate=DateTimeUtils.now(), put.finds by callTaskId, sets isCompleted=true + answerDate=DateTimeUtils.now(), put.encuentra por callTaskId, setea isCompleted=true + answerDate=DateTimeUtils.now(), put.
updateCallTaskOriginalDate({callTaskId, newDate})
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
acha por callTaskId, seta originalDate=newDate, put.finds by callTaskId, sets originalDate=newDate, put.encuentra por callTaskId, setea originalDate=newDate, put.
mergeAdhocCallTasks({incoming, refreshedVisitSfids}) merge aditivo · Visita Adhocadditive merge · Adhoc Visitmerge aditivo · Visita Adhoc
RetornoReturnRetorno
void
AssinaturaSignatureFirma
mergeAdhocCallTasks({required List<CallTaskEntity> incoming, required Set<String> refreshedVisitSfids})
ComportamentoBehaviorComportamiento
Caminho de escrita read-modify-write chamado pela Visita Adhoc (não pelo Repository de Call Task): lê o cache via getCachedCallTasks(), delega a AdhocCallTasksMerge.merge(current:, incoming:, refreshedVisitSfids:) e persiste via saveCallTasks(entity:). O merge retém toda call task cujo visitSfid não está em refreshedVisitSfids e anexa as recebidas. Como CallTask não tem accountSfid, o escopo é por visita: refreshedVisitSfids = união de (visitSfid das call tasks recebidas) ∪ (sfid das visitas do reply), sem strings vazias. Erro → CacheException.Read-modify-write write path called by the Adhoc Visit (not by the Call Task Repository): reads the cache via getCachedCallTasks(), delegates to AdhocCallTasksMerge.merge(current:, incoming:, refreshedVisitSfids:) and persists via saveCallTasks(entity:). The merge retains every call task whose visitSfid is not in refreshedVisitSfids and appends the incoming ones. Since CallTask has no accountSfid, the scope is per visit: refreshedVisitSfids = union of (incoming call tasks' visitSfid) ∪ (reply visits' sfid), empty strings removed. Error → CacheException.Read-modify-write llamado por la Visita Adhoc (no por el Repository de Call Task): lee el caché vía getCachedCallTasks(), delega a AdhocCallTasksMerge.merge(current:, incoming:, refreshedVisitSfids:) y persiste vía saveCallTasks(entity:). El merge retiene toda call task cuyo visitSfid no está en refreshedVisitSfids y anexa las recibidas. Como CallTask no tiene accountSfid, el alcance es por visita: refreshedVisitSfids = unión de (visitSfid de las call tasks recibidas) ∪ (sfid de las visitas del reply), sin strings vacías. Error → CacheException.
clearCallTasks()
RetornoReturnRetorno
void
ComportamentoBehaviorComportamiento
esvazia os 4 boxes (history → product → callTask → container).empties the 4 boxes (history → product → callTask → container).vacía los 4 boxes (history → product → callTask → container).
Mock CallTaskMockDataSource assets

Envio / fluxo: lê currentMarketProvider e carrega assets/mocks/call_task/{market}_call_task.json. Erro: CacheException.Sends / flow: reads currentMarketProvider and loads assets/mocks/call_task/{market}_call_task.json. Error: CacheException.Envío / flujo: lee currentMarketProvider y carga assets/mocks/call_task/{market}_call_task.json. Error: CacheException.

getCallTasks()
RetornoReturnRetorno
Future<CallTasksEntity>
ComportamentoBehaviorComportamiento
loadMockAssetStringjsonDecodeCallTasksDTOJsonMapper.fromMaptoDomain().loadMockAssetStringjsonDecodeCallTasksDTOJsonMapper.fromMaptoDomain().loadMockAssetStringjsonDecodeCallTasksDTOJsonMapper.fromMaptoDomain().
10

Enums e labelsEnums & labelsEnums y labels

CallTaskCategory 13 · value == name
casevaluei18n key
orderCreation"orderCreation"callTaskCategoryOrderCreation
buyback"buyback"callTaskCategoryBuyback
merchan"merchan"callTaskCategoryMerchan
financialManagement"financialManagement"callTaskCategoryFinancialManagement
oos"oos"callTaskCategoryOos
surveys"surveys"callTaskCategorySurveys
tasks"tasks"callTaskCategoryTasks
avancePerformance"avancePerformance"callTaskCategoryAvancePerformance
shelfWatch"shelfWatch"callTaskCategoryShelfWatch
deliveriesOfTheDay"deliveriesOfTheDay"callTaskCategoryDeliveriesOfTheDay
staff"staff"callTaskCategoryStaff
notes"notes"callTaskCategoryNotes
unknown"unknown"callTaskCategoryUnknown

fromValue faz trim e cai em unknown. O icon é o mesmo para todas (ConectaIcons.tasksTypeCopyAlt); só o label muda por categoria.fromValue trims and falls back to unknown. The icon is the same for all (ConectaIcons.tasksTypeCopyAlt); only the label changes per category.fromValue hace trim y cae en unknown. El icon es el mismo para todas (ConectaIcons.tasksTypeCopyAlt); solo el label cambia por categoría.

CallTaskStatus 3 · value + tagVariant
casevaluetagVariant
pending"pending"warning (laranja)(orange)(naranja)
completed"completed"positive (verde)(green)(verde)
unknown"unknown"neutral

O getter CallTaskEntity.status só produz pending/completed (derivado de isCompleted); unknown existe para fromValue. static selectable = valores menos unknown.The CallTaskEntity.status getter only yields pending/completed (derived from isCompleted); unknown exists for fromValue. static selectable = values minus unknown.El getter CallTaskEntity.status solo produce pending/completed (derivado de isCompleted); unknown existe para fromValue. static selectable = valores menos unknown.

CallTaskCode 2 · discriminador OOSOOS discriminatordiscriminador OOS
casevaluesignificadomeaningsignificado
oos"CallTaskOOS"tarefa de ruptura (respostas por produto)out-of-stock task (per-product answers)tarea de quiebre (respuestas por producto)
general""tarefa simples (fallback de fromValue)simple task (fromValue fallback)tarea simple (fallback de fromValue)
DispatcherType · call task 2 · serviceName + mercadosmarketsmercados
caseserviceNamemercadosmarketsmercadospropósitopurposepropósito
answerTaskAnswerTaskAPIBR · CL · ZAconclusão da tarefa (+ respostas OOS)task completion (+ OOS answers)completar tarea (+ respuestas OOS)
reschedulingCallTaskReschedulingCallTaskAPIBR · CL · ZAreagendamento da call taskcall task reschedulereprogramación de la call task
CallTaskDetailSubmissionStatus · CallTaskDetailAction estado do enviosubmit stateestado del envío
enumvaloresvaluesvalores
CallTaskDetailSubmissionStatusidle · submitting · success · failure
CallTaskDetailActionnone · complete · reschedule
11

UseCases

Um dropdown por UseCase; dentro, cada método com assinatura, o que retorna e uso. Todos têm provider keepAlive.One dropdown per UseCase; inside, each method with its signature, what it returns and use. All have a keepAlive provider.Un dropdown por UseCase; dentro, cada método con su firma, qué devuelve y uso. Todos tienen provider keepAlive.

LeituraReadLectura

GetCallTasksUseCase 2
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
execute({source = local})Result<CallTasksEntity, Failure>delega a repository.getCallTasks. Alimenta o Call Task Detail (busca por id).delegates to repository.getCallTasks. Feeds the Call Task Detail (finds by id).delega a repository.getCallTasks. Alimenta el Call Task Detail (busca por id).
getCachedLastSyncAt()DateTime?timestamp para o DataLoadInfo.timestamp for DataLoadInfo.timestamp para DataLoadInfo.
GetCallTasksForVisitUseCase 1
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
execute({visitSfid})Result<List<CallTaskEntity>, Failure>delega a repository.getCallTasksForVisit. Usado pelo Detalhe da visita.delegates to repository.getCallTasksForVisit. Used by the Visit detail.delega a repository.getCallTasksForVisit. Usado por el Detalle de la visita.

Escrita (cache) e transaçãoWrite (cache) and transactionEscritura (caché) y transacción

MarkCallTaskAnsweredUseCase · RescheduleCallTaskUseCase 2 · só cachecache-onlysolo caché
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
MarkCallTaskAnsweredUseCase.execute({callTaskId})Result<void, Failure>repository.markCallTaskAnswered (após o ack do Dispatcher).repository.markCallTaskAnswered (after the Dispatcher ack).repository.markCallTaskAnswered (tras el ack del Dispatcher).
RescheduleCallTaskUseCase.execute({callTaskId, newDate})Result<void, Failure>repository.rescheduleCallTaskLocally (após o ack).repository.rescheduleCallTaskLocally (after the ack).repository.rescheduleCallTaskLocally (tras el ack).
Build{Answer|Reschedule}CallTaskDispatcherPayloadUseCase 2 · builders
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
build({input: AnswerCallTaskDispatcherPayloadInput})DispatcherEnvelopeimplements DispatcherPayloadBuilder (§36). Input cru (callTask, visitSfid, submittedAt). DispatcherType.answerTask. Monta answerTask[] com oosAnswerList por produto.implements DispatcherPayloadBuilder (§36). Raw input (callTask, visitSfid, submittedAt). DispatcherType.answerTask. Builds answerTask[] with a per-product oosAnswerList.implements DispatcherPayloadBuilder (§36). Input crudo (callTask, visitSfid, submittedAt). DispatcherType.answerTask. Arma answerTask[] con oosAnswerList por producto.
build({input: RescheduleCallTaskDispatcherPayloadInput})DispatcherEnvelopeInput cru (callTask, visitSfid, newDate, resource, submittedAt). DispatcherType.reschedulingCallTask. sfid_rep = resource.sfid derivado no build() (§25 exceção de escrita).Raw input (callTask, visitSfid, newDate, resource, submittedAt). DispatcherType.reschedulingCallTask. sfid_rep = resource.sfid derived in build() (§25 write exception).Input crudo (callTask, visitSfid, newDate, resource, submittedAt). DispatcherType.reschedulingCallTask. sfid_rep = resource.sfid derivado en build() (§25 excepción de escritura).
Submit{Answer|Reschedule}CallTaskUseCase 2 · transportetransporttransporte
MétodoMethodMétodoRetornaReturnsDevuelveUsoUseUso
submit({envelope})Result<DispatcherAck, Failure>delegate fino: orchestrator.dispatch(envelope:). Não decide o DispatcherType (isso é do builder).thin delegate: orchestrator.dispatch(envelope:). Doesn't decide the DispatcherType (the builder does).delegate fino: orchestrator.dispatch(envelope:). No decide el DispatcherType (eso es del builder).

Payload da conclusãoCompletion payloadPayload de la conclusión O answerTask[] leva visitUuid, answerDate (iso datetime de submittedAt), originaldate, callTaskVisit (= callTask.id), callTaskCode, answer: true e o oosAnswerList (um item por produto: answer, callTaskVisitProduct, product_name, call_task_visit). O reagendar leva sfid_visit_current, rescheduling_visit_date, sfid_rep, id_call_task_visit, call_task_visit_original_date. The answerTask[] carries visitUuid, answerDate (iso datetime of submittedAt), originaldate, callTaskVisit (= callTask.id), callTaskCode, answer: true and the oosAnswerList (one item per product: answer, callTaskVisitProduct, product_name, call_task_visit). Reschedule carries sfid_visit_current, rescheduling_visit_date, sfid_rep, id_call_task_visit, call_task_visit_original_date. El answerTask[] lleva visitUuid, answerDate (iso datetime de submittedAt), originaldate, callTaskVisit (= callTask.id), callTaskCode, answer: true y el oosAnswerList (un ítem por producto: answer, callTaskVisitProduct, product_name, call_task_visit). Reprogramar lleva sfid_visit_current, rescheduling_visit_date, sfid_rep, id_call_task_visit, call_task_visit_original_date.

12

Notifier & State

O CallTaskDetailNotifier (@riverpod, family por callTaskId) é o cérebro da tela de detalhe. O build() carrega o container do cache e acha o item por id. O State (CallTaskDetailState, Freezed) é a fonte única de verdade. A conclusão pelo checkbox da lista mora no VisitDetailNotifier (ver nota).CallTaskDetailNotifier (@riverpod, family by callTaskId) is the detail screen's brain. build() loads the container from cache and finds the item by id. The State (CallTaskDetailState, Freezed) is the single source of truth. Completing via the list checkbox lives in VisitDetailNotifier (see note).El CallTaskDetailNotifier (@riverpod, family por callTaskId) es el cerebro de la pantalla de detalle. El build() carga el container del caché y encuentra el ítem por id. El State (CallTaskDetailState, Freezed) es la fuente única de verdad. Completar por el checkbox de la lista vive en VisitDetailNotifier (ver nota).

MétodosMethodsMétodos

build({callTaskId}) cache

RetornoReturnRetorno FutureOr<CallTaskDetailState>

Carrega o container via GetCallTasksUseCase.execute() (cache), acha o item pelo id (StateError se ausente) e retorna o State com lastSyncAt do container.Loads the container via GetCallTasksUseCase.execute() (cache), finds the item by id (StateError if missing) and returns the State with the container's lastSyncAt.Carga el container vía GetCallTasksUseCase.execute() (caché), encuentra el ítem por id (StateError si ausente) y retorna el State con el lastSyncAt del container.

setProductAnswer({productId, answer})

RetornoReturnRetorno void

Copia o answer do produto correspondente (resposta OOS local); habilita/desabilita o botão Concluir via allProductsAnswered.Copies the matching product's answer (local OOS answer); enables/disables the Complete button via allProductsAnswered.Copia el answer del producto correspondiente (respuesta OOS local); habilita/deshabilita el botón Completar vía allProductsAnswered.

complete()

RetornoReturnRetorno Future<void>

Guarda canComplete; marca submitting. Monta AnswerCallTaskDispatcherPayloadInputSubmitAnswerCallTaskUseCase; no ack de sucesso → MarkCallTaskAnsweredUseCase, seta isCompleted:true, answerDate:now, status success.Guards canComplete; sets submitting. Builds AnswerCallTaskDispatcherPayloadInputSubmitAnswerCallTaskUseCase; on ack success → MarkCallTaskAnsweredUseCase, sets isCompleted:true, answerDate:now, status success.Guarda canComplete; marca submitting. Arma AnswerCallTaskDispatcherPayloadInputSubmitAnswerCallTaskUseCase; en ack de éxito → MarkCallTaskAnsweredUseCase, setea isCompleted:true, answerDate:now, status success.

reschedule({newDate})

RetornoReturnRetorno Future<void>

Guarda canReschedule; resolve currentResourceProvider (null → falha). Monta RescheduleCallTaskDispatcherPayloadInputSubmitRescheduleCallTaskUseCase; no sucesso → RescheduleCallTaskUseCase.execute, seta originalDate:newDate, status success.Guards canReschedule; resolves currentResourceProvider (null → failure). Builds RescheduleCallTaskDispatcherPayloadInputSubmitRescheduleCallTaskUseCase; on success → RescheduleCallTaskUseCase.execute, sets originalDate:newDate, status success.Guarda canReschedule; resuelve currentResourceProvider (null → fallo). Arma RescheduleCallTaskDispatcherPayloadInputSubmitRescheduleCallTaskUseCase; en éxito → RescheduleCallTaskUseCase.execute, setea originalDate:newDate, status success.

resetSubmissionStatus()

RetornoReturnRetorno void

Volta o submissionStatus para idle após a Page mostrar o aviso.Returns submissionStatus to idle after the Page shows the notice.Vuelve el submissionStatus a idle tras que la Page muestre el aviso.

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

CallTaskDetailState campos + gettersfields + getterscampos + getters
campotipodefault
callTaskCallTaskEntityrequired
lastSyncAtDateTime?null
submissionStatusCallTaskDetailSubmissionStatusidle
lastActionCallTaskDetailActionnone
submissionErrorMessageString?null

Getters: isOos, isCompleted, isSubmitting, allProductsAnswered (todo produto com answer não-vazio), canComplete (!isCompleted && !isSubmitting && (!isOos || allProductsAnswered)), canReschedule (!isSubmitting).Getters: isOos, isCompleted, isSubmitting, allProductsAnswered (every product with non-empty answer), canComplete (!isCompleted && !isSubmitting && (!isOos || allProductsAnswered)), canReschedule (!isSubmitting).Getters: isOos, isCompleted, isSubmitting, allProductsAnswered (todo producto con answer no vacío), canComplete (!isCompleted && !isSubmitting && (!isOos || allProductsAnswered)), canReschedule (!isSubmitting).

Integração no Detalhe da visitaVisit detail integrationIntegración en el Detalle de la visita O VisitDetailState guarda List<CallTaskEntity> visitCallTasks; o VisitDetailNotifier._loadVisitCallTasks chama GetCallTasksForVisitUseCase e ordena (incompletas primeiro, depois por originalDate). O completeCallTask({callTaskId}) despacha answerTask e recarrega a lista — mesmo caminho de complete(), mas a partir do checkbox inline. VisitDetailState holds List<CallTaskEntity> visitCallTasks; VisitDetailNotifier._loadVisitCallTasks calls GetCallTasksForVisitUseCase and sorts (incomplete first, then by originalDate). completeCallTask({callTaskId}) dispatches answerTask and reloads the list — same path as complete(), but from the inline checkbox. VisitDetailState guarda List<CallTaskEntity> visitCallTasks; VisitDetailNotifier._loadVisitCallTasks llama GetCallTasksForVisitUseCase y ordena (incompletas primero, luego por originalDate). completeCallTask({callTaskId}) despacha answerTask y recarga la lista — mismo camino que complete(), pero desde el checkbox inline.

13

Page e widgetsPage & widgetsPage y widgets

Módulo no Detalhe da visitaModule in the Visit detailMódulo en el Detalle de la visita

  • VisitDetailCallTaskWidget shrink se módulo (visit_detail_call_task) ausente
    • Title "Call Tasks"
    • CustomEmptyState lista vazia
    • _CallTaskRow por tarefa · card xxl30
      • category icon + title + CustomTag(status) + _CompleteCheckbox
      • onTap → VisitStartGuard.run → goToCallTaskDetail(callTaskId)
      • onComplete → VisitStartGuard.run → completeCallTask(callTaskId)

Call Task Detail

A CallTaskDetailPage (ConsumerWidget) recebe só o callTaskId (§17), observa callTaskDetailProvider(callTaskId:) e usa ref.listen para transformar o submissionStatus em ConectaNotice (verde/vermelho) + resetSubmissionStatus. Loading/erro globais. Árvore:CallTaskDetailPage (ConsumerWidget) takes only callTaskId (§17), watches callTaskDetailProvider(callTaskId:) and uses ref.listen to turn submissionStatus into a ConectaNotice (green/red) + resetSubmissionStatus. Global loading/error. Tree:La CallTaskDetailPage (ConsumerWidget) recibe solo el callTaskId (§17), observa callTaskDetailProvider(callTaskId:) y usa ref.listen para transformar el submissionStatus en ConectaNotice (verde/rojo) + resetSubmissionStatus. Loading/error globales. Árbol:

  • CallTaskDetailPage
    • AppPageShell displayBackButton
      • CustomLoadingIndicator loading
      • FailureStateView error → ref.invalidate
      • SingleChildScrollView → Column data
        • DataLoadInfo state.lastSyncAt
        • CallTaskDetailHeaderWidget título
        • CallTaskDetailCardWidget categoria + status + título + mensagem
        • CallTaskDetailOosWidget shrink se !isOos ou sem produtos
          • _ProductCard por produto
            • _AnswerOption Disponível ("1", verde) / Em falta ("0", vermelho) setProductAnswer · disabled se completed
            • history chips dot verde status==1 / vermelho · data
        • CallTaskDetailActionsWidget
          • Concluir (filled) enable: canComplete → complete()
          • Reagendar (outlined) enable: !isCompleted && !isSubmitting → _onReschedule
          • CallTaskRescheduleModalContent modal (widgets/modals/) · CalendarDatePicker amanhã→+90d · Cancelar / Confirmar → reschedule(newDate)

Fluxo de reagendar: tocar em ReagendarConectaModal.show<DateTime> (ConectaModalScaffold com CalendarDatePicker, janela amanhã→+90 dias) → backWithResult<DateTime>notifier.reschedule(newDate:). Modal e navegação ficam no widget por precisarem de BuildContext; a lógica de envio mora no Notifier (§39).Reschedule flow: tapping RescheduleConectaModal.show<DateTime> (ConectaModalScaffold with a CalendarDatePicker, window tomorrow→+90 days) → backWithResult<DateTime>notifier.reschedule(newDate:). Modal and navigation stay in the widget because they need BuildContext; the submit logic lives in the Notifier (§39).Flujo de reprogramar: tocar ReprogramarConectaModal.show<DateTime> (ConectaModalScaffold con un CalendarDatePicker, ventana mañana→+90 días) → backWithResult<DateTime>notifier.reschedule(newDate:). Modal y navegación quedan en el widget porque necesitan BuildContext; la lógica de envío vive en el Notifier (§39).

Notas por mercadoMarket notesNotas por mercado

A Call Task é dirigida pelo End Market Configuration — o módulo visit_detail_call_task no Detalhe da visita. As duas transações (answerTask, reschedulingCallTask) também estão habilitadas em BR/CL/ZA.Call Task is driven by the End Market Configuration — the visit_detail_call_task module in the Visit detail. Both transactions (answerTask, reschedulingCallTask) are also enabled in BR/CL/ZA.La Call Task es dirigida por el End Market Configuration — el módulo visit_detail_call_task en el Detalle de la visita. Las dos transacciones (answerTask, reschedulingCallTask) también están habilitadas en BR/CL/ZA.

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

HabilitadosEnabledHabilitados Nos três, visit_detail_call_task = isVisible: true e visit_detail_task_manager = false — ou seja, o slot de tarefas no Detalhe da visita mostra Call Tasks, não Manager Tasks. Os mocks (br/cl/za_call_task.json) trazem tarefas OOS, de criação de pedido, merchandising e pesquisa. In all three, visit_detail_call_task = isVisible: true and visit_detail_task_manager = false — i.e. the tasks slot in the Visit detail shows Call Tasks, not Manager Tasks. The mocks (br/cl/za_call_task.json) carry OOS, order-creation, merchandising and survey tasks. En los tres, visit_detail_call_task = isVisible: true y visit_detail_task_manager = false — es decir, el slot de tareas en el Detalle de la visita muestra Call Tasks, no Manager Tasks. Los mocks (br/cl/za_call_task.json) traen tareas OOS, de creación de pedido, merchandising y encuesta.

AR · PY · PE Não carregam bloco de módulo do Detalhe da visita (nem visit_detail_call_task nem visit_detail_task_manager), então a Call Task não existe nesses mercados. Os mocks ar/py/pe_call_task.json são stubs vazios ({}). They carry no Visit-detail module block (neither visit_detail_call_task nor visit_detail_task_manager), so Call Task doesn't exist in those markets. The ar/py/pe_call_task.json mocks are empty stubs ({}). No cargan bloque de módulo del Detalle de la visita (ni visit_detail_call_task ni visit_detail_task_manager), así que la Call Task no existe en esos mercados. Los mocks ar/py/pe_call_task.json son stubs vacíos ({}).

Pendências / roadmapPending / roadmapPendientes / roadmap Fora do escopo desta versão: (1) criar uma call task pelo app + os lookups CallTaskType/CallTaskSubType/CallTaskDuration; (2) o reagendamento envia uma data futura livre — o contrato final de backend ainda está por confirmar. As mutações de cache (markCallTaskAnswered, rescheduleCallTaskLocally) são o espelho local; a verdade do backend chega pelo Dispatcher. Out of scope for this version: (1) creating a call task from the app + the CallTaskType/CallTaskSubType/CallTaskDuration lookups; (2) reschedule sends a free future date — the final backend contract is still to be confirmed. The cache mutations (markCallTaskAnswered, rescheduleCallTaskLocally) are the local mirror; the backend truth arrives via the Dispatcher. Fuera de alcance de esta versión: (1) crear una call task desde la app + los lookups CallTaskType/CallTaskSubType/CallTaskDuration; (2) la reprogramación envía una fecha futura libre — el contrato final de backend está por confirmar. Las mutaciones de caché (markCallTaskAnswered, rescheduleCallTaskLocally) son el espejo local; la verdad del backend llega vía Dispatcher.