From 017a34c965276db70638b7d953d504541901c62f Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Wed, 24 Dec 2025 11:12:52 -0300 Subject: [PATCH] docs: comprehensive documentation update - DATABASE.md: Complete schema with ER diagram, all tables, migrations history - ROADMAP.md: Project status, completed/in-progress/backlog items - TASKS.md: Detailed task list to avoid rework - README.md: Added documentation links table - backoffice/README.md: Added auth section (JWT Bearer + Cookie) Schema notes: - Core tables use SERIAL (INT): users, companies, jobs - Newer tables use UUID v4: notifications, tickets, payments - Schema is unified (removed core_* redundant tables) --- README.md | 13 +- backoffice/README.md | 11 + docs/DATABASE.md | 748 ++++++++++++++++++++++++++++++------------- docs/ROADMAP.md | 155 +++++++++ docs/TASKS.md | 97 ++++++ 5 files changed, 803 insertions(+), 221 deletions(-) create mode 100644 docs/ROADMAP.md create mode 100644 docs/TASKS.md diff --git a/README.md b/README.md index 54c8931..b9113dd 100644 --- a/README.md +++ b/README.md @@ -220,8 +220,17 @@ Acesse a documentação interativa em: **http://localhost:8521/docs/index.html** ### Modelagem de Banco Veja a documentação completa do banco de dados em: [docs/DATABASE.md](docs/DATABASE.md) -### Roadmap -Acompanhe o desenvolvimento do projeto em: [ROADMAP.md](ROADMAP.md) +### Roadmap & Tarefas +- 🗺️ **Roadmap:** [docs/ROADMAP.md](docs/ROADMAP.md) - Status e progresso do projeto +- 📋 **Tarefas:** [docs/TASKS.md](docs/TASKS.md) - Lista detalhada para evitar retrabalho + +### Documentação por Componente +| Componente | Documentação | +|------------|--------------| +| **Backend** | [backend/README.md](backend/README.md) | +| **Frontend** | [frontend/README.md](frontend/README.md) | +| **Backoffice** | [backoffice/README.md](backoffice/README.md) | +| **Seeder** | [seeder-api/README.md](seeder-api/README.md) | ### Endpoints Principais diff --git a/backoffice/README.md b/backoffice/README.md index 03c7919..e625f3d 100644 --- a/backoffice/README.md +++ b/backoffice/README.md @@ -9,6 +9,16 @@ GoHorse Jobs SaaS Administration and Subscription Management API. - 👥 **User Management** - Admin controls for users - 🏢 **Company Management** - Tenant administration - 📋 **Subscription Plans** - Monthly/yearly plans +- 🔐 **JWT Authentication** - Bearer token and Cookie support + +## Authentication + +The backoffice supports **two authentication methods**: + +1. **Bearer Token** - `Authorization: Bearer ` +2. **JWT Cookie** - `jwt=` (fallback) + +This is implemented in `src/auth/jwt-auth.guard.ts`. ## Tech Stack @@ -16,6 +26,7 @@ GoHorse Jobs SaaS Administration and Subscription Management API. - TypeScript - Stripe SDK - Swagger (OpenAPI) +- JWT (jsonwebtoken) ## Getting Started diff --git a/docs/DATABASE.md b/docs/DATABASE.md index dc217ae..e1010b2 100644 --- a/docs/DATABASE.md +++ b/docs/DATABASE.md @@ -1,46 +1,69 @@ -# Database Schema Documentation +# 🗄️ Database Schema Documentation -This document outlines the database schema for the GoHorseJobs platform. +Complete database documentation for the GoHorseJobs platform. -## Entity Relationship Diagram +> **Last Updated:** 2024-12-24 +> **Database:** PostgreSQL 15+ +> **ID Strategy:** SERIAL (INT) for core tables, UUID v4 for newer tables + +--- + +## 📊 Entity Relationship Diagram ```mermaid erDiagram + %% Core Entities + users ||--o{ user_companies : "belongs to" + users ||--o{ user_roles : "has roles" + users ||--o{ applications : "submits" + users ||--o{ favorite_jobs : "saves" + users ||--o{ notifications : "receives" + + companies ||--o{ user_companies : "has members" + companies ||--o{ jobs : "posts" + + jobs ||--o{ applications : "receives" + jobs ||--o{ favorite_jobs : "saved by" + jobs ||--o{ job_payments : "has payments" + + regions ||--o{ cities : "contains" + regions ||--o{ companies : "located in" + regions ||--o{ jobs : "located in" + + %% Entities users { - int id PK - varchar identifier UK + int id PK "SERIAL" + varchar identifier UK "login" varchar password_hash - varchar role + varchar role "enum" varchar full_name - varchar language - boolean active - timestamp created_at - timestamp updated_at - timestamp last_login_at + varchar email + varchar name + int tenant_id FK "nullable" + varchar status + } + + user_roles { + int user_id PK,FK + varchar role PK "composite key" } companies { - int id PK + int id PK "SERIAL" varchar name varchar slug UK varchar type varchar document - varchar address + text address int region_id FK - int city_id FK - varchar phone varchar email varchar website - varchar logo_url - text description - boolean active boolean verified - timestamp created_at - timestamp updated_at + boolean active } jobs { - int id PK + int id PK "SERIAL" int company_id FK int created_by FK varchar title @@ -51,263 +74,550 @@ erDiagram varchar currency varchar employment_type varchar work_mode - varchar working_hours - varchar location - int region_id FK - int city_id FK - jsonb requirements - jsonb benefits - boolean visa_support - varchar language_level varchar status boolean is_featured - timestamp created_at - timestamp updated_at } applications { - int id PK + int id PK "SERIAL" int job_id FK - int user_id FK - varchar name - varchar email - varchar phone - varchar line_id - varchar whatsapp + int user_id FK "nullable" + varchar status text message varchar resume_url - jsonb documents - varchar status - text notes - timestamp created_at - timestamp updated_at } regions { - int id PK + int id PK "SERIAL" varchar name varchar country_code varchar code } cities { - int id PK + int id PK "SERIAL" int region_id FK varchar name } - user_companies { - int id PK + notifications { + uuid id PK int user_id FK - int company_id FK - varchar role - jsonb permissions - } - - favorite_jobs { - int id PK - int user_id FK - int job_id FK + varchar type + varchar title + text message + boolean read } job_payments { uuid id PK - uuid job_id FK - uuid user_id FK - varchar stripe_session_id - varchar stripe_payment_intent + int job_id FK + int user_id FK decimal amount - varchar currency varchar status - varchar billing_type - varchar billing_name - varchar billing_email - int duration_days - timestamp created_at - timestamp paid_at + varchar stripe_session_id } - - job_posting_prices { - int id PK - varchar name - decimal price - varchar currency - int duration_days - boolean is_featured - varchar stripe_price_id - boolean active - } - - users ||--o{ user_companies : "belongs to" - companies ||--o{ user_companies : "has members" - companies ||--o{ jobs : "posts" - users ||--o{ jobs : "creates" - jobs ||--o{ applications : "receives" - users ||--o{ applications : "submits" - jobs ||--o{ job_payments : "has payment" - companies ||--o{ user_companies : "has members" - companies ||--o{ jobs : "posts" - users ||--o{ jobs : "creates" - jobs ||--o{ applications : "receives" - users ||--o{ applications : "submits" - regions ||--o{ cities : "contains" - regions ||--o{ companies : "located in" - cities ||--o{ companies : "located in" - regions ||--o{ jobs : "located in" - cities ||--o{ jobs : "located in" - users ||--o{ favorite_jobs : "saves" - jobs ||--o{ favorite_jobs : "saved by" ``` -## Core Tables +--- -### Users (`users`) -Represents system users including Candidates, Recruiters, and Admins. +## 🏗️ Table Overview -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| identifier | VARCHAR | Unique, Email or Username | -| password_hash | VARCHAR | Bcrypt hash | -| role | VARCHAR | `superadmin`, `companyAdmin`, `recruiter`, `jobSeeker` | -| full_name | VARCHAR | Display name | -| language | VARCHAR | Default: 'pt' | -| active | BOOLEAN | Account status | -| created_at | TIMESTAMP | Creation time | -| updated_at | TIMESTAMP | Last update | -| last_login_at | TIMESTAMP | Last login | +| Table | ID Type | Description | Migration | +|-------|---------|-------------|-----------| +| `users` | SERIAL | System users (candidates, recruiters, admins) | 001 | +| `user_roles` | Composite | Additional roles per user | 020 | +| `companies` | SERIAL | Employer organizations | 002 | +| `user_companies` | SERIAL | User ↔ Company mapping | 003 | +| `regions` | SERIAL | States/Provinces/Prefectures | 004 | +| `cities` | SERIAL | Cities within regions | 004 | +| `jobs` | SERIAL | Job postings | 005 | +| `applications` | SERIAL | Job applications | 006 | +| `favorite_jobs` | SERIAL | Saved jobs by users | 007 | +| `password_resets` | SERIAL | Password reset tokens | 008 | +| `notifications` | UUID v4 | User notifications | 016 | +| `tickets` | UUID v4 | Support tickets | 017 | +| `ticket_messages` | UUID v4 | Ticket messages | 017 | +| `job_payments` | UUID v4 | Payment records | 019 | +| `job_posting_prices` | SERIAL | Pricing configuration | 019 | +| `login_audits` | SERIAL | Login audit trail | 013 | +| `activity_logs` | SERIAL | Activity logging | 013 | --- -### Companies (`companies`) -Represents employer organizations. +## 📋 Core Tables -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| name | VARCHAR | Company name | -| slug | VARCHAR | URL-friendly identifier | -| type | VARCHAR | Company type | -| document | VARCHAR | Houjin Bangou / CNPJ | -| address | VARCHAR | Physical address | -| region_id | INTEGER | FK → regions.id | -| city_id | INTEGER | FK → cities.id | -| phone, email, website | VARCHAR | Contact info | -| logo_url | VARCHAR | Logo image URL | -| description | TEXT | Company description | -| active | BOOLEAN | Active status | -| verified | BOOLEAN | Verification status | +### `users` + +System users including Candidates, Recruiters, and Admins. + +```sql +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + identifier VARCHAR(100) UNIQUE NOT NULL, -- Login (username/email) + password_hash VARCHAR(255) NOT NULL, + role VARCHAR(20) NOT NULL, -- 'superadmin'|'companyAdmin'|'recruiter'|'jobSeeker' + + -- Profile + full_name VARCHAR(255), + email VARCHAR(255), + name VARCHAR(255), + phone VARCHAR(30), + + -- Candidate Profile Fields (015) + city VARCHAR(100), + state VARCHAR(50), + title VARCHAR(100), + experience VARCHAR(100), + skills TEXT[], + bio TEXT, + objective TEXT, + + -- Multi-tenancy (020) + tenant_id INT REFERENCES companies(id), + status VARCHAR(20) DEFAULT 'active', + + -- Settings + language VARCHAR(5) DEFAULT 'en', + active BOOLEAN DEFAULT true, + + -- Timestamps + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + last_login_at TIMESTAMP +); +``` + +**Roles:** +- `superadmin` - Platform administrator +- `companyAdmin` - Company administrator +- `recruiter` - Job poster/recruiter +- `jobSeeker` - Candidate/job seeker --- -### Jobs (`jobs`) -Represents job postings. +### `user_roles` -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| company_id | INTEGER | FK → companies.id | -| created_by | INTEGER | FK → users.id | -| title | VARCHAR | Job title | -| description | TEXT | Full job description | -| salary_min | DECIMAL | Minimum salary | -| salary_max | DECIMAL | Maximum salary | -| salary_type | VARCHAR | `hourly`, `daily`, `weekly`, `monthly`, `yearly` | -| currency | VARCHAR | `BRL`, `USD`, `EUR`, `GBP`, `JPY` | -| employment_type | VARCHAR | `full-time`, `part-time`, `contract`, `temporary`, `training`, `voluntary`, `permanent`, `dispatch` | -| work_mode | VARCHAR | `onsite`, `hybrid`, `remote` | -| working_hours | VARCHAR | e.g. "9:00-18:00" | -| location | VARCHAR | Location string | -| region_id | INTEGER | FK → regions.id | -| city_id | INTEGER | FK → cities.id | -| requirements | JSONB | Skills/requirements array | -| benefits | JSONB | Benefits array | -| visa_support | BOOLEAN | Visa sponsorship | -| language_level | VARCHAR | `N5`, `N4`, `N3`, `N2`, `N1`, `beginner`, `none` | -| status | VARCHAR | `draft`, `open`, `closed`, `published`, `paused`, `expired`, `archived`, `reported`, `review` | -| is_featured | BOOLEAN | Featured job flag | +Additional roles per user (for multi-role support). + +```sql +CREATE TABLE user_roles ( + user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + role VARCHAR(50) NOT NULL, + PRIMARY KEY (user_id, role) +); +``` --- -### Applications (`applications`) -Represents job applications. +### `companies` -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| job_id | INTEGER | FK → jobs.id | -| user_id | INTEGER | FK → users.id (nullable for guests) | -| name | VARCHAR | Applicant name | -| email | VARCHAR | Contact email | -| phone | VARCHAR | Phone number | -| line_id | VARCHAR | LINE ID | -| whatsapp | VARCHAR | WhatsApp number | -| message | TEXT | Cover message | -| resume_url | VARCHAR | Resume file URL | -| documents | JSONB | Additional documents | -| status | VARCHAR | `pending`, `reviewed`, `shortlisted`, `rejected`, `hired` | -| notes | TEXT | Recruiter notes | +Employer organizations that post jobs. + +```sql +CREATE TABLE companies ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + slug VARCHAR(255) UNIQUE NOT NULL, -- URL-friendly name + type VARCHAR(50) DEFAULT 'company', -- 'company'|'agency'|'system' + document VARCHAR(100), -- CNPJ/Tax ID + + -- Location + address TEXT, + region_id INT REFERENCES regions(id), + city_id INT REFERENCES cities(id), + + -- Contact + phone VARCHAR(30), + email VARCHAR(255), + website VARCHAR(255), + + -- Branding + logo_url TEXT, + description TEXT, -- JSON or plain text + + -- Status + active BOOLEAN DEFAULT true, + verified BOOLEAN DEFAULT false, + + -- Timestamps + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` --- -## Reference Tables +### `jobs` -### Regions (`regions`) -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| name | VARCHAR | Region name | -| country_code | VARCHAR | e.g. "JP", "BR" | -| code | VARCHAR | Region code | +Job postings created by companies. -### Cities (`cities`) -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| region_id | INTEGER | FK → regions.id | -| name | VARCHAR | City name | +```sql +CREATE TABLE jobs ( + id SERIAL PRIMARY KEY, + company_id INT NOT NULL REFERENCES companies(id) ON DELETE CASCADE, + created_by INT NOT NULL REFERENCES users(id), + + -- Job Details + title VARCHAR(255) NOT NULL, + description TEXT NOT NULL, + + -- Salary + salary_min DECIMAL(12,2), + salary_max DECIMAL(12,2), + salary_type VARCHAR(20), -- 'hourly'|'daily'|'weekly'|'monthly'|'yearly' + currency VARCHAR(3), -- 'BRL'|'USD'|'EUR'|'GBP'|'JPY' + + -- Employment + employment_type VARCHAR(30), -- 'full-time'|'part-time'|'contract'|'dispatch'|... + work_mode VARCHAR(10), -- 'onsite'|'hybrid'|'remote' + working_hours VARCHAR(100), + + -- Location + location VARCHAR(255), + region_id INT REFERENCES regions(id), + city_id INT REFERENCES cities(id), + + -- Requirements & Benefits + requirements JSONB, -- Array of skills/requirements + benefits JSONB, -- Array of benefits + + -- Visa & Language + visa_support BOOLEAN DEFAULT false, + language_level VARCHAR(20), -- 'N5'|'N4'|'N3'|'N2'|'N1'|'beginner'|'none' + + -- Status + status VARCHAR(20) DEFAULT 'open', -- 'draft'|'open'|'closed'|'published'|... + is_featured BOOLEAN DEFAULT false, + + -- Timestamps + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +**Status Values:** +- `draft` - Not published yet +- `open` - Accepting applications +- `published` - Live and visible +- `paused` - Temporarily hidden +- `closed` - No longer accepting +- `expired` - Past expiration date +- `archived` - Archived by employer +- `reported` - Flagged for review +- `review` - Under admin review --- -## Junction Tables +### `applications` + +Job applications from candidates. + +```sql +CREATE TABLE applications ( + id SERIAL PRIMARY KEY, + job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE, + user_id INT REFERENCES users(id), -- Nullable for guest applications + + -- Applicant Info + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + phone VARCHAR(30), + line_id VARCHAR(100), + whatsapp VARCHAR(30), + + -- Application Content + message TEXT, + resume_url VARCHAR(500), + documents JSONB, + + -- Status + status VARCHAR(20) DEFAULT 'pending', -- 'pending'|'reviewed'|'shortlisted'|'rejected'|'hired' + notes TEXT, -- Recruiter notes + + -- Timestamps + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +--- + +## 🌍 Geographic Tables + +### `regions` + +States, provinces, or prefectures. + +```sql +CREATE TABLE regions ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, + country_code VARCHAR(2) NOT NULL, -- 'BR'|'US'|'JP' + code VARCHAR(10) NOT NULL -- 'SP'|'CA'|'13' +); +``` + +**Seeded Regions:** +- 🇧🇷 Brazil: São Paulo (SP), Rio de Janeiro (RJ), Minas Gerais (MG) +- 🇺🇸 USA: California (CA), New York (NY), Texas (TX) +- 🇯🇵 Japan: Tokyo (13), Osaka (27) + +--- + +### `cities` + +Cities within regions. + +```sql +CREATE TABLE cities ( + id SERIAL PRIMARY KEY, + region_id INT NOT NULL REFERENCES regions(id), + name VARCHAR(100) NOT NULL +); +``` + +--- + +## 💰 Payment Tables + +### `job_payments` (UUID) + +Payment records for job postings. + +```sql +CREATE TABLE job_payments ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE, + user_id INT REFERENCES users(id) ON DELETE SET NULL, + + -- Stripe + stripe_session_id VARCHAR(255), + stripe_payment_intent VARCHAR(255), + stripe_customer_id VARCHAR(255), + + -- Amount + amount DECIMAL(12,2) NOT NULL, + currency VARCHAR(3) DEFAULT 'USD', + + -- Status + status VARCHAR(20) DEFAULT 'pending', -- 'pending'|'completed'|'failed'|'refunded'|'expired' + + -- Billing + billing_type VARCHAR(20), -- 'company'|'individual' + billing_name VARCHAR(255), + billing_email VARCHAR(255), + + -- Job Details + duration_days INT DEFAULT 30, + is_featured BOOLEAN DEFAULT false, + + -- Timestamps + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + paid_at TIMESTAMP, + expires_at TIMESTAMP +); +``` + +--- + +### `job_posting_prices` + +Pricing configuration for job postings. + +```sql +CREATE TABLE job_posting_prices ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, + description TEXT, + price DECIMAL(12,2) NOT NULL, + currency VARCHAR(3) DEFAULT 'USD', + duration_days INT DEFAULT 30, + is_featured BOOLEAN DEFAULT false, + stripe_price_id VARCHAR(255), + active BOOLEAN DEFAULT true, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +--- + +## 🔔 Notification Tables + +### `notifications` (UUID) + +User notifications. + +```sql +CREATE TABLE notifications ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + type VARCHAR(50), + title VARCHAR(255), + message TEXT, + read BOOLEAN DEFAULT false, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +--- + +## 🎫 Support Tables + +### `tickets` (UUID) + +Support tickets. + +```sql +CREATE TABLE tickets ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id INT NOT NULL, + subject VARCHAR(255) NOT NULL, + status VARCHAR(20) DEFAULT 'open', -- 'open'|'in_progress'|'resolved'|'closed' + priority VARCHAR(10) DEFAULT 'medium', -- 'low'|'medium'|'high'|'urgent' + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +### `ticket_messages` (UUID) + +Messages within tickets. + +```sql +CREATE TABLE ticket_messages ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + ticket_id UUID NOT NULL REFERENCES tickets(id) ON DELETE CASCADE, + user_id INT NOT NULL, + message TEXT NOT NULL, + is_staff BOOLEAN DEFAULT false, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +--- + +## 📝 Audit Tables + +### `login_audits` + +Login attempt tracking. + +```sql +CREATE TABLE login_audits ( + id SERIAL PRIMARY KEY, + user_id INT, + identifier VARCHAR(100), + success BOOLEAN, + ip_address VARCHAR(45), + user_agent TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +### `activity_logs` + +General activity logging. + +```sql +CREATE TABLE activity_logs ( + id SERIAL PRIMARY KEY, + user_id INT, + entity_type VARCHAR(50), + entity_id INT, + action VARCHAR(50), + details JSONB, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +--- + +## 🔗 Junction Tables + +### `user_companies` -### User Companies (`user_companies`) Maps users to companies (N:M relationship). -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| user_id | INTEGER | FK → users.id | -| company_id | INTEGER | FK → companies.id | -| role | VARCHAR | `companyAdmin`, `recruiter` | -| permissions | JSONB | Custom permissions | +```sql +CREATE TABLE user_companies ( + id SERIAL PRIMARY KEY, + user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + company_id INT NOT NULL REFERENCES companies(id) ON DELETE CASCADE, + role VARCHAR(30) DEFAULT 'recruiter', -- 'companyAdmin'|'recruiter' + permissions JSONB, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(user_id, company_id) +); +``` -### Favorite Jobs (`favorite_jobs`) -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| user_id | INTEGER | FK → users.id | -| job_id | INTEGER | FK → jobs.id | +### `favorite_jobs` + +Saved jobs by users. + +```sql +CREATE TABLE favorite_jobs ( + id SERIAL PRIMARY KEY, + user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(user_id, job_id) +); +``` --- -## Audit Tables +## 🔄 Migrations History -### Login Audits (`login_audits`) -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| user_id | VARCHAR | User identifier | -| identifier | VARCHAR | Login identifier used | -| ip_address | VARCHAR | Client IP | -| user_agent | VARCHAR | Browser/client info | -| created_at | TIMESTAMP | Login time | +| # | File | Description | +|---|------|-------------| +| 001 | `001_create_users_table.sql` | Core users table | +| 002 | `002_create_companies_table.sql` | Companies/employers | +| 003 | `003_create_user_companies_table.sql` | User ↔ Company mapping | +| 004 | `004_create_prefectures_cities_tables.sql` | Geographic data | +| 005 | `005_create_jobs_table.sql` | Job postings | +| 006 | `006_create_applications_table.sql` | Job applications | +| 007 | `007_create_favorite_jobs_table.sql` | Saved jobs | +| 008 | `008_create_password_resets_table.sql` | Password reset tokens | +| 010 | `010_seed_super_admin.sql` | Default superadmin | +| 011 | `011_add_is_featured_to_jobs.sql` | Featured jobs flag | +| 012 | `012_add_work_mode.sql` | Work mode column | +| 013 | `013_create_backoffice_tables.sql` | Audit tables | +| 014 | `014_update_job_status_constraint.sql` | Status enum update | +| 015 | `015_add_candidate_profile_fields.sql` | Candidate profile | +| 016 | `016_create_notifications_table.sql` | Notifications | +| 017 | `017_create_tickets_table.sql` | Support tickets | +| 018 | `018_add_currency_to_jobs.sql` | Currency support | +| 019 | `019_create_job_payments_table.sql` | Payment tracking | +| 020 | `020_unify_schema.sql` | Schema unification | +| 999 | `999_fix_gohorse_schema.sql` | Schema fixes | -### Password Resets (`password_resets`) -| Column | Type | Description | -|--------|------|-------------| -| id | INTEGER | Primary key | -| user_id | INTEGER | FK → users.id | -| token | VARCHAR | Reset token | -| expires_at | TIMESTAMP | Token expiry | -| used | BOOLEAN | Token used status | +--- + +## ⚠️ ID Strategy Notes + +The database uses a **hybrid ID strategy**: + +| Strategy | Tables | Rationale | +|----------|--------|-----------| +| **SERIAL (INT)** | users, companies, jobs, applications, regions, cities | Legacy tables, simpler, faster | +| **UUID v4** | notifications, tickets, job_payments | Newer tables, distributed-friendly | + +> **Note:** The system does NOT use UUID v7 (time-ordered UUIDs). It uses PostgreSQL's `gen_random_uuid()` which generates UUID v4. + +--- + +## 🔒 Security Notes + +1. **Password Hashing:** BCrypt with optional `PASSWORD_PEPPER` environment variable +2. **Soft Deletes:** Not implemented (uses `CASCADE` for referential integrity) +3. **Row-Level Security:** Not implemented (uses application-level checks) +4. **Audit Trail:** `login_audits` and `activity_logs` for compliance + +--- + +## 📚 Related Documentation + +- [Backend README](../backend/README.md) - API documentation +- [Seeder README](../seeder-api/README.md) - Database seeding +- [Backoffice README](../backoffice/README.md) - Admin panel diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..c784e8e --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,155 @@ +# 🗺️ GoHorse Jobs - Roadmap + +Roadmap de desenvolvimento do projeto GoHorse Jobs. + +> **Última Atualização:** 2024-12-24 +> **Branch Atual:** `dev` + +--- + +## 📊 Status Geral + +| Área | Progresso | Status | +|------|-----------|--------| +| **Backend API** | 85% | 🟢 Funcional | +| **Frontend** | 75% | 🟡 Em desenvolvimento | +| **Backoffice** | 60% | 🟡 Em desenvolvimento | +| **Seeder** | 95% | 🟢 Completo | +| **Documentação** | 70% | 🟡 Em progresso | + +--- + +## ✅ Concluído + +### Backend +- [x] Estrutura Clean Architecture +- [x] Autenticação JWT com HttpOnly cookies +- [x] CRUD de usuários, empresas, vagas +- [x] Sistema de candidaturas +- [x] Notificações +- [x] Password reset +- [x] XSS sanitization middleware +- [x] Swagger documentation +- [x] Multi-tenancy básico +- [x] PASSWORD_PEPPER para hash seguro +- [x] 🆕 Schema unificado (eliminado core_*) + +### Frontend +- [x] Login/Logout com cookies +- [x] Dashboard candidato +- [x] Dashboard empresa +- [x] Listagem de vagas +- [x] Detalhes da vaga +- [x] Candidatura a vaga +- [x] Eye icon toggle de senha +- [x] Responsividade básica +- [x] Sonner para notificações + +### Seeder +- [x] 31 empresas (30 tech + System) +- [x] 13 empresas fictícias (ACME, Stark, etc) +- [x] 1129+ vagas +- [x] Users e candidatos +- [x] Regiões (BR, US, JP) +- [x] Cidades +- [x] Notificações +- [x] 🆕 Schema unificado + +### DevOps +- [x] Docker setup backend +- [x] Migrations automáticas +- [x] start.sh script unificado +- [x] Seed reset option + +--- + +## 🔄 Em Progresso + +### Backend +- [ ] Rate limiting +- [ ] Upload de arquivos (currículos) +- [ ] Busca full-text com pg_trgm +- [ ] Webhooks para integrações +- [ ] API de pagamentos (Stripe) + +### Frontend +- [ ] Dashboard admin completo +- [ ] Gestão de candidaturas +- [ ] Filtros avançados de vagas +- [ ] Favoritos (bookmark jobs) +- [ ] Perfil do candidato editável +- [ ] Upload de currículo +- [ ] PWA / Offline support + +### Backoffice +- [ ] Gestão de tenants +- [ ] Gestão de usuários +- [ ] Relatórios +- [ ] Auditoria +- [ ] Moderação de vagas + +--- + +## 📋 Backlog + +### Alta Prioridade +- [ ] Email transacional (welcome, reset, application) +- [ ] Integração Stripe completa +- [ ] Busca avançada com filtros +- [ ] Internacionalização (i18n) +- [ ] Testes E2E frontend + +### Média Prioridade +- [ ] OAuth (Google, LinkedIn) +- [ ] Notificações push (web) +- [ ] Chat em tempo real +- [ ] Analytics dashboard +- [ ] Export CSV/Excel + +### Baixa Prioridade +- [ ] App mobile (React Native) +- [ ] Integração ATS +- [ ] AI matching (job ↔ candidate) +- [ ] Video interviews + +--- + +## 🐛 Bugs Conhecidos + +| ID | Descrição | Prioridade | Status | +|----|-----------|------------|--------| +| #001 | job_payments FK precisa de migration 019 atualizada | Média | 🟡 Pendente | +| #002 | Swagger docs desatualizado em alguns endpoints | Baixa | 🟡 Pendente | + +--- + +## 📁 Estrutura de Documentação + +``` +docs/ +├── DATABASE.md # Schema completo +├── ROADMAP.md # Este arquivo +├── TASKS.md # Tarefas pendentes detalhadas +└── ARCHITECTURE.md # (futuro) Arquitetura detalhada + +backend/ +└── README.md # Documentação da API + +backoffice/ +└── README.md # Documentação do backoffice + +seeder-api/ +└── README.md # Documentação do seeder + +frontend/ +└── README.md # Documentação do frontend +``` + +--- + +## 🔗 Links Úteis + +- **API Docs:** http://localhost:8521/docs/index.html +- **Frontend:** http://localhost:3000 +- **Database Schema:** [docs/DATABASE.md](DATABASE.md) +- **Seeder Info:** [seeder-api/README.md](../seeder-api/README.md) diff --git a/docs/TASKS.md b/docs/TASKS.md new file mode 100644 index 0000000..f70586d --- /dev/null +++ b/docs/TASKS.md @@ -0,0 +1,97 @@ +# 📋 GoHorse Jobs - Tarefas + +Lista detalhada de tarefas para evitar retrabalho. + +> **Última Atualização:** 2024-12-24 + +--- + +## 🔥 Sprint Atual (Dezembro 2024) + +### Backend +- [ ] Corrigir migration 019 (job_payments FK) +- [ ] Atualizar Swagger docs +- [ ] Adicionar testes para novos endpoints +- [ ] Implementar rate limiting + +### Frontend +- [ ] Página de perfil editável +- [ ] Upload de currículo +- [ ] Filtros avançados na listagem de vagas +- [ ] Página de favoritos + +### Documentação +- [x] DATABASE.md - Schema completo +- [x] ROADMAP.md - Este arquivo +- [x] TASKS.md - Tarefas +- [ ] ARCHITECTURE.md - Arquitetura detalhada +- [ ] API.md - Endpoints detalhados + +--- + +## ✅ Recentemente Concluído + +### 2024-12-24 +- [x] **Schema Unification** - Eliminado tabelas core_* redundantes + - Removido `core_companies`, `core_users`, `core_user_roles` + - Unificado em `companies`, `users`, `user_roles` + - Atualizado 11 arquivos (migrations, repositories, seeders) + +- [x] **start.sh Updates** + - Opção 4: Run migrations (Node.js) + - Opção 6: Reset + Migrate + Seed completo + +- [x] **Migration Runner** + - Criado `seeder-api/src/migrate.js` + - Suporte a erros de tabelas existentes + +- [x] **Documentação** + - DATABASE.md reescrito completo + - ROADMAP.md criado + - TASKS.md criado + +### 2024-12-23 +- [x] JWT Auth Guard no backoffice (Bearer + Cookie) +- [x] PASSWORD_PEPPER integration +- [x] Frontend auth improvements +- [x] seeder-api README atualizado + +--- + +## 🚧 Não Fazer (Evitar Retrabalho) + +> ⚠️ **IMPORTANTE:** Estas tarefas NÃO devem ser feitas pois já foram resolvidas ou descartadas. + +| Tarefa | Motivo | +|--------|--------| +| Criar core_companies | REMOVIDO - Usar `companies` | +| Criar core_users | REMOVIDO - Usar `users` | +| Usar UUID para users/jobs | MANTIDO SERIAL - Decisão arquitetural | +| psql para migrations | REMOVIDO - Usar `npm run migrate` | + +--- + +## 📝 Notas de Implementação + +### IDs do Banco +- **SERIAL (INT):** users, companies, jobs, applications, regions, cities +- **UUID v4:** notifications, tickets, job_payments +- **NÃO usar UUID v7** - Não suportado pelo gen_random_uuid() + +### Autenticação +- Backend: JWT em HttpOnly cookie OU Authorization header +- Frontend: Usa cookies automaticamente +- Backoffice: Suporta ambos (Bearer e Cookie) + +### Senhas +- BCrypt com 10 rounds +- PASSWORD_PEPPER obrigatório em produção +- Hash: `bcrypt.hash(password + PEPPER, 10)` + +--- + +## 🔗 Referências + +- [DATABASE.md](DATABASE.md) - Schema do banco +- [ROADMAP.md](ROADMAP.md) - Roadmap geral +- [seeder-api/README.md](../seeder-api/README.md) - Como popular dados