Skip to content

Módulo 3 - Motor de Agendamento & Recorrência (scheduling)

Módulo 3: Motor de Agendamento & Recorrência (scheduling)

Section titled “Módulo 3: Motor de Agendamento & Recorrência (scheduling)”

O módulo Scheduling é o motor de agendamentos do Prime Crown. Ele cuida do ciclo de vida das solicitações de serviço, garante a não sobreposição de horários e projeta agendamentos futuros recorrentes.


A. AvailabilityService (Janelas de Horários Livres)

Section titled “A. AvailabilityService (Janelas de Horários Livres)”
  • Função: Identifica horários disponíveis para agendamento em um determinado dia.
  • Buffer de Trânsito (Transit Buffer): Adiciona automaticamente 30 minutos de deslocamento antes e depois de cada limpeza para permitir que a funcionária viaje entre os imóveis com segurança.

B. ConflictService (Prevenção de Sobreposição)

Section titled “B. ConflictService (Prevenção de Sobreposição)”
  • Função: Audita qualquer nova solicitação ou reagendamento.
  • Validações:
    • Garante que a funcionária alocada não tenha dois serviços no mesmo horário.
    • Verifica se o cliente possui mais de um agendamento no mesmo endereço simultaneamente.

C. RecurrenceService (Motor de Recorrência)

Section titled “C. RecurrenceService (Motor de Recorrência)”
  • Função: Projeta os próximos atendimentos com base na frequência contratada:
    • Weekly: Agenda a cada 7 dias no mesmo dia da semana.
    • Bi-weekly: Agenda a cada 14 dias.
    • Monthly: Agenda na mesma semana/dia do mês seguinte.

  • Serviço de Disponibilidade: src/features/scheduling/services/AvailabilityService.ts
  • Serviço de Conflitos: src/features/scheduling/services/ConflictService.ts
  • Serviço de Recorrência: src/features/scheduling/services/RecurrenceService.ts
  • Página da Agenda: src/pages/Schedule.tsx

HolidaySuspensionModal envia uma intenção UUID retomável para POST /api/scheduling/holiday-suspension. O backend cancela todo o intervalo elegível em um único statement D1, preserva preço/VAT originais para auditoria e devolve exatamente o mesmo resultado em retries. Navegador, PWA, Android e iOS compartilham o contrato e só confirmam depois da resposta autoritativa. A mutação encerra em 15 segundos; fechar/desmontar ou trocar o cliente aborta o transporte e uma resposta que perdeu ownership não altera store, cache, toast ou modal. Datas e fechamento ficam bloqueados durante a aplicação. O modal segue o design system claro, usa campos e botões canônicos, respeita safe areas e reorganiza datas, métricas e ações para telas estreitas.

CalendarSyncPanel oferece a mesma assinatura ICS em todas as superfícies: webcal:// abre Apple Calendar no iOS/macOS e a URL HTTPS abre Google Calendar no Android ou navegador; outras agendas podem copiar o feed. O painel permanece renderizado durante a consulta e em falhas iniciais para que Retry nunca dependa de já existir uma resposta bem-sucedida.

useIcsCalendarSync e useEmployeeCalendarSync mantêm apenas uma consulta ativa por painel. Um refresh aborta a anterior, e o cleanup aborta a rede ao sair da Agenda; somente a execução mais recente pode atualizar dados, erro e loading.

useRouteOptimization aplica o mesmo contrato às duas chamadas de IA. Reexecutar ou fechar o insight cancela a operação; o resultado só é aceito quando contém cada atendimento do dia exatamente uma vez, sem IDs desconhecidos, e distâncias/tempos finitos não negativos. Saída inválida usa a ordem cronológica segura.

O portal público /proposal lê a proposta com teto de 12 segundos e envia aceite/recusa com teto de 15 segundos. Navegação cancela ambas as operações, um lock síncrono impede decisões duplicadas e falha de conexão oferece Try again sem afirmar que o link expirou. A mesma superfície e o mesmo ciclo de vida são usados em browser, PWA e WebViews Android/iOS.

Na agenda desktop, trabalhos não alocados permanecem arrastáveis, mas cada cartão também é um botão nativo dentro de uma lista semântica. Assim, Enter/Espaço, foco visível, TalkBack e VoiceOver usam o comportamento padrão sem anunciar um listbox que exigiria navegação por setas.

Os painéis drag-and-drop laterais não ficam apenas escondidos por CSS: equipe é montada a partir de 1024 px e tarefas sem alocação a partir de 1280 px, usando o useMediaQuery compartilhado. Telefones, tablets estreitos, split-screen e orientação horizontal mantêm somente o grid, sem árvores interativas invisíveis. A altura acompanha 80dvh em todos os breakpoints, com mínimo reduzido no mobile e 700 px no desktop para a operação ampla.

Nos cartões de agenda do cliente, a faixa temporal usa o ProgressBar compartilhado: atendimentos futuros anunciam “Not started”, os ativos expõem a percentagem decorrida e os concluídos anunciam “Completed”. O preenchimento colorido permanece decorativo e idêntico no touch/desktop.

Estado autoritativo das sugestões de recorrência

Section titled “Estado autoritativo das sugestões de recorrência”

O Ops Commander só calcula Recurring Series Left Hanging depois que a tabela recurring_series confirma quais grupos estão ativos ou terminados. Página e badge lateral usam a mesma query autenticada e cacheada; falha não vira conjunto vazio, não infla a contagem e pausa as ações de retomada com alerta e retry. Resume from today e End series adquirem lock antes do próximo render, validam a sessão antes de cada commit e descartam conclusões tardias depois de logout ou troca de conta. Encerrar uma série exige resposta success do endpoint antes de atualizar o cache compartilhado, mantendo desktop, PWA, Android e iOS no mesmo estado autoritativo.