126 lines
6.1 KiB
Markdown
126 lines
6.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project overview
|
|
|
|
**Reem Logística** is a Rails 7 web application for controlling delivery costs for **Gade Hospitalar** (account_id: 95907). It manages consolidations of driver payments across delivery routes (UBS SUL, UBS LESTE, EMAD, STS, SAD, etc.).
|
|
|
|
## Commands
|
|
|
|
All commands run inside Docker. The PostgreSQL database lives externally (not in docker-compose).
|
|
|
|
```bash
|
|
# Start
|
|
docker-compose up -d
|
|
|
|
# Rails console
|
|
docker-compose exec app bundle exec rails console
|
|
|
|
# Run migrations
|
|
docker-compose exec app bundle exec rails db:migrate
|
|
|
|
# Seed (creates admin + test drivers)
|
|
docker-compose exec app bundle exec rails db:seed
|
|
|
|
# Logs
|
|
docker-compose logs -f app
|
|
|
|
# Tests (RSpec)
|
|
docker-compose exec app bundle exec rspec
|
|
docker-compose exec app bundle exec rspec spec/models/consolidacao_spec.rb # single file
|
|
|
|
# Rake task (runs manually what the cron job runs hourly)
|
|
docker-compose exec app bundle exec rake historico:atualizar
|
|
|
|
# Activate the hourly cron job on the server
|
|
docker-compose exec app bundle exec whenever --update-crontab
|
|
```
|
|
|
|
## Setup from scratch
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
# Edit .env: set DB_HOST, DB_PASSWORD, and generate SECRET_KEY_BASE with:
|
|
# openssl rand -hex 64
|
|
docker-compose build --no-cache
|
|
docker-compose up -d
|
|
docker-compose exec app bundle exec rails db:create db:migrate db:seed
|
|
```
|
|
|
|
Default credentials (change in production): `admin@gade.com` / `Gade@2026!`
|
|
|
|
## Critical constraint: read-only external table
|
|
|
|
The table `public.db_reem_simplerout_2026` is owned by an external system (SimpleRoute) that updates it every hour. **NEVER** create migrations for it, and never run INSERT/UPDATE/DELETE/DROP/TRUNCATE on it.
|
|
|
|
`Entrega` (app/models/entrega.rb) maps to this table and enforces `readonly? = true`. All queries go through its scopes — the most important being `.pagas` (`status='completed' AND checkin IS NOT NULL`), which defines payment eligibility.
|
|
|
|
## Architecture
|
|
|
|
### Data flow
|
|
|
|
1. External system writes to `db_reem_simplerout_2026` hourly
|
|
2. `Atualizar HistoricoEstimadoJob` (triggered by Whenever cron every hour) counts paid deliveries per driver and writes to `historico_estimados`
|
|
3. Admins/managers create **Consolidações** (payment batches) covering a date range + list of drivers
|
|
4. A 3-step wizard classifies each delivery per driver (Normal/Retirada/Bônus/Desconto toggles)
|
|
5. Finalizing a consolidation sends WhatsApp (Twilio) and email notifications to drivers
|
|
6. Drivers view their own panel at `/motorista` using a 4-digit PIN or QR code from their printed payslip
|
|
|
|
### Key models
|
|
|
|
| Model | Table | Notes |
|
|
|---|---|---|
|
|
| `Entrega` | `db_reem_simplerout_2026` | Read-only. External data. |
|
|
| `Consolidacao` | `consolidacoes` | Payment batch. Enum status: `rascunho/finalizada/arquivada`. Soft-delete via `deleted_at`. |
|
|
| `ConsolidacaoMotorista` | `consolidacao_motoristas` | Join: which drivers are in a consolidation. |
|
|
| `ConsolidacaoEntrega` | `consolidacao_entregas` | Each classified delivery. Enum tipo: `normal/retirada/bonus/desconto`. |
|
|
| `HistoricoEstimado` | `historico_estimados` | Snapshot of hourly estimated values per driver. |
|
|
| `Configuracao` | `configuracoes` | Key-value store for prices and feature flags. Access via `Configuracao.valor('chave')`. |
|
|
| `AuditoriaLog` | `auditoria_logs` | Audit trail. Controllers include `Auditavel` concern and call `auditar!(:acao, registro)`. |
|
|
| `User` | `users` | Devise auth. Roles: `admin/gerente/operador/motorista`. Drivers may have no email — they log in via `pin_code` (4 digits, unique per driver) or `login_token` (QR). |
|
|
|
|
### Authorization
|
|
|
|
Pundit policies in `app/policies/`. `ApplicationController` includes `Pundit::Authorization` and calls `authenticate_user!` on every action. The motorista panel (`/motorista/**`) uses a separate session mechanism (`motorista/sessoes_controller.rb`) — drivers are NOT authenticated via Devise.
|
|
|
|
### Two login flows for drivers
|
|
|
|
- `/auth/login` (Devise, Fase 2) — PIN tab on the standard login page
|
|
- `/motorista/login` (Fase 8) — dedicated numeric keypad, used by QR codes printed on payslips. Prefer this for mobile. Both use `pin_code`.
|
|
|
|
### PDF generation
|
|
|
|
`app/services/pdf/` contains three classes:
|
|
- `BasePdf` — shared black/orange header and footer layout
|
|
- `RelatorioMotoristaPdf` — detailed delivery table per driver
|
|
- `HoleritePdf` — payslip style + embedded QR code (via `rqrcode`/`chunky_png`) linking to `/motorista/acesso/:token`
|
|
|
|
### The consolidation wizard
|
|
|
|
`/consolidacoes/:id/wizard` → `/consolidacao_entregas/validar` → `/consolidacao_entregas/revisar`
|
|
|
|
- **Passo 1** (wizard): pick a driver. Shows progress per driver.
|
|
- **Passo 2** (validar): color-coded toggle buttons per delivery (orange=Normal, dark orange=Retirada, white=Bônus, black=Desconto). Toggle individual or mass-classify. Stimulus controller (`validacao_controller.js`) handles real-time totals and progress.
|
|
- **Passo 3** (revisar): summary for the selected driver, then move to the next driver or save as draft.
|
|
|
|
Finalizing is blocked (server-side + UI) until all drivers have all eligible deliveries classified.
|
|
|
|
### Notifications (NotificacaoService)
|
|
|
|
Controlled by `Configuracao` flags `notificacao_whatsapp` and `notificacao_email`. Failures are rescued and logged — they never abort the finalization. WhatsApp requires Twilio ENV vars + driver `telefone` field in `+5511999998888` format.
|
|
|
|
## Design system
|
|
|
|
Dark theme (default). Colors: background `#0a0a0a`, cards `#1a1a1a`, accent/buttons `#f97316` (orange), text `#ffffff`, success `#22c55e`, error `#ef4444`. Minimum font 16px desktop / 18px mobile. Touch targets minimum 48px height.
|
|
|
|
## Environment variables
|
|
|
|
All config comes from `.env` (never hardcoded). Key variables:
|
|
- `DB_HOST` / `DB_NAME` / `DB_USER` / `DB_PASSWORD` — PostgreSQL connection
|
|
- `DB_EXISTING_ACCOUNT_ID` — filters `db_reem_simplerout_2026` to Gade's account (default: 95907)
|
|
- `SECRET_KEY_BASE` — generate with `openssl rand -hex 64`
|
|
- `APP_HOST` — used in QR code URLs and notification links
|
|
- `TWILIO_*` — WhatsApp notifications (optional)
|
|
- `SMTP_*` — Email notifications (optional, only activates if `SMTP_USERNAME` is set)
|