Arquitetura — Chronos¶
Visao Geral¶
graph TB
subgraph Frontend
FE[Next.js<br/>App Router]
end
subgraph Backend
BE[Quarkus<br/>:5050]
end
subgraph Banco
MG[(MongoDB<br/>chronosdb)]
end
subgraph Servicos Haus
OATH[OATH<br/>:5001]
GUILD[Guild<br/>:5002]
HERALD[Herald<br/>:5004]
VAULT[Vault<br/>:5006]
CK[CoinKeeper<br/>:5005]
SCROLLS[Scrolls<br/>:5003]
end
subgraph Externos
EVO[Evolution API<br/>WhatsApp]
end
FE --> BE
BE --> MG
BE --> OATH
BE --> GUILD
BE --> HERALD
BE --> VAULT
BE --> CK
BE --> SCROLLS
HERALD --> EVO
Backend¶
Camadas¶
chronos/
├── api/
│ ├── controllers/ # BFF controllers (/bff/*)
│ └── controllers/ # Webhook controllers
├── application/
│ ├── services/ # Business logic
│ └── engines/ # AvailabilityEngine, PromotionEngine
├── domain/
│ └── entities/ # MongoDB entities
└── infrastructure/
├── clients/ # REST clients (OATH, Guild, Herald, WhatsApp)
├── persistence/ # MongoDB Panache repositories
├── scheduler/ # Jobs agendados
└── security/ # AuthFilter, context service
Endpoints BFF¶
| Controller | Path | Funcao |
|---|---|---|
| BffAuthController | /bff/auth |
Login, signup, refresh, tenant selection |
| BffAppointmentController | /bff/appointments |
CRUD agendamentos + status |
| BffServiceController | /bff/services |
CRUD catalogo de servicos |
| BffProfessionalController | /bff/professionals |
CRUD profissionais |
| BffCustomerController | /bff/customers |
CRUD clientes + busca |
| BffScheduleController | /bff/schedules |
Agenda + excecoes |
| BffLocationController | /bff/locations |
CRUD locais |
| BffRoomController | /bff/rooms |
CRUD salas + booking |
| BffPromotionController | /bff/promotions |
CRUD promocoes |
| BffDashboardController | /bff/dashboard |
Estatisticas + calendario |
| BffTenantController | /bff/tenant |
Config do tenant |
| BffPublicController | /bff/public |
Pagina publica de booking |
| WhatsAppWebhookController | /webhooks/whatsapp |
Recebe msgs do Herald |
Entidades Principais (MongoDB)¶
erDiagram
Tenant ||--o{ Professional : "tem"
Tenant ||--o{ ServiceItem : "oferece"
Tenant ||--o{ Location : "opera em"
Tenant ||--o{ Customer : "atende"
Tenant ||--o{ Appointment : "agenda"
Tenant ||--o{ Schedule : "define"
Tenant ||--o{ Promotion : "oferece"
Tenant ||--o{ Room : "tem"
Professional ||--o{ Schedule : "segue"
Professional ||--o{ Appointment : "atende"
Customer ||--o{ Appointment : "agenda"
Location ||--o{ Room : "contem"
Room ||--o{ RoomBooking : "reservado"
Appointment ||--o{ AppointmentItem : "contem"
Tenant ||--o{ ScheduledMessage : "programa"
Engines¶
AvailabilityEngine¶
Calcula slots disponiveis para agendamento:
flowchart TD
A[Data + Profissional] --> B[Carregar Schedule]
B --> C{Modo?}
C -->|INTERVALS| D[Gerar slots com<br/>slotDurationMinutes]
C -->|FIXED_SLOTS| E[Usar slots fixos]
D --> F[Remover excecoes]
E --> F
F --> G[Remover agendamentos<br/>existentes]
G --> H[Retornar TimeSlots]
PromotionEngine¶
Valida e calcula descontos:
flowchart TD
A[Codigo da promocao] --> B{Promocao existe?}
B -->|Nao| X[Erro]
B -->|Sim| C{Periodo valido?}
C -->|Nao| X
C -->|Sim| D{Limite de uso?}
D -->|Excedido| X
D -->|OK| E{Restricoes de servico?}
E -->|Nao aplica| X
E -->|Aplica| F[Calcular desconto]
F --> G{Cap de desconto?}
G -->|Sim| H[Aplicar cap]
G -->|Nao| I[Retornar desconto]
H --> I
Schedulers¶
| Scheduler | Intervalo | Funcao |
|---|---|---|
AppointmentReminderScheduler |
15 min | Envia lembretes email + WhatsApp 24h |
ScheduledMessageSenderScheduler |
5 min | Processa fila de msgs agendadas |
StaleAppointmentCleanupScheduler |
— | Limpa agendamentos draft/stale |
Webhook de WhatsApp¶
- Recebe
{ ownerRef, phoneFrom, message, timestamp }do Herald - Extrai
tenantIddo ownerRef ("chronos-{tenantId}") - Normaliza mensagem
- Se contem "CONFIRMAR" ou "CONFIRMO":
- Busca agendamentos nas proximas 48h com esse telefone
- Confirma o mais proximo
- Envia ack via WhatsApp
Frontend¶
Arquitetura¶
chronos-frontend/
├── src/
│ ├── app/
│ │ ├── (auth)/ # Login, signup
│ │ ├── (dashboard)/ # Area protegida
│ │ │ ├── dashboard/
│ │ │ ├── appointments/
│ │ │ ├── schedule/
│ │ │ ├── services/
│ │ │ ├── professionals/
│ │ │ ├── customers/
│ │ │ ├── locations/
│ │ │ ├── rooms/
│ │ │ ├── promotions/
│ │ │ └── settings/
│ │ ├── (public)/ # Booking publico
│ │ │ └── c/[tenantSlug]/
│ │ └── api/auth/ # NextAuth handler
│ ├── actions/ # Server Actions
│ ├── components/
│ │ ├── dashboard/ # Calendar, upcoming
│ │ └── public/ # BookingWizard
│ ├── lib/
│ │ ├── api.ts # fetchChronosAPI
│ │ ├── tenant.ts # Tenant resolution
│ │ └── utils.ts # Formatters
│ └── auth.ts # NextAuth config
Autenticacao¶
- NextAuth com Credentials Provider
- Login via OATH externo (provider=OATH, application=chronos)
- JWT armazenado na sessao
- Middleware protege rotas
/dashboard/*
Booking Wizard (Public)¶
O componente BookingWizard implementa 5 passos:
- Servico — Selecao do servico com preco e duracao
- Profissional — Selecao do profissional (condicional)
- Data/Hora — Calendario + slots do
AvailabilityEngine - Confirmacao — Dados do cliente + codigo promocional
- Sucesso — Codigo do agendamento
Server Actions¶
O frontend usa Next.js Server Actions para comunicacao com o backend:
getAppointments(),createDashboardAppointment()getAvailability(),getProfessionalAvailability()createPublicBooking(),validatePublicPromotion()getDashboardSummary(),getDashboardCalendar()
Configuracao¶
Backend¶
# MongoDB
quarkus.mongodb.connection-string=${QUARKUS_MONGODB_CONNECTION_STRING}
quarkus.mongodb.database=chronosdb
# Porta
quarkus.http.port=5050
# Servicos
quarkus.rest-client.oath-api.url=http://localhost:5001
quarkus.rest-client.guild-api.url=http://localhost:5002
quarkus.rest-client.herald-api.url=http://localhost:5004
quarkus.rest-client.vault-api.url=http://localhost:5006
quarkus.rest-client.coinkeeper-api.url=http://localhost:5005