311 lines
14 KiB
Markdown
311 lines
14 KiB
Markdown
# 🚛 Gade Logística — Sistema de Controle de Custos
|
||
|
||
Sistema web para controle de custos de entregas hospitalares da **Gade Hospitalar**.
|
||
|
||
**Stack:** Ruby on Rails 7+ · PostgreSQL 15 · Docker · Tailwind CSS · Hotwire (Turbo + Stimulus)
|
||
**Repositório:** https://git.xenserver.com.br/Cludio-code/logistica-controle-custos
|
||
|
||
---
|
||
|
||
## 📋 CONTEXTO DO PROJETO (leia antes de tudo)
|
||
|
||
A **Gade Hospitalar** precisa controlar o custo de cada operação de entrega
|
||
(UBS SUL, UBS LESTE, EMAD, STS, SAD, etc.).
|
||
|
||
O banco **já existe** e é atualizado a cada 1 hora por outro sistema externo:
|
||
- Tabela: `public.db_reem_simplerout_2026`
|
||
- Account: Gade Hospitalar (account_id: 95907)
|
||
- **NUNCA** fazer `DROP TABLE`, `TRUNCATE`, `DELETE` ou migration nessa tabela.
|
||
|
||
O sistema novo cria suas próprias tabelas no mesmo PostgreSQL (schema separado ou prefixo)
|
||
e lê a tabela existente apenas para exibir e consolidar entregas.
|
||
|
||
---
|
||
|
||
## 🏗️ Estado atual — O que já foi feito (Fase 1 ✅)
|
||
|
||
```
|
||
logistica-controle-custos/
|
||
├── Gemfile # Todas as gems (Devise, Pundit, Prawn, Whenever, Tailwind…)
|
||
├── Dockerfile # Ruby 3.2.2-slim
|
||
├── docker-compose.yml # app + db (postgres:15)
|
||
├── tailwind.config.js # Paleta preto #0a0a0a / laranja #f97316 / branco
|
||
├── .env.example # Template de variáveis — copiar para .env
|
||
├── .gitignore # Protege .env, master.key, credenciais
|
||
│
|
||
├── config/
|
||
│ ├── database.yml # 100% via ENV — nunca hardcode
|
||
│ └── routes.rb # Rotas completas para todas as 8 fases
|
||
│
|
||
├── app/
|
||
│ ├── models/
|
||
│ │ ├── entrega.rb # ⚠️ READ-ONLY — tabela existente db_reem_simplerout_2026
|
||
│ │ ├── user.rb # Devise + roles (admin/gerente/operador/motorista) + PIN
|
||
│ │ ├── configuracao.rb # Preços configuráveis (entrega, retirada, bonus, desconto)
|
||
│ │ ├── consolidacao.rb # Soft delete, enum status, cálculo de progresso
|
||
│ │ ├── consolidacao_motorista.rb
|
||
│ │ ├── consolidacao_entrega.rb # Enum tipo: normal/retirada/bonus/desconto
|
||
│ │ ├── historico_estimado.rb # Job 1h + cálculo ao vivo
|
||
│ │ └── auditoria_log.rb # Log de ações críticas
|
||
│ │
|
||
│ ├── controllers/
|
||
│ │ └── application_controller.rb # Auth + Pundit + tema
|
||
│ ├── policies/
|
||
│ │ └── application_policy.rb # Base Pundit
|
||
│ ├── helpers/
|
||
│ │ └── application_helper.rb # nav_link_to, moeda(), badge_status(), progress_bar()
|
||
│ └── views/layouts/
|
||
│ ├── application.html.erb # Layout base dark theme laranja/preto/branco
|
||
│ └── _navbar.html.erb # Sidebar responsiva com hamburguer mobile
|
||
│
|
||
└── db/
|
||
├── seeds.rb # Admin: admin@gade.com / Gade@2026! + configs de preço
|
||
└── migrate/
|
||
├── ..._create_users.rb
|
||
├── ..._create_configuracoes.rb
|
||
├── ..._create_consolidacoes.rb
|
||
├── ..._create_consolidacao_motoristas.rb
|
||
├── ..._create_consolidacao_entregas.rb
|
||
├── ..._create_historico_estimados.rb
|
||
└── ..._create_auditoria_logs.rb
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 Setup do zero (próximo dev)
|
||
|
||
### 1. Clone
|
||
```bash
|
||
git clone https://git.xenserver.com.br/Cludio-code/logistica-controle-custos.git
|
||
cd logistica-controle-custos
|
||
```
|
||
|
||
### 2. Configure o .env
|
||
```bash
|
||
cp .env.example .env
|
||
nano .env # preencha DB_HOST, DB_PASSWORD, etc.
|
||
```
|
||
|
||
### 3. Gere o SECRET_KEY_BASE
|
||
```bash
|
||
docker run --rm ruby:3.2.2-slim bash -c "gem install rails --no-doc -q && rails secret"
|
||
# Cole o resultado no .env → SECRET_KEY_BASE=...
|
||
```
|
||
|
||
### 4. Suba os containers
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
### 5. Banco + seeds
|
||
```bash
|
||
docker-compose exec app bundle exec rails db:create db:migrate db:seed
|
||
```
|
||
|
||
### 6. Acesse
|
||
```
|
||
http://localhost:3000
|
||
Login: admin@gade.com
|
||
Senha: Gade@2026! ← ALTERE NO PRIMEIRO ACESSO
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 Comandos do dia a dia
|
||
|
||
```bash
|
||
docker-compose exec app bundle exec rails db:migrate # nova migration
|
||
docker-compose exec app bundle exec rails console # console Rails
|
||
docker-compose logs -f app # logs em tempo real
|
||
docker-compose down # parar tudo
|
||
```
|
||
|
||
---
|
||
|
||
## 🗺️ Fases de implementação
|
||
|
||
| Fase | Status | O que fazer |
|
||
|------|--------|-------------|
|
||
| **1** | ✅ **CONCLUÍDA** | Setup + Docker + Models + Migrations + Seeds + Layout base |
|
||
| **2** | ⏳ Pendente | Login por role + CRUD usuários + pilares de preço + toggle tema |
|
||
| **3** | ⏳ Pendente | Dashboard: cards grandes laranja/preto/branco + gráfico Chart.js + cálculo ao vivo |
|
||
| **4** | ✅ **CONCLUÍDA** | Job Whenever (1h) + HistoricoEstimado + AuditoriaLog + API métricas |
|
||
| **5** | ✅ **CONCLUÍDA** | Nova Consolidação + filtros + Wizard Passo 1 (selecionar motorista) |
|
||
| **6** | ✅ **CONCLUÍDA** | Toggles coloridos + ações em massa + barra progresso + Wizard Passos 2 e 3 (Stimulus) |
|
||
| **7** | ✅ **CONCLUÍDA** | PDFs Prawn: relatório individual + holerite com QR code + modal preview |
|
||
| **8** | ✅ **CONCLUÍDA** | Painel motorista + login PIN/QR + notificações WhatsApp/email |
|
||
|
||
### 📂 Arquivos das Fases 4, 5 e 6
|
||
|
||
**Fase 4 — Job 1h + Auditoria:**
|
||
```
|
||
config/schedule.rb # Whenever — roda a cada 1h
|
||
lib/tasks/historico.rake # rake historico:atualizar
|
||
app/jobs/application_job.rb
|
||
app/jobs/atualizar_historico_estimado_job.rb # conta entregas pagas × preco_entrega
|
||
app/controllers/api/v1/dashboard_controller.rb # GET /api/v1/dashboard/metricas
|
||
app/controllers/concerns/auditavel.rb # auditar!(:acao, registro) nos controllers
|
||
app/policies/dashboard_policy.rb
|
||
```
|
||
Ativar o cron no servidor: `bundle exec whenever --update-crontab`
|
||
Testar manualmente: `docker-compose exec app bundle exec rake historico:atualizar`
|
||
|
||
**Fase 5 — Consolidação + Wizard Passo 1:**
|
||
```
|
||
db/migrate/20260101000008_add_route_ids_to_consolidacoes.rb # rodar db:migrate!
|
||
app/controllers/consolidacoes_controller.rb # index/new/create/show/wizard/finalizar/arquivar
|
||
app/policies/consolidacao_policy.rb
|
||
app/views/consolidacoes/index.html.erb # lista com filtros (status/nome/período/motorista/rota)
|
||
app/views/consolidacoes/new.html.erb # form: nome + 2 date pickers + multi-select motoristas/rotas
|
||
app/views/consolidacoes/wizard.html.erb # Passo 1: lista motoristas com progresso
|
||
```
|
||
|
||
**Fase 6 — Validação + Toggles + Massa:**
|
||
```
|
||
app/controllers/consolidacao_entregas_controller.rb # validar/classificar/classificar_em_massa/revisar
|
||
app/views/consolidacao_entregas/validar.html.erb # Passo 2: toggles coloridos + checkbox massa + resumo lateral
|
||
app/views/consolidacao_entregas/revisar.html.erb # Passo 3: resumo + próximo motorista / salvar rascunho
|
||
app/javascript/controllers/validacao_controller.js # Stimulus: tempo real (progresso, resumo, toggles)
|
||
config/routes.rb # ATUALIZADO — rotas do wizard
|
||
```
|
||
|
||
**Cores dos toggles (padrão do projeto):**
|
||
🟧 Laranja = Entrega Normal · 🟫 Laranja escuro = Retirada · ⬜ Branco = Bônus · ⬛ Preto = Desconto
|
||
|
||
**Regras implementadas:**
|
||
- Entregas elegíveis: `status='completed'` AND `checkin IS NOT NULL` (somente leitura da tabela existente)
|
||
- Não permite finalizar consolidação com entregas não classificadas (botão desabilitado + validação server-side)
|
||
- Consolidação finalizada não pode ser editada por operadores (Pundit)
|
||
- Todas ações críticas registradas em `auditoria_logs`
|
||
|
||
**Fase 7 — PDFs (Prawn + QR Code):**
|
||
```
|
||
Gemfile # + rqrcode, chunky_png
|
||
db/migrate/20260101000009_add_login_token_to_users.rb # token para QR — rodar db:migrate!
|
||
app/services/pdf/base_pdf.rb # layout base: cabeçalho preto/laranja + rodapé
|
||
app/services/pdf/relatorio_motorista_pdf.rb # tabela detalhada de entregas + resumo + total
|
||
app/services/pdf/holerite_pdf.rb # estilo contracheque + QR Code de login rápido
|
||
app/controllers/consolidacoes_controller.rb # ATUALIZADO: gerar_pdf_relatorio/gerar_pdf_holerite/preview_holerite
|
||
app/views/consolidacoes/show.html.erb # botões por motorista + modal de preview
|
||
app/views/consolidacoes/preview_holerite.html.erb # preview HTML antes de confirmar o PDF
|
||
app/models/user.rb # ATUALIZADO: regenerar_login_token!
|
||
```
|
||
Soft delete já implementado: consolidações finalizadas vão para "arquivada", nunca são excluídas.
|
||
|
||
**Fase 8 — Painel Motorista + Notificações:**
|
||
```
|
||
Gemfile # + twilio-ruby
|
||
app/controllers/motorista/sessoes_controller.rb # login PIN 4 dígitos + acesso via QR (/motorista/acesso/:token)
|
||
app/controllers/motorista/dashboard_controller.rb # 2 cards: estimado (mês) + consolidado (finalizadas)
|
||
app/views/motorista/sessoes/new.html.erb # teclado numérico gigante mobile-first (envia no 4º dígito)
|
||
app/views/motorista/dashboard/index.html.erb # cards laranja/branco + lista com download do próprio holerite
|
||
app/services/notificacao_service.rb # WhatsApp (Twilio) + email — falha nunca quebra a finalização
|
||
app/mailers/application_mailer.rb
|
||
app/mailers/consolidacao_mailer.rb # pagamento_fechado
|
||
app/views/consolidacao_mailer/pagamento_fechado.html.erb # email com identidade visual da marca
|
||
app/views/layouts/mailer.html.erb
|
||
config/initializers/smtp.rb # SMTP via ENV (só ativa se SMTP_USERNAME existir)
|
||
config/routes.rb # ATUALIZADO: /motorista/login + /motorista/acesso/:token
|
||
```
|
||
|
||
**Notificações — como ativar:**
|
||
1. WhatsApp: preencha `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN` e `TWILIO_WHATSAPP_FROM` no `.env` e mude a configuração `notificacao_whatsapp` para `true` no sistema. Motorista precisa ter `telefone` cadastrado (formato `+5511999998888`).
|
||
2. Email: preencha as variáveis `SMTP_*` no `.env` e mude `notificacao_email` para `true`. Motorista precisa ter `email`.
|
||
3. Ao finalizar uma consolidação, cada motorista recebe automaticamente a mensagem com o valor e o link do painel.
|
||
|
||
**Fluxo do motorista (público de baixo nível técnico):**
|
||
- Acessa `/motorista/login` → digita PIN de 4 números num teclado gigante (envia sozinho no 4º dígito)
|
||
- OU escaneia o QR Code impresso no holerite → entra direto sem digitar nada
|
||
- Vê 2 cards: 🟧 valor estimado do mês ("aproximado") e ⬜ valor fechado para pagamento
|
||
- Baixa o próprio holerite das consolidações finalizadas
|
||
|
||
### 🧪 Teste end-to-end sugerido
|
||
1. Login admin → criar consolidação (nome + período + motoristas)
|
||
2. Wizard Passo 1 → escolher motorista → Passo 2: classificar entregas com os toggles
|
||
3. Usar "Marcar todos como Normal" → Passo 3: revisar → próximo motorista
|
||
4. Com tudo classificado → Finalizar (motoristas notificados)
|
||
5. Na tela da consolidação → "Ver antes de gerar" → Confirmar → baixar Holerite PDF
|
||
6. Logout → `/motorista/login` → entrar com PIN do motorista
|
||
7. Conferir cards de valores → baixar próprio holerite → sair
|
||
|
||
### ▶️ Para continuar (faltam apenas Fases 2 e 3)
|
||
|
||
Cole este contexto no início da conversa com o Claude:
|
||
|
||
```
|
||
Continue o Sistema de Controle de Custos Logística da Gade Hospitalar.
|
||
|
||
CHECKPOINT — FASES 1, 4, 5, 6, 7 e 8 CONCLUÍDAS:
|
||
- Rails 7+ com Docker, PostgreSQL externo, Tailwind (preto #0a0a0a / laranja #f97316)
|
||
- Models: Entrega (read-only db_reem_simplerout_2026), User (Devise+roles+pin_code
|
||
+login_token), Configuracao, Consolidacao (+route_ids), ConsolidacaoMotorista,
|
||
ConsolidacaoEntrega, HistoricoEstimado, AuditoriaLog — 9 migrations
|
||
- Fase 4: Whenever (1h) + job + rake historico:atualizar + API /api/v1/dashboard/metricas
|
||
- Fase 5: ConsolidacoesController (filtros, multi-select) + Wizard Passo 1
|
||
- Fase 6: validar/classificar/classificar_em_massa/revisar + toggles + Stimulus
|
||
- Fase 7: PDFs Prawn (Pdf::RelatorioMotoristaPdf, Pdf::HoleritePdf com QR code)
|
||
+ modal preview em consolidacoes/show
|
||
- Fase 8: login motorista por PIN (/motorista/login) e QR (/motorista/acesso/:token)
|
||
+ painel motorista (2 cards + holerites) + NotificacaoService (Twilio/ActionMailer)
|
||
|
||
FALTAM SOMENTE:
|
||
- FASE 2: tela de login Devise estilizada + CRUD usuários (admin/usuarios) +
|
||
CRUD pilares de preço (admin/configuracoes) + tela auditoria + toggle tema claro/escuro
|
||
- FASE 3: DashboardController + view com cards grandes (valor estimado, entregas
|
||
do dia/mês, motoristas ativos) + gráfico Chart.js do historico_estimados
|
||
Consulte o README.md do repositório para a lista completa de arquivos.
|
||
```
|
||
|
||
---
|
||
|
||
## 🗄️ Banco existente — referência rápida
|
||
|
||
| Campo | Uso |
|
||
|-------|-----|
|
||
| `tracking_id` | PK lógico da entrega |
|
||
| `reference_id` | Número da NF |
|
||
| `planned_date` | Data da entrega (filtro principal) |
|
||
| `driver` | Nome do motorista |
|
||
| `status` | `'completed'` = entrega paga |
|
||
| `checkin` | NULL = motorista não registrou chegada |
|
||
| `route_id` | UUID da operação (UBS SUL, EMAD, etc.) |
|
||
| `contact_name` | Nome do local (UBS SACOMA, EMAD VELEIROS…) |
|
||
|
||
**Regra de pagamento:** `status = 'completed'` AND `checkin IS NOT NULL`
|
||
|
||
---
|
||
|
||
## 🎨 Design — padrão da marca
|
||
|
||
| Elemento | Cor | Hex |
|
||
|----------|-----|-----|
|
||
| Fundo | Preto | `#0a0a0a` |
|
||
| Cards | Cinza escuro | `#1a1a1a` |
|
||
| Destaque / botões | Laranja | `#f97316` |
|
||
| Textos | Branco | `#ffffff` |
|
||
| Sucesso | Verde | `#22c55e` |
|
||
| Erro/desconto | Vermelho | `#ef4444` |
|
||
|
||
- Fonte mínima 16px desktop / 18px mobile
|
||
- Botões mínimo 48px altura (acessibilidade touch)
|
||
- Tema escuro como padrão
|
||
|
||
---
|
||
|
||
## 👥 Perfis de acesso
|
||
|
||
| Perfil | Login | Acesso |
|
||
|--------|-------|--------|
|
||
| Admin | email + senha | Tudo |
|
||
| Gerente | email + senha | Dashboard + Consolidações + PDFs |
|
||
| Operador | email + senha | Consolidações (criar + validar) |
|
||
| Motorista | PIN 4 dígitos ou QR | Painel pessoal + baixar próprio PDF |
|
||
|
||
---
|
||
|
||
## 🔐 Segurança
|
||
|
||
- **NUNCA** versione `.env`, `config/master.key` ou qualquer arquivo com senha
|
||
- Repositório **PRIVADO** em git.xenserver.com.br
|
||
- Use sempre `ENV['VARIAVEL']` no código Ruby
|