semillero-special-hotel/docs/ARCHITECTURE.md

7.4 KiB

Architecture and System Design

Variable Remuneration, Compensation, and Commissions System - Hoteles Estelar


1. Technical Stack

  • Frontend: Next.js App Router (React + TypeScript).
  • Styling: Vanilla CSS utilizing CSS Modules (*.module.css) for component-level style isolation, paired with a global variables system (globals.css) defining the design tokens.
  • Backend: Next.js API Routes (Node.js runtime).
  • ORM: Prisma ORM (providing type-safe database queries and automated schema migrations).
  • Database: PostgreSQL (decoupled, configured via environment variables to run on any host/network).
  • Workflow Engine: n8n (external service triggered via API Webhooks). Runs the actual calculation steps, anomaly checks, AI-assisted audits, and notifications. This allows live monitoring of tasks and flexible AI model switching (e.g., swapping OpenAI/Anthropic/Ollama models within n8n nodes without rebuilding the Next.js codebase).
  • Auditing: Custom Prisma Client Extension that automatically intercepts mutations (create, update, delete) and logs the changes into an AuditLog table. This approach is database-agnostic, requires no native OS dependencies, and runs purely inside the runtime.

2. Decoupled Network & Environment Independence

The project is structured to run in any isolated Docker environment. All parameters are fed via environment variables:

  • DATABASE_URL: Connection string for PostgreSQL (e.g. postgresql://user:pass@host:port/dbname).
  • N8N_WEBHOOK_URL: The entry point for the n8n workflow engine.
  • N8N_API_KEY: Token to authorize callbacks from n8n to the Next.js API.
  • NEXTAUTH_SECRET: Secret for securing JWT cookies.

Component Interaction:

graph TD
    User([User Client]) -->|HTTPS| WebApp[Next.js App Router]
    
    subgraph Isolated Network
        WebApp -->|Prisma Client| DB[(PostgreSQL)]
        WebApp -->|HTTP POST Webhook| n8n[n8n Workflow Engine]
        n8n -->|HTTP POST Callback| WebApp
        n8n -->|Interact| LLM[AI Model / Provider]
    end

3. Database Schema Design (Entity-Relationship Diagram)

erDiagram
    REGIONS ||--o{ HOTELS : contains
    HOTELS ||--o{ USERS : houses
    USERS ||--o{ GOALS : achieves
    USERS ||--o{ SALES_RESULTS : generates
    USERS ||--o{ SETTLEMENTS : receives
    
    COMPENSATION_PLANS ||--o{ CALCULATION_RULES : dictates
    COMPENSATION_PLANS ||--o{ SETTLEMENTS : calculates
    
    USERS ||--o{ AUDIT_LOGS : executes
    USERS ||--o{ NOTIFICATIONS : receives

    REGIONS {
        int id PK
        string name
        string code
    }

    HOTELS {
        int id PK
        string name
        string code
        int region_id FK
        string status
    }

    USERS {
        int id PK
        string username
        string email
        string password_hash
        string role "ADMIN | DIRECTOR | GERENTE | LIDER | ANALISTA | CONSULTA | COLABORADOR"
        int hotel_id FK
        string area
        string status "ACTIVE | INACTIVE"
        datetime created_at
    }

    COMPENSATION_PLANS {
        int id PK
        string name
        string code UK
        datetime validity_start
        datetime validity_end
        string type "PERCENTAGE | SCALE | CONDITIONAL | FIXED"
        string formula "JSON or string representation"
        decimal meta_amount
        decimal percentage_rate
        decimal max_cap
        string status "DRAFT | ACTIVE | INACTIVE"
        int version
        int created_by FK
        datetime created_at
    }

    CALCULATION_RULES {
        int id PK
        int plan_id FK
        string type "TIER | BONUS"
        decimal min_achievement "percentage"
        decimal max_achievement "percentage"
        decimal rate "multiplier or percentage"
        decimal payout_amount "fixed payment"
    }

    GOALS {
        int id PK
        string target_type "INDIVIDUAL | TEAM | HOTEL"
        int target_id "user_id, team_id, or hotel_id"
        string period "YYYY-MM"
        decimal amount
        datetime created_at
    }

    SALES_RESULTS {
        int id PK
        string source "EXCEL | API"
        int hotel_id FK
        int user_id FK "colaborador"
        string period "YYYY-MM"
        decimal amount
        int sales_count
        string status "PENDING | PROCESSED"
        int uploaded_by FK
        datetime created_at
    }

    SETTLEMENTS {
        int id PK
        string period "YYYY-MM"
        int plan_id FK
        int user_id FK
        decimal sales_amount
        decimal goal_amount
        decimal achievement_percentage
        decimal calculated_commission
        decimal calculated_bonus
        decimal total_payout
        string status "SIMULATED | PENDING | APPROVED | REJECTED"
        int approved_by FK
        datetime approved_at
        string rejection_reason
        datetime created_at
    }

    AUDIT_LOGS {
        int id PK
        int user_id FK
        string action "CREATE | UPDATE | DELETE | APPROVE | REJECT | LOGIN"
        string target_table
        int target_id
        json previous_value
        json new_value
        string ip_address
        datetime created_at
    }

    NOTIFICATIONS {
        int id PK
        int user_id FK
        string title
        string message
        string status "UNREAD | READ"
        string type "EMAIL | PUSH"
        datetime sent_at
    }

4. Workflows & n8n Integration Model

By offloading calculations and integrations to n8n, we achieve a highly visual, modular, and editable workflow architecture.

4.1. Sales Data Import Workflow

  1. Trigger: Next.js calls POST /api/n8n/import-sales which forwards the parsed Excel payload to n8n's webhook URL.
  2. n8n Processing:
    • Iterates through sales records.
    • Queries Next.js APIs to validate collaborator codes and hotel IDs.
    • Cleanses data and identifies duplicates.
    • Uses an LLM node (with configurable models: GPT-4, Claude 3.5, Gemini, etc.) to perform semantic anomaly checks (e.g., flag sales values that deviate more than 2.5 standard deviations from the collaborator's monthly average).
  3. Response: n8n POSTs the sanitized/flagged list back to POST /api/sales/batch-save in Next.js to update the database.

4.2. Settlement Calculation Workflow

  1. Trigger: Next.js calls n8n to execute the calculation for period YYYY-MM.
  2. n8n Processing:
    • Pulls active plans, individual goals, and actual sales from the Next.js API.
    • Evaluates the mathematical formulas.
    • Evaluates rule scales and applies caps.
    • Generates notifications (via email or push notifications) using n8n integrations.
  3. Response: Updates database records via the Next.js API and completes the task.

5. Security & Access Control Model (RBAC)

We define role-based access restrictions as follows:

Role Access Level Restrictions
Administrador Full system write & read. None.
Director Comercial Reads all dashboards & reports. Can configure metadata. Cannot calculate or approve.
Gerente Hotel Reads data, sales, and settlements for their specific Hotel. Restricted to hotel_id.
Líder Comercial Triggers simulations, views dashboards. Approves/Rejects settlements. Restricted to their region/team.
Analista Financiero Reviews calculations. Exports consolidated PDF/Excel reports. Cannot approve.
Consulta Read-only. No mutations allowed.
Colaborador Consults own history & dashboard. Restricted to user_id.