Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

GreenDeal — Proyecto Programado II

Carrera: Ingeniería en Sistemas de Información
Curso: Fundamentos de Programación Web
Profesor: Eddier López
Proyecto: API GraphQL + Aplicación SPA PWA
Fecha de entrega y presentación: miércoles, 10 de junio de 2026
Valor: 30 % de la nota final


1. Datos del equipo

Campo Información
Nombre del proyecto GreenDeal
Modelo de negocio Gestión de ventas turísticas (proveedores, tours, comisiones e informes)
Integrantes Britney Montero Suárez, Diana Monterrey Castillo, Jenyfer Montano Altamirano, Fabricio Álvarez Rodríguez
Repositorio https://github.com/Fabr-i10/greenDeal.git
Frontend (PWA) http://localhost:5000
API GraphQL http://localhost:9002/graphql
Login REST http://localhost:9002/login

Nota: El proyecto está pensado para ejecutarse en local. No se requiere despliegue en la nube para la entrega ni la demostración ante el profesor.


2. Resumen ejecutivo

GreenDeal es una plataforma web para agentes o pequeños operadores turísticos que necesitan:

  • Registrar proveedores (empresas que ofrecen experiencias).
  • Definir tours asociados a un proveedor y un precio por persona en USD.
  • Registrar ventas con cálculo automático de comisión (20 %) e IVA incluido en esa comisión.
  • Consultar reportes mensuales o por rango de fechas.
Requisito del enunciado Cumplimiento en GreenDeal
API GraphQL Apollo Server 5 + Express, esquema en Graph-API/schema.graphql
SPA Una sola página (greendeal/index.html) con navegación por vistas sin recargar
PWA instalable manifest.json, service worker, iconos y modo standalone
Funcionamiento offline Service worker, caché, cola de mutaciones (PouchDB) y sincronización al reconectar
Módulo de usuarios Registro, inicio de sesión, perfil y sesión JWT
Al menos 3 módulos adicionales Proveedores, tours, ventas y reportes (4 módulos)
Seguridad JWT, bcrypt, CORS, validación Zod, aislamiento de datos por usuario

3. Modelo de negocio

3.1 Problema

Los vendedores de experiencias turísticas suelen llevar proveedores, precios y ventas en hojas de cálculo o mensajes. Eso dificulta calcular comisiones, ver totales por periodo y trabajar sin conexión en campo.

3.2 Solución propuesta

GreenDeal centraliza el ciclo:

  1. El usuario (vendedor) se registra y accede a un panel.
  2. Da de alta proveedores y tours con precio por persona en dólares.
  3. Registra ventas indicando tour, fecha y cantidad de personas.
  4. El sistema calcula montos y muestra reportes de desempeño.

3.3 Reglas de negocio acordadas por el grupo

Regla Decisión del grupo Implementación
Moneda Trabajar en USD para precios y reportes formatCurrency con Intl (en-US, USD)
Comisión 20 % sobre el total de la venta salesservice.js (API) y vista previa en formulario de venta
IVA El 20 % ya incluye 13 % de IVA; se desglosa comisión con/sin IVA commissionWithoutVAT = commissionTotal / 1.13
Fecha de venta No puede ser anterior al día actual Validación Zod (cliente) + reglas en salesservice.js (servidor)
Aislamiento de datos Cada usuario solo ve sus proveedores, tours y ventas Columna userId en tablas y filtros en servicios
Integridad referencial No eliminar proveedor con tours; no eliminar tour con ventas Errores de dominio (PROVIDER_HAS_TOURS, TOUR_HAS_SALES)

4. Arquitectura del sistema

4.1 Vista general

flowchart TB
    subgraph cliente ["Cliente (navegador)"]
        SPA["SPA PWA :5000"]
        SW["Service Worker"]
        SPA --> SW
    end

    subgraph local ["Equipo de desarrollo (localhost)"]
        FE["npx serve greendeal/"]
        API["Graph-API :9002"]
        EXP["Express.js"]
        GQL["Apollo /graphql"]
        WS["WebSocket graphql-ws"]
        EXP --> GQL
        EXP --> WS
        API --> EXP
    end

    subgraph datos ["Persistencia"]
        DB[(SQLite db.sqlite3)]
    end

    FE --- SPA
    SPA -->|HTTP POST /graphql + JWT| GQL
    SPA -->|HTTP POST /login| EXP
    SPA -->|WS suscripción newSale| WS
    SW -->|fetch interceptado| GQL
    GQL --> DB
    EXP --> DB
Loading

4.2 Separación de capas (backend)

Capa Responsabilidad Ubicación
Transporte HTTP, CORS, login REST, WebSocket server.js, auth.js, utils/corsconfig.js
GraphQL Esquema, resolvers, errores GraphQL schema.graphql, resolvers.js
Validación Entradas con Zod y reportes utils/domainvalidation.js, utils/reportvalidation.js
Negocio Reglas y acceso a datos services/*.js
Datos Knex + SQLite services/connection.js, database/db.sqlite3

Decisión del grupo: mantener resolvers delgados y no duplicar lógica de negocio en GraphQL; toda regla de cálculo o validación de dominio vive en services/.

4.3 Separación de capas (frontend)

Capa Responsabilidad Ubicación
Shell Arranque, sesión, registro SW index.html, shared/js/app.js
Vistas UI por módulo features/*/
Servicios API Queries y mutations GraphQL js/*service.js
Compartido Utilidades, validación, layout shared/js/, shared/css/
Offline Caché y cola de mutaciones serviceworker.js, sw/*

4.4 Estructura del repositorio

proyectoFunda/
├── README.md                 ← Este documento
├── Graph-API/                ← Backend Node.js + GraphQL
│   ├── server.js
│   ├── schema.graphql
│   ├── resolvers.js
│   ├── auth.js
│   ├── services/
│   ├── utils/
│   ├── init_script/dbscript.js
│   └── database/db.sqlite3
└── greendeal/                ← Frontend SPA PWA
    ├── index.html
    ├── manifest.json
    ├── serviceworker.js
    ├── sw/                   ← Módulos del service worker
    ├── js/                   ← Clientes GraphQL por dominio
    ├── features/               ← Módulos de interfaz
    └── shared/                 ← CSS y JS compartidos

5. Tecnologías utilizadas

5.1 Backend (según enunciado y preferencia del grupo)

Tecnología Versión / uso Motivo de elección
Node.js ES modules Mismo lenguaje que el frontend
Express.js 4.x Servidor HTTP y endpoint /login
Apollo Server 5.x Implementación estándar de API GraphQL
graphql-ws 6.x Suscripciones en tiempo real (newSale)
Knex 3.x Consultas SQL mantenibles
SQLite better-sqlite3 Base relacional simple para desarrollo y demo
JWT jsonwebtoken Sesión stateless para SPA
bcrypt 10 rondas Hash de contraseñas
Zod 3.x Validación de entradas en servidor

5.2 Frontend

Tecnología Uso Motivo de elección
HTML5 / CSS3 Estructura y estilos Requisito base del curso
JavaScript ES modules Sin bundler Servidor estático local (npx serve)
Bootstrap 5 Grid, modales, utilidades Rapidez y diseño responsive
Boxicons Iconografía Consistencia visual
Zod (CDN) Validación de formularios Misma librería conceptual que el backend
PouchDB (CDN) Cola offline en SW Persistir mutaciones sin conexión

6. Módulos funcionales

6.1 Módulo de administración de usuarios (obligatorio)

Funcionalidad Descripción
Registro Alta con nombre, correo, teléfono opcional y contraseña fuerte
Login Autenticación vía POST /login → JWT
Perfil Drawer con correo, teléfono y fecha de registro
Sesión Token en sessionStorage; consulta me en GraphQL

Decisiones:

  • Contraseña con requisitos: mínimo 8 caracteres, mayúscula, minúscula, número y carácter especial; no puede contener el nombre.
  • Token con expiración configurable (JWT_EXPIRES_IN, por defecto 2 horas).

6.2 Módulo de proveedores

CRUD de empresas proveedoras (nombre, cédula jurídica, teléfono, correo, dirección). Listado paginado en interfaz.

6.3 Módulo de tours

CRUD de tours ligados a un proveedor: nombre, descripción, ubicación, precio por persona (USD). No se puede crear tour sin al menos un proveedor.

6.4 Módulo de ventas

Registro de ventas por tour, fecha (YYYY-MM-DD) y cantidad de personas. Vista prevía de totales antes de guardar. Notificación en tiempo real vía suscripción GraphQL al crear una venta.

6.5 Módulo de reportes (análisis de datos)

Reporte mensual o por rango de fechas: totales de ventas, comisiones, IVA, cantidad de ventas y ranking de tours.


7. API GraphQL

7.1 Endpoint y autenticación

  • GraphQL HTTP: POST /graphql
  • Cabecera: Authorization: Bearer <token> en operaciones protegidas
  • Registro público: mutation register (sin token)
  • Login: POST /login con { "email", "password" }{ token, user }

7.2 Operaciones principales

Tipo Operaciones
Query me, providers, tours, sales, provider, tour, sale, monthlyReport, dateRangeReport
Mutation register, createProvider, updateProvider, deleteProvider, createTour, updateTour, deleteTour, createSale, deleteSale
Subscription newSale (canal por usuario: NEW_SALE_<userId>)

7.3 Paginación

Las listas providers, tours y sales aceptan limit (máx. 100, default 10) y offset, y devuelven totalCount.

Decisión del grupo: paginar para mejorar rendimiento en móvil y preparar crecimiento de datos sin cambiar el contrato GraphQL más adelante.

7.4 Ejemplo de cálculo en createSale

Para precio por persona P y cantidad N:

  • totalSale = P × N
  • commissionTotal = totalSale × 0.20
  • commissionWithoutVAT = commissionTotal / 1.13
  • vatAmount = commissionTotal - commissionWithoutVAT

8. Aplicación SPA PWA

8.1 Características PWA

Característica Implementación
Instalable manifest.json, display: standalone, iconos 48–512 px
Responsive CSS propio + Bootstrap; tablas como tarjetas en móvil
Splash Pantalla de carga al iniciar
Offline Service worker versión v41 (módulos en greendeal/sw/)

8.2 Flujo offline (decisión de diseño)

sequenceDiagram
    participant U as Usuario
    participant SW as Service Worker
    participant API as API local :9002

    U->>SW: Mutation sin red
    SW->>SW: Guardar en PouchDB + respuesta optimista
    U->>U: UI actualizada / aviso offline
    Note over U,API: Al volver online
    SW->>API: Reenviar mutaciones pendientes
    API-->>SW: Confirmación
    SW->>SW: Limpiar cola
Loading

Decisiones:

  • Interceptar solo peticiones GraphQL al origen configurado en js/env.js.
  • Caché de lecturas GraphQL por usuario (scope del JWT) para evitar mezclar datos entre cuentas en el mismo navegador.
  • Al cerrar sesión, mensaje al SW para limpiar caché GraphQL del usuario (CLEAR_GRAPHQL_CACHE).

8.3 Configuración de entorno (frontend)

greendeal/js/env.js apunta siempre a la API local:

  • GraphQL: http://localhost:9002/graphql
  • Login: http://localhost:9002/login
  • WebSocket: ws://localhost:9002/graphql

Decisión del grupo: no usar despliegue en la nube; simplificar configuración para la entrega y la exposición en el laboratorio o en el equipo del estudiante.


9. Seguridad

Medida Descripción
Contraseñas Hash con bcrypt; nunca se devuelve el hash al cliente
JWT Secreto en variable JWT_SECRET (archivo .env, no en Git)
Expiración de token JWT_EXPIRES_IN (ej. 2h)
CORS Orígenes locales permitidos (localhost:5000, :5500); opcional CORS_ORIGINS en .env
WebSocket Misma validación de origen que CORS
Autorización userId del token en todas las operaciones de datos
Validación de entrada Zod en servidor; Zod + errores inline en formularios
XSS escapeHtml en contenido dinámico de tablas
Suscripciones Publicación en canal NEW_SALE_<userId> para no exponer ventas de otros usuarios

10. Base de datos

10.1 Motor y ubicación

  • Motor: SQLite 3
  • Archivo: Graph-API/database/db.sqlite3
  • Acceso: Knex (services/connection.js)

10.2 Modelo relacional

erDiagram
    users ||--o{ providers : owns
    users ||--o{ tours : owns
    users ||--o{ sales : owns
    providers ||--o{ tours : offers
    tours ||--o{ sales : has

    users {
        text id PK
        text email UK
        text password
    }
    providers {
        text id PK
        text userId FK
    }
    tours {
        text id PK
        text userId FK
        text providerId FK
        float pricePerPerson
    }
    sales {
        text id PK
        text userId FK
        text tourId FK
        text saleDate
        int quantityPeople
    }
Loading

10.3 Inicialización

cd Graph-API
node init_script/dbscript.js

Advertencia: el script elimina y recrea todas las tablas. Usar solo en desarrollo o antes de una demo controlada.

10.4 Formato de saleDate

Se almacena como texto en formato YYYY-MM-DD (fecha local del formulario input type="date").


11. Validación de datos

Ámbito Herramienta Archivo
Formularios (cliente) Zod + UI inline greendeal/shared/js/schemas.js, form-validation.js
API (servidor) Zod Graph-API/utils/domainvalidation.js
Reportes (servidor) Validadores dedicados Graph-API/utils/reportvalidation.js

Decisión del grupo: validar en cliente y servidor; el cliente mejora la experiencia, el servidor garantiza seguridad aunque alguien llame la API directamente.


12. Instalación y ejecución en local

El profesor o el equipo pueden evaluar el proyecto solo con Node.js, sin Netlify, Render ni otros hostings.

12.1 Requisitos

  • Node.js 18 o superior
  • npm

12.2 Variables de entorno (API)

Copiar Graph-API/.env.example a Graph-API/.env y definir al menos:

Variable Descripción
JWT_SECRET Secreto largo y aleatorio (obligatorio)
JWT_EXPIRES_IN Opcional; por defecto 2h
PORT Opcional; por defecto 9002

CORS_ORIGINS solo hace falta si el frontend se sirve en un puerto distinto a los ya permitidos (5000 y 5500).

12.3 API (terminal 1)

cd Graph-API
npm install
cp .env.example .env
# Editar .env y definir JWT_SECRET
node init_script/dbscript.js
npm start
  • GraphQL: http://localhost:9002/graphql
  • Login: http://localhost:9002/login

12.4 Frontend (terminal 2)

cd greendeal
npx serve -l 5000

Abrir en el navegador: http://localhost:5000

12.5 PWA en local

  • En Chrome/Edge: menú → Instalar aplicación o Añadir a pantalla de inicio (sigue siendo localhost).
  • Para probar en el celular en la misma red: usar la IP del PC (http://192.168.x.x:5000) y agregar ese origen en CORS_ORIGINS del .env.

12.6 Orden recomendado para la demo

  1. Iniciar API (npm start).
  2. Iniciar frontend (npx serve).
  3. Registrar usuario → crear proveedor → tour → venta → reporte.

13. Decisiones de implementación por área (resumen para exposición)

Área Alternativas consideradas Decisión final
Framework frontend React, Vue, vanilla Vanilla JS — menos tooling, encaje con curso
Base de datos PostgreSQL, SQLite SQLite — un archivo local, adecuado para el alcance del curso
Autenticación Sesiones en servidor, JWT JWT — adecuado para SPA desacoplada
API REST puro, GraphQL GraphQL — requisito del proyecto; una sola URL, tipado por esquema
Tiempo real Polling, WebSocket graphql-ws — notificación al registrar venta
Offline Solo caché, cola de mutaciones Caché de queries + cola PouchDB — cumple PWA offline
Estilos Solo Bootstrap, CSS custom Variables CSS + Bootstrap — identidad GreenDeal oscura
Validación Manual, Zod Zod en cliente y servidor
Ejecución Nube vs solo local Solo localnpm start + npx serve en dos terminales

14. Control de versiones y respaldo

El enunciado recomienda un sistema de control de versiones. El grupo utiliza Git con historial de commits (features, correcciones de PWA, paginación, seguridad y validación).

Política acordada: no subir .env ni secretos; respaldar el repositorio remoto antes de la entrega del 10 de junio de 2026.


15. Guion sugerido para la exposición (5–8 min)

  1. Problema y modelo de negocio GreenDeal.
  2. Arquitectura: SPA + API GraphQL + SQLite.
  3. Demo en vivo: registro → proveedor → tour → venta (mostrar cálculo) → reporte.
  4. PWA: instalación en móvil o “Añadir a pantalla de inicio”.
  5. Offline: desconectar red, crear registro, reconectar y sincronizar.
  6. Seguridad: JWT, validación, datos por usuario.
  7. Cómo ejecutar en local (dos terminales).
  8. Limitaciones y trabajo futuro (recordatorios 24 h antes del tour, etc.).

16. Trabajo futuro (fuera del alcance actual)

  • Recordatorios 24 horas antes del tour con fecha/hora y notificaciones push programadas.
  • Despliegue opcional en la nube (no requerido para este curso).
  • Optimización de imagen de fondo (monteverde.jpg) a WebP comprimido.
  • Unificar cálculo de ventas en un solo módulo compartido front/back.
  • Índices SQL en userId y saleDate.

17. Referencias

  • GraphQL — especificación y conceptos
  • Apollo Server — documentación del servidor
  • MDN: Progressive Web Apps
  • Zod — validación de esquemas
  • Enunciado del curso: PROYECTO II.pdf (Proyecto Programado II, Fundamentos de Programación Web)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages