commit 0211bea1864489e6c7d89fc1fb8603ec97b5f36b Author: Consultoria AS Date: Sat Jan 17 18:52:34 2026 -0800 Commit inicial - Sistema de Gestion Hotelera Hacienda San Angel - Backend Node.js/Express con PostgreSQL - Frontend React 19 con Vite - Docker Compose para orquestacion - Documentacion completa en README.md - Scripts SQL para base de datos - Configuracion de ejemplo (.env.example) diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..0fa9f52 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "Bash(curl:*)", + "Bash(git add:*)" + ] + } +} diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a0266be --- /dev/null +++ b/.env.example @@ -0,0 +1,11 @@ +# Variables de entorno para Docker Compose + +# Base de datos PostgreSQL +POSTGRES_PASSWORD=tu_password_seguro + +# Configuracion de correo electronico (Brevo/Sendinblue) +EMAIL_USER=tu_email@ejemplo.com +EMAIL_PASS=tu_api_key + +# Token de Banxico para tipo de cambio +BANXICO_TOKEN=tu_token_banxico diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f510fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Dependencias +node_modules/ +.pnpm-store/ + +# Variables de entorno (contienen secretos) +.env +!.env.example + +# Archivos de build +dist/ +build/ + +# Logs +logs/ +*.log +npm-debug.log* + +# Sistema operativo +.DS_Store +Thumbs.db + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# Archivos temporales +*.tmp +*.temp + +# Base de datos local +*.sql +!scripts bd/**/*.sql + +# Archivos de respaldo +*.bak +*.backup diff --git a/README.md b/README.md new file mode 100644 index 0000000..281c63e --- /dev/null +++ b/README.md @@ -0,0 +1,358 @@ +# Hacienda San Angel - Sistema de Gestion Hotelera + +Sistema integral de gestion para el hotel Hacienda San Angel. Incluye modulos de administracion de empleados, nomina, inventario, gastos, ingresos, y reporteria. + +## Tecnologias + +### Backend +- **Node.js** con Express 5 +- **PostgreSQL 15** como base de datos +- **Nodemailer** para envio de correos (Brevo/Sendinblue) +- **Stripe** para procesamiento de pagos +- **Axios** para consultas externas (tipo de cambio Banxico) + +### Frontend +- **React 19** con Vite 7 +- **React Router DOM 7** para navegacion +- **React Hook Form** + **Yup** para validacion de formularios +- **Bootstrap 5** + **Tailwind CSS** para estilos +- **Axios** para peticiones HTTP +- **XLSX** para exportacion de datos a Excel + +### Infraestructura +- **Docker** y **Docker Compose** para contenedorizacion +- **PostgreSQL 15** en contenedor + +--- + +## Estructura del Proyecto + +``` +Hotel/ +├── backend/ +│ ├── Dockerfile +│ └── hotel_hacienda/ +│ ├── src/ +│ │ ├── app.js # Configuracion Express +│ │ ├── server.js # Punto de entrada +│ │ ├── controllers/ # Logica de negocio +│ │ ├── routes/ # Definicion de rutas API +│ │ ├── middlewares/ # Validadores +│ │ ├── db/ # Conexion a PostgreSQL +│ │ └── services/ # Servicios (email) +│ ├── scripts bd/ # Scripts SQL para la BD +│ └── package.json +├── frontend/ +│ ├── Dockerfile +│ └── Frontend-Hotel/ +│ ├── src/ +│ │ ├── App.jsx # Rutas principales +│ │ ├── main.jsx # Punto de entrada +│ │ ├── components/ # Componentes reutilizables +│ │ ├── pages/ # Paginas de la aplicacion +│ │ ├── services/ # Servicios API +│ │ ├── context/ # Context API +│ │ └── styles/ # Estilos globales +│ └── package.json +├── docker-compose.yml +├── .env.example +└── README.md +``` + +--- + +## Modulos del Sistema + +### 1. Dashboard +- **Income**: Vista general de ingresos +- **Hotel P&L**: Estado de perdidas y ganancias del hotel +- **Restaurant P&L**: Estado de perdidas y ganancias del restaurante +- **Budget**: Presupuesto +- **Cost Per Room**: Costo por habitacion +- **Room Analysis**: Analisis de ocupacion de habitaciones +- **Expenses**: Resumen de gastos + +### 2. Nomina y Empleados (Payroll) +- Gestion de empleados (alta, baja, modificacion) +- Contratos laborales +- Control de asistencia +- Uniformes +- Pago diario + +### 3. Gastos (Expenses) +- Registro de gastos +- Pagos mensuales recurrentes +- Aprobacion de gastos (flujo de aprobacion) +- Proveedores +- Reportes de gastos +- Entradas de compras + +### 4. Inventario (Inventory) +- Catalogo de productos +- Ajustes de inventario +- Salidas de inventario +- Salidas de ama de llaves (Housekeeper) +- Reportes de inventario +- Descarte de productos + +### 5. Ingresos (Income) +- Registro de ingresos +- Reportes de ingresos +- Integracion con sistema Horux + +### 6. Hotel +- Gestion de propiedades +- Gestion de habitaciones + +### 7. Configuracion (Settings) +- Gestion de habitaciones +- Configuracion del sistema +- Gestion de usuarios + +--- + +## API Endpoints + +### Autenticacion +- `POST /api/auth/login` - Iniciar sesion +- `POST /api/auth/create` - Crear usuario +- `POST /api/auth/recover` - Recuperar contrasena + +### Empleados +- `GET /api/employees` - Listar empleados +- `POST /api/employees/new` - Crear empleado +- `PUT /api/employees/update` - Actualizar empleado +- `GET /api/employees/attendance` - Obtener asistencia + +### Contratos +- `GET /api/contracts` - Listar contratos +- `POST /api/contracts` - Crear contrato +- `PUT /api/contracts` - Actualizar contrato + +### Productos/Inventario +- `GET /api/products` - Listar productos +- `POST /api/products` - Crear producto +- `PUT /api/products` - Actualizar producto + +### Gastos +- `GET /api/expenses` - Listar gastos +- `POST /api/expenses` - Crear gasto +- `PUT /api/expenses` - Actualizar gasto +- `GET /api/expenses/pending` - Gastos pendientes de aprobacion + +### Ingresos +- `GET /api/incomes` - Listar ingresos +- `POST /api/incomes` - Registrar ingreso +- `GET /api/incomeshrx` - Ingresos Horux + +### Pagos +- `POST /api/payment` - Procesar pago con Stripe + +### Tipo de Cambio +- `GET /api/exchange` - Obtener tipo de cambio (Banxico) + +### Configuracion +- `GET /api/settings` - Obtener configuracion +- `PUT /api/settings` - Actualizar configuracion + +--- + +## Guia de Instalacion + +### Requisitos Previos +- Docker y Docker Compose instalados +- Git + +### Opcion 1: Instalacion con Docker (Recomendado) + +1. **Clonar el repositorio** +```bash +git clone https://git.consultoria-as.com/usuario/Hacienda-San-Angel.git +cd Hacienda-San-Angel +``` + +2. **Configurar variables de entorno** +```bash +cp .env.example .env +``` + +Editar el archivo `.env` con los valores correspondientes: +```env +POSTGRES_PASSWORD=tu_password_seguro +EMAIL_USER=tu_email@ejemplo.com +EMAIL_PASS=tu_api_key_brevo +BANXICO_TOKEN=tu_token_banxico +``` + +3. **Construir e iniciar los contenedores** +```bash +docker-compose up -d --build +``` + +4. **Verificar que los servicios esten corriendo** +```bash +docker-compose ps +``` + +5. **Importar la base de datos** +```bash +# Copiar el archivo SQL al contenedor +docker cp backupcondatos22122025.sql postgres_db:/tmp/ + +# Ejecutar el script SQL +docker exec -it postgres_db psql -U oposgres -d haciendasanangel -f /tmp/backupcondatos22122025.sql +``` + +6. **Acceder a la aplicacion** +- Frontend: http://localhost:5172 +- Backend API: http://localhost:4000/api + +### Opcion 2: Instalacion Manual (Desarrollo) + +#### Backend + +1. **Navegar al directorio del backend** +```bash +cd backend/hotel_hacienda +``` + +2. **Instalar dependencias** +```bash +npm install +``` + +3. **Configurar variables de entorno** +```bash +cp .env.example .env +# Editar .env con los valores correspondientes +``` + +4. **Iniciar el servidor** +```bash +npm run dev # Desarrollo con nodemon +npm start # Produccion +``` + +#### Frontend + +1. **Navegar al directorio del frontend** +```bash +cd frontend/Frontend-Hotel +``` + +2. **Instalar dependencias** +```bash +npm install +``` + +3. **Configurar variables de entorno** +```bash +cp .env.example .env +# Editar .env con la URL del API +``` + +4. **Iniciar la aplicacion** +```bash +npm run dev # Desarrollo +npm run build # Construir para produccion +``` + +--- + +## Base de Datos + +### Configuracion +- **Motor**: PostgreSQL 15 +- **Base de datos**: haciendasanangel +- **Usuario**: oposgres + +### Scripts SQL +Los scripts de la base de datos se encuentran en `backend/hotel_hacienda/scripts bd/funcionesparaproduccion/`. Incluyen: + +- Funciones para empleados y contratos +- Funciones para gastos e ingresos +- Funciones para inventario +- Funciones para reporteria +- Funciones de autenticacion + +--- + +## Variables de Entorno + +### Backend (.env) +| Variable | Descripcion | +|----------|-------------| +| PORT | Puerto del servidor (default: 4000) | +| DB_HOST | Host de PostgreSQL | +| DB_PORT | Puerto de PostgreSQL (default: 5432) | +| DB_USER | Usuario de PostgreSQL | +| DB_PASSWORD | Contrasena de PostgreSQL | +| DB_NAME | Nombre de la base de datos | +| EMAIL_HOST | Servidor SMTP | +| EMAIL_PORT | Puerto SMTP | +| EMAIL_USER | Usuario SMTP | +| EMAIL_PASS | Contrasena/API Key SMTP | +| URL_CORS | URL permitida para CORS | +| BANXICO_TOKEN | Token API de Banxico | +| STRIPE_SECRET_KEY | Llave secreta de Stripe | + +### Frontend (.env) +| Variable | Descripcion | +|----------|-------------| +| VITE_API_BASE_URL | URL base del API backend | + +--- + +## Despliegue en Produccion + +### Con Docker Compose + +1. Asegurarse de tener configurado el archivo `.env` con valores de produccion + +2. Modificar `docker-compose.yml` si es necesario: + - Cambiar `URL_CORS` a tu dominio de produccion + - Configurar volumenes persistentes para la base de datos + +3. Iniciar los servicios: +```bash +docker-compose up -d +``` + +### Notas de Seguridad +- Cambiar las contrasenas por defecto +- Usar HTTPS en produccion (configurar con nginx o similar) +- Respaldar la base de datos regularmente +- No exponer el puerto de PostgreSQL al exterior + +--- + +## Mantenimiento + +### Respaldo de Base de Datos +```bash +docker exec postgres_db pg_dump -U oposgres haciendasanangel > backup_$(date +%Y%m%d).sql +``` + +### Ver logs +```bash +docker-compose logs -f backend +docker-compose logs -f frontend +docker-compose logs -f postgres +``` + +### Reiniciar servicios +```bash +docker-compose restart +``` + +--- + +## Licencia + +Proyecto privado - Hacienda San Angel + +--- + +## Contacto + +Para soporte tecnico, contactar al equipo de desarrollo. diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..856ae91 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,19 @@ +FROM node:20-alpine + +WORKDIR /app + +# Copiar archivos de dependencias +COPY hotel_hacienda/package*.json ./ + +# Instalar dependencias +RUN npm ci --only=production + +# Copiar codigo fuente +COPY hotel_hacienda/src ./src +COPY hotel_hacienda/index.js ./ + +# Exponer puerto +EXPOSE 4000 + +# Comando de inicio +CMD ["node", "src/server.js"] diff --git a/backend/hotel_hacienda/.env.example b/backend/hotel_hacienda/.env.example new file mode 100644 index 0000000..42ae6ff --- /dev/null +++ b/backend/hotel_hacienda/.env.example @@ -0,0 +1,24 @@ +# Configuracion del servidor +PORT=4000 + +# Configuracion de base de datos PostgreSQL +DB_HOST=localhost +DB_PORT=5432 +DB_USER=oposgres +DB_PASSWORD=tu_password_seguro +DB_NAME=haciendasanangel + +# Configuracion de correo electronico (Brevo/Sendinblue) +EMAIL_HOST=smtp-relay.brevo.com +EMAIL_PORT=587 +EMAIL_USER=tu_email@ejemplo.com +EMAIL_PASS=tu_api_key + +# Configuracion de CORS +URL_CORS=http://localhost:5172 + +# Token de Banxico para tipo de cambio +BANXICO_TOKEN=tu_token_banxico + +# Stripe (pagos) +STRIPE_SECRET_KEY=sk_test_xxx diff --git a/backend/hotel_hacienda/.gitignore b/backend/hotel_hacienda/.gitignore new file mode 100644 index 0000000..9a5aced --- /dev/null +++ b/backend/hotel_hacienda/.gitignore @@ -0,0 +1,139 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite logs files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/backend/hotel_hacienda/README.md b/backend/hotel_hacienda/README.md new file mode 100644 index 0000000..4aca821 --- /dev/null +++ b/backend/hotel_hacienda/README.md @@ -0,0 +1,2 @@ +# hotel_hacienda +Proyecto para el hotel_hacienda, trabajo independiente. diff --git a/backend/hotel_hacienda/index.js b/backend/hotel_hacienda/index.js new file mode 100644 index 0000000..357cba9 --- /dev/null +++ b/backend/hotel_hacienda/index.js @@ -0,0 +1 @@ +require('./src/server.js'); \ No newline at end of file diff --git a/backend/hotel_hacienda/package-lock.json b/backend/hotel_hacienda/package-lock.json new file mode 100644 index 0000000..c940d9e --- /dev/null +++ b/backend/hotel_hacienda/package-lock.json @@ -0,0 +1,1669 @@ +{ + "name": "api_hotelhacienda", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "api_hotelhacienda", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.13.2", + "cors": "^2.8.5", + "csv-parser": "^3.2.0", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "express-validator": "^7.2.1", + "nodemailer": "^7.0.10", + "pg": "^8.16.3", + "stripe": "^20.1.2", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "nodemon": "^3.1.10" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/csv-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz", + "integrity": "sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA==", + "license": "MIT", + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-validator": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.2.1.tgz", + "integrity": "sha512-CjNE6aakfpuwGaHQZ3m8ltCG2Qvivd7RHtVMS/6nVxOM7xVGqr4bhflsm4+N5FP5zI7Zxp+Hae+9RE+o8e3ZOQ==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "validator": "~13.12.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemailer": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.10.tgz", + "integrity": "sha512-Us/Se1WtT0ylXgNFfyFSx4LElllVLJXQjWi2Xz17xWw7amDKO2MLtFnVp1WACy7GkVGs+oBlRopVNUzlrGSw1w==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/nodemon": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pg": { + "version": "8.16.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", + "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", + "license": "MIT", + "peer": true, + "dependencies": { + "pg-connection-string": "^2.9.1", + "pg-pool": "^3.10.1", + "pg-protocol": "^1.10.3", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.2.7" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", + "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", + "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", + "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", + "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stripe": { + "version": "20.1.2", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-20.1.2.tgz", + "integrity": "sha512-qU+lQRRJnTxmyvglYBPE24/IepncmywsAg0GDTsTdP2pb+3e3RdREHJZjKgqCmv0phPxN/nmgNPnIPPH8w0P4A==", + "license": "MIT", + "dependencies": { + "qs": "^6.14.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@types/node": ">=16" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + } + } +} diff --git a/backend/hotel_hacienda/package.json b/backend/hotel_hacienda/package.json new file mode 100644 index 0000000..9611451 --- /dev/null +++ b/backend/hotel_hacienda/package.json @@ -0,0 +1,29 @@ +{ + "name": "api_hotelhacienda", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js", + "dev": "nodemon server.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "axios": "^1.13.2", + "cors": "^2.8.5", + "csv-parser": "^3.2.0", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "express-validator": "^7.2.1", + "nodemailer": "^7.0.10", + "pg": "^8.16.3", + "stripe": "^20.1.2", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "nodemon": "^3.1.10" + } +} diff --git a/backend/hotel_hacienda/src/app.js b/backend/hotel_hacienda/src/app.js new file mode 100644 index 0000000..7a9762e --- /dev/null +++ b/backend/hotel_hacienda/src/app.js @@ -0,0 +1,51 @@ +const express = require('express'); +const app = express(); +const cors = require('cors'); +require("dotenv").config(); + +const corsOptions = { + origin: process.env.URL_CORS, // sin slash al final + methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowedHeaders: ["Content-Type", "Authorization"] +}; +app.use(cors(corsOptions)); + +app.use(express.json()); + +//rutas +const authRoutes = require('./routes/auth.routes'); +const employeeRoutes = require('./routes/employee.routes'); +const contractsRoutes = require('./routes/contract.routes'); +const reportcontractRoutes = require('./routes/reportcontract.routes'); +const productRoutes = require('./routes/product.routes'); +const expenseRoutes = require('./routes/expense.routes'); +const statusRoutes = require('./routes/status.routes'); +const paymentRoutes = require('./routes/payment.routes'); +const settingsRoutes = require('./routes/settings.routes'); +const emailRoutes = require('./routes/mail.routes'); +const incomeRoutes = require('./routes/incomes.routes'); +const purchaseRoutes = require('./routes/purchase.routes'); +const exchangeRoutes = require('./routes/exchange.routes'); +const hotelRoutes = require('./routes/hotelpl.routes'); +const restaurantRoutes = require('./routes/restaurantpl.routes'); +const incomehrxRoutes = require('./routes/incomehrx.routes'); + +//Prefijo +app.use('/api/employees', employeeRoutes); +app.use('/api/contracts', contractsRoutes); +app.use('/api/reportcontracts', reportcontractRoutes); +app.use('/api/products', productRoutes); +app.use('/api/auth', authRoutes); +app.use('/api/expenses', expenseRoutes); +app.use('/api/status', statusRoutes); +app.use('/api/payment', paymentRoutes); +app.use('/api/settings',settingsRoutes); +app.use('/api/emails',emailRoutes); +app.use('/api/incomes',incomeRoutes); +app.use('/api/incomeshrx',incomehrxRoutes); +app.use('/api/purchases',purchaseRoutes); +app.use('/api/exchange',exchangeRoutes); +app.use('/api/hotelpl',hotelRoutes); +app.use('/api/restaurantpl',restaurantRoutes); + +module.exports = app; diff --git a/backend/hotel_hacienda/src/controllers/auth.controller.js b/backend/hotel_hacienda/src/controllers/auth.controller.js new file mode 100644 index 0000000..626578e --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/auth.controller.js @@ -0,0 +1,102 @@ +const pool = require('../db/connection'); +const transporter = require('../services/mailService'); +const crypto = require('crypto'); + +const login = async (req, res) => { + const { name_mail_user, user_pass } = req.body; + + try { + const result = await pool.query('SELECT * from validarusuario($1, $2)', [name_mail_user, user_pass]); + const { status, rol, user_id,user_name } = result.rows[0]; + + + let message = ''; + switch (status) { + case 1: + message = 'Usuario autenticado correctamente'; + break; + case 2: + message = 'Usuario o contraseña incorrectos'; + break; + default: + message = 'Error desconocido en la validación'; + } + + res.json({ + rol, + user_id, + user_name, + message }); + } catch (error) { + console.error(error); + res.status(500).json({ status: 500, message: 'Error interno del servidor' }); + } +}; +const createuser = async (req, res) => { + const { name_user,id_rol, email,user_pass } = req.body; + + try { + const result = await pool.query('SELECT createuser($1, $2, $3, $4) AS status', [name_user, id_rol, email, user_pass]); + + const status = result.rows[0].status; + + + res.json({ + message: "Se agrego el usuario correctamente", + status}); + } catch (error) { + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo agregar al usuario' }); + } +}; + +const passRecover = async (req, res) => { + try { + const {user_mail } = req.body; + + const new_pass = crypto + .randomBytes(12) + .toString('base64') + .slice(0, 12); + + const result = await pool.query( + 'SELECT reppassuser($1,$2) AS status', + [user_mail, new_pass] + ); + + const status = result.rows[0].status; + + if (status !== 1) { + return res.json({ + message: 'Correo NO registrado.' + }); + } + + const mailOptions = { + from: 'soporte@horuxfin.com', + to: user_mail, + subject: `Nueva contraseña`, + html: ` +

Recuperación de contraseña

+

Se generó una nueva contraseña para el correo ${user_mail}

+

Contraseña: ${new_pass}

+

Por favor mantenla y borra el correo una vez resguardada.

+ `, + }; + + await transporter.sendMail(mailOptions); + + res.json({ + message: 'Correo enviado con nueva contraseña.', + status + }); + + } catch (error) { + console.error(error); + res.status(500).json({ + message: 'No se pudo mandar el correo de recuperación' + }); + } +}; + +module.exports = { login,createuser,passRecover}; diff --git a/backend/hotel_hacienda/src/controllers/contract.controller.js b/backend/hotel_hacienda/src/controllers/contract.controller.js new file mode 100644 index 0000000..cb08f2a --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/contract.controller.js @@ -0,0 +1,298 @@ +const pool = require('../db/connection'); +const transporter = require('../services/mailService'); // importa el transporter + +const getContracts = async (req, res) => { + try { + // Leer query params con valores por defecto + const page = parseInt(req.query.page) || 1; // Página actual + const limit = parseInt(req.query.limit) || 1000; // Cantidad por página + const offset = (page - 1) * limit; // Desde dónde empezar + + // Llamamos a la función con LIMIT y OFFSET + const result = await pool.query( + `SELECT * FROM getcontracts() LIMIT $1 OFFSET $2`, + [limit, offset] + ); + + // Obtener total para calcular páginas + const totalResult = await pool.query('SELECT COUNT(*) FROM contracts'); + const total = parseInt(totalResult.rows[0].count); + const totalPages = Math.ceil(total / limit); + + const contracts = result.rows.map(con => ({ + id_contract: con.id_contract, + name_employee: con.name_employee, + position_employee: con.position_employee, + area_employee: con.area_employee, + contract_start: con.contratc_start, + contract_end: con.contratc_end, + uniforms: con.uniforms, + daily_pay: con.daily_pay, + status_contract: con.status_contract, + })); + + res.json({ + page, + limit, + total, + totalPages, + data: contracts + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener los contratos' }); + } +}; +//CONTRATOS CERCA DE TERMINAR, 1 MES O MENOS DE TIEMPO +const neartoend = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM contratcsneartoend() as contractsneartoend', + ); + const neartoend = result.rows[0].contractsneartoend; + + res.json({ + message: 'Contratos cerca de terminar', + data: neartoend + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener los contratos' }); + } +} + + +//listado de posiciones +const getpositions = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM getpositions()', + ); + const positions = result.rows.map(pos => ({ + id_position: pos.id_position, + name_position: pos.name_position, + spanish_name: pos.spanish_name + })); + + res.json({ + data:positions + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener las posiciones' }); + } +}; + +const getareas = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM getareas()', + ); + const areas = result.rows.map(ar => ({ + id_area: ar.id_area, + name_area: ar.name_area, + })); + + res.json({ + data:areas + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener las areas' }); + } +}; + +const newContract = async (req, res) => { + try { + const { + rfc_emp, + id_position_emp, + id_area_emp, + start_contract, + end_contract, + new_daily_pay, + boss_rfc, + boss_name, + uniforms} = req.body; + let message = ""; + + const result = await pool.query('SELECT newcontract($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb) AS status', + [rfc_emp,id_position_emp,id_area_emp,start_contract,end_contract,new_daily_pay,boss_rfc,boss_name,JSON.stringify(uniforms)]); + const newcontract = result.rows[0].status; + if(newcontract == 1) + message = "Contrato generado correctamente"; + else + message = "No se pudo agregar el contrato" + res.json({ + message, + idNewContract: newcontract + }); + } catch (error) { + console.error(error); + res.status(500).json({ message: 'No se pudo generar el nuevo contrato' }); + } +} +const updateContract = async (req, res) => { + try { + const { + rfc_emp, + id_position_emp, + id_area_emp, + start_contract, + end_contract, + status_contract, + new_daily_pay, + boss_rfc, + boss_name, + reason, + uniforms} = req.body; + const { id } = req.params; + let message = ""; + + const result = await pool.query('SELECT updatecontract($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12::jsonb) AS status', + [id,rfc_emp,id_position_emp,id_area_emp,start_contract,end_contract,status_contract,new_daily_pay,boss_rfc,boss_name,reason,JSON.stringify(uniforms)]); + const newcontract = result.rows[0].status; + if(newcontract == 1) + message = "Contrato actualizado correctamente"; + else + message = "No se pudo actualizar el contrato" + res.json({ + message, + idNewContract: newcontract + }); + } catch (error) { + console.error(error); + res.status(500).json({ message: 'No se pudo generar el nuevo contrato' }); + } +}; + +const getContract = async (req, res) => { + try { + + const { id } = req.params; + console.log(id); + + const result = await pool.query( + `SELECT * FROM getcontracts() WHERE id_contract = $1 LIMIT 1 `, + [id] + ); + const contracts = result.rows.map(con => ({ + id_contract: con.id_contract, + name_employee: con.name_employee, + position_employee: con.position_employee, + area_employee: con.area_employee, + contract_start: con.contratc_start, + contract_end: con.contratc_end, + uniforms: con.uniforms, + daily_pay: con.daily_pay, + status_contract: con.status_contract + })); + + res.json({ + + data: contracts + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener los contratos' , error}); + } +}; + +const getbosses = async (req, res) => { + try { + + const result = await pool.query( + `SELECT * FROM getbosses()` + ); + const bosses = result.rows.map(con => ({ + rfc_boss: con.rfc_boss, + name_boss: con.name_boss, + })); + + res.json({ + + data: bosses + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'No se pudieron obtener los jefes' , error}); + } +}; + +const disabledcontracts = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM disabledcontracts() as total', + ); + const disabled = result.rows[0].contractsneartoend; + + res.json({ + message: "contratos expirados", + data:disabled + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener las areas' }); + } +}; +const reportEmployeeContract = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM reportemployeecontract()', + ); + const report = result.rows.map(rep => ({ + name_employee: rep.name_employee, + rfc_employee: rep.rfc_employee, + nss_employee: rep.nss_employee, + name_position: rep.name_position, + spanish_name: rep.spanish_name, + name_area: rep.name_area, + addres_employee: rep.name_area, + phone_employee: rep.phone_employee, + email_employee: rep.email_employee , + birthday: rep.birthday, + curp: rep.curp , + name_study: rep.name_study, + id_contract: rep.id_contract , + contratc_start:rep.contract_start, + contratc_end: rep.contract_end, + name_status: rep.name_status , + daily_pay:rep.daily_pay , + rfc_boss: rep.rfc_boss , + name_boss: rep.name_boss , + reasonfordismissal: rep.reasonfordismissal , + name_contact: rep.name_contact, + tel_contact: rep.tel_contact , + name_relationship: rep.name_relationship + + })); + + res.json({ + data:report + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener el reporte' }); + } +}; + +module.exports = { + getContract, + getContracts, + neartoend, + getpositions, + getareas, + newContract, + updateContract, + disabledcontracts, + getbosses, + reportEmployeeContract +}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/employee.controller.js b/backend/hotel_hacienda/src/controllers/employee.controller.js new file mode 100644 index 0000000..df38162 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/employee.controller.js @@ -0,0 +1,269 @@ +const pool = require('../db/connection'); + +const getEmployees = async (req, res) => { + try { + // Leer query params con valores por defecto + const page = parseInt(req.query.page) || 1; // Página actual + const limit = parseInt(req.query.limit) || 500; // Cantidad por página + const offset = (page - 1) * limit; // Desde dónde empezar + + // Llamamos a la función con LIMIT y OFFSET + const result = await pool.query( + `SELECT * FROM getemployees() LIMIT $1 OFFSET $2`, + [limit, offset] + ); + + // Obtener total para calcular páginas + const totalResult = await pool.query('SELECT COUNT(*) FROM employees'); + const total = parseInt(totalResult.rows[0].count); + const totalPages = Math.ceil(total / limit); + + const employees = result.rows.map(emp => ({ + employee_rfc: emp.employee_rfc, + name_employee: emp.name_employee, + nss_employe: emp.nss_employe, + position_employee: emp.position_employee, + area_employee: emp.area_employee, + phone_employee: emp.phone_employee, + end_contract: emp.end_contract, + daily_pay: emp.daily_pay, + uniforms: emp.uniforms, + status: emp.status, + birthday: emp.birthday, + curp: emp.curp + })); + + res.json({ + page, + limit, + total, + totalPages, + data: employees + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener empleados' }); + } +}; + +//TOTAL DE EMPLEADOS CON CONTRATO ACTIVO +const getTotalActiveEmployees = async (req, res) => { + try { + + const result = await pool.query( + 'SELECT * FROM activeemployeesnumber() as activenumber', + ); + const activeEmployees = result.rows[0].activenumber; + + res.json({ + message: 'Total de empleados activos', + data: activeEmployees + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener el total de empleados ' }); + } +}; + +//OBTENER UN SOLO EMPLEADO +const getEmployee = async (req, res) => { + try { + const { rfcEmployee} = req.body; + const result = await pool.query( + 'SELECT * FROM getoneemployee($1)', + [rfcEmployee] + ); + + const employee = result.rows.map(emp => ({ + name_emp: emp.name_emp, + rfc_emp: emp.rfc_emp, + nss_emp: emp.nss_emp, + id_position_emp: emp.id_position_emp, + id_area_emp: emp.id_area_emp, + addres_emp:emp.addres_emp, + phone_emp: emp.phone_emp, + email_emp: emp.email_emp, + daily_pay: emp.daily_pay, + uniforms: emp.uniforms, + birthday: emp.birthday, + curp: emp.curp + })); + + if (result.rows.length > 0) { + res.json({ + message: 'Empleado existio previamente', + data: employee + }); + } + else + { + res.json({ + message: 'El pleneado no existe.', + data: 0 // Devuelve la primera fila (o todas si quieres) + }); + } + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener empleado' }); + } +} + +const newEmployee = async(req,res)=>{ + try{ + const { + name_emp, + rfc_emp, + nss_emp, + addres_emp, + phone_emp, + email_emp, + birthday_emp, + curp_emp, + study_emp , + emergency_name , + emergency_tel, + relationship_id + } = req.body; + const result = await pool.query('SELECT newemployee($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12) AS STATUS', + [name_emp,rfc_emp,nss_emp,addres_emp,phone_emp,email_emp,birthday_emp,curp_emp, study_emp, emergency_name, emergency_tel,relationship_id] + ); + const status = result.rows[0].status; + if(status == 1) + message = "Empleado añadido correctamente"; + else + message = "Empleado no se pudo agregar" + res.json({ + message, + status: status + }); + }catch(error){ + console.error(error); + res.status(500).json({ error }); + } + +} +const updateEmployee = async(req,res)=>{ + try{ + const { + name_emp, + rfc_emp, + nss_emp, + addres_emp, + phone_emp, + email_emp, + birthday_emp, + curp_emp, + study_emp , + emergency_name , + emergency_tel, + relationship_id + } = req.body; + const result = await pool.query('SELECT updateemployee($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12) AS STATUS', + [name_emp,rfc_emp,nss_emp,addres_emp,phone_emp,email_emp,birthday_emp,curp_emp, study_emp, + emergency_name, emergency_tel, relationship_id] + ); + const status = result.rows[0].status; + if(status == 1) + message = "Empleado actualizado correctamente"; + else + message = "No se pudo agregar el empleado" + res.json({ + message, + status: status + }); + }catch(error){ + console.error(error); + res.status(500).json({ error }); + } + +} +const getattendance = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM getattendance()', + ); + + const attendance = result.rows.map(emp => ({ + aid_attendance: emp.aid_attendance, + aname_emp: emp.aname_emp, + alast_name: emp.alast_name, + aID_tran: emp.aID_tran, + arol: emp.arol, + adate_atten:emp.adate_atten, + atime_atten: emp.atime_atten, + alaboral_day: emp.alaboral_day, + adata_origin: emp.adata_origin, + aname_device: emp.aname_device, + aserie_device: emp.aserie_device, + aperforation: emp.aperforation, + aubication: emp.aubication, + aobservations: emp.aobservations + })); + + res.json({ + message: 'attendance', + data: attendance + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener checador' }); + } +}; + +const getGradeOfStudy = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM degreeofstudy', + ); + + const study = result.rows.map(emp => ({ + id_study: emp.id_study, + name_study: emp.name_study + })); + + res.json({ + message: 'grados de estudio', + data: study + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener los grados de estudio' }); + } +}; +const getRelationshipEmployee = async (req, res) => { + try { + const result = await pool.query( + 'SELECT * FROM relationship_employee', + ); + + const relationship = result.rows.map(emp => ({ + id_relationship: emp.id_relationship, + name_relationship: emp.name_relationship + })); + + res.json({ + message: 'Parentesco', + data: relationship + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener los parentescos' }); + } +} + +module.exports = +{ getEmployees, + getTotalActiveEmployees, + getEmployee, + newEmployee, + updateEmployee, + getattendance, + getGradeOfStudy, + getRelationshipEmployee +}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/exchange.controller.js b/backend/hotel_hacienda/src/controllers/exchange.controller.js new file mode 100644 index 0000000..caca047 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/exchange.controller.js @@ -0,0 +1,82 @@ +const pool = require('../db/connection'); +const axios = require('axios'); +const BANXICO_SERIE = 'SF43718'; + +function formatDate(date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +function mapBanxicoData(bmxJson) { + const serie = bmxJson.bmx.series[0]; + return serie.datos.map(item => { + const [day, month, year] = item.fecha.split('/'); + return { + fecha: `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`, + valor: parseFloat(item.dato) + }; + }); +} + +const consultExchange = async (req, res) => { + try { + const token = process.env.BANXICO_TOKEN; + if (!token) return res.status(400).json({ error: 'No se encontró token de Banxico' }); + + const today = formatDate(new Date()); + const url = `https://www.banxico.org.mx/SieAPIRest/service/v1/series/${BANXICO_SERIE}/datos/2021-11-07/${today}`; + + const response = await axios.get(url, { + headers: { 'Bmx-Token': token, 'Accept': 'application/json' } + }); + + const datos = mapBanxicoData(response.data); + + if (datos.length === 0) return res.status(404).json({ message: 'No hay datos para la fecha actual.' }); + + let savedCount = 0; + for (const item of datos) { + const result = await pool.query( + `INSERT INTO exchangetype(fecha, valor) + VALUES ($1, $2) + ON CONFLICT (fecha) DO NOTHING`, + [item.fecha, item.valor] + ); + if (result.rowCount > 0) savedCount++; + } + + const message = savedCount > 0 + ? 'Datos de tipo de cambio guardados correctamente' + : 'No se pudieron guardar los datos (quizá ya existían)'; + + res.json({ message, savedCount, datos }); + + } catch (err) { + console.error('Error consultExchange:', err.response ? err.response.data : err); + res.status(500).json({ error: 'Error interno al consultar exchange' }); + } +}; + +const getExchange = async (req, res) => { + try { + const result = await pool.query('SELECT * FROM getexange()'); + const units = result.rows.map(u => ({ + id: u.id_exchange, + fecha: u.fecha, + dato: parseFloat(u.dato) + })); + res.json({ + message: "Se obtuvieron los tipos de cambio.", + request: units + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'No se pudo recuperar los tipos de cambio.' }); + } +}; + +module.exports = { consultExchange, getExchange }; diff --git a/backend/hotel_hacienda/src/controllers/expense.controller.js b/backend/hotel_hacienda/src/controllers/expense.controller.js new file mode 100644 index 0000000..dbff69a --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/expense.controller.js @@ -0,0 +1,699 @@ +const pool = require('../db/connection'); +const transporter = require('../services/mailService'); + +const getPendingAppExpenses = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getpendingappexpenses()'); + + const status_approval = result.rows.map(pxp => ({ + id_expense: pxp.id_expense, + expense_description: pxp.description, + request_date: pxp.request_date, + requested_by: pxp.name_user, + area: pxp.name_area, + amount: pxp.total, + status_appr: pxp.status_approval + })); + + + + res.json({ + data:status_approval + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener gastos pendientes.' }); + } + +}; + +const getApprovedAppExpenses = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getapprovedappexpenses()'); + + const status_approval = result.rows.map(pxp => ({ + id_expense: pxp.id_expense, + expense_description: pxp.description, + request_date: pxp.request_date, + approval_date: pxp.approval_date, + requested_by: pxp.name_user, + area: pxp.name_area, + amount: pxp.total, + status_appr: pxp.status_approval + })); + + + + res.json({ + data:status_approval + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener gastos aprobados.' }); + } + +}; +const getRejectedappExpenses = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getrejectedappexpenses()'); + + const status_approval = result.rows.map(pxp => ({ + id_expense: pxp.id_expense, + expense_description: pxp.description, + request_date: pxp.request_date, + reject_date: pxp.reject_date, + requested_by: pxp.name_user, + area: pxp.name_area, + amount: pxp.total, + status_appr: pxp.status_approval + })); + + + + res.json({ + data:status_approval + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener gastos rechazados.' }); + } + +}; + +const getTotalApproved = async (req, res) => { + try{ + const {option} = req.body; + if(option ==1 ) + { + const result = await pool.query('SELECT totalApproved() as total'); + const total = result.rows[0].total; + res.json({ + message: "Total aprobado", + data:total + }); + } + else if (option ==2){ + const result = await pool.query('SELECT totalrejected() as total'); + const total = result.rows[0].total; + res.json({ + message: "Total rechazado", + data:total }); + }else { + return res.status(400).json({ + message: "El parámetro 'option' solo puede ser 1 (aprobado) o 2 (rechazado).", + data: 0 + }); + } + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el total de aprobados.' }); + } +}; +const mainSupplier = async (req, res) => { + try{ + + const result = await pool.query('SELECT * from mainsupplier()'); + const mainSupp = result.rows.map(ms => ({ + supplier: ms.name_suppliers, + percentage: ms.percentage, + })); + res.json({ + message: "Proveedor Principal", + data:mainSupp + }); + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el total de aprobados.' }); + } +}; + +const getReportExpenses = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM report_expenses()'); + + const reportExpenses = result.rows.map(re => ({ + id_expense: re.id_expense, + expense_description: re.description, + name_suppliers: re.name_suppliers, + rfc_suppliers: re.rfc_suppliers, + request_date: re.request_date, + approval_date: re.approval_date, + payment_date: re.payment_date, + requested_by: re.requested_by, + totalpesos: re.totalpesos, + totaldolares: re.totaldolares, + category: re.category, + area: re.area, + status_approval: re.approval_status, + status_payment: re.payment_status, + is_monthly : re.is_monthly + })); + + + + res.json({ + data:reportExpenses + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el reporte.' }); + } + +}; + +const getReportPayments = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM paymentsreport()'); + + const reportPayment = result.rows.map(rp => ({ + id_expense: rp.id_expense, + expense_description: rp.description, + approval_date: rp.approval_date, + area: rp.area, + supplier: rp.supplier, + totalpesos: rp.totalpesos, + totaldolares: rp.totaldolares, + status_approval: rp.approval_status, + status_payment: rp.payment_status + })); + + + + res.json({ + data:reportPayment + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el reporte de pagos.' }); + } + +}; + +const countpending = async (req, res) => { + try{ + const {option} = req.body; + if(option ==1 ) //OBtienes cuantas aprobaciones tienes pendientes + { + const result = await pool.query('SELECT countpendingapprove() as countpen'); + const total = result.rows[0].countpen; + res.json({ + message: "Pagos pendientes de aprobación", + data:total + }); + }else if(option ==2) //Obtienes los pagos pendientes de los gastos mensuales + { + const result = await pool.query('SELECT countpendingmonthly() as monthpen'); + const total = result.rows[0].monthpen; + res.json({ + message: "Pagos mensuales pendientes", + data:total + }); + } +} + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el conteo de pendientes.' }); + } + +}; + +const getmonthlypayments = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getmonthlypayments()'); + + const monthlypayment = result.rows.map(mp => ({ + id_expense: mp.id_expense, + expense_description: mp.description, + recurrence_name: mp.recurrence_name, + payment_type: mp.payment_type, + payment_deadline: mp.payment_deadline, + area: mp.name_area, + supplier: mp.name_suppliers, + status: mp.status, + total: mp.total, + status_payment: mp.name_pay_status + })); + + + + res.json({ + data:monthlypayment + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el reporte de pagos mensuales.' }); + } + +}; +const getExpense = async(req,res) => +{ + const { id } = req.params; + try{ + const result = await pool.query('SELECT * FROM getexpense($1)',[parseInt(id)]); + + const expense = result.rows.map(exp => ({ + id_exp: exp.id_exp, + description_exp: exp.description_exp, + suppliers_id: exp.suppliers_id, + request_date: exp.request_date, + payment_deadline: exp.payment_deadline, + request_by: exp.request_by, + approval_by: exp.approval_by, + id_area: exp.id_area, + category_exp: exp.category_exp, + currency: exp.currency, + subtotal: exp.subtotal, + iva: exp.iva, + ieps: exp.ieps, + total: exp.total, + needtoapprove: exp.needtoapprove, + products: exp.products, + })); + res.json({ + data:expense + }); + + }catch(error){ + console.error(error); + res.status(500).json(error); + } + +}; + +const getInfoExpense = async(req,res) => +{ + try{ + const infoSuppliers = await pool.query('SELECT * FROM getsuppliers()'); + const infoCategories = await pool.query('SELECT * FROM getcategoryexpense()'); + const infoAreas = await pool.query('SELECT * FROM getareas()'); + const infoUsers = await pool.query('SELECT * FROM getapproveby()'); + const infoCurrencies = await pool.query('SELECT * FROM getcurrency()'); + const infoUniforms = await pool.query('SELECT * FROM getuniforms()'); + const taxes = await pool.query('SELECT * FROM gettaxes()'); + + const suppliers = infoSuppliers.rows.map(supp => ({ + id: supp.id_supplier, + rfc: supp.rfc_suppliers, + name: supp.name_suppliers + })); + const categories = infoCategories.rows.map(cat => ({ + id: cat.id_category, + name: cat.name_category, + spanish_name: cat.spanish_name + })); + const areas = infoAreas.rows.map(area => ({ + id: area.id_area, + name: area.name_area, + })); + const users = infoUsers.rows.map(user => ({ + id: user.id_user, + name: user.user_name, + })); + const currencies = infoCurrencies.rows.map(cur => ({ + id: cur.id_currency, + name: cur.name_currency, + })); + const uniforms = infoUniforms.rows.map(uni => ({ + id: uni.id_uniform, + name: uni.name_uniform + })); + const tax = taxes.rows.map(uni => ({ + id: uni.id_tax, + name: uni.name_tax, + number: uni.number + })); + + res.json({ + suppliers, + categories, + areas, + users, + currencies, + uniforms, + tax + }); + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'Error al obtener la información especifica.' }); + } +}; + +const newExpense = async (req, res) => { + try{ + const {new_description, + suppliers_id, + new_request_date, + new_payment_deadline, + request_by, + area, + expense_cat, + currency_id, + products, + new_iva, + new_ieps, + new_subtotal, + new_total, + needtoapprove + }= req.body; + + const product = Array.isArray(products) && products.length > 0 ? JSON.stringify(products) : null; + const result = await pool.query('SELECT newexpensev2($1,$2,$3,$4,$5,$6,$7,$8,$9,$10::jsonb,$11,$12,$13,$14) AS STATUS',[ + new_description,suppliers_id,new_request_date,new_payment_deadline,request_by, + area,expense_cat,currency_id,needtoapprove,product,new_subtotal,new_iva,new_ieps,new_total]); + const userEmail = await pool.query('SELECT * FROM getusersmailowner()'); + + const newExpense = result.rows[0].status; + const user = userEmail.rows; + /*let fechaFormateada = 'No definida'; + if (new_payment_deadline) { + try { + const fecha = new Date(new_payment_deadline); + fechaFormateada = isNaN(fecha) + ? (() => { + const [dia, mes, anio] = new_payment_deadline.split('/'); + return new Date(`${anio}-${mes}-${dia}`).toLocaleDateString('en-US'); + })() + : fecha.toLocaleDateString('en-US'); + } catch { + fechaFormateada = 'Fecha inválida'; + } + }*/ + const productosHTML = Array.isArray(products) + ? products.map(p => `
  • ${p.id_product || 'N/A'} - QUANTITY: ${p.quantity || 1}
  • `).join('') + : 'without products associate'; + const recipients = user.map(u => u.email); + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: `Approval of the new expense ${newExpense}`, + html: `
    + +
    +

    + Expenditure approval required +

    +

    + Action pending on your part +

    +
    + + +
    +

    + An expense has been recorded that requires your approval. +

    + +
    + ID EXPENSE: + ${newExpense} +
    + + + + + + + + + + + + + + +
    Description:${new_description}
    Deadline:${new_payment_deadline}
    Total: + ${new_total || 'N/A'} +
    + +
    +

    Products included:

    +
      + ${productosHTML} +
    +
    + + +
    + + Review and approve spending + +
    + +

    + We recommend reviewing this application before the deadline. +

    +
    + + +
    + Financial management system · Consultoría AS +
    + +
    `, + }; + if(needtoapprove== true){ + await transporter.sendMail(mailOptions); + }; + res.json({ + message: "Gasto agregado correctamente.", + new_expense: newExpense + }); + }catch(error) + { + console.error(error); + res.status(500).json(error); + } + +}; + +const updateExpense = async (req, res) => { + try{ + + let message = ''; + const { id } = req.params; + const {up_description, + suppliers_id, + up_req_date, + up_deadline, + up_currency, + up_request_by, + up_area, + up_category, + needtoapprove, + up_subtotal, + up_iva, + up_ieps, + up_total, + products + }= req.body; + + const product = Array.isArray(products) && products.length > 0 ? JSON.stringify(products) : null; + + const result = await pool.query('SELECT updateexpensev4($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15::jsonb) AS status', + [parseInt(id),up_description,suppliers_id,up_req_date,up_deadline,up_currency, + up_request_by,up_area,up_category,needtoapprove,up_subtotal,up_iva,up_ieps,up_total,product]); + const userEmail = await pool.query('SELECT * FROM getusersmailowner()'); + + const user = userEmail.rows; + const upExpense = result.rows[0].status; + switch (upExpense) { + case 0: + message = 'El gasto ya fue pagado, no se puede actualizar'; + break; + case 1: + message = 'El gasto se actualizo correctamente'; + break; + default: + message = 'Error desconocido en la validación'; + }; + +/*let fechaFormateada = 'No definida'; +if (up_deadline) { + try { + // Manejo de formato "DD-MM-YYYY" + if (typeof up_deadline === 'string' && up_deadline.includes('-')) { + const [dia, mes, anio] = up_deadline.split('-'); + const fecha = new Date(`${anio}-${mes}-${dia}`); + fechaFormateada = !isNaN(fecha) + ? fecha.toLocaleDateString('es-MX', { timeZone: 'UTC' }) + : 'Fecha inválida'; + } else { + const fecha = new Date(up_deadline); + fechaFormateada = !isNaN(fecha) + ? fecha.toLocaleDateString('es-MX', { timeZone: 'UTC' }) + : 'Fecha inválida'; + } + } catch (err) { + console.error('Error al formatear fecha:', err); + fechaFormateada = 'Fecha inválida'; + } +};*/ + const productosHTML = Array.isArray(products) + ? products.map(p => `
  • ${p.id_product || 'N/A'} - Quantity: ${p.quantity || 1}
  • `).join('') + : 'Without products associate'; + const recipients = user.map(u => u.email); + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: `An updated ID expense approval is required: ${id}`, + html: `
    + +
    +

    + Expenditure approval required +

    +

    + Action pending on your part +

    +
    + + +
    +

    + An expense has been updated that requires your approval. +

    + +
    + ID EXPENSE: + ${id} +
    + + + + + + + + + + + + + + +
    Description:${up_description}
    Deadline:${up_deadline}
    Total: + ${up_total || 'N/A'} +
    + +
    +

    Products included:

    +
      + ${productosHTML} +
    +
    + + +
    + + Review and approve spending + +
    + +

    + We recommend reviewing this application before the deadline. +

    +
    + + +
    + Financial management system · Consultoría AS +
    + +
    `, + }; + if(needtoapprove== true){ + await transporter.sendMail(mailOptions); + }; + + res.json({ + message, + upExpense: upExpense + }); + }catch(error) + { + console.error(error); + res.status(500).json(error); + } + +}; + +const getTaxes = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM gettaxes()'); + + const taxes = result.rows.map(tx => ({ + id_tax: tx.id_tax, + name_tax: tx.name_tax, + })); + + + + res.json({ + data:taxes + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los Taxes.' }); + } + +}; + +const formatDateDMY = (value) => { + if (!value) return ''; + const date = value instanceof Date ? value : new Date(value); + if (isNaN(date.getTime())) return ''; + return date.toLocaleDateString('es-MX', { + day: '2-digit', + month: '2-digit', + year: 'numeric' + }); +}; + +module.exports = { getPendingAppExpenses,getApprovedAppExpenses,countpending, + getTotalApproved,mainSupplier,getReportExpenses,newExpense, + getReportPayments,getmonthlypayments,getRejectedappExpenses, + updateExpense,getExpense,getInfoExpense, getTaxes }; diff --git a/backend/hotel_hacienda/src/controllers/hotelp.controller.js b/backend/hotel_hacienda/src/controllers/hotelp.controller.js new file mode 100644 index 0000000..d1641d8 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/hotelp.controller.js @@ -0,0 +1,161 @@ +const pool = require('../db/connection'); + +const totalrevenue = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body + const result = await pool.query('SELECT * FROM totalrevenue($1,$2) as status',[start_date,end_date]); + const totalrenueve = result.rows[0].status; + /*const totalrenueve = result.rows.map(re => ({ + total: re.total + }));*/ + + + res.json({ + data:totalrenueve + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const cogs = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body; + const result = await pool.query('SELECT * FROM cogs($1,$2) as status',[start_date,end_date]); + const cogs = result.rows[0].status; + /*const cogs = result.rows.map(re => ({ + cogs_total: re.cogs_total, + }));*/ + + + res.json({ + message: "Se obtuvieron los ingresos", + data:cogs + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: error }); + } +}; + +const employeeshare = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body + const result = await pool.query('SELECT * FROM employeeshare($1,$2) as status ',[start_date,end_date]); + const employeeshare = result.rows[0].status; + /*const employeeshare = result.rows.map(re => ({ + total_share: re.total_share, + }));*/ + res.json({ + data:employeeshare + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const tips = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body + const result = await pool.query('SELECT * FROM tips($1,$2) as status',[start_date,end_date]); + const tips = result.rows[0].status; + /*const tips = result.rows.map(re => ({ + tips: re.tips + }));*/ + + + res.json({ + message: "Se obtuvieron los ingresos", + data:tips + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const grossprofit = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body; + const result = await pool.query('SELECT * FROM grossprofit($1,$2) as status',[start_date,end_date]); + const grossprofit = result.rows[0].status; + /*const grossprofit = result.rows.map(re => ({ + grossprofit: re.grossprofit + }));*/ + + + res.json({ + message: "Se obtuvieron los ingresos", + data:grossprofit + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + + +const weightedCategoriesCost = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body + const result = await pool.query('SELECT * FROM weighted_categories_cost($1,$2)',[start_date,end_date]); + const weightedCategoriesCost = result.rows.map(re => ({ + id_expense_cat : re.id_expense_cat , + category_name: re.category_name , + spanish_name : re.spanish_name , + total : re.total, + participation : re.participation + })); + res.json({ + data:weightedCategoriesCost + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const ebitda = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body; + const result = await pool.query('SELECT * FROM ebitda($1,$2)', [start_date,end_date]); + const ebitda = result.rows.map(re => ({ + expenses_total: re.expenses_total, + ebitda : re.ebitda + })); + + + res.json({ + message: "Se obtuvieron los ingresos", + data:ebitda + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +module.exports = {ebitda,weightedCategoriesCost,grossprofit,totalrevenue,cogs,employeeshare,tips}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/incomehrx.controller.js b/backend/hotel_hacienda/src/controllers/incomehrx.controller.js new file mode 100644 index 0000000..cd9d1b1 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/incomehrx.controller.js @@ -0,0 +1,309 @@ +const pool = require('../db/connection'); +const axios = require('axios'); +const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); +const getFacturas = async (initialDate, finalDate) => { + try { + const response = await axios.get(process.env.FACTURAS_API_URL, { + params: { + issuerRfc: process.env.FACTURAS_ISSUER_RFC, + type: process.env.FACTURAS_TYPE, + initialDate: initialDate, + finalDate: finalDate + }, + headers: { + Authorization: `Bearer ${process.env.FACTURAS_API_TOKEN}` + }, + timeout: 15000 + }); + + return response.data; + + } catch (error) { + console.error( + 'Error API Facturas:', + error.response?.data || error.message + ); + throw error; + } + +}; +const addfacturas = async (req, res) => { +try { + const now = new Date(); + + const startOfYear = new Date(now.getFullYear(), 0, 1, 0, 0, 0); + //console.log(startOfYear); + const formatDateTime = (date) => + date.toISOString().slice(0, 19).replace('T', ' '); + const FACTURAS_INITIAL_DATE = formatDateTime(startOfYear); + const FACTURAS_FINAL_DATE = formatDateTime(now); + console.log(FACTURAS_INITIAL_DATE); + console.log(FACTURAS_FINAL_DATE); + const facturas = await getFacturas(FACTURAS_INITIAL_DATE,FACTURAS_FINAL_DATE); + + const result = await pool.query('SELECT addhoruxdata($1::jsonb) as total',[JSON.stringify(facturas)]); + const total = result.rows[0].total; + res.json({ + message: 'Facturas subidas a la base de datos', + total + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al sincronizar' }); + } +}; + + + +const getCategoryIncome = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getcategoryincome()'); + + const categoriesIncome = result.rows.map(inc => ({ + id_cat_income: inc.id_cat_income, + name_cat_income: inc.name_cat_income, + english_name: inc.english_name + })); + res.json({ + data:categoriesIncome + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener las categorias' }); + } + +}; + +const getInvoiceIncome = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getinvoiceincome()'); + + const invoiceIncome = result.rows.map(inc => ({ + id_inv_income: inc.id_inv_income, + name_inv_income: inc.name_inv_income, + amount: inc.amount, + dateinvoice: inc.dateinvoice + + })); + res.json({ + data:invoiceIncome + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener las facturas.' }); + } + +}; + +const getAccountIncome = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getaccountincome()'); + + const aacountIncome = result.rows.map(inc => ({ + id_acc_income: inc.id_acc_income, + name_acc_income: inc.name_acc_income, + })); + res.json({ + data:aacountIncome + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener las cuentas' }); + } + +}; + +const getIncomeHorux = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getincomehorux()'); + + const incomeHorux = result.rows.map(inc => ({ + id_hrx_income: inc.id_hrx_income, + date_in: inc.date_in, + createddate: inc.createddate, + account_name: inc.account_name, + categories: inc.categories, + amount:inc.amount, + amountinvoice: inc.amountinvoice, + invoice: inc.invoice, + status_in: inc.status_in + })); + res.json({ + data:incomeHorux + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los income' }); + } + +}; +const getTotalIncome = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM gettotalincome() as total'); + + const totalIncome = result.rows[0].total; + + res.json({ + message: 'Total de income', + data: totalIncome + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los income' }); + } + +}; + +const newIncome = async (req, res) => { + try{ + const { + account_id, + amount, + new_date, + newinvoice, + area_id, + categories, + + } = req.body; + const categoriesJson = categories ? JSON.stringify(categories) : '[]'; + + const result = await pool.query('SELECT newincome($1,$2,$3,$4,$5,$6::jsonb) AS status',[ + account_id,amount,new_date,newinvoice,area_id,categoriesJson]); + const newIncome = result.rows[0].status; + res.json({ + message: "Income agregado correctamente", + new_expense: newIncome + }); + } + catch(error) + { + console.error(error); + res.status(500).json(error); + } + +}; + +const getOneIncome = async (req, res) => { + try{ + const { id } = req.params; + const result = await pool.query('SELECT * FROM getoneincome($1)',[parseInt(id)]); + + const incomeHorux = result.rows.map(inc => ({ + id_hrx_income: inc.id_hrx_income, + date_in: inc.date_in, + account_id: inc.account_id, + amount:inc.amount, + invoice: inc.invoice, + categories: inc.categories + })); + res.json({ + data:incomeHorux + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el income' }); + } + +}; + +const updateIncome = async (req, res) => { + try{ + const {id} = req.params; + const { + account_id, + amount, + up_date, + up_invoice, + area_id, + categories + } = req.body; + const categoriesJson = categories ? JSON.stringify(categories) : '[]'; + + const result = await pool.query('SELECT updateincome($1,$2,$3,$4,$5,$6,$7::jsonb) AS status',[ + id,account_id,amount,up_date,up_invoice,area_id,categoriesJson]); + const newIncome = result.rows[0].status; + res.json({ + message: "Income actualizado correctamente", + new_expense: newIncome + }); + } + catch(error) + { + console.error(error); + res.status(500).json(error); + } + +}; +const getstripeservice = async (req, res) => { + try{ + /*const paymentIntent = await stripe.paymentIntents.create({ + amount: 4805510, + currency: 'usd', + payment_method: 'pm_card_visa', + confirm: true, + automatic_payment_methods: { + enabled: true, + allow_redirects: 'never' + } + });*/ + const balanceTransactions = await stripe.transfers.list(); + const result = await pool.query( + 'SELECT addstripedatav2($1::jsonb) AS inserted', + [JSON.stringify(balanceTransactions)]); + res.json({ + message: "Se obtuvieron datos de stripe y se insertaron", + transactions: result.rows[0].inserted, + //data: balanceTransactions + }); + } + catch(error) + { + console.error(error); + res.status(500).json(error); + } + + +}; +const addDemostripeData = async (req, res) => { + try{ + const transfer = await stripe.transfers.create({ + amount: 1000, // centavos + currency: 'usd', + destination: 'acct_1Sm54nEzzXSLq34b', + transfer_group: 'ORDER_95',}); + res.json({ + message: 'Pago creado y confirmado', + transfer + }); + }catch(error) + { + console.error(error); + res.status(500).json(error); + } + + +}; + + +module.exports = {getCategoryIncome,getInvoiceIncome,getAccountIncome, + getIncomeHorux,getTotalIncome,newIncome,getOneIncome,updateIncome,getFacturas,addfacturas,getstripeservice, + addDemostripeData}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/incomes.controller.js b/backend/hotel_hacienda/src/controllers/incomes.controller.js new file mode 100644 index 0000000..574faae --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/incomes.controller.js @@ -0,0 +1,514 @@ +const pool = require('../db/connection'); +const path = require('path'); +const fs = require('fs'); +const XLSX = require('xlsx'); +const csv = require('csv-parser'); +const getincomes = async (req, res) => +{ + try{ + const {checkin_initial,checkin_final} = req.body; + const result = await pool.query('SELECT * FROM getincomesv2($1,$2)',[checkin_initial,checkin_final]); + const incomereport = result.rows.map(re => ({ + room: re.room, + occupation: re.occupation, + income_per_night: re.income_per_night, + total_income: re.total_income + })); + + + res.json({ + message: "Se obtuvieron los ingresos", + data:incomereport + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos.' }); + } +}; + +const getSoftRestaurant = async (req, res) => +{ + try{ + //const {checkin_initial,checkin_final} = req.body; + const result = await pool.query('SELECT * FROM getdataproductsolds()',); + const incomereport = result.rows.map(re => ({ + id_soldpro: re.id_soldpro, + clave: re.clave, + description: re.description, + group_sp: re.group_sp, + price: re.price, + quantity: re.quantity, + totalsale: re.totalsale, + cost_sp: re.cost_sp, + totalcost: re.totalcost, + salecost: re.salecost, + catalogprice: re.catalogprice, + totalsalecatalogprice: re.totalsalecatalogprice, + vat_rate: re.vat_rate + })); + + + res.json({ + message: "Se obtuvieron los ingresos", + data:incomereport + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos.' }); + } +}; + +const getdetallecheques = async (req, res) => +{ + try{ + //const {checkin_initial,checkin_final} = req.body; + const result = await pool.query('SELECT * FROM getchequesdetalles()',); + const incomereport = result.rows.map(re => ({ + id_cheque: re.id_cheque, + folio: re.folio, + fecha: re.fecha, + descuento: re.descuento, + importe: re.importe, + cargo: re.cargo, + efectivo: re.efectivo, + tarjeta: re.tarjeta, + vales: re.vales, + propina: re.propina, + OTROS: re.OTROS, + })); + + + res.json({ + message: "Se obtuvieron los ingresos", + data:incomereport + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos.' }); + } +}; + +const totalincomes = async (req, res) => +{ + try{ + const {checkin_initial,checkin_final} = req.body; + const result = await pool.query('SELECT totalincomesv2($1,$2) as total',[checkin_initial,checkin_final]); + const totalincomes = result.rows[0].total; + + res.json({ + message: "Se obtuvieron los ingresos de las fechas seleccionadas", + data:totalincomes + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos totales.' }); + } +}; + +const channelscards = async (req, res) => +{ + try{ + const {checkin_initial,checkin_final} = req.body; + const result = await pool.query('SELECT * from channelscardsv2($1,$2)',[checkin_initial,checkin_final]); + const incomef = result.rows.map(re => ({ + channel: re.channel, + total_channel: re.total_channel, + percentage: re.percentage, + })); + + res.json({ + message: "Canal donde se obtuvieron más ingresos", + data:incomef + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const loadincomes = (req, res) => { + const {nombrearchivo} = req.body; + const CSV_PATH = `/home/Hotel/backend/hotel_hacienda/src/resources/littleHotelier/${nombrearchivo}`; + //const CSV_PATH = `C:/Users/otamegane/Desktop/Trabajo_free_lancer/reservations/${nombrearchivo}`; + const results = []; + + if (!fs.existsSync(CSV_PATH)) { + return res.status(404).json({ + message: 'El archivo CSV no existe' + }); + } + + fs.createReadStream(CSV_PATH) + .pipe(csv()) + .on('data', (row) => { + results.push(row); + }) + .on('end', async () => { + try { + const result = await pool.query( + 'SELECT insertincomesandtempV2($1::jsonb) AS inserted', + [JSON.stringify(results)] + ); + + res.json({ + message: 'CSV procesado e insertado en base de datos', + rows_read: results.length, + rows_inserted: result.rows[0].inserted + }); + + } catch (error) { + console.error('Error insertando en BD:', error); + res.status(500).json({ message: 'Error al insertar datos en BD' }); + } + }) + .on('error', (err) => { + console.error('Error leyendo el CSV:', err); + res.status(500).json({ error: 'No se pudo leer el CSV' }); + }); +}; + +/*const loadsoftrestaurant = (req, res) => { + const {nombrearchivo} = req.body; + //const CSV_PATH = `/home/Hotel/backend/hotel_hacienda/src/resources/littleHotelier/${nombrearchivo}`; + const CSV_PATH = `C:/Users/otamegane/Desktop/Trabajo_free_lancer/reservations/${nombrearchivo}`; + const results = []; + + if (!fs.existsSync(CSV_PATH)) { + return res.status(404).json({ + message: 'El archivo CSV no existe' + }); + } + + fs.createReadStream(CSV_PATH) + .pipe(csv()) + .on('data', (row) => { + results.push(row); + }) + .on('end', async () => { + try { + const result = await pool.query( + 'SELECT insertproductsale($1::jsonb) AS inserted', + [JSON.stringify(results)] + ); + + res.json({ + message: 'CSV procesado e insertado en base de datos', + rows_read: results.length, + rows_inserted: result.rows[0].inserted + }); + + } catch (error) { + console.error('Error insertando en BD:', error); + res.status(500).json({ message: 'Error al insertar datos en BD' }); + } + }) + .on('error', (err) => { + console.error('Error leyendo el CSV:', err); + res.status(500).json({ error: 'No se pudo leer el CSV' }); + }); +};*/ + +const loadsoftrestaurant = async (req, res) => { + try { + const { nombrearchivo } = req.body; + //const FILE_PATH = `C:/Users/otamegane/Desktop/Trabajo_free_lancer/reservations/${nombrearchivo}`; + const FILE_PATH = `/home/Hotel/backend/hotel_hacienda/src/resources/littleHotelier/${nombrearchivo}`; + if (!fs.existsSync(FILE_PATH)) { + return res.status(404).json({ + message: 'El archivo Excel no existe' + }); + } + + //Se lee el archivo + const workbook = XLSX.readFile(FILE_PATH); + + //Toma la primera hoja primera hoja + const sheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[sheetName]; + + //Se convierte a json + const results = XLSX.utils.sheet_to_json(worksheet, { + defval: null, + range: 4 + }); + + //console.log(results[0]); + + if (results.length === 0) { + return res.status(400).json({ + message: 'El archivo no contiene datos' + }); + } + + // Insertar en PostgreSQL + const result = await pool.query( + 'SELECT insertproductsale($1::jsonb) AS inserted', + [JSON.stringify(results)] + ); + + res.json({ + message: 'Excel procesado e insertado en base de datos', + rows_read: results.length, + rows_inserted: result.rows[0].inserted + }); + + } catch (error) { + console.error('Error procesando Excel:', error); + res.status(500).json({ + message: 'Error al procesar el archivo Excel' + }); + } +}; + +const loadChequesDetalle = async (req, res) => { + try { + const { nombrearchivo } = req.body; + const FILE_PATH = `/home/Hotel/backend/hotel_hacienda/src/resources/littleHotelier/${nombrearchivo}`; + //const FILE_PATH = `C:/Users/otamegane/Desktop/Trabajo_free_lancer/reservations/${nombrearchivo}`; + + if (!fs.existsSync(FILE_PATH)) { + return res.status(404).json({ + message: 'El archivo Excel no existe' + }); + } + + //Se lee el archivo + const workbook = XLSX.readFile(FILE_PATH); + + //Toma la primera hoja primera hoja + const sheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[sheetName]; + + //Se convierte a json + const results = XLSX.utils.sheet_to_json(worksheet, { + defval: null, + range: 5 + }); + + //console.log(results[0]); + + if (results.length === 0) { + return res.status(400).json({ + message: 'El archivo no contiene datos' + }); + } + + // Insertar en PostgreSQL + const result = await pool.query( + 'SELECT insertchequesdetalles($1::jsonb) AS inserted', + [JSON.stringify(results)] + ); + + res.json({ + message: 'Excel procesado e insertado en base de datos', + rows_read: results.length, + rows_inserted: result.rows[0].inserted + }); + + } catch (error) { + console.error('Error procesando Excel:', error); + res.status(500).json({ + message: 'Error al procesar el archivo Excel' + }); + } +}; + + +const reportIncomes = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT * from stadisticsrooms($1,$2)',[initial_date,final_date]); + const reportincome = result.rows.map(re => ({ + room_type: re.room_type, + total_uses: re.total_uses, + total_income: re.total_income, + occupation_percentage: re.occupation_percentage, + income_percentage: re.income_percentage, + ADR: re.adr, + CPOR: re.cpor, + CPAR: re.cpar, + PPOR: re.ppor, + fixed_cost: re.fixed_cost, + break_event_point: re.break_event_point, + gift_room: re.gift_room + })); + + res.json({ + message: "Reporte del income", + data:reportincome + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato', + error}); + } +}; + +const countFolios = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT countFolios($1,$2) as total',[initial_date,final_date]); + const count = result.rows[0].total; + + res.json({ + message: "Se obtuvo el conteo de los tickets", + data:count + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos totales.' }); + } +}; + +const sumasTotales = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT sumasTotales($1,$2) as total',[initial_date,final_date]); + const sumatotal = result.rows[0].total; + + res.json({ + message: "Se obtuvo el total", + data:sumatotal + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos totales.' }); + } +}; + +const sumaEfectivo = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT sumaEfectivo($1,$2) as total',[initial_date,final_date]); + const efectivo = result.rows[0].total; + + res.json({ + message: "Se obtuvo el total de efectivo", + data:efectivo + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos efectivo.' }); + } +}; + +const sumaTarjeta = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT sumaTarjeta($1,$2) as total',[initial_date,final_date]); + const tarjeta = result.rows[0].total; + + res.json({ + message: "Se obtuvo el total de tarjeta", + data:tarjeta + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos tarjeta.' }); + } +}; + +const sumaVales = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT sumaVales($1,$2) as total',[initial_date,final_date]); + const vales = result.rows[0].total; + + res.json({ + message: "Se obtuvo el total de vales", + data:vales + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos vales.' }); + } +}; + +const sumaOtros = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT sumaOtros($1,$2) as total',[initial_date,final_date]); + const otros = result.rows[0].total; + + res.json({ + message: "Se obtuvo el total de otros", + data:otros + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos otros.' }); + } +}; + +const sumaPropinas = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT sumaPropinas($1,$2) as total',[initial_date,final_date]); + const propinas = result.rows[0].total; + + res.json({ + message: "Se obtuvo el total de propinas", + data:propinas + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los ingresos propinas.' }); + } +}; + +const ticketPromedio = async (req, res) => +{ + try{ + const {initial_date,final_date} = req.body; + const result = await pool.query('SELECT ticketPromedio($1,$2) as total',[initial_date,final_date]); + const promedio = result.rows[0].total; + + res.json({ + message: "Se obtuvo el promedio de ticket", + data:promedio + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el promedio.' }); + } +}; + +module.exports = {getincomes,totalincomes,loadChequesDetalle,getdetallecheques, + channelscards,loadincomes,reportIncomes,loadsoftrestaurant,getSoftRestaurant, + ticketPromedio,sumaEfectivo,sumaOtros,sumaPropinas,sumaTarjeta,sumaVales,sumasTotales,countFolios}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/mail.controller.js b/backend/hotel_hacienda/src/controllers/mail.controller.js new file mode 100644 index 0000000..9c89309 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/mail.controller.js @@ -0,0 +1,650 @@ +const pool = require('../db/connection'); +const transporter = require('../services/mailService'); + +const contractsNearToEnd = async (req, res) => { + try{ + const countResult = await pool.query('SELECT contratcsneartoend() as total'); + const contractsResult = await pool.query('SELECT * FROM contractsneartoenddata()'); + const userEmails = await pool.query('SELECT * FROM getusersmailneartoend()'); + const totalExpiring = countResult.rows[0].total; + const contracts = contractsResult.rows; + const users = userEmails.rows; + + if(totalExpiring >= 1 && users.length > 0){ + + const recipients = users.map(u => u.email); + + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: 'Contratos próximos a expirar', + html: ` +
    + +
    +

    + Notificación de contratos +

    +
    + + +
    +

    + Actualmente hay ${totalExpiring} contrato(s) por expirar. +

    +

    + Los siguientes contratos son los que expiran: +

    + + + + + + + + + + + + + ${contracts.map(c => { + const inicio = formatDateDMY(c.start_contract); + const fin = formatDateDMY(c.end_contract); + return ` + + + + + + + + + `; + }).join('')} + +
    ID contractRFCNombreFecha inicio contratoFecha fin contratoSalario diario
    ${c.id_contract}${c.rfc_emp}${c.name_employee}${inicio}${fin}${c.dailypay}
    + + +
    + + Revisar en la web + +
    + +

    + Por favor considere si seran recontratados o finalizados. +

    +
    + + +
    + Sistema de gestión financiera · Consultoría AS +
    + +
    +` + }; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con contratos por expirar.', + data:totalExpiring + }); + }else{ + res.json({ + message: 'No hay contratos por expirar', + data:totalExpiring + }); + } + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo mandar el correo con los contratos por expirar' }); + } +}; +const paymentDeadLine = async (req, res) => { + try{ + const deadLineCount = await pool.query('SELECT countdelaypayments() as total'); + const deadLineResult = await pool.query('SELECT * FROM getdelaypayments()'); + const usersDeadLine = await pool.query('SELECT * FROM getusersmailpaymentdelay()'); + const totalDeadline = deadLineCount.rows[0].total; + const deadLines = deadLineResult.rows; + const users = usersDeadLine.rows; + + if(totalDeadline >= 1 && users.length >0){ + const recipients = users.map(u => u.email); + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: 'WARNING: OVERDUE PAYMENTS', + html: ` +
    + +
    +

    + Notification regarding overdue payments +

    +
    + + +
    +

    + Currently there are ${totalDeadline} overdue payment(s). +

    + + + + + + + + + + + ${deadLines.map(c => { + const fecha = new Date(c.payment_deadline); + const fechaFormateada = fecha.toLocaleDateString('en-US', { + day: '2-digit', + month: 'long' + }); + return ` + + + + + + + `; + }).join('')} + +
    IDDescriptionDeadlineTotal
    ${c.id_expense}${c.description}${fechaFormateada}${c.total || 'N/A'}
    + + +
    + + Please review and pay as soon as possible. + +
    + +

    + We recommend that review your overdue expenses as soon as possible. +

    +
    + + +
    + Financial management system · Consultoría AS +
    + +
    ` + }; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con pagos atrasados.', + data:totalDeadline + }); + }else{ + res.json({ + message: 'No hay pagos con atraso', + data:totalDeadline + }); + } + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo mandar el correo con con los pagos atrasados' }); + } +}; + +const expensesNearToDeadline = async (req, res) => { + try{ + const deadLineCount = await pool.query('SELECT COUNT(*) FROM expensesneartodeadline()'); + const deadLineResult = await pool.query('SELECT * FROM expensesneartodeadline()'); + const usersDeadLine = await pool.query('SELECT * FROM getusersmailpaymentdelay()'); + + const totalDeadline = deadLineCount.rows[0].count; + const deadLines = deadLineResult.rows; + const users = usersDeadLine.rows; + console.log(totalDeadline); + if(totalDeadline >= 1 && users.length >0){ + const recipients = users.map(u => u.email); + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: 'WARNING: PAYMENTS DUE SOON FOR LATE PAYMENTS', + html: ` +
    + +
    +

    + Notification of payments approaching a deadline +

    +
    + + +
    +

    + Currently there are ${totalDeadline} payment(s) close to deadline. +

    + + + + + + + + + + + ${deadLines.map(c => { + const fecha = new Date(c.payment_deadline); + const fechaFormateada = fecha.toLocaleDateString('en-US', { + day: '2-digit', + month: 'long' + }); + return ` + + + + + + + `; + }).join('')} + +
    IDDescriptionDeadlineTotal
    ${c.id_expense}${c.description}${fechaFormateada}${c.total || 'N/A'}
    + + +
    + + Review and pay spendings + +
    + +

    + We recommend reviewing this application before the deadline. +

    +
    + + +
    + Financial management system · Consultoría AS +
    + +
    + ` + }; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con pagos por expirar.', + data:totalDeadline + }); + }else{ + res.json({ + message: 'No hay pagos con atraso', + data:totalDeadline + }); + } + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo mandar el correo con los pagos prontos a fecha limite' }); + } +}; + +const expensesspecial = async (req, res) => { + try{ + const expensesCount = await pool.query('SELECT COUNT(*) AS total FROM getexpensesspecial()'); + const expensesResult = await pool.query('SELECT * FROM getexpensesspecial()'); + const totalExpenses = expensesCount.rows[0].total; + const expenses = expensesResult.rows; + + if(totalExpenses >= 1){ + const mailOptions = { + from: 'soporte@horuxfin.com', + to: 'soporte@horuxfin.com', + subject: 'Recordatorio: Hay gastos por aprobar', + html: ` +

    Notificación de gastos por aprobar

    +

    Actualmente hay ${totalExpenses} gasto(s) por aprobar

    + + ` + }; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con gastos por aprobar', + data:totalExpenses + }); + }else{ + res.json({ + message: 'No hay pagos por aprobar', + data:totalExpenses + }); + } + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo mandar el correo con los contratos por expirar' }); + } +}; + +const emailbirthday = async (req, res) => { + try{ + const endpointName = 'emailbirthday'; + const current = new Date(); + const mes = current.getMonth() + 1; + const anio = current.getFullYear(); + const validateEndpoint = await pool.query('SELECT validateendpoint($1,$2::int,$3::int) AS total',[endpointName,mes,anio]); + + if (validateEndpoint.rows[0].total > 0) { + return res.status(400).json({ + message: `Este endpoint ya fue ejecutado en ${current.toLocaleString('es-MX', { month: 'long' })}.` + }); + }else { + await pool.query(`INSERT INTO endpoint_logs (endpoint_name) VALUES ($1)`,[endpointName]); + const birthdayCount = await pool.query('SELECT COUNT(*) AS total FROM getbirthdaysemployees()'); + const birthdayResult = await pool.query('SELECT * FROM getbirthdaysemployees()'); + const userEmails = await pool.query('SELECT * FROM getusersmailbirthday()'); + + const totalBirthday = birthdayCount.rows[0].total; + const birthdays = birthdayResult.rows; + const users = userEmails.rows; + const currentMonth = new Date().toLocaleString('en-US', { month: 'long' }); + + if(totalBirthday >= 1 && users.length >0){ + + const recipients = users.map(u => u.email); + + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: `Friendly reminder: Birthdays of the month of ${currentMonth}`, + html: ` +
    + +
    +

    + In this month there are ${totalBirthday} birthday person(s) +

    +
    + + +
    +

    + The following employees are celebrating their birthdays this month: +

    + + + + + + + + + + + ${birthdays.map(c => { + const fecha = new Date(c.birthday); + const fechaFormateada = fecha.toLocaleDateString('en-US', { + day: '2-digit', + month: 'long' + }); + return ` + + + + + + `; + }).join('')} + +
    RFCNameBirthday
    ${c.rfc}${c.fullname}${fechaFormateada}
    + + +

    + Remember to congratulate them on their special day! +

    +
    + + +
    + Financial management system · Consultoría AS +
    + +
    `}; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con los cumpleaños', + data:totalBirthday + }); + }else{ + res.json({ + message: 'No hay cumpleañeros este mes', + data:totalBirthday + }); + }} + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo enviar correo con los cumpleañeros' }); + } +}; +const expiredcontracts = async (req, res) => { + try{ + const expiredCountTotal = await pool.query('SELECT expiredcontracts() as total'); + const expiredResult = await pool.query('SELECT * FROM getexpirecontracts()'); + const expiredCountDay = await pool.query('SELECT COUNT(*) AS total FROM getexpirecontracts()'); + const totalExpired = expiredCountTotal.rows[0].total; + const totalDayExpired = expiredCountDay.rows[0].total; + const expiredContracts = expiredResult.rows; + + if(totalExpired >= 1){ + const mailOptions = { + from: 'soporte@horuxfin.com', + to: 'soporte@horuxfin.com', + subject: 'Contratos expirados el día de hoy', + html: ` +

    Notificación contratos expirados el día de hoy

    +

    Cantidad de contratos ${totalDayExpired} que expiraron hoy.

    + + +

    Por favor considere si seran recontratados o no para que se inicie el proceso.

    ` + }; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con contratos expirados hoy', + data:totalDayExpired + }); + }else{ + res.json({ + message: 'Hoy no expiro ningun contrato', + data:totalDayExpired + }); + } + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo mandar el correo con los contratos por expirar' }); + } +}; +const expiredContractsMonth = async (req, res) => { + try{ + // Verifica si hoy es el último día del mes + if (isLastDayOfMonth()) { + return res.status(200).json({ + message: 'El proceso solo se ejecuta el último día del mes', + executed: false + }); + } + const endpointName = 'expiredContractsMonth'; + const current = new Date(); + const mes = current.getMonth() + 1; + const anio = current.getFullYear(); + const validateEndpoint = await pool.query('SELECT validateendpoint($1,$2::int,$3::int) AS total',[endpointName,mes,anio]); + if (validateEndpoint.rows[0].total > 0) { + return res.status(400).json({ + message: `Este endpoint ya fue ejecutado en ${current.toLocaleString('es-MX', { month: 'long' })}.` + }); + }else + { + await pool.query(`INSERT INTO endpoint_logs (endpoint_name) VALUES ($1)`,[endpointName]); + const expiredCountTotal = await pool.query('SELECT COUNT(*) AS total FROM getexpirecontractsmonth()'); + const expiredResult = await pool.query('SELECT * FROM getexpirecontractsmonth()'); + const userEmails = await pool.query('SELECT * FROM getusersmailneartoend()'); + + const totalExpired = expiredCountTotal.rows[0].total; + const expiredContracts = expiredResult.rows; + const currentMonth = new Date().toLocaleString('es-MX', { month: 'long' }); + const users = userEmails.rows; + + if(totalExpired >= 1 && users.length > 0){ + const recipients = users.map(u => u.email); + const mailOptions = { + from: 'soporte@horuxfin.com', + to: recipients, + subject: `Contratos expirados en el mes ${currentMonth} `, + html: ` +
    + +
    +

    + Notificación contratos expirados del mes de ${currentMonth} +

    +
    + + +
    +

    + En este mes expiraron ${totalExpired}. +

    +

    + Los contratos expirados son en el mes fueron: +

    + + + + + + + + + + + ${expiredContracts.map(c => { + const fin = formatDateDMY(c.end_contract); + return ` + + + + + + + `; + }).join('')} + +
    ID contractRFCNombreFecha que expiro:
    ${c.id_contract}${c.rfc_employee}${c.name_employee}${fin}
    + + +
    + + Revisar en la web + +
    + +

    + Le recomendamos generar el contrato en caso de recontratación. +

    +
    + + +
    + Sistema de gestión financiera · Consultoría AS +
    + +
    ` + }; + await transporter.sendMail(mailOptions); + res.json({ + message: 'Correo enviado con contratos expirados en el mes', + data:totalExpired + }); + }else{ + res.json({ + message: 'Este mes no expiro ningun contrato', + data:totalExpired + }); + }} + }catch(error){ + console.error(error); + res.status(500).json({ status: 500, message: 'No se pudo mandar el correo con los contratos por expirar' }); + } +}; + + +const isLastDayOfMonth = () => { + const today = new Date(); + const tomorrow = new Date(today); + tomorrow.setDate(today.getDate() + 1); + return tomorrow.getDate() === 1; +}; +const formatDateDMY = (value) => { + if (!value) return ''; + const date = value instanceof Date ? value : new Date(value); + if (isNaN(date.getTime())) return ''; + return date.toLocaleDateString('es-MX', { + day: '2-digit', + month: '2-digit', + year: 'numeric' + }); +}; + +module.exports = {contractsNearToEnd,paymentDeadLine,expensesspecial, + emailbirthday,expiredcontracts,expiredContractsMonth,expensesNearToDeadline}; diff --git a/backend/hotel_hacienda/src/controllers/payment.controller.js b/backend/hotel_hacienda/src/controllers/payment.controller.js new file mode 100644 index 0000000..7c38d96 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/payment.controller.js @@ -0,0 +1,174 @@ +const pool = require('../db/connection'); + +const newMonthlyExpense = async (req, res) => { + try{ + const { + descriptionex, + recurrence_id, + payment_type, + currency_id, + suppliers_id, + area, + expense_category, + day_expense, + tax_id, + new_subtotal, + } = req.body; + const subtotal = new_subtotal && !isNaN(parseFloat(new_subtotal))? parseFloat(new_subtotal): 0; + const result = await pool.query('SELECT newmonthlyexpensev2($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) AS status',[ + descriptionex,recurrence_id,payment_type,currency_id,suppliers_id, + area,expense_category,day_expense,tax_id,parseFloat(subtotal)]); + + const newMonthly = result.rows[0].status; + res.json({ + message: "Gasto mensual agregado correctamente", + status: newMonthly + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se puede agregar el gasto mensual',error }); + } +}; +const setPaymentStatusMonthly = async (req, res) => { + try{ + + const {id} = req.params; + const { + status_payment, + tax_id, + subtotal, + } = req.body; + const total = subtotal && subtotal !== '' ? subtotal : null; + if(total ==null) + { + const result = await pool.query('SELECT setpaymentstatusmonthlyv2($1,$2) as status',[id,status_payment]); + const statuspayment = result.rows[0].status; + res.json({ + message:'Se actualizo el estatus del pago correctamente', + status_monthly: statuspayment + }); + }else{ + const result = await pool.query('SELECT setpaymentstatusmonthlyv2($1,$2,$3,$4) as status',[id,status_payment,tax_id,parseFloat(total)]); + const statuspayment = result.rows[0].status; + res.json({ + message:'Se actualizo estatus y pago correctamente', + status_monthly: statuspayment + }); + + } + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo actualizar el pago' }); + } +}; + +const refreshMonthlyExpenses = async(req,res) =>{ + try{ + const result = await pool.query('SELECT refresh_monthly_expenses() as status'); + const refresh = result.rows[0].status; + res.json({ + message:"se realizo actualizacion de gastos mensuales", + status_monthly: refresh + }); + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo actualizar' }); + } + +}; + +const updateMonthlyExpense = async (req, res) => { + try{ + const { + descriptionex, + recurrence_id, + payment_type, + currency_id, + suppliers_id, + area, + expense_category, + day_expense, + tax_id, + new_subtotal, + } = req.body; + const {id} = req.params; + const subtotal = new_subtotal && !isNaN(parseFloat(new_subtotal))? parseFloat(new_subtotal): 0; + const result = await pool.query('SELECT updatemonthlyexpensev2($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) AS status', + [id,descriptionex,recurrence_id,payment_type,currency_id,suppliers_id, + area,expense_category,day_expense,tax_id,parseFloat(subtotal)]); + + const update = result.rows[0].status; + res.json({ + message: "Gasto mensual actualizado correctamente", + status: update + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se puede actualizar el gasto mensual' }); + } +}; +const getOneMonthly = async (req, res) => { + try{ + const {id} = req.params; + const result = await pool.query('SELECT * FROM getONEmonthlypayment($1)',[id]); + + const monthlypayment = result.rows.map(mp => ({ + expense_id: mp.expense_id, + descriptionex: mp.descriptionex, + recurrence_id: mp.recurrence_id, + payment_type: mp.payment_type, + currency_idea: mp.currency_id, + suppliers_id: mp.suppliers_id, + area: mp.area, + expense_category: mp.expense_category, + day_expense: mp.day_expense, + tax_id: mp.tax_id, + new_subtotal: mp.new_subtotal + })); + + + + res.json({ + data:monthlypayment + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el pago mensual' }); + } + +}; +const needtorefresh = async (req, res) => { + try{ + const {id} = req.params; + const {notrefresh} = req.body; + let mensaje; + const result = await pool.query('SELECT needToRefresh($1,$2)',[id,notrefresh]); + const rows = result.rowCount; + if (notrefresh == true) + mensaje = 'El gasto mensual se estara actualizando.'; + else + mensaje = 'El gasto mensual NO se estara actualizando' + res.json({ + data:rows, + message: mensaje + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo completar la accion' }); + } + +}; + + + +module.exports = {newMonthlyExpense,setPaymentStatusMonthly,refreshMonthlyExpenses,updateMonthlyExpense,getOneMonthly,needtorefresh}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/product.controller.js b/backend/hotel_hacienda/src/controllers/product.controller.js new file mode 100644 index 0000000..1e066d0 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/product.controller.js @@ -0,0 +1,513 @@ +const pool = require('../db/connection'); + +const getproductsdisplay = async (req, res) => { + try{ + const result = await pool.query( + 'SELECT * FROM getproductsdisplay()' + ); + const productsDisplay = result.rows.map(pro => ({ + id_product:pro.id_product, + image_product: pro.image_product, + name_product: pro.name_product, + price_product: pro.price_product, + units: pro.units + })); + + + + res.json({ + data:productsDisplay + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los productos' }); + } + +}; + +const getproduct = async (req, res) => { + const { id } = req.params; + try{ + const result = await pool.query('SELECT * FROM getoneproduct($1)',[parseInt(id)]); + const product = result.rows.map(pro => ({ + id_product: pro.id_product, + image_product: pro.image_product, + name_product: pro.name_product, + sku_product: pro.sku_product, + supplier_product: pro.supplier_product, + price_product: pro.price_unit, + id_tax: pro.tax_product, + id_category_pro: pro.category_product, + product_type: pro.product_type, + stock: pro.stock, + id_curreny: pro.currency, + id_unit: pro.unit + })); + + res.json({ + data:product + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el producto' }); + } + +}; + +const getcategoryproducts = async (req, res) => { + try{ + const result = await pool.query( + 'SELECT * FROM getcategoryproducts()' + ); + const productCategory = result.rows.map(cat => ({ + id_prod_category: cat.id_prod_category, + name_prod_category: cat.name_prod_category, + spanish_name: cat.spanish_name + })); + + + + res.json({ + data:productCategory + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener las categorias del producto' }); + } + +}; + +const gettypeproduct = async (req, res) => { + try{ + const result = await pool.query( + 'SELECT * FROM gettypeproduct()' + ); + const productType = result.rows.map(type => ({ + id_product_type: type.id_product_type, + name_product_type: type.name_product_type, + spanish_name: type.spanish_name + })); + + + + res.json({ + data:productType + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los tipos del producto' }); + } + +}; +const getsuppliers = async (req, res) => { + try{ + const result = await pool.query( + 'SELECT * FROM getsuppliers()' + ); + const suppliers = result.rows.map(supp => ({ + name_suppliers: supp.name_suppliers, + rfc_suppliers: supp.rfc_suppliers, + })); + + + + res.json({ + data:suppliers + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los proveedores del producto' }); + } + +}; +const newsupplier = async (req, res) => { + try{ + const {new_name_supp, + new_rfc_supp, + new_mail_supp, + new_phone_supp} = req.body + const result = await pool.query('SELECT newsupplier($1,$2,$3,$4) AS status', + [new_name_supp,new_rfc_supp, new_mail_supp, new_phone_supp]); + const newsupplier = result.rows[0].status; + res.json({ + message: "Proveedor agregado correctamente", + new_supplier: newsupplier + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al ingresar un nuevo proveedor' }); + } +}; + +const updateSupplier = async (req, res) => { + try{ + const {id} = req.params; + const { + name_supp, + rfc_supp, + mail_supp , + phone_supp} = req.body + const result = await pool.query('SELECT updateSupplier($1,$2,$3,$4) AS status', + [parseInt(id),name_supp,rfc_supp, mail_supp, phone_supp]); + const updatesupplier = result.rows[0].status; + res.json({ + message: "Proveedor actualizado", + new_supplier: updatesupplier + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al actualizar el proveedor' }); + } +}; + +const disabledSupplier = async (req, res) => { + try{ + const {supplier_id} = req.body + const result = await pool.query('SELECT disableSuppliers($1) AS status', [supplier_id]); + const disabled = result.rows[0].status; + res.json({ + message: "Proveedor deshabilitado", + new_supplier: disabled + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al deshabilitar' }); + } +}; +const newproduct = async (req, res) => { + try{ + const {new_name_product, + new_sku_product, + product_type, + new_category, + suppliers_id, + unit, + new_stock, + newprice_product, + new_tax, + currency, + image_product} = req.body + const result = await pool.query('SELECT newproduct($1,$2,$3::jsonb,$4,$5,$6,$7,$8,$9,$10,$11) AS status', + [new_name_product,new_sku_product,JSON.stringify(product_type),new_category,suppliers_id,unit,new_stock, + newprice_product,new_tax,currency,image_product]); + const newproduct = result.rows[0].status; + res.json({ + message: "Producto agregado correctamente", + new_product: newproduct + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al ingresar un nuevo proveedor' }); + } +}; +const updateproduct = async (req, res) => { + try{ + const { id } = req.params; + const { + product_type, + up_name_product, + up_sku_product, + suppliers_id, + up_price_product, + up_id_tax, + id_category, + new_stock, + img_product, + currency, + unit + } = req.body + + const result = await pool.query('SELECT updateproduct($1,$2::jsonb,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12) AS status', + [parseInt(id),JSON.stringify(product_type),up_name_product,up_sku_product,suppliers_id, + up_price_product,parseInt(up_id_tax),parseInt(id_category),parseInt(new_stock),img_product,currency,unit]); + + const updateProduct = result.rows[0].status; + res.json({ + message: "Se actualizo el producto correctamente", + new_product: updateProduct + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo actualizar el usuario'}); + } + + +}; + +const discardProduct = async (req, res) => { + try{ + const { id } = req.params; + const { quantity, + reasons} = req.body + + const result = await pool.query('SELECT discardproductsstock($1,$2,$3) AS status', + [parseInt(id),quantity,reasons]); + + const discardProduct = result.rows[0].status; + res.json({ + message: "Producto descartado correctamente", + discard_product: discardProduct + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo hacer el descarte del producto'}); + } + + +}; +const getdiscardproduct = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getdiscardproduct()'); + + const discartProducts = result.rows.map(dp => ({ + id_discard: dp.id_discard, + product: dp.product, + original: dp.original, + quantity: dp.quantity, + reasons: dp.reasons, + date_discard : dp.date_dis, + total: dp.total + })); + res.json({ + message: "Se obtuvieron los productos descartados", + product: discartProducts + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo hacer el descarte del producto'}); + } + + +}; +const reportInventory = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM report_inventoryv2()'); + + const reportInventory = result.rows.map(ri => ({ + date_movement: ri.date_movement, + id_product: ri.id_product, + name_product: ri.name_product, + category_en: ri.category_en, + category_esp:ri.category_esp, + movement: ri.movement, + comments_discard: ri.comments_discard, + housekeeper_name: ri.housekepper_name, + quantity: ri.quantity, + average_cost: ri.average_cost, + before_stock: ri.before_stock, + stock : ri.stock, + })); + res.json({ + message: "Se obtuvo el reporte de inventario", + new_product: reportInventory + }); + + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo obtener el reporte'}); + } +}; +const getstockadjusments = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getstockadjusments()'); + + const productAdjusment = result.rows.map(ri => ({ + id_product: ri.id_product, + name_product: ri.name_product, + category_en: ri.category_en, + category_esp: ri.category_esp, + stock: ri.stock, + })); + res.json({ + message: "Se obtuvo el reporte de inventario", + productAdjusment: productAdjusment + }); + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo obtener el reporte'}); + } +}; + +const setstockadjusments = async (req, res) => { + try{ + const { stockproductadjusment} = req.body + const result = await pool.query('SELECT * FROM setstockadjusmentsv2($1::jsonb) as stockadjus',[JSON.stringify(stockproductadjusment)]); + + const stockproduct = result.rows[0].stockadjus; + res.json({ + message: "Se hicieron los ajustes correspondientes", + stockproduct: stockproduct}); + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo realizar el ajuste'}); + } +} +const getHouseKeeper = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM gethousekeeper()'); + const houseKeepers = result.rows.map(hk => ({ + rfc_employee: hk.rfc_employee, + name_emp: hk.name_emp, + })); + res.json({ + message: "Se obtuvieron los datos", + houseKeeper: houseKeepers}); + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo obtener los datos'}); + } +} +const newConsumptionStock = async (req, res) => { + try{ + const { + product_id, + quantity_consumption, + date_consumption, + rfc_emp} = req.body + const result = await pool.query('SELECT consumptionstock($1,$2,$3,$4) as STATUS',[product_id,quantity_consumption,date_consumption,rfc_emp]); + const status = result.rows[0].status; + if(status == 1) + message = "El consumo del producto fue realizado con exito"; + else + message = "No se pudo hacer el consumo" + res.json({ + message, + status: status + }); + } + catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo obtener los datos'}); + } +} +const getConsumptionStockReport = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getconsumptionreport()'); + const stockConsumptions = result.rows.map(sc => ({ + rfc_employee: sc.rfc_employee, + name_emp: sc.name_emp, + date_consumption:sc.date_consumption, + product_id:sc.product_id, + product_name:sc.product_name, + quantity:sc.quantity, + stocktotal:sc.stocktotal + })); + res.json({ + message: "Se obtuvieron los datos", + stockConsumption: stockConsumptions}); + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo obtener los datos'}); + } +}; +const getproducts = async (req, res) => { + try{ + const page = parseInt(req.query.page) || 1; // Página actual + const limit = parseInt(req.query.limit) || 10; // Cantidad por página + const offset = (page - 1) * limit; // Desde dónde empezar + const result = await pool.query('SELECT * FROM getproducts() LIMIT $1 OFFSET $2',[limit, offset]); + + const totalResult = await pool.query('SELECT COUNT(*) FROM products'); + const total = parseInt(totalResult.rows[0].count); + const totalPages = Math.ceil(total / limit); + + const products = result.rows.map(pro => ({ + id_product: pro.id_product, + name_product:pro.name_product, + sku_product:pro.sku_product, + price_product:pro.price_product, + id_tax:pro.id_tax, + percentage: pro.percentage, + id_prod_category: pro.id_prod_category, + name_prod_category: pro.name_prod_category, + id_unit: pro.id_unit, + name_unit: pro.name_unit, + id_currency: pro.id_currency, + name_currency: pro.name_currency, + image_product: pro.image_product, + id_suppliers: pro.id_suppliers, + name_suppliers: pro.name_suppliers + })); + res.json({ + page, + limit, + total, + totalPages, + message: "Se obtuvieron los datos", + product: products}); + } + catch(error) + { + console.error(error); + res.status(500).json({ message: 'No se pudo obtener los datos'}); + } +}; + +module.exports = +{ + getproductsdisplay, + getproducts, + getcategoryproducts, + gettypeproduct, + getsuppliers, + getproduct, + newsupplier, + newproduct, + updateproduct, + discardProduct, + getdiscardproduct, + reportInventory, + getstockadjusments, + setstockadjusments, + getHouseKeeper, + newConsumptionStock, + getConsumptionStockReport, + updateSupplier, + disabledSupplier +} \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/purchase.controller.js b/backend/hotel_hacienda/src/controllers/purchase.controller.js new file mode 100644 index 0000000..4ea00b9 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/purchase.controller.js @@ -0,0 +1,51 @@ +const pool = require('../db/connection'); + + +const getpurchases = async (req, res) => +{ + try{ + const result = await pool.query('SELECT * From getpurchases()'); + const purchases = result.rows.map(re => ({ + id_purchase_dt: re.id_purchase_dt, + id_expense :re.id_expense , + id_product :re.id_product , + product_name: re.product_name, + quantity: re.quantity , + delivered: re.delivered , + id_tax :re.id_tax , + total : re.total + + })); + + res.json({ + message: "Se obtuvieron todos los Purchases details", + data:purchases + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener los purchases details.',error }); + } +}; +const purchaseid = async (req, res) => +{ + try{ + const {id} = req.params; + const {checking} = req.body; + + console.log(id,checking); + const result = await pool.query('SELECT * FROM purchaseentry($1,$2) as status',[id,checking]);; + const newentry = result.rows[0].status; + res.json({ + message: 'Se obtuvo el Purchases details', newentry + + }); + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el Purchases details',error }); + } +}; + +module.exports = {getpurchases,purchaseid}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/reportcontract.controller.js b/backend/hotel_hacienda/src/controllers/reportcontract.controller.js new file mode 100644 index 0000000..4935385 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/reportcontract.controller.js @@ -0,0 +1,44 @@ +const pool = require('../db/connection'); + +const getReportContracts = async (req, res) => { + try { + // Leer query params con valores por defecto + const page = parseInt(req.query.page) || 1; // Página actual + const limit = parseInt(req.query.limit) || 10; // Cantidad por página + const offset = (page - 1) * limit; // Desde dónde empezar + + // Llamamos a la función con LIMIT y OFFSET + const result = await pool.query( + `SELECT * FROM reportcontracts() LIMIT $1 OFFSET $2`, + [limit, offset] + ); + + // Obtener total para calcular páginas + const totalResult = await pool.query('SELECT COUNT(*) FROM contracts'); + const total = parseInt(totalResult.rows[0].count); + const totalPages = Math.ceil(total / limit); + + const contracts = result.rows.map(con => ({ + name_employee: con.id_contract, + position_employee: con.name_employee, + area_employee: con.position_employee, + contract_end: con.end_contract, + daily_pay: con.daily_pay, + status_contracts: con.status_contracts + })); + + res.json({ + page, + limit, + total, + totalPages, + data: contracts + }); + + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener los contratos' }); + } +}; + +module.exports = { getReportContracts }; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/reporter.controller.js b/backend/hotel_hacienda/src/controllers/reporter.controller.js new file mode 100644 index 0000000..ad23066 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/reporter.controller.js @@ -0,0 +1,39 @@ +const pool = require('../db/connection'); + + +const getSharedExpenses = async (req, res) => { + try { + + const result = await pool.query(`SELECT * FROM shared_expenses_dashboard`); + + const data = result.rows.map(row => ({ + id_expense: row.id_expense, + id_properties: row.id_properties, + id_expense_type: row.id_expense_type, + request_date: row.request_date, + payment_deadline: row.payment_deadline, + id_area: row.id_area, + id_expense_cat: row.id_expense_cat, + id_approval_stat: row.id_approval_stat, + id_currency: row.id_currency, + is_purchase: row.is_purchase, + total: row.total, + subtotal: row.subtotal, + iva: row.iva, + ieps: row.ieps, + id_suppliers: row.id_suppliers, + id_payment_status: row.id_payment_status, + id_cat_percent: row.id_cat_percent, + participation: row.participation, + id_fix_variable: row.id_fix_variable + })); + + res.json({ count: data.length, data }); + + } catch (error) { + console.error(error); + res.status(500).json({ error: 'Error al obtener los datos del dashboard' }); + } +}; + +module.exports = { getSharedExpenses }; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/restaurantpl.controller.js b/backend/hotel_hacienda/src/controllers/restaurantpl.controller.js new file mode 100644 index 0000000..0a303ea --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/restaurantpl.controller.js @@ -0,0 +1,118 @@ +const pool = require('../db/connection'); + +const totalrevenue = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body + const result = await pool.query('SELECT * FROM totalrevenue_rest($1,$2) as status',[start_date,end_date]); + const totalrenueve = result.rows[0].status; + /*const totalrenueve = result.rows.map(re => ({ + total: re.total + }));*/ + + + res.json({ + data:totalrenueve + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const cogs = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body; + const result = await pool.query('SELECT * FROM cogs_rest($1,$2) as status',[start_date,end_date]); + const cogs = result.rows[0].status; + /*const cogs = result.rows.map(re => ({ + cogs_total: re.cogs_total, + }));*/ + + + res.json({ + message: "Se obtuvieron los ingresos", + data:cogs + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: error }); + } +}; + +const grossprofit = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body; + const result = await pool.query('SELECT * FROM grossprofit_rest($1,$2) as status',[start_date,end_date]); + const grossprofit = result.rows[0].status; + /*const grossprofit = result.rows.map(re => ({ + grossprofit: re.grossprofit + }));*/ + + + res.json({ + message: "Se obtuvieron los ingresos", + data:grossprofit + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + + +const weightedCategoriesCost = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body + const result = await pool.query('SELECT * FROM weighted_categories_rest_cost($1,$2)',[start_date,end_date]); + const weightedCategoriesCost = result.rows.map(re => ({ + id_expense_cat : re.id_expense_cat , + category_name: re.category_name , + spanish_name : re.spanish_name , + total : re.total, + participation : re.participation + })); + res.json({ + data:weightedCategoriesCost + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +const ebitda = async (req, res) => +{ + try{ + const {start_date,end_date} = req.body; + const result = await pool.query('SELECT * FROM ebitda_rest($1,$2)', [start_date,end_date]); + const ebitda = result.rows.map(re => ({ + expenses_total: re.expenses_total, + ebitda : re.ebitda + })); + + + res.json({ + message: "Se obtuvieron los ingresos", + data:ebitda + }); + + }catch(error) + { + console.error(error); + res.status(500).json({ message: 'Error al obtener el dato' }); + } +}; + +module.exports = {ebitda,weightedCategoriesCost,grossprofit,totalrevenue,cogs}; diff --git a/backend/hotel_hacienda/src/controllers/settings.controller.js b/backend/hotel_hacienda/src/controllers/settings.controller.js new file mode 100644 index 0000000..63d63ba --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/settings.controller.js @@ -0,0 +1,188 @@ +const pool = require('../db/connection'); + +const addNewRoom = async (req, res) => { + try{ + const {room,units,cost_per_nigth,guest,bed,amenities,products} = req.body; + + const result = await pool.query(`SELECT new_room($1,$2,$3,$4,$5,$6::jsonb,$7::jsonb) AS room_id`, + [room,units,cost_per_nigth,guest,bed,JSON.stringify(amenities),JSON.stringify(products)]); + const newRoom = result.rows[0].room_id; + res.json({ + message: "Se agrego correctamente la habitacion", + new_room: newRoom + }); + }catch(error) { + console.error(error); + res.status(500).json({ message: 'No se pudo agregar nueva habitacion' }); + } + + +}; +const reportRoom = async(req,res) =>{ + try{ + const result = await pool.query('SELECT * FROM reportrooms()'); + + const rooms = result.rows.map(ro => ({ + id_room: ro.id_room, + name_room: ro.name_room, + guests: ro.guests, + bed_type: ro.bed_type, + quantity: ro.quantity + })); + res.json({ + message: "Se obtuvo el reporte de habitaciones", + new_product: rooms + }); + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No pudo recuperar la tabla de reporte.'}); + } +}; +const addNewProperty = async (req, res) => { + try{ + const {new_name,addres_pro,main_area_pro,rfc_pro,phone,areas,services} = req.body; + + const result = await pool.query(`SELECT new_property($1,$2,$3,$4,$5,$6::jsonb,$7::jsonb) AS property_id`, + [new_name,addres_pro,main_area_pro,rfc_pro,phone,JSON.stringify(areas),JSON.stringify(services)]); + const newRoom = result.rows[0].property_id; + res.json({ + message: "Se agrego correctamente la propiedad", + new_property: newRoom + }); + }catch(error) { + console.error(error); + res.status(500).json({ message: 'No se pudo agregar nueva propiedad' }); + } + + +}; +const reportProperties = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM reportproperties()'); + const property = result.rows.map(ro => ({ + id_prop: ro.id_prop, + name_property: ro.name_property, + areas: ro.areas + })); + res.json({ + message: "Se obtuvo el reporte de propiedades", + reportProperties: property + }); + }catch(error) { + console.error(error); + res.status(500).json({ message: 'No se pudo consultar las propiedades' }); + } +}; + +const getunits = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getunits()'); + const units = result.rows.map(u => ({ + id_unit: u.id_unit, + name_unit: u.name_unit})); + res.json({ + message: "Se obtuvieron las unidades de medida", + units: units + }); + + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo recuperar las unidades' }); + } + +}; + +const getapproveby = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getapproveby()'); + const approveby = result.rows.map(ap => ({ + id_user: ap.id_user, + user_name: ap.user_name})); + res.json({ + message: "Se obtuvieron las aprobadores", + approve: approveby + }); + + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo recuperar los aprobadores' }); + } + +}; + +const getcurrency = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getcurrency()'); + const currency = result.rows.map(u => ({ + id_currency: u.id_currency, + name_currency: u.name_currency})); + res.json({ + message: "Se obtuvieron las monedas", + currency: currency + }); + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo recuperar las monedas' }); + } + +}; +const getrecurrence = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getrecurrence()'); + const recurrence = result.rows.map(u => ({ + id_recurrence: u.id_recurrence, + name_recurrence: u.name_recurrence})); + res.json({ + message: "Se obtuvieron las recurrencias", + currency: recurrence + }); + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo recuperar la recurrencia' }); + } + +}; + +const getrequestby = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getrequestby()'); + const units = result.rows.map(u => ({ + id_user: u.id_user, + user_name: u.user_name})); + res.json({ + message: "Se obtuvieron los solicitantes", + request: units + }); + + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo recuperar los solicitantes' }); + } + +}; + +const getcategoryexpense = async (req, res) => { + try{ + const result = await pool.query('SELECT * FROM getcategoryexpense()'); + const categoryex = result.rows.map(u => ({ + id_category: u.id_category, + name_category: u.name_category})); + res.json({ + message: "Se obtuvieron las categorias del gasto", + categoryex: categoryex + }); + + + }catch(error){ + console.error(error); + res.status(500).json({ message: 'No se pudo las categorias del gasto' }); + } + +}; +module.exports = {addNewRoom,reportRoom,addNewProperty,reportProperties,getunits, + getcategoryexpense,getrequestby,getcurrency,getapproveby,getrecurrence}; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/controllers/status.controller.js b/backend/hotel_hacienda/src/controllers/status.controller.js new file mode 100644 index 0000000..49a01c0 --- /dev/null +++ b/backend/hotel_hacienda/src/controllers/status.controller.js @@ -0,0 +1,107 @@ +const pool = require('../db/connection'); + +const setapprovalstatus = async (req, res) => { + try { + const { id } = req.params; + const {status, approved_by} = req.body; + console.log('params:', id); + console.log('body:', status); + const result = await pool.query('SELECT setapprovalstatus($1,$2,$3) AS status',[id,status,approved_by]); + const updateapproval = result.rows[0].status; + if(updateapproval == 3) + { + res.json({ + message: "El usuario no tiene permisos para aprobar.", + new_product: updateapproval + }); + }else{ + res.json({ + message: "Se actualizo correctamente el estatus de aprobación", + new_product: updateapproval + }); + + } + + } + catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al actualizar el estatus de aprobacion' }); + } + +}; + +const setpaymentstatus = async (req, res) => { + try { + const { id } = req.params; + const {status} = req.body; + console.log('params:', id); + console.log('body:', status); + const result = await pool.query('SELECT setpaymentstatusv2($1,$2) AS status',[id,status]); + + const updatepayment = result.rows[0].status; + if(updatepayment == -3){ + res.json({ + message: "El gasto no esta aprobado o fue rechazado", + paymentstatus: updatepayment + });} + else { + res.json({ + message: "Se actualizo correctamente el estatus del pago", + paymentstatus: updatepayment + }); + } + } + catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al actualizar el estatus del pago' }); + } + +}; + +const pendingAppPayments = async (req, res) => { +try{ +const result = await pool.query('SELECT pendingapppayments() AS pendingapp',); +const pendingapprov = result.rows[0].pendingapp; + +console.log(result.rows[0].pendingApp); + res.json({ + message: "Pagos pendientes de aprobación", + data: pendingapprov + }); + +}catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener pagos pendientes por aprobar' }); + } +}; + +const countDelayPayments = async (req, res) => { +try{ +const result = await pool.query('SELECT countdelaypayments() AS delaypayments',); +const delayPay = result.rows[0].delaypayments; + res.json({ + message: "Pagos con retraso", + data: delayPay + }); + +}catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener pagos con retraso' }); + } +}; +const totalSpent = async (req, res) => { +try{ +const result = await pool.query('SELECT totalspent() AS spent',); +const totalSpent = result.rows[0].spent; + res.json({ + message: "Total gastado", + data: totalSpent + }); + +}catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al obtener total gastado' }); + } +}; + + module.exports = { setapprovalstatus,setpaymentstatus,pendingAppPayments,countDelayPayments,totalSpent }; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/db/connection.js b/backend/hotel_hacienda/src/db/connection.js new file mode 100644 index 0000000..984b81d --- /dev/null +++ b/backend/hotel_hacienda/src/db/connection.js @@ -0,0 +1,16 @@ +const { Pool } = require('pg'); +require('dotenv').config(); + +const pool = new Pool({ + host: process.env.DB_HOST, + port: process.env.DB_PORT, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME +}); + +pool.connect() + .then(() => console.log('Conectado a PostgreSQL')) + .catch(err => console.error('Error de conexión:', err)); + +module.exports = pool; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/middlewares/handleValidation.js b/backend/hotel_hacienda/src/middlewares/handleValidation.js new file mode 100644 index 0000000..e4230b1 --- /dev/null +++ b/backend/hotel_hacienda/src/middlewares/handleValidation.js @@ -0,0 +1,15 @@ +const { validationResult } = require('express-validator'); + +const handleValidation = (req, res, next) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ + status: 400, + message: 'Error en la validación de datos', + errors: errors.array() + }); + } + next(); +}; + +module.exports = handleValidation; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/middlewares/validators.js b/backend/hotel_hacienda/src/middlewares/validators.js new file mode 100644 index 0000000..9f24271 --- /dev/null +++ b/backend/hotel_hacienda/src/middlewares/validators.js @@ -0,0 +1,12 @@ +const { body } = require('express-validator'); + +const loginValidator = [ + body('name_mail_user') + .trim() + .notEmpty().withMessage('El correo o nombre de usuario es obligatorio'), + body('user_pass') + .trim() + .notEmpty().withMessage('La contraseña es obligatoria') +]; + +module.exports = { loginValidator }; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/resources/littleHotelier/reservations1.csv b/backend/hotel_hacienda/src/resources/littleHotelier/reservations1.csv new file mode 100644 index 0000000..e8674b1 --- /dev/null +++ b/backend/hotel_hacienda/src/resources/littleHotelier/reservations1.csv @@ -0,0 +1,5652 @@ +Booking reference,Booked,Property name,Channel name,Promotion code,Guest first name,Guest last name,Guest email,Guest phone number,Guest organisation,Guest address,Guest address2,Guest city,Guest state,Guest country,Guest post code,Check in date,Check out date,Length of stay (nights),Arrival time,Guest comments,Notes,Requested newsletter,Status,Cancelled at,Room types,Room rates,Subtotal amount (excluding tax),Subtotal amount (including tax),Extra adult amount,Extra child amount,Extra infant amount,Extras total amount,Credit card surcharge processed amount,Surcharge Percentage,Promotional Discount,Payment total,Payment Received,Number of adults,Number of children,Number of infants,Number of Rooms,Custom Property Specific Data,Referral,Payments deposit processed total,Payment outstanding,Mobile booking?,Promotion Description,Enter rates including fees,Fixed Taxes Total,Percentage Taxes Total,Rooms,Invoice Number +EXP-X-387040053,2025-01-01,Hacienda San Angel,Expedia,,Nicole,Royer,p69xmmmymt@m.expediapartnercentral.com,1 0 7202618375,,,,,,,,2025-01-01,2025-01-02,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 576.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION TRHU EXP // +LAS MINUTE // +CONFIRMATION SENT ENE01 // +CREDIT CARD INFORMATION OK // +VIRTUAL CARD FOR CHARGE // +SUITE ANGEL VIEW // +STAY ENE01-022025 // +RATE 480 USD + TAXES // +ENE01225GV +**************************************** +GUEST REQUEST ROOM CHANGE AS 3 PEOPLE ARE TRAVELING +NEW RESERVATION SJ (2PAX) ROOM CHANGE AV- VS (1PAX) +RATE WAS ADJUSTED $90 USD + TAXES FOR CHANGE TO VISTA DE SANTOS SINCE RATE WAS $570 USD + TAXES IN VS",,Checked-out,"", Vista de Santos - Master Suite,Manual,480.0,759.33,0.0,0.0,0.0,159.33,0.0,0.0,0.0,759.33,754.53,2,0,0,1,,,0,4.8,false,"",false,0,120.0,Room 121,"2323-1, 2323-2" +EXP-X-387049250,2025-01-01,Hacienda San Angel,Expedia,,Nicole,Royer,fgb8kgt8iv@m.expediapartnercentral.com,0 0 7202618375,,,,,,,,2025-01-01,2025-01-02,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 600.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION TRHU EXP // +LAS MINUTE // +CONFIRMATION SENT ENE01 // +CREDIT CARD INFORMATION OK // +VIRTUAL CARD FOR CHARGE // +SUITE SAN JOSE // +STAY ENE01-022025 // +RATE 500 USD + TAXES // +ENE01225GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,500.0,814.06,0.0,0.0,0.0,189.06,0.0,0.0,0.0,814.06,809.06,1,0,0,1,,,0,5.0,false,"",false,0,125.0,Room 122,"2322-1, 2322-2" +EXP-X-387137494,2025-01-01,Hacienda San Angel,Expedia,,IGOR,GRUBAC,"",1 4156726234,,,,,,,,2025-01-02,2025-01-03,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 768.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +RATE $ 640 USD + TAXES // +CREDIT CARD INFORMATION OK // +VIRTUAL CARD FOR CHARGE // +NO PROMO // +STAY ENE02-032025 // +SUITE RICON DE ANGELES // +ENE012025GV",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,640.0,1035.36,0.0,0.0,0.0,235.36,0.0,0.0,0.0,1035.36,1028.96,2,0,0,1,,,0,6.4,false,"",false,0,160.0,Room 119,2327-1 +EXP-X-386807881,2025-01-01,Hacienda San Angel,Expedia,,Richard,Chpiman,ml2wl6v8n2@m.expediapartnercentral.com,0 0 14088237706,,,,,,,,2025-01-05,2025-01-06,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 744.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIA .COM // +CONFIRMATION SENT DEC312024 // +CREDIT CARD INFORMATION OK // +RATE $ 620 USD + TAXES // +STAY DEC05-062024 // +SUITE SAN MIGUEL // +SUBMITED DEC.312024NGR//",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,620.0,740.33,0.0,0.0,0.0,-34.67,0.0,0.0,0.0,740.33,744.0,2,0,0,1,,,0,-3.67,false,"",false,0,155.0,Room 107,"2339-1, 2339-2" +MMS-OBH25010119302605-2699879,2025-01-01,Hacienda San Angel,Mr and Mrs Smith,,Michael,Gold,MCG3832@YAHOO.COM,,,,,,,,,2025-01-05,2025-01-07,2,,PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MR&MRS SMITH // +CONFIRMATION SENT // +RATE $493.35 USD + TAXES // +CREDIT CARD INFORMATION OK // +VIRTUAL CARD FOR CHARGE // +RSV BYE HYATT // +NO PROMO // +STAY ENE05-072025 // +SUITE RINCON DE ANGELES // +ENE012025GV",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,939.34,1223.51,0.0,0.0,0.0,49.33,0.0,0.0,0.0,1223.51,1223.51,1,0,0,1,,,0,0.0,false,"",false,0,234.835,Room 119,2343-1 +BDC-4840294814,2025-01-03,Hacienda San Angel,Booking.com,,Stephen,Fish,sfish.917282@guest.booking.com,+1 888 6447452,,822 Cleveland St,,Oakland,,United States,94606,2025-01-06,2025-01-08,2,,smoking preference: Non-Smoking,"RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JAN032025 // +CREDIT CARD INFORMATION OK // +RATE $ 472.50 USD + TAXES // +STAY JAN06-082025 // +SUITE ANGEL DOME // +SUBMITED JAN032025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,945.0,1179.36,0.0,0.0,0.0,7.56,0.0,0.0,0.0,1179.36,1179.36,2,0,0,1,,,0,0.0,false,"",false,0,226.8,Room 113,"2350-1, 2350-2, 2350-3" +MMS-OBH25010619354808-2705398,2025-01-06,Hacienda San Angel,Mr and Mrs Smith,,Michael,Gold,MCG3832@YAHOO.COM,,,,,,,,,2025-01-07,2025-01-08,1,,"PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +Hi I am already here. Extending my stay in Same suite","RESERVATION FROM MR. & MRES. SMITH +HYATT (OBH) +RATE $434.16 + TAXES +NO PORMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT ENE06/25 +OK MARIANA ENE06/25 + + +GUEST INS THE HOUSE HE IS ONLY EXTENDING ONE MORE NIGHT",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,430.69,655.84,0.0,0.0,0.0,117.48,0.0,0.0,0.0,655.84,655.84,1,0,0,1,,,0,0.0,false,"",false,0,107.6725,Room 119,2346-1 +LH25010645284136,2025-01-06,Hacienda San Angel,Extranet,,Jenny,Hart,adoyle@ptgconsulting.com,5579403250,,,,,,,,2025-01-08,2025-01-10,2,,"","Writer Jenny Hart story package for Condé Nast traveler publication in USA. +complimentary stay in exchange of publication. + +Habitación con continental incluido +Jenny Hart tiene alimentos y bebidas incluidos (no alcohol) .. si quiere alcohol las 30% off + +Su acompañante tiene 30% off en sus consumos",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1115.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,1,0,0,1,,,0,0.0,false,"",false,0,0,Room 121,2356-1 +LH25010745303000,2025-01-07,Hacienda San Angel,Extranet,,Stephen,Fish,info@haciendasanangel.com,+1 888 6447452,,822 Cleveland St,,Oakland,,United States,94606,2025-01-08,2025-01-09,1,,"","ANGEL RATE +COMP",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,415.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 113,2354-1 +SMP-2025010537230832,2025-01-05,Hacienda San Angel,Simple Booking,,Steven,Erickson,stevengerickson@gmail.com,+1303-618-7869,,,,,,,"",2025-01-09,2025-01-11,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN052025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 600 USD + TAXES // +STAY 9-11JAN2025// +SUITE SAN JOSE // +SUBMITED JAN052025NGR//",,Cancelled,2025-01-05 10:32:13, San Jose - Master Suite,San Jose - Standard Rate,1190.4,1488.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1488.0,0,2,0,0,1,,,0,1488.0,false,"",false,0,288.0,Room 122,"" +LH25010545259544,2025-01-05,Hacienda San Angel,Extranet,,STEVEN,ERIKSON,stevengerickson@gmail.com,3036187869,,,,,,,,2025-01-09,2025-01-11,2,,"","RESERVATION THRU simplebooking // +CONFIRMATION SENT JAN052025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 600 USD + TAXES // +STAY JAN9-112025 // +SUITE SAN JOSE// +SUBMITED JAN052025NGR//",,Checked-out,"", San Jose - Master Suite,Manual,1200.0,1621.06,0.0,0.0,0.0,121.06,0.0,0.0,0.0,1621.06,1609.06,2,0,0,1,,,0,12.0,false,"",false,0,300.0,Room 122,2358-1 +LH25010945342383,2025-01-09,Hacienda San Angel,Extranet,,Stephen,Fish,info@haciendasanangel.com,+1 888 6447452,,822 Cleveland St,,Oakland,,United States,94606,2025-01-09,2025-01-10,1,,"","ANGEL RATE +COMP",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,535.0,544.02,0.0,0.0,0.0,544.02,0.0,0.0,0.0,544.02,544.02,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,2355-1 +EXP-X-389688123,2025-01-05,Hacienda San Angel,Expedia,,Rodolfo,Corona,8i6gmnb0kd@m.expediapartnercentral.com,1 917 6478642,,,,,,,,2025-01-10,2025-01-14,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,592.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $540.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD +CONFIRMATION SENT ENE05/2025 +OK MARIANA ENE05/25",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,2160.0,2955.08,0.0,0.0,0.0,255.08,0.0,0.0,0.0,2955.08,2933.48,2,0,0,1,,,0,21.6,false,"",false,0,540.0,Room 121,2364-1 +LH25011145389790,2025-01-11,Hacienda San Angel,Extranet,,Tim,Hobby,tim@hamodern.com,+14048220604,,,,,,United States of America,"",2025-01-11,2025-01-12,1,,"","ANGEL RATE +COMP",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,540.0,2260.46,0.0,0.0,0.0,2260.46,0.0,0.0,0.0,2260.46,2260.46,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,"2359-1, 2359-2" +EXP-X-389206041,2025-01-05,Hacienda San Angel,Expedia,,Sidney,Henderson,qytql4vkt7@m.expediapartnercentral.com,1 6172838716,,,,,,,,2025-01-16,2025-01-18,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,440.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT JAN042025// +CREDIT CARD INFORMATION OK// +RATE $ 600 USD + TAXES // +STAY 16-18JAN2025// +SUITE SAN JOSE// +SUBMITED JAN042025NGR//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1200.0,2269.59,0.0,0.0,0.0,769.59,0.0,0.0,0.0,2269.59,2269.59,2,0,0,1,,,0,0.0,false,"",false,0,300.0,Room 122,"2378-1, 2378-2" +EXP-X-393330032,2025-01-11,Hacienda San Angel,Expedia,,Hubert,Luu,d1ba8e5e9o@m.expediapartnercentral.com,1 415 6994331,,,,,,,,2025-01-17,2025-01-19,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,296.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay",,,Cancelled,2025-01-10 18:21:46, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1080.0,1339.2,0.0,0.0,0.0,0.0,0,0.0,0.0,1339.2,0,2,0,0,1,,,0,1339.2,false,"",false,0,259.2,Room 118,"" +SMP-2025010437204562,2025-01-04,Hacienda San Angel,Simple Booking,,Sarah Beth,Thie,sarahbeth@sarahelizabethevents.com,8433248810,,,,,,,"",2025-01-18,2025-01-19,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN032024 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 410 USD + TAXES // +STAY JAN18-192025 // +SUITE ANGEL DOME // +SUBMITED JAN032025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,406.72,666.59,0.0,0.0,0.0,158.19,0.0,0.0,0.0,666.59,666.59,2,0,0,1,,,0,0.0,false,"",false,0,101.68,Room 113,2379-1 +EXP-X-393425392,2025-01-11,Hacienda San Angel,Expedia,,Jose,Faz,n8ly98tfm8@m.expediapartnercentral.com,34 871180461,,,,,,,,2025-01-19,2025-01-22,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, 32nd Wedding Anniv.., Remittance amount: 1,567.44, Expedia Virtual Card will be activated from the day of Check-in.","ARESERVATION FROM EXPEDIA +RATE $435.40 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT ENE10/25 +OK MARIANA ENE10/25 + + CELEBRATE 32 ANNIVERSARY",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1306.2,1858.02,0.0,0.0,0.0,225.27,0.0,0.0,0.0,1858.02,1858.02,2,0,0,1,,,0,0.0,false,"",false,0,326.55,Room 109,"2389-1, 2389-2" +EXP-X-398816552,2025-01-19,Hacienda San Angel,Expedia,,Heather,Nichols,yq1wsnyq8w@m.expediapartnercentral.com,0 0 3034786845,,,,,,,,2025-01-19,2025-01-20,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 438.60, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,365.5,553.08,0.0,0.0,0.0,96.2,0.0,0.0,0.0,553.08,553.08,1,0,0,1,,,0,0.0,false,"",false,0,91.375,Room 113,2384-1 +SMP-2025010537221856,2025-01-05,Hacienda San Angel,Simple Booking,,chet,petrow,cpetrow@hotmail.com,+13033248663,,,,,,,"",2025-01-20,2025-01-22,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN042025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 410 USD + TAXES // +STAY 20-22JAN2025// +SUITE ANGELS DOME// +SUBMITED JAN042025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,813.44,1219.04,0.0,0.0,0.0,202.24,0.0,0.0,0.0,1219.04,1219.04,2,0,0,1,,,0,0.0,false,"",false,0,203.36,Room 113,2390-1 +LH25010645282986,2025-01-06,Hacienda San Angel,Extranet,,MARGIE & BOB,LITMAN,reservations@verana.com,"",,,,,,,,2025-01-20,2025-01-22,2,,"","RESERVATION FROM VERANA +CXC VERANA +CONFIRMATION SENT ENE06/25 +OK MARIANA ENE/25",,Checked-out,"",Crown View - Junior Suite,Manual,800.0,857.1,0.0,0.0,0.0,57.1,0.0,0.0,0.0,857.1,857.1,2,0,0,1,,,0,0.0,false,"",false,0,200.0,Room 112,2391-1 +EXP-X-399762858,2025-01-20,Hacienda San Angel,Expedia,,Veronika,Stukan,fekwx13a9b@m.expediapartnercentral.com,86 021 60781960,,,,,,,,2025-01-20,2025-01-21,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 2 Double Beds, Non-Smoking, Remittance amount: 415.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT JAN202025 // +CREDIT CARD INFORMATION OK // +RATE $ 346.50 USD + TAXES // +STAY JAN20-212025 // +SUITE SAN GABRIEL // +SUBMITED JAN202025NGR//",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,346.5,452.0,0.0,0.0,0.0,18.87,0.0,0.0,0.0,452.0,452.0,2,0,0,1,,,0,0.0,false,"",false,0,86.625,Room 118,"2387-1, 2387-2" +SMP-2025011637468511,2025-01-15,Hacienda San Angel,Simple Booking,,Alberto,Szekely,john@uttonkery.com,+15056991445,,,,,,,"",2025-01-22,2025-01-23,1,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT JAN152024// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 640 USD + TAXES // +STAY JAN22-232025 // +SUITE RINCÓN OF ANGELS// +SUBMITED JAN152025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,640.0,824.23,0.0,0.0,0.0,24.23,0.0,0.0,0.0,824.23,824.23,2,0,0,1,,,0,0.0,false,"",false,0,160.0,Room 119,"2394-1, 2394-2" +SMP-2025012337626803,2025-01-23,Hacienda San Angel,Simple Booking,,Glenda,Hammond,gghammond42@gmail.com,+18018308668,,,,,,,"",2025-01-23,2025-01-25,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $530.00 TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT JANUARY 22/2025 +OK MARIANA ZAVALA JANUARY22/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1060.0,1487.28,0.0,0.0,0.0,162.28,0.0,0.0,0.0,1487.28,1487.28,2,0,0,1,,,0,0.0,false,"",false,0,265.0,Room 106,2400-1 +EXP-X-400038908,2025-01-21,Hacienda San Angel,Expedia,,Ekta,Sholanki,subscriptionsonly000@gmail.com,1 416 3188557,,,,,,,,2025-01-25,2025-01-28,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,728.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $480.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT JANUARY20/25 +OK MARIANA ZAVALA JANUARY20/25",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1440.0,1800.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1800.0,1800.0,2,0,0,1,,,0,0.0,false,"",false,0,360.0,Room 118,2414-1 +LH25012345655773,2025-01-23,Hacienda San Angel,Extranet,,RENE,CERVANTES,info@haciendasanangel.com,"",,,,,,,,2025-01-25,2025-01-26,1,,"","RSERVATION DIRECTLY +ANGEL'S RATE +CREDIT CARD INFO +CONFIRMATION SENT ENE23/2025 +OK MARIANA ENE23/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,480.0,43.07,0.0,0.0,0.0,43.07,0.0,0.0,0.0,43.07,43.07,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,"2402-1, 2402-2" +BDC-4492381311,2025-01-12,Hacienda San Angel,Booking.com,,robin,kay,rkay.595462@guest.booking.com,+1 416 888 6486,,,,,,Canada,"",2025-01-26,2025-01-30,4,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING.COM +RATE $419.17+ TAXES +NO PROMO +CRECIT CARD VISA OK +CONFIRMATION SENT ENE12/25 +OK MARIANA ENE12/25",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1676.7,2267.89,0.0,0.0,0.0,172.01,0.0,0.0,0.0,2267.89,2267.89,1,0,0,1,,,0,0.0,false,"",false,0,419.175,Room 102,2416-1 +MMS-OBH25011423464406-2715327,2025-01-14,Hacienda San Angel,Mr and Mrs Smith,,Chris,Evans,DADDYOCJ@AOL.COM,,,,,,,,,2025-01-26,2025-01-28,2,,PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT JAN142025// +CREDIT CARD INFORMATION OK// +STAY JAN26-282025// +SUITE RINCÓN DE ANGELES// +SUBMITED JAN142025NGR// + + +RATE $ 463.95 WITH OUT COMISSION (20%)",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1101.47,1203.29,0.0,0.0,0.0,-173.55,0,0.0,0.0,1203.29,0.0,2,0,0,1,,,0,1203.29,false,"",false,0,275.3675,Room 119,2413-1 +BDC-4967646191,2025-01-23,Hacienda San Angel,Booking.com,,Mike,Watters,mwatte.884051@guest.booking.com,+1 970 376 8570,,,,.,,United States,"",2025-01-26,2025-01-27,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING.COM +RATE $ 468.00 + TAXES +NO PROMO +CREDIT CARD INFO CVV VISA +CONFRIMATION SENT ENE23/2025 +OK MARIANA ENE23/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,468.0,848.41,0.0,0.0,0.0,263.41,0.0,0.0,0.0,848.41,848.41,2,0,0,1,,,0,0.0,false,"",false,0,117.0,Room 109,2404-1 +EXP-X-399264212,2025-01-20,Hacienda San Angel,Expedia,,Jarrid,Lafferty,yrdx0dwy7j@m.expediapartnercentral.com,0 0 3072674572,,,,,,,,2025-01-27,2025-01-31,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,424.36, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $ 530.33 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT JANUARY19/2025 +OK MARIANA JANUARY19/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,2020.3,2546.91,0.0,0.0,0.0,21.53,0.0,0.0,0.0,2546.91,2546.91,2,0,0,1,,,0,0.0,false,"",false,0,505.075,Room 106,2418-1 +LH25012545695962,2025-01-25,Hacienda San Angel,Extranet,,Patty,Waltcher,ptywaltcher@mac.com,8053403774,,,,,,,,2025-01-27,2025-01-28,1,,"","DIRECT RESERVATION // +CONFIRMATION SENT ENE25 // +CREDIT CARD INFORMATION AMEX // +RATE $ 465 USD + TAX // +SUITE ANGEL DOME // +STAY ENE27-28 2025 // +NO PROMO // +ENE252025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,465.0,608.45,0.0,0.0,0.0,27.2,0.0,0.0,0.0,608.45,608.45,2,0,0,1,,,0,0.0,false,"",false,0,116.25,Room 113,2410-1 +LH25012745735793,2025-01-27,Hacienda San Angel,Extranet,,Natasha,Carvajal,natasha@haciendasanangel.com,7076942437,,"","","","",,"",2025-01-27,2025-01-28,1,,"CLP - ONE NIGHT = 25 PTS, ENTERED IN SPREADSHEET- TASHA JAN 27, 2025","",,Cancelled,2025-01-27 16:16:44,Serafin - Junior Suite,Serafin - Standard Rate,375.0,468.75,0.0,0.0,0.0,0.0,0,0.0,0.0,468.75,0,1,0,0,1,,,0,468.75,false,"",false,0,93.75,Room 110,2409-1 +LH25012745734986,2025-01-27,Hacienda San Angel,Extranet,,PATTY,WALTCHER,info@haciendasanangel.com,"",,,,,,,,2025-01-28,2025-01-29,1,,"","",,Cancelled,2025-01-27 17:42:58,Angels Dome - Junior Suite,Angels Dome - Standard Rate,365.0,456.25,0.0,0.0,0.0,0.0,0,0.0,0.0,456.25,0,2,0,0,1,,,0,456.25,false,"",false,0,91.25,Room 113,"" +LH25013045791877,2025-01-30,Hacienda San Angel,Extranet,,TOM,LECLAIR,tdleclair@msn.com,7024985457,,,,,,United States of America,"",2025-01-30,2025-02-01,2,,"","RESERVATION DIRECTLY +RATE $427.50 + TAXES + NO PROMO +CREDIT CARD AMEX CVV OK +CONFIRMATION SENT JANUARY30/2025 +OK MARIANA JAUANRY30/2025",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,855.0,1068.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1068.75,1068.75,2,0,0,1,,,0,0.0,false,"",false,0,213.75,Room 110,2419-1 +BDC-4861025224,2025-01-11,Hacienda San Angel,Booking.com,,Rachel,Gardner,rgardn.447556@guest.booking.com,7139068865,,,,,,United States,"",2025-01-31,2025-02-01,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING. COM +RATE $600.00 + TAXES +NO PROMO +VISA CREDIT CARD OK +CONFIRMATION SENT ENE10/25 +OK MARIABNA ZAVALA ENE10/25",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,600.0,880.86,0.0,0.0,0.0,130.86,0.0,0.0,0.0,880.86,880.86,2,0,0,1,,,0,0.0,false,"",false,0,150.0,Room 121,2421-1 +EXP-X-390377064,2025-01-06,Hacienda San Angel,Expedia,,Hugo,Linares,pfpbmpaqy2@m.expediapartnercentral.com,1 703 8567559,,,,,,,,2025-02-01,2025-02-07,6,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, We are excited to come to your lovely lodging, we are celebrating our 34 yr anniversary. Please ensure we are on the quiet side, as we are light sleepers. We would also like to have a transport from the airport., Remittance amount: 3,018.96, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA +RATE $419.30 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT ENE06/25 +OK MARIANA ENE06/25",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,2515.8,3187.82,0.0,0.0,0.0,43.07,0.0,0.0,0.0,3187.82,3187.82,1,0,0,1,,,0,0.0,false,"",false,0,628.95,Room 110,"2422-1, 2422-2" +BDC-4841280122,2025-01-15,Hacienda San Angel,Booking.com,,Jordan,Muraglia,jmurag.108421@guest.booking.com,+1 303 478 6508,,,,.,,United States,"",2025-02-01,2025-02-04,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-01-30., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT ENE 16 // +RATE $ 486 USD + TAXES // +CREDIT CARD INFORMATION OK VISA VIRTUAL CARD// +STAY FEB 01- 04 2025 // +SUITE SAN GABRIEL // +NO PROMO //",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1458.0,1855.69,0.0,0.0,0.0,33.19,0.0,0.0,0.0,1855.69,1855.69,2,0,0,1,,,0,0.0,false,"",false,0,364.5,Room 118,2430-1 +LH25012845763559,2025-01-28,Hacienda San Angel,Extranet,,robin,kay,INFO@HACIENDASANANGEL.COM,+1 416 888 6486,,,,,,Canada,"",2025-02-01,2025-02-02,1,,"","",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,600.0,836.13,0.0,0.0,0.0,86.13,0.0,0.0,0.0,836.13,836.13,1,0,0,1,,,0,0.0,false,"",false,0,150.0,Room 121,2423-1 +MMS-OBH25010819010307-2708067,2025-01-08,Hacienda San Angel,Mr and Mrs Smith,,Karl,Seppi,NSEPPI@GMAIL.COM,,,,,,,,,2025-02-02,2025-02-05,3,,PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $449.13+ TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION ENE08/2025 +OK MARIANA ENE08/2025",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1336.61,2078.31,0.0,0.0,0.0,407.55,0.0,0.0,0.0,2078.31,2078.31,2,0,0,1,,,0,0.0,false,"",false,0,334.1525,Room 121,2434-1 +BDC-4854052336,2025-01-29,Hacienda San Angel,Booking.com,,Mark,Campion,mcampi.829705@guest.booking.com,+44 7456 459555,,,,.,,United Kingdom,"",2025-02-02,2025-02-03,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROMM BOOOKING +RATE $600.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT JANAURY29/2025 +OK MARIANA ZAVALA JANUARY29/2025",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,600.0,842.01,0.0,0.0,0.0,92.01,0.0,0.0,0.0,842.01,842.01,2,0,0,1,,,0,0.0,false,"",false,0,150.0,Room 122,2426-1 +SMP-2025011637469727,2025-01-16,Hacienda San Angel,Simple Booking,,Nicholas,Gonzales,330capt@gmail.com,+13602867008,,,,,,,"",2025-02-05,2025-02-06,1,,"","RESERVATION THRU SBCOM // +CONFIRMATION SENT JAN152025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 580 USD + TAXES // +STAY FEB5-62025// +SUITE ANGEL VIEW // +SUBMITED JAN152025NGR//",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,580.0,924.22,0.0,0.0,0.0,199.22,0.0,0.0,0.0,924.22,924.22,2,0,0,1,,,0,0.0,false,"",false,0,145.0,Room 106,2435-1 +MMS-OBH25020101583203-2733936,2025-02-01,Hacienda San Angel,Mr and Mrs Smith,,Joseph,Altchech,JALTCHECH@GMAIL.COM,,,,,,,,,2025-02-05,2025-02-07,2,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out ++1-425-761-5554","RESERVATION THRU MMS.COM // +CONFIRMATION SENT FEB12025// +CREDIT CARD INFORMATION OK// +RATE $ 438.05 USD + TAXES // +STAY FEB5-72025 // +SUITE CELESTIAL// +SUBMITED JAN312025NGR//",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,876.1,1140.76,0.0,0.0,0.0,45.63,0.0,0.0,0.0,1140.76,1140.76,2,0,0,1,,,0,0.0,false,"",false,0,219.025,Room 103,2442-1 +SMP-2025020237847929,2025-02-02,Hacienda San Angel,Simple Booking,,Sixiang,Dong,simondong0919@gmail.com,+12816382433,,,,,,,"",2025-02-05,2025-02-06,1,,1 year Anniversary with Ms Lu Xia,"RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT FEB022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 500.20 USD + TAXES // +STAY FEB05-062025 // +SUITE SAN MIGUEL // +SUBMITED FEB022025NGR//",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,500.2,625.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,625.25,625.25,2,0,0,1,,,0,0.0,false,"",false,0,125.05,Room 107,2436-1 +LH25020445901492,2025-02-04,Hacienda San Angel,Extranet,,Nathaniel,Weil,nweil@cwitechsales.com,1+732-547-9868,,,,,,United States of America,"",2025-02-05,2025-02-08,3,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT FEB042025// +CREDIT CARD INFORMATION OK // +RATE $ 475 USD + TAXES // +STAY FEB05-082025 // +SUITE SAN GABRIEL // +SUBMITED FEB042025NGR//",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1425.0,1918.05,0.0,0.0,0.0,136.8,0.0,0.0,0.0,1918.05,1918.05,2,0,0,1,,,0,0.0,false,"",false,0,356.25,Room 118,"2447-1, 2447-2" +BDC-4856663736,2025-01-06,Hacienda San Angel,Booking.com,,CHRI,LONGSTREET,clongs.469588@guest.booking.com,+1 415 336 7260,,,,,,United States,"",2025-02-06,2025-02-10,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-02-04. +Approximate time of arrival: between 17:00 and 18:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $ 520.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT ENE06/25 +OK MARIANA ENE06/25",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,2080.0,2695.84,0.0,0.0,0.0,95.84,0.0,0.0,0.0,2695.84,2695.84,2,0,0,1,,,0,0.0,false,"",false,0,520.0,Room 112,2455-1 +LH25011645507856,2025-01-16,Hacienda San Angel,Extranet,,Frank,Seddigh,ap@sedbetter.com,+13059157174,,,,,,United States of America,"",2025-02-06,2025-02-08,2,,,,,Cancelled,2025-01-16 20:42:36, Garden of Angels - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,"" +LH25011645508026,2025-01-16,Hacienda San Angel,Extranet,,Frank,Seddigh,ap@sedbetter.com,+13059157174,,,,,,United States of America,"",2025-02-06,2025-02-08,2,,,,,Cancelled,2025-01-16 21:08:51, San Gabriel - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 118,"" +LH25012045586763,2025-01-20,Hacienda San Angel,Extranet,,Frank,Seddigh,ap@sedbetter.com,+13059157174,,,,,,United States of America,"",2025-02-06,2025-02-08,2,,"","RESERVATION THRU LH.COM // +CONFIRMATION SENT JAN202025 // +CREDIT CARD INFORMATION OK // +RATE $ 497.50 USD + TAXES // +STAY FEB06-072025// +SUITE ANGEL DOME// +SUBMITED JAN202025NGR//",,Cancelled,2025-01-21 21:57:48,Angels Dome - Junior Suite,Angels Dome - Standard Rate,995.0,-342.46,0.0,0.0,0.0,-1586.21,0,0.0,0.0,-342.46,0,2,0,0,1,,,0,-342.46,false,"",false,0,248.75,Room 113,"" +LH25012045586850,2025-01-20,Hacienda San Angel,Extranet,,Frank,Seddigh,ap@sedbetter.com,+13059157174,,,,,,United States of America,"",2025-02-06,2025-02-08,2,,"","RESERVATION THRU LH.COM // +CONFIRMATION SENT JAN202025 // +CREDIT CARD INFORMATION OK // +RATE $ 540 USD + TAXES // +STAY FEB06-072025// +SUITE SAN GABRIEL// +SUBMITED JAN202025NGR//",,Cancelled,2025-01-21 21:59:00, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1080.0,-1030.8,0.0,0.0,0.0,-2380.8,0,0.0,0.0,-1030.8,0,2,0,0,1,,,0,-1030.8,false,"",false,0,270.0,Room 118,"" +SMP-2025012437669478,2025-01-24,Hacienda San Angel,Simple Booking,,Luis,Aguilera,la38920@gmail.com,+14699950373,,,,,,,"",2025-02-06,2025-02-08,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE24 // +CREDIT CARD INFORMATION VISA PENDING CVV // +RATE $426.40 USD + TAXES // +SITE GARDEN OF ANGEL // +STAY FEB 06- 08 2025 // +NO PROMO // +SECRET RATE // +ENE242025GV",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,852.8,1066.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1066.0,1066.0,2,0,0,1,,,0,0.0,false,"",false,0,213.2,Room 109,"2449-1, 2449-2" +SMP-2025020637951551,2025-02-06,Hacienda San Angel,Simple Booking,,Chris,Martindale,cmartindale.yoga@gmail.com,5178619538,,,,,,,"",2025-02-06,2025-02-07,1,,Hyatt Discoverist 573311293O; early check in 3pm if possible. Very excited to stay for the night.,"RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT FEB022025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 336.20 USD + TAXES // +STAY FEB6-72025 // +SUITE ANGEL DOME // +SUBMITED FEB062025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,336.2,479.72,0.0,0.0,0.0,59.47,0.0,0.0,0.0,479.72,479.72,1,0,0,1,,,0,0.0,false,"",false,0,84.05,Room 113,"2438-1, 2438-2" +BDC-4777549770,2025-01-26,Hacienda San Angel,Booking.com,,Dagmara,Krecioch,dkreci.698099@guest.booking.com,+1 215 480 8042,,,,.,,United States,"",2025-02-07,2025-02-08,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JAN26012025 // +CREDIT CARD INFORMATION OK // +RATE $ 640 USD + TAXES // +STAY FEB7-082025 // +SUITE RINCÓN // +SUBMITED JAN262025NGR//",,Cancelled,2025-02-04 22:46:58, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,640.0,805.12,0.0,0.0,0.0,5.12,0,0.0,0.0,805.12,0,2,0,0,1,,,0,805.12,false,"",false,0,160.0,Room 119,"" +MMS-OBH25020101431007-2733931,2025-02-01,Hacienda San Angel,Mr and Mrs Smith,,Joseph,Altchech,JALTCHECH@GMAIL.COM,,,,,,,,,2025-02-07,2025-02-09,2,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out ++1-425-761-5554","RESERVATION THRU MMS.COM // +CONFIRMATION SENT FEB12025// +CREDIT CARD INFORMATION OK// +RATE $ 529.73 USD + TAXES // +STAY FEB5-72025 // +SUITE CELESTIAL// +SUBMITED JAN312025NGR//",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1059.46,1914.39,0.0,0.0,0.0,590.06,0.0,0.0,0.0,1914.39,1914.39,2,0,0,1,,,0,0.0,false,"",false,0,264.865,Room 103,"2450-1, 2450-2, 2450-3" +SMP-2025020237854731,2025-02-02,Hacienda San Angel,Simple Booking,,Ryan,Jennings,ryan@ryanjennings.ca,+14034719457,,,,,,Canada,"",2025-02-07,2025-02-08,1,,"","RESERVATION THRU SIMPLEBOOPKING.COM // +CONFIRMATION SENT FEB022025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 05.90 USD + TAXES // +STAY FEB7-082025 // +SUITE ANGEL DOME// +SUBMITED FEB022025NGR//",,Cancelled,2025-02-07 16:53:51,Angels Dome - Junior Suite,Angels Dome - Standard Rate,405.9,507.38,0.0,0.0,0.0,0.0,0,0.0,0.0,507.38,0,2,0,0,1,,,0,507.38,false,"",false,0,101.475,Room 113,"" +BDC-4511310613,2025-02-05,Hacienda San Angel,Booking.com,,Dagmara,Krecioch,dkreci.435566@guest.booking.com,+1 215 480 8042,,,,.,,United States,"",2025-02-07,2025-02-08,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION TRHU BOOKING.COM // +CONFIRMATION SENT ENE05 // +RATE $ 640 USD + TAX // +CREDIT CARD INFORMATION OK VISA // +SUITE RINCON DE ANGELES // +STAY FEB 07- 08 2025 // +NO PROMO // +FEB0520205GV",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,640.0,1145.28,0.0,0.0,0.0,345.28,0.0,0.0,0.0,1145.28,1145.28,2,0,0,1,,,0,0.0,false,"",false,0,160.0,Room 119,"2445-1, 2445-2, 2445-3, 2445-4" +LH25020745981395,2025-02-07,Hacienda San Angel,Extranet,,RYAN,JENNINGS,"","",,,,,,,,2025-02-07,2025-02-08,1,,"","",,Cancelled,2025-02-07 19:23:35,Angels Dome - Junior Suite,Angels Dome - Standard Rate,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 113,"" +LH25020745981462,2025-02-07,Hacienda San Angel,Extranet,,RYAN,JENNINGS,ryan@ryanjenning.ca,4034719457,,,,,,,,2025-02-07,2025-02-08,1,,"","RESERVATION MADE DIRECTLY +RATE $400.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT FEB07/2025 +OK MARIANA FEB07/2025",,Checked-out,"",Angels Dome - Junior Suite,Manual,400.0,588.67,0.0,0.0,0.0,88.67,0.0,0.0,0.0,588.67,588.67,2,0,0,1,,,0,0.0,false,"",false,0,100.0,Room 113,"2443-1, 2443-2, 2443-3" +SMP-2025020137842817,2025-02-01,Hacienda San Angel,Simple Booking,,Allen,Hopkins,kathyohopkins@gmail.com,+19253600200,,,,,,,"",2025-02-08,2025-02-09,1,,"",,,Cancelled,2025-02-02 11:22:22, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,640.0,800.0,0.0,0.0,0.0,0.0,0,0.0,0.0,800.0,0,2,0,0,1,,,0,800.0,false,"",false,0,160.0,Room 119,"" +BDC-4891590736,2025-02-02,Hacienda San Angel,Booking.com,,Tanja,Tajmel,ttajme.943083@guest.booking.com,+1 514 604 9108,,,,,,Canada,"",2025-02-08,2025-02-11,3,,"Approximate time of arrival: between 17:00 and 18:00 +This guest is interested in your airport shuttle service and would like to get more information from you. +Hello, we'd like to book an airport transfer. +Our flight will arrive from Montreal at 4pm on February 8. Flightnumber TS106. +Please could you kindly let us know if this is possible? Thank you very much! +Best wishes, +Tanja, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT FEB022025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 531.66 USD + TAXES // +STAY FEB8-112025// +SUITE SAN GABRIEL // +SUBMITED FEB022025NGR//",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1780.0,3065.3,0.0,0.0,0.0,840.3,0.0,0.0,0.0,3065.3,3065.3,2,0,0,1,,,0,0.0,false,"",false,0,445.0,Room 121,"2459-1, 2459-2, 2459-3" +EXP-X-397464740,2025-01-17,Hacienda San Angel,Expedia,,julian,scarmana,u9cgyjajvo@m.expediapartnercentral.com,1 0 7375004114,,,,,,,,2025-02-09,2025-02-13,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIA // +CONFIRMATION SENT JAN162025// +CREDIT CARD INFORMATION OK// +RATE $ 562.10 USD + TAXES // +STAY FEB9-132025 // +SUITE RINCÓN DE ANGELES // +SUBMITED JAN162025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2248.4,3055.35,0.0,0.0,0.0,244.85,0.0,0.0,0.0,3055.35,3055.35,1,0,0,1,,,0,0.0,false,"",false,0,562.1,Room 119,"2467-1, 2467-2" +SMP-2025011837530447,2025-01-18,Hacienda San Angel,Simple Booking,,Lauren,Paez,laurenpaezburt@gmail.com,+12132207889,,,,,,,"",2025-02-10,2025-02-11,1,,we are coming from Verana Heniz & Vero told us about your hotel,"RESERVATION FROM SIMPLE BOOKING +RATE $405.90 + TAXES +NO PROMO +CREDIR CARD AMEX CVV PENDING +CONFIRMATION SENT JANU19/2025 +OK MARIANA ZAVALA JANUARY19/25",,Cancelled,2025-01-25 13:22:49,Angels Dome - Junior Suite,Angels Dome - Standard Rate,405.9,507.38,0.0,0.0,0.0,0.0,0,0.0,0.0,507.38,0,2,0,0,1,,,0,507.38,false,"",false,0,101.475,Room 113,"" +LH25012145609080,2025-01-21,Hacienda San Angel,Extranet,,Paula,Seligman,Seligman.paula@gmail.com,1.416.436.7790,,,,,,,,2025-02-10,2025-02-11,1,,"","Treat as a normal reservation. + +She booked directly through email to me- Paula",,Checked-out,"", Angels View - Master Suite,Angels View - Package Rate,522.0,920.16,0.0,0.0,0.0,267.66,0.0,0.0,0.0,920.16,920.16,2,0,0,1,,,0,0.0,false,"",false,0,130.5,Room 106,2456-1 +SMP-2025020537914784,2025-02-05,Hacienda San Angel,Simple Booking,,Tenley,van der Wal,tenley@vanderwal.com,+14012252295,,,,,,,"",2025-02-10,2025-02-11,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $510.00 + TAXES +NO PROMO +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT FEB04/2025 +OK MARIANA ZAVALA FEB04/2025",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,510.0,1129.83,0.0,0.0,0.0,492.33,0.0,0.0,0.0,1129.83,1129.83,3,0,0,1,,,0,0.0,false,"",false,0,127.5,Room 118,2460-1 +SMP-2025020537914793,2025-02-05,Hacienda San Angel,Simple Booking,,Tenley,van der Wal,tenley@vanderwal.com,+14012252295,,,,,,,"",2025-02-10,2025-02-11,1,,"","RESERVATION FROM SIMPLE BOOOKING +RATE $389.50 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB04/2025 +OK MARIANA FEB04/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,389.5,491.95,0.0,0.0,0.0,5.07,0.0,0.0,0.0,491.95,491.95,2,0,0,1,,,0,0.0,false,"",false,0,97.375,Room 102,2461-1 +SMP-2025020537914802,2025-02-05,Hacienda San Angel,Simple Booking,,Tenley,van der Wal,tenley@vanderwal.com,+14012252295,,,,,,,"",2025-02-10,2025-02-11,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $373.10 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB04/2025 +OK MARIANA FEB04/2025",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,373.1,509.45,0.0,0.0,0.0,43.07,0.0,0.0,0.0,509.45,509.45,2,0,0,1,,,0,0.0,false,"",false,0,93.275,Room 113,2462-1 +LH25021046045750,2025-02-10,Hacienda San Angel,Extranet,,FABRICIO,SOLORIO ACEVES,fabriciosolorio@gmail.com,9729838122,,,,,,,,2025-02-10,2025-02-11,1,,"","RESERVATION THRU DIRECT // +CONFIRMATION SENT FEB102025// +CREDIT CARD INFORMATION OK // +STAY FEB10-112025 // +SUITE ANGEL VIEW// +SUBMITED FEB102025NGR// + +COMP +ANGEL RATE",,Checked-out,"", Garden of Angels - Junior Suite,Manual,390.0,152.01,0.0,0.0,0.0,152.01,0.0,0.0,0.0,152.01,152.01,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,"2463-1, 2463-2" +BDC-4495650565,2025-01-04,Hacienda San Angel,Booking.com,,John,Scott,jscott.867039@guest.booking.com,+1 303 902 6695,,,,.,,United States,"",2025-02-11,2025-02-12,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-02-09., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JAN032025 // +CREDIT CARD INFORMATION OK // +RATE $ 508.50 USD + TAXES // +STAY FEB11-122025 // +SUITE ANGEL VIEW // +SUBMITED JAN032025NGR//",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,508.5,921.1,0.0,0.0,0.0,285.47,0.0,0.0,0.0,921.1,921.1,2,0,0,1,,,0,0.0,false,"",false,0,127.125,Room 106,2465-1 +EXP-2147890936,2025-01-28,Hacienda San Angel,Expedia,,Gary,Winston,3nvj7jjbyo@m.expediapartnercentral.com,1 415 9022312,,,,,,,,2025-02-12,2025-02-15,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,609.92, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $ 447.20+ TAXES +$85.00 CREDIT ON FOOD & BEVERAGE // UPGRADE OR BOTTLE +CRETIDT CARD INFO OK +CONFIRMATION SENT JANUARY 28/2025 +OK MARIANA JANUARY 28/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1341.6,1799.8,0.0,0.0,0.0,122.8,0.0,0.0,0.0,1799.8,1799.8,2,0,0,1,,,0,0.0,false,"",false,0,335.4,Room 102,"2466-1, 2466-2" +SMP-2025013037784141,2025-01-30,Hacienda San Angel,Simple Booking,,Shweta,Sharma,shwetasharmama@gmail.com,+17348469615,,,,,,,"",2025-02-12,2025-02-14,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $508.40 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JANUARY30/2025 +OK MARIANA JANUARY30/2025",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1016.8,1362.21,0.0,0.0,0.0,91.21,0.0,0.0,0.0,1362.21,1362.21,2,0,0,1,,,0,0.0,false,"",false,0,254.2,Room 103,2469-1 +EXP-X-413441109,2025-02-14,Hacienda San Angel,Expedia,,Andrew,Barker,sjebi77w2a@m.expediapartnercentral.com,1 403 8701621,,,,,,,,2025-02-15,2025-02-16,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 540.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT FEB142025// +CREDIT CARD INFORMATION OK// +RATE $ 450 USD + TAXES // +STAY FEB15-162025 // +SUITE SERAFÍN // +SUBMITED FEB142025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,450.0,1043.37,0.0,0.0,0.0,480.87,0.0,0.0,0.0,1043.37,1043.37,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 110,2473-1 +BDC-4338861746,2025-01-11,Hacienda San Angel,Booking.com,,Don,Eng,deng.594493@guest.booking.com,+1 416 948 8450,,,,.,,Canada,"",2025-02-16,2025-02-18,2,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT JAN122025// +CREDIT CARD INFORMATION OK // +RATE $ 450 USD + TAXES // +STAY FEB14-162025// +SUITE SERAFIN // +SUBMITED JAN112025//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,900.0,1351.89,0.0,0.0,0.0,226.89,0.0,0.0,0.0,1351.89,1351.89,2,0,0,1,,,0,0.0,false,"",false,0,225.0,Room 110,2477-1 +SMP-2025020337885094,2025-02-03,Hacienda San Angel,Simple Booking,,MADISON,KENNEDY,astrotravel@travelleaders.com,+12169700940,,,,,,,"",2025-02-16,2025-02-17,1,,NONSMOKING PLEASE,"RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT OK FEB 03 // +RATE $ 520 USD + TAX // +CREDIT CARD INFORMATION OK MASTERCARD // +NO PROMO // +SUITE GARDEN OS ANGEKS // +STAY DEB 16- 17 2025 //",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,520.0,650.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,650.0,650.0,2,0,0,1,,,0,0.0,false,"",false,0,130.0,Room 109,2474-1 +LH25020345888655,2025-02-03,Hacienda San Angel,Extranet,,PAUL,SANDERS,ps2505@gmail.com,6192008960,,,,,,,,2025-02-16,2025-02-19,3,,"","RESERVATION THRU DIRECT .COM // +CONFIRMATION SENT FEB032025// +CREDIT CARD INFORMATION OK// +RATE $ 500 USD + TAXES // +STAY FEB16-192025 // +SUITE ANGEL DOME // +SUBMITED FEB032025NGR// + +ANGEL RATE",,Checked-out,"",Angels Dome - Junior Suite,Manual,1500.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1500.0,1500.0,2,0,0,1,,,0,0.0,false,"",false,0,375.0,Room 113,2486-1 +SMP-2025021138070744,2025-02-11,Hacienda San Angel,Simple Booking,,MADISON,KENNEDY,astrotravel@travelleaders.com,+12169700940,,,,,,,"",2025-02-17,2025-02-18,1,,This is Donna Scicolone of Astro Travel/ Travel Leaders. Ms. Kennedy is already booked into the Archangel Suite on February 16 and is now adding the night of the 17th. Please note this so there is no confu- sion on her check out date. Thank you.,"RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB112025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 520 USD + TAXES // +STAY FEB17-182025// +SUITE GA// +SUBMITED FEB112025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,520.0,806.87,0.0,0.0,0.0,156.87,0.0,0.0,0.0,806.87,806.87,2,0,0,1,,,0,0.0,false,"",false,0,130.0,Room 109,"2475-1, 2475-2" +SMP-2025021738170402,2025-02-17,Hacienda San Angel,Simple Booking,,Frank,Guinta,frankguinta20@gmail.com,+16038600474,,,,,,,"",2025-02-18,2025-02-19,1,,"","RESERVATIN FROM SIMPLEBOOKING // +CONFIRMATION SENT FEB17 // +CREDIT CAR INFORMATION VISA PENDIN CVV // +SUITE ANGEL VIEW // +STAY FEB 18- 19 20 25 // +MO PROMO // +RATE 4 515 USD + TAXE // +FEB172025GV",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,515.0,643.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,643.75,643.75,2,0,0,1,,,0,0.0,false,"",false,0,128.75,Room 106,"2484-1, 2484-2" +BDC-4830865969,2025-01-09,Hacienda San Angel,Booking.com,,James,Beshoff,jbesho.141248@guest.booking.com,+44 7710 066486,,,,.,,United Kingdom,"",2025-02-19,2025-02-22,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-02-17., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JAN92025// +CREDIT CARD INFORMATION OK// +RATE $ 415.80 USD + TAXES // +STAY FEB19-222025// +SUITE GARDEN OF ANGELS// +SUBMITED JAN92025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1247.4,1712.42,0.0,0.0,0.0,153.17,0.0,0.0,0.0,1712.42,1712.42,2,0,0,1,,,0,0.0,false,"",false,0,311.85,Room 109,"2492-1, 2492-2" +SMP-2025011537444332,2025-01-15,Hacienda San Angel,Simple Booking,,Brian,Tieszen,briantieszen@gmail.com,+16043181212,,,,,,Canada,"",2025-02-19,2025-02-22,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN152025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 600 USD + TAXES // +STAY FEB19-222025// +SUITE SAN JOSE // +SUBMITED JAN152025NGR//",,Cancelled,2025-02-03 14:43:43, San Jose - Master Suite,San Jose - Standard Rate,1785.6,2232.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2232.0,0,2,0,0,1,,,0,2232.0,false,"",false,0,446.4,Room 122,"" +SMP-2025012437648888,2025-01-23,Hacienda San Angel,Simple Booking,,Gretchen,Reynolds,gretchenwr@gmail.com,+16507967215,,,,,,,"",2025-02-19,2025-02-26,7,,"","RESERVATION FROM SIMPLE BOOKING +RATE $422..00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT ENE23/2025 +OK MARIANA ENE23/2025",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,2960.21,4306.18,0.0,0.0,0.0,605.92,0.0,0.0,0.0,4306.18,4306.18,2,0,0,1,,,0,0.0,false,"",false,0,740.0525,Room 112,2504-1 +SMP-2025013037785183,2025-01-30,Hacienda San Angel,Simple Booking,,Prisila V,Saltzman,prisilavillar@gmail.com,+17182889031,,,,,,,"",2025-02-19,2025-02-21,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $475.60 + TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CINFIRMATION SENT JANUARY30/2025 +OK MARIANA JANUARY30/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,951.2,1760.77,0.0,0.0,0.0,571.77,0.0,0.0,0.0,1760.77,1760.77,2,0,0,1,,,0,0.0,false,"",false,0,237.8,Room 106,"2489-1, 2489-2, 2489-3" +LH25020345888713,2025-02-03,Hacienda San Angel,Extranet,,Paul,Saunders,ps2505@gmail.com,6192008960,,,,,,United States of America,"",2025-02-19,2025-02-22,3,,"","RESERVATION THRU DIRECT .COM // +CONFIRMATION SENT FEB032025// +CREDIT CARD INFORMATION OK// +RATE $600 USD + TAXES // +STAY FEB16-192025 // +SUITE SAN JOSE // +SUBMITED FEB032025NGR// + +ANGEL RATE + +********************************** +WAS A ROOM CHANGE +AD FEB16-19 +SJ FEB19-22 +BOTH RESERVATIONS ANGEL RATE",,Checked-out,"", San Jose - Master Suite,Manual,1800.0,2351.27,0.0,0.0,0.0,551.27,0.0,0.0,0.0,2351.27,2351.27,2,0,0,1,,,0,0.0,false,"",false,0,450.0,Room 122,2490-1 +LH25021946232671,2025-02-19,Hacienda San Angel,Extranet,,FRANK,GUINTA,frankguinta20@gmail.com,6038600474,,,,,,,,2025-02-19,2025-02-20,1,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT FEB192025// +CREDIT CARD INFORMATION OK// +RATE $ 480 USD + TAXES // +STAY FEB19-202025// +SUITE RINCÓN // +SUBMITED FEB192025NGR// +*************************************** +IT WAS A ROOM CHANGE +1 NIGHT IN AV FEB18 +1 NIGHT IN R FEB19",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,480.0,1100.36,0.0,0.0,0.0,500.36,0.0,0.0,0.0,1100.36,1100.36,2,0,0,1,,,0,0.0,false,"",false,0,120.0,Room 119,"2483-1, 2483-2, 2483-3, 2483-4, 2483-5" +SMP-2025010337202702,2025-01-03,Hacienda San Angel,Simple Booking,,Mark,Clark,mdcmd59@gmail.com,+12317501257,,,,,,,"",2025-02-20,2025-02-23,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN032025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 793.60 USD + TAXES // +STAY FEB20-232025 // +SUITE RINCÓN DE ANGELES // +SUBMITED JAN032025NGR//",,Cancelled,2025-02-04 09:14:16, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1904.64,2380.8,0.0,0.0,0.0,0.0,0,0.0,0.0,2380.8,0,2,0,0,1,,,0,2380.8,false,"",false,0,476.16,Room 119,"" +EXP-X-399023977,2025-01-19,Hacienda San Angel,Expedia,,Kelly,Coker,"",1 8582849065,,,,,,,,2025-02-20,2025-02-25,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,791.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT ENE19 // +CREDIT CARD INFORMATION VIRTUAL CARD FOR CHARGE // +RATE $ 465.30 USD + TAXES // +BLUE DISCOUNT 10% // +SUITE MILAGROS // +STAY FEB 20- 25 2025 // +ENE192025GV",,Cancelled,2025-01-25 11:19:57, Milagros - Junior Suite,Milagros - Standard Rate,2326.5,2908.13,0.0,0.0,0.0,0.0,0,0.0,0.0,2908.13,0,2,0,0,1,,,0,2908.13,false,"",false,0,581.625,Room 102,"" +BDC-4435543425,2025-01-25,Hacienda San Angel,Booking.com,,Tarsa,Hatefi,thatef.840726@guest.booking.com,+1 949 632 0062,,,,.,,United States,"",2025-02-20,2025-02-23,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-02-18., booker_is_genius +smoking preference: Non-Smoking","RESERVATION TRHU BOOKING.COM // +CONFIRMATION SENT ENE25 // +RATE $ 418.5 USD + TAXES // +CREDIT CARD OK INFORMATION VIRTUAL CARD FOR CHARGE // +STAY FEB 20- 23 2025 // +SUITE MILAGROS // +NO PROMO // +ENE252025GV",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1255.5,1934.82,0.0,0.0,0.0,365.44,0.0,0.0,0.0,1934.82,1934.82,2,0,0,1,,,0,0.0,false,"",false,0,313.875,Room 102,"2496-1, 2496-2" +LH25020445901450,2025-02-04,Hacienda San Angel,Extranet,,Mark,Clark,mdcmd59@gmail.com,+12317501257,,,,,,,"",2025-02-20,2025-02-23,3,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT FEB042025// +CREDIT CARD INFORMATION OK // +RATE $ 634.90 USD + TAXES // +STAY FEB20-232025 // +SUITE SAN GABRIEL // +SUBMITED FEB042025NGR//",,Checked-out,"", San Gabriel - Junior Suite,Manual,1904.7,2776.61,0.0,0.0,0.0,395.73,0.0,0.0,0.0,2776.61,2776.61,3,0,0,1,,,0,0.0,false,"",false,0,476.175,Room 118,2494-1 +LH25021746197892,2025-02-17,Hacienda San Angel,Extranet,,LESLIE,REDDY,lesliereddy67@gmail.com,4403134415,,,,,,,,2025-02-20,2025-02-22,2,,"","RESERVATION MADE DIRECTLY +RATE $640.00 +CREDIT CARD INFO OK +CONFIRMATION SENT FEB17/2025 +OK MARIANA FEB17/2025 + +GUEST EXTENDING THEY ARE COMING FROM CELESTIAL",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1280.0,2457.61,0.0,0.0,0.0,1017.61,0.0,0.0,0.0,2457.61,2457.61,2,0,0,1,,,0,0.0,false,"",false,0,288.0,Room 119,2491-1 +SMP-2025010337202055,2025-01-03,Hacienda San Angel,Simple Booking,,Eric,Baughman,ebaughman71@gmail.com,+18013301076,,,,,,,"",2025-02-21,2025-02-23,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN032025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 492.50 USD + TAXES // +STAY FEB21-232025 // +SUITE ANGELS DOME // +SUBMITED JAN032025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,977.12,1422.19,0.0,0.0,0.0,200.79,0.0,0.0,0.0,1422.19,1422.19,2,0,0,1,,,0,0.0,false,"",false,0,244.28,Room 113,2495-1 +SMP-2025010437217684,2025-01-04,Hacienda San Angel,Simple Booking,,Sarah,Norris,sarahnorris2@me.com,+13127352035,,,,,,,"",2025-02-21,2025-02-23,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN042025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 600 USD + TAXES // +STAY 21-23FEB2025// +SUITE VISTA DE SANTOS // +SUBMITEDJAN042025NGR //",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1190.4,1590.6,0.0,0.0,0.0,102.6,0.0,0.0,0.0,1590.6,1590.6,2,0,0,1,,,0,0.0,false,"",false,0,297.6,Room 121,2493-1 +EXP-X-396778076,2025-01-16,Hacienda San Angel,Expedia,,Sheri,Siegfried Markowitz,"",1 8312476905,,,,,,,,2025-02-21,2025-02-23,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,080.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +RATE $ 450 USD + TAXES // +CREDIT CARD OK VIRTUAL CARD FOR CHARGE // +SUITE SERAFIN // +STAY FEB 21- 23 2025 // +PROMOTION BLUE 10% DISCOUNT // +ENE152025GV",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,900.0,1339.94,0.0,0.0,0.0,214.94,0.0,0.0,0.0,1339.94,1339.94,2,0,0,1,,,0,0.0,false,"",false,0,225.0,Room 110,2497-1 +EXP-X-397325724,2025-01-16,Hacienda San Angel,Expedia,,Richard,Chpiman,yspqx54211@m.expediapartnercentral.com,0 0 4088237706,,,,,,,,2025-02-21,2025-02-22,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 612.48, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT JAN162025 // +CREDIT CARD INFORMATION OK// +RATE $ 510.40 USD + TAXES // +STAY FEB21-222025 // +SUITE ANGEL VIEW// +SUBMITED JAN162025NGR//",,Cancelled,2025-02-18 16:47:28, Angels View - Master Suite,Angels View - Standard Rate,510.4,638.0,0.0,0.0,0.0,0.0,0,0.0,0.0,638.0,0,2,0,0,1,,,0,638.0,false,"",false,0,127.6,Room 106,"" +EXP-X-409207796,2025-02-06,Hacienda San Angel,Expedia,,Muhammad,Saigol,abkk2aqw5d@m.expediapartnercentral.com,1 401 4516964,,,,,,,,2025-02-22,2025-02-23,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 691.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT FEB062025// +CREDIT CARD INFORMATION OK // +RATE $ 576 USD + TAXES // +STAY FEB22-232025 // +SUITE RINCÓN OF ANGELS// +SUBMITED FEB062025NGR//",,Cancelled,2025-02-06 19:41:06, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,576.0,720.0,0.0,0.0,0.0,0.0,0,0.0,0.0,720.0,0,2,0,0,1,,,0,720.0,false,"",false,0,144.0,Room 119,"" +MMS-OBH25011923181208-2720509,2025-01-19,Hacienda San Angel,Mr and Mrs Smith,,Lee,Running,LARUNNIN@GMAIL.COM,,,,,,,,,2025-02-23,2025-02-27,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRES. SMITH +RATE $544.68 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT ENE19/2025 +OK MARIANA ZAVALA ENE19/2025",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2178.72,2824.92,0.0,0.0,0.0,101.52,0.0,0.0,0.0,2824.92,2824.92,2,0,0,1,,,0,0.0,false,"",false,0,544.68,Room 119,2506-1 +SMP-2025010237181228,2025-01-02,Hacienda San Angel,Simple Booking,,Christopher,Daffin,cdaffin777@hotmail.com,+1404-354-0005,,,,,,,"",2025-02-24,2025-03-01,5,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 530 USD + TAXES // +STAY FEB24-MAR12025// +SUITE SAN GABRIEL // +SUBMITED JAN022025NGR//",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,2628.8,3823.64,0.0,0.0,0.0,537.64,0.0,0.0,0.0,3823.64,3823.64,2,0,0,1,,,0,0.0,false,"",false,0,657.2,Room 118,2512-1 +SMP-2025012837757245,2025-01-28,Hacienda San Angel,Simple Booking,,John,Siqueiros,johnsiqueiros@gmail.com,+12133000149,,,,,,,"",2025-02-24,2025-02-28,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $423.32 + TAXES +NO PROMO +CREDIT CARD CVV PENDING +CONFIRMATION SENT JANAURY 28/2024 +OK MARIANA ZAVALA JANUARY28/2024",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1693.3,2346.86,0.0,0.0,0.0,230.23,0.0,0.0,0.0,2346.86,2346.86,2,0,0,1,,,0,0.0,false,"",false,0,423.325,Room 102,2509-1 +EXP-X-403746973,2025-01-27,Hacienda San Angel,Expedia,,James,Farley,b9mt6avs6j@m.expediapartnercentral.com,1 541 9699539,,,,,,,,2025-02-25,2025-02-26,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 626.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $522.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JANUARY26/2025 +OK MARIANA JANUARY26/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,522.0,745.16,0.0,0.0,0.0,92.66,0.0,0.0,0.0,745.16,745.16,2,0,0,1,,,0,0.0,false,"",false,0,130.5,Room 106,2503-1 +SMP-2025020137835369,2025-02-01,Hacienda San Angel,Simple Booking,,Nancy and Steve,Bigelsen,snrbig2@gmail.com,+1201774085,,,,,,,"",2025-02-26,2025-02-28,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $610.10 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SNET FEBRUARY 01/2025 +OK MARIANA FEB01/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1238.2,1888.76,0.0,0.0,0.0,341.01,0.0,0.0,0.0,1888.76,1888.76,2,0,0,1,,,0,0.0,false,"",false,0,309.55,Room 107,2508-1 +EXP-X-388360262,2025-01-03,Hacienda San Angel,Expedia,,Louis,Lemieux,rdfoxktgne@m.expediapartnercentral.com,1 0 9175998079,,,,,,,,2025-02-27,2025-03-04,5,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIPPREMIUM.COM // +CONFIRMATION SENT JAN032025 // +CREDIT CARD INFORMATION OK// +RATE $ 408.50 USD + TAXES // +STAY FEB27-MAR42025 // +SUITE CROWN VIEW // +SUBMITED JAN032025NGR//",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,2042.5,2553.13,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2553.13,2553.13,2,0,0,1,,,0,0.0,false,"",false,0,510.625,Room 112,"2507-1, 2507-2" +LH25011745524838,2025-01-17,Hacienda San Angel,Extranet,,MARGUERITE,KELLY,clairenell1@me.com,7083087308,,70,,|,,,,2025-02-27,2025-03-01,2,,"","RESERVATION MADE DIRECTLY BY PHONE +RATE $550.00 + TAXES +NO PROMO +CREDIT CARD INFO VISA OK +CONFIRMATION SENT ENE17/25 +OK MARIANA ZAVALA ENE 17/25 + + 3 PAX",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,1000.0,1581.2,0.0,0.0,0.0,331.2,0.0,0.0,0.0,1581.2,1581.2,2,0,0,1,,,0,0.0,false,"",false,0,250.0,Room 110,2511-1 +SMP-2025020137842456,2025-02-01,Hacienda San Angel,Simple Booking,,David,Izard,dwfi@shaw.ca,+12508880803,,,,,,Canada,"",2025-02-28,2025-03-04,4,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 746.875 USD + TAXES // +STAY FEB28-MAR42025// +SUITE SAN JOSE // +SUBMITED FEB022025NGR//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,2390.0,3449.36,0.0,0.0,0.0,461.86,0.0,0.0,0.0,3449.36,3449.36,2,0,0,1,,,0,0.0,false,"",false,0,597.5,Room 122,2527-1 +SMP-2025020537915674,2025-02-05,Hacienda San Angel,Simple Booking,,Hyunbin,Kim,Binakim1009@gmail.com,4152541066,,,,,,,"",2025-02-28,2025-03-01,1,,This is our 1year wedding anniversary!,"RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT FEB 05 // +RATE $ 504.30 USD + TAXES // +SECRET RATE // +CREDIT CARD INFORMATION OK VISA CVV PENDING // +SUITE CELESTIAL // +STAY FEB 28- MAR 01 2025 // +NO PROMO // +FEB052025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,504.3,630.38,0.0,0.0,0.0,0.0,0.0,0.0,0.0,630.38,630.38,2,0,0,1,,,0,0.0,false,"",false,0,126.075,Room 103,2516-1 +SMP-2025021338096302,2025-02-13,Hacienda San Angel,Simple Booking,,Dongze,Yue,steven.yuedongze@gmail.com,+16072794462,,,,,,,"",2025-02-28,2025-03-01,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT FEB13 // +RATE $ 410 USD + TAXES // +CREDIT CARD INFORMATION VISA PENDING CVV // +NO PROMO // +SECRET RATE // +SUITE ANGEL DOME // +STAY FEB28-MAR01 2025 // +FEB132025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,410.0,566.33,0.0,0.0,0.0,53.83,0.0,0.0,0.0,566.33,566.33,2,0,0,1,,,0,0.0,false,"",false,0,102.5,Room 113,2515-1 +BDC-4901823000,2025-02-16,Hacienda San Angel,Booking.com,,Jeanne,Morrissette,jmorri.271735@guest.booking.com,+1 713 854 4363,,,,.,,United States,"",2025-02-28,2025-03-01,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $459.00 + TAXES +NO PROMO +CREDIT CARD INFO VISA OK +CONFIRMATION SEND FEB16/2025 +OK MARIANA ZAVALA FEB16/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,459.0,590.42,0.0,0.0,0.0,16.67,0.0,0.0,0.0,590.42,590.42,2,0,0,1,,,0,0.0,false,"",false,0,114.75,Room 109,2513-1 +EXP-X-416141709,2025-02-19,Hacienda San Angel,Expedia,,Dave,McCormick,4xjauybqt2@m.expediapartnercentral.com,1 253 2555847,,,,,,,,2025-02-28,2025-03-01,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 648.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $540 + TAXES +$85.00 AS CREDIT ON FOOD & BEVERAGE // UPGRADE OR BOTTLE +CREDIT CARD INFO OK +CONFIRMATION SENT FEB18/2025 +OK MARIANA FEB18/2025 + + +THIS $197.39 IS IN THEIR NEW RESERVATION AT SG",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,540.0,872.39,0.0,0.0,0.0,197.39,0.0,0.0,0.0,872.39,675.0,1,0,0,1,,,0,197.39,false,"",false,0,135.0,Room 121,"2510-1, 2510-2, 2510-3" +EXP-X-390827606,2025-01-07,Hacienda San Angel,Expedia,,RONALD,BIANCHI,g6cd1a3fnn@m.expediapartnercentral.com,1 414 9342099,,,,,,,,2025-03-01,2025-03-07,6,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 3,210.48, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP.COM // +CONFIRMATION SENT // +CREDIT CARD INFORMATION OK // +RATE $445.90 USD + TAXES // +STAYMARCH1-72025 // +SUITE AV// +SUBMITED JAN72025//",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,2675.4,3417.71,0.0,0.0,0.0,73.46,0.0,0.0,0.0,3417.71,3417.71,2,0,0,1,,,0,0.0,false,"",false,0,668.85,Room 106,"2517-1, 2517-2" +EXP-X-393924421,2025-01-12,Hacienda San Angel,Expedia,,Amy,Murphy,wjmew2sclt@m.expediapartnercentral.com,0 0 6129631400,,,,,,,,2025-03-01,2025-03-02,1,,"Hotel Collect Booking, 1 Queen Bed, Non-Smoking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIA // +CONFIRMATION SENT JAN122025 // +CREDIT CARD INFORMATION OK // +RATE $ 610 USD + TAXES // +STAY MARCH1-22025 // +SUITE CELESTIAL// +exp vip// +SUBMITED JAN112025NGR//",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,610.0,886.76,0.0,0.0,0.0,124.26,0.0,0.0,0.0,886.76,886.76,2,0,0,1,,,0,0.0,false,"",false,0,152.5,Room 103,"2518-1, 2518-2" +LH25011645507661,2025-01-16,Hacienda San Angel,Extranet,,Marc,Spears,MarcJSpears@yahoo.com,"",,,,,,,,2025-03-01,2025-03-06,5,,Angels Rate.,Celebrity sports journalist here to promote us. His friend arrives one day later and staying in Rincon. No discounts on food and beverage- Paula,,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,0.0,459.83,0.0,0.0,0.0,459.83,0.0,0.0,0.0,459.83,459.83,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 121,2534-1 +LH25011645507713,2025-01-16,Hacienda San Angel,Extranet,,Marc,Spears,"","",,,,,,,,2025-03-01,2025-03-06,5,,"",Information coming- Paula,,Cancelled,2025-01-27 16:07:35, Garden of Angels - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,"" +LH25011645507735,2025-01-16,Hacienda San Angel,Extranet,,Marc,Spears,"","",,,,,,,,2025-03-01,2025-03-06,5,,"",Information coming- Paula,,Cancelled,2025-01-22 19:01:06, San Gabriel - Junior Suite,San Gabriel - Package Rate,2299.5,2874.38,0.0,0.0,0.0,0.0,0,0.0,0.0,2874.38,0,2,0,0,1,,,0,2874.38,false,"",false,0,574.875,Room 118,"" +LH25012745735701,2025-01-27,Hacienda San Angel,Extranet,,Al,Gordon,al.gordon635@gmail.com,15104723936,,,,,,,,2025-03-01,2025-03-06,5,,"Friend of Marc Spears who is staying in VDS (friend of family and doing some marketing for us). +Al should be calling in the next couple of days with his CC info.- Natasha","",,Cancelled,2025-01-28 12:45:59, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,2575.0,2639.38,0.0,0.0,0.0,0.0,0,0.0,0.0,2639.38,0,2,0,0,1,,,0,2639.38,false,"",false,0,527.875,Room 109,2408-1 +LH25012845758973,2025-01-28,Hacienda San Angel,Extranet,,Marc,Spears,natasha@haciendasanangel.com,"",,,,,,,,2025-03-01,2025-03-02,1,,more details to follow- natasha,,,Cancelled,2025-01-28 21:46:16, San Jose - Master Suite,San Jose - Standard Rate,590.0,737.5,0.0,0.0,0.0,0.0,0,0.0,0.0,737.5,0,2,0,0,1,,,0,737.5,false,"",false,0,147.5,Room 122,"" +SMP-2025020537915685,2025-02-05,Hacienda San Angel,Simple Booking,,Hyunbin,Kim,Binakim1009@gmail.com,+14152541066,,,,,,,"",2025-03-01,2025-03-02,1,,It's our 1 year wedding anniversary !,"RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT FEB 05 // +RATE $ 424.35 USD + TAXES // +SECRET RATE // +CREDIT CARD INFORMATION OK VISA CVV PENDING // +SUITE GARDEN // +STAY MAR 01- 03 2025 // +NO PROMO // +FEB052025GV",,Checked-out,"", Garden of Angels - Junior Suite,Manual,422.3,527.88,0.0,0.0,0.0,0.0,0.0,0.0,0.0,527.88,527.88,2,0,0,1,,,0,0.0,false,"",false,0,105.575,Room 109,"" +EXP-X-416132412,2025-02-18,Hacienda San Angel,Expedia,,Dave,McCormick,37d031simm@m.expediapartnercentral.com,1 253 2555847,,,,,,,,2025-03-01,2025-03-03,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,166.40, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","CONFIRMATION EXPEDIA VIP PREMIUM +RATE $486.00 + TAXES +$85.00 CREDIT IN FOOD & BEVERAGE//UPGRADE OR BOTTLE +CREDIT CARD OK +CONFIRMATION SENT FEB18/2025 +OK MARIANA FEB18/2025",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,972.0,1212.0,0.0,0.0,0.0,-3.0,0.0,0.0,0.0,1212.0,1215.0,2,0,0,1,,,0,-3.0,false,"",false,0,243.0,Room 118,"2521-1, 2521-2, 2521-3" +LH25012845758750,2025-01-28,Hacienda San Angel,Extranet,,Mike,Brown,brown4mike@aol.com,(440)539-4819,,,,,,,,2025-03-02,2025-03-06,4,,"","Visiting friend in Rincon + +No discounts- Paula +***************************** +SE HARA CARGO POR TRANSPORTACION DE $ 4,640 MN",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Package Rate,2268.0,3871.31,0.0,0.0,0.0,1319.81,0.0,0.0,0.0,3871.31,3871.31,2,0,0,1,,,0,0.0,false,"",false,0,510.3,Room 119,2533-1 +SMP-2025021838215807,2025-02-18,Hacienda San Angel,Simple Booking,,James,Wallace,walja206@gmail.com,+12063497627,,,,,,,"",2025-03-02,2025-03-03,1,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB182025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $410 USD + TAXES // +STAY MAR02-032025 // +SUITE ANGEL DOME // +SUBMITED FEB182025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,410.0,753.78,0.0,0.0,0.0,241.28,0.0,0.0,0.0,753.78,753.78,2,0,0,1,,,0,0.0,false,"",false,0,102.5,Room 113,2525-1 +LH25030146458612,2025-03-01,Hacienda San Angel,Extranet,,Hyunbin,Kim,Binakim1009@gmail.com,+14152541066,,,,,,United States of America,"",2025-03-02,2025-03-03,1,,"","",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,450.0,720.35,0.0,0.0,0.0,157.85,0.0,0.0,0.0,720.35,720.35,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 102,"2524-1, 2524-2" +SMP-2025020737961425,2025-02-07,Hacienda San Angel,Simple Booking,,Alex,Hickman,alex@chaletview.com,+15037780737,,,,,,,"",2025-03-03,2025-03-05,2,,"Late checkout on Wednesday, March 5th, if possible. Thank you so much!",,,Cancelled,2025-02-06 19:59:08, San Miguel - Presidential Suite,San Miguel - Standard Rate,1168.5,1460.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1460.63,0,2,0,0,1,,,0,1460.63,false,"",false,0,292.125,Room 107,"" +LH25022546373258,2025-02-25,Hacienda San Angel,Extranet,,Maurice,Thompson,mofish1966@gmail.com,707-694-2742,,,,,,,,2025-03-03,2025-03-06,3,,made by natasha- may cancel,"RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT FEB262025// +CREDIT CARD INFORMATION PENDIENT // +RATE $ 493.33 USD + TAXES // +STAY MAR03-062025 // +SUITE SAN GABRIEL // +SUBMITED FEB252025NATASHA//",,Cancelled,2025-02-26 14:41:41, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1480.0,1850.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1850.0,0,2,0,0,1,,,0,1850.0,false,"",false,0,370.0,Room 118,"" +EXP-X-424153154,2025-03-02,Hacienda San Angel,Expedia,,Dave,McCormick,lofatythsy@m.expediapartnercentral.com,1 253 2555847,,,,,,,,2025-03-03,2025-03-04,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 372.60, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,310.5,1087.37,0.0,0.0,0.0,699.24,0.0,0.0,0.0,1087.37,1087.37,2,0,0,1,,,0,0.0,false,"",false,0,77.625,Room 109,"2522-1, 2522-2, 2522-3" +EXP-X-411752023,2025-02-12,Hacienda San Angel,Expedia,,DONNA,EASOM,"",1 2145352398,,,,,,,,2025-03-04,2025-03-06,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,074.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $447.75 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT FEB12/2025 +OK MARIANA FEB12/2025",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,895.5,1166.38,0.0,0.0,0.0,47.0,0.0,0.0,0.0,1166.38,1166.38,2,0,0,1,,,0,0.0,false,"",false,0,223.875,Room 110,"2528-1, 2528-2" +LH25030346496270,2025-03-03,Hacienda San Angel,Extranet,,Louis,Lemieux,info@haciendasanangel.com,"",,,,,,,,2025-03-04,2025-03-05,1,,"","RESERVATION MADE DIRECTLY +RATE $345.00 +ANGEL'S RATE +CREDIT CARD INFO OK +OK MARIANA MARCH03/2025 + + +THIS RESERVATION IS A EXTENSION THEY ALREADY HARE AT CV +ANGEL RATE +COMP",,Checked-out,"",Crown View - Junior Suite,Manual,0.0,689.73,0.0,0.0,0.0,689.73,0.0,0.0,0.0,689.73,689.73,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 112,2529-1 +EXP-X-399265747,2025-01-20,Hacienda San Angel,Expedia,,William,Hansen,"",1 7049754640,,,,,,,,2025-03-05,2025-03-09,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,219.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $462.37 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT JANAUARY19/2025 +OK MARIANA ZAVALA JANUARY19/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1849.5,2613.88,0.0,0.0,0.0,302.0,0.0,0.0,0.0,2613.88,2613.88,2,0,0,1,,,0,0.0,false,"",false,0,462.375,Room 102,"2531-1, 2531-2" +EXP-X-392472412,2025-01-09,Hacienda San Angel,Expedia,,Jonas,Putsch,234goraa9f@m.expediapartnercentral.com,1 805 9144248,,,,,,,,2025-03-06,2025-03-09,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT JAN92025 // +CREDIT CARD INFORMATION OK// +RATE $ 505.50 USD + TAXES // +STAY MAR6-92025// +SUITE SAN JOSE // +SUBMITED JAN092025NGR//",,Cancelled,2025-03-01 17:09:11, San Jose - Master Suite,San Jose - Standard Rate,1516.5,1895.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1895.63,0,2,0,0,1,,,0,1895.63,false,"",false,0,379.125,Room 122,"" +EXP-X-402934454,2025-01-25,Hacienda San Angel,Expedia,,Kelly,Coker,"",1 8582849065,,,,,,,,2025-03-06,2025-03-10,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,737.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION TRHU EXP// +CONFIRMATION SENT ENE25 // +RATE $570.37 USD + TAXES // +CREDIT CARD OK INFORMATION VIRTUAL CARD FOR CHARGE // +STAY MAR 06- 10 2025 // +SUITE RINCON DE ANGELES // +NO PROMO // +ENE252025GV",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2281.5,4271.88,0.0,0.0,0.0,1420.0,0.0,0.0,0.0,4271.88,4271.88,2,0,0,1,,,0,0.0,false,"",false,0,570.375,Room 119,"2544-1, 2544-2" +SMP-2025020837982888,2025-02-08,Hacienda San Angel,Simple Booking,,Vincent,O'Rourke,vincent.j.orourke@gmail.com,+15623356080,,,,,,,"",2025-03-06,2025-03-08,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $600.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB07/2025 +OK MARIANA FEB07/2025",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1200.0,1550.26,0.0,0.0,0.0,50.26,0.0,0.0,0.0,1550.26,1550.26,2,0,0,1,,,0,0.0,false,"",false,0,300.0,Room 121,"2538-1, 2538-2, 2538-3" +SMP-2025030738573024,2025-03-07,Hacienda San Angel,Simple Booking,,Caitlin,Northcote,caitlinnorthcote@gmail.com,+18584146858,,,,,,,"",2025-03-06,2025-03-07,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $325.00 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT MARCH06/2025 +OK MARIANA MARCH06/2025",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,325.0,406.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,406.25,406.25,2,0,0,1,,,0,0.0,false,"",false,0,81.25,Room 113,2535-1 +SMP-2025022338307302,2025-02-23,Hacienda San Angel,Simple Booking,,Julie,Hale,julie@v2eventco.com,+12069991577,,,,,,,"",2025-03-07,2025-03-09,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $540.00 + TAXES +CREDIT CARD MC CVV INFO PENDING +NO PROMO +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1080.0,1728.74,0.0,0.0,0.0,378.74,0.0,0.0,0.0,1728.74,1728.74,2,0,0,1,,,0,0.0,false,"",false,0,270.0,Room 118,2541-1 +EXP-X-423761861,2025-03-01,Hacienda San Angel,Expedia,,Jonas,Putsch,45vh574823@m.expediapartnercentral.com,1 805 9144248,,,,,,,,2025-03-07,2025-03-09,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXP // +CONFIRMATION SENT FEB 02 // +RATE $ 537.75 USD + TAX // +NO PROMO // +CREDIT CARD VISA OK // +BLUE DISCOUNT 10% EXP // +SUITE SAN JOSE // +STAY MAR 07- 09 2025 // +FEB022025GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1075.5,1640.69,0.0,0.0,0.0,296.31,0.0,0.0,0.0,1640.69,1640.69,2,0,0,1,,,0,0.0,false,"",false,0,268.875,Room 122,2542-1 +BDC-4330782770,2025-03-05,Hacienda San Angel,Booking.com,,Ruben,Menacho,rmenac.726121@guest.booking.com,+1 949 514 1438,,,,.,,United States,"",2025-03-07,2025-03-09,2,,"booker_is_genius +smoking preference: Non-Smoking","",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,935.0,1284.1,0.0,0.0,0.0,115.35,0.0,0.0,0.0,1284.1,1284.1,2,0,0,1,,,0,0.0,false,"",false,0,233.75,Room 112,2540-1 +LH25030746579844,2025-03-07,Hacienda San Angel,Extranet,,Caitlin,Northcote,caitlinnorthcote@gmail.com,+18584146858,,,,,,United States of America,"",2025-03-07,2025-03-09,2,,"","RESERVATION THRU DIRECTA.COM // +CONFIRMATION SENT MAR072025 // +CREDIT CARD INFORMATION OK// +RATE $ 377.50 USD + TAXES // +STAY MAR07-092025// +SUITE ANGEL DOME // +SUBMITED MAR072025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,755.0,986.82,0.0,0.0,0.0,43.07,0.0,0.0,0.0,986.82,986.82,2,0,0,1,,,0,0.0,false,"",false,0,188.75,Room 113,"2536-1, 2536-2" +EXP-X-409820924,2025-02-08,Hacienda San Angel,Expedia,,Dylan,Hoos,pa1buxxefi@m.expediapartnercentral.com,1 540 5211518,,,,,,,,2025-03-08,2025-03-10,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,073.28, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $447.20 + TAXES +EXPEDIA VIP PREMIUM $85.00// BOTTLE OR UPGRADE +CREDIT XARD INFO OK +CONFIRMATION SENT FEB07/2025 +OK MARIANA FEB07/2025",,Cancelled,2025-02-08 19:05:12,Crown View - Junior Suite,Crown View - Standard Rate,894.4,1118.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1118.0,0,2,0,0,1,,,0,1118.0,false,"",false,0,223.6,Room 112,"" +EXP-X-415859201,2025-02-18,Hacienda San Angel,Expedia,,Kevin,Bryant,buxsic9va3@m.expediapartnercentral.com,1 469 2234615,,,,,,,,2025-03-08,2025-03-10,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,101.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPPREMVIP.COM // +CONFIRMATION SENT FEB182025// +CREDIT CARD INFORMATION OK// +RATE $459 USD + TAXES // +STAY MAR08-102025 // +SUITE GARDEN // +EXP VIP PREMIUM $85 CREDIT F&B + UP-GRADO OR WINE BOTTLE // +SUBMITED FEB182025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,918.0,1208.96,0.0,0.0,0.0,61.46,0.0,0.0,0.0,1208.96,1208.96,2,0,0,1,,,0,0.0,false,"",false,0,229.5,Room 109,2545-1 +EXP-2152282848,2025-03-08,Hacienda San Angel,Expedia,,Emmanuel,Santos,n2dvxqmm0s@m.expediapartnercentral.com,1 206 7080384,,,,,,,,2025-03-08,2025-03-10,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 717.24, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $298.85 + TAXES +$85.00 CREDIT ON FOOD & BEVERAGE // BOTTLE +CREDIT CARD INFO OK +CONFIRMATION SENT MARCH08/25 +OK MARIANA MARCH08/2025",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,597.7,899.42,0.0,0.0,0.0,152.29,0.0,0.0,0.0,899.42,899.42,2,0,0,1,,,0,0.0,false,"",false,0,149.425,Room 110,"2546-1, 2546-2" +SMP-2025022338311691,2025-02-23,Hacienda San Angel,Simple Booking,,CARRIE,O PANCAKE,myspiritfull@gmail.com,+1304-692-4112,,,,,,,"",2025-03-12,2025-03-14,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $410.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,820.0,1224.67,0.0,0.0,0.0,199.67,0.0,0.0,0.0,1224.67,1224.67,2,0,0,1,,,0,0.0,false,"",false,0,205.0,Room 113,2552-1 +SMP-2025021838195148,2025-02-17,Hacienda San Angel,Simple Booking,,Kenneth,Ward,ksward88005@gmail.com,+13138707420,,,,,,,"",2025-03-13,2025-03-15,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $615.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB17/2025 +OK MARIANA FEB17/2025",,Cancelled,2025-03-07 08:43:07, San Miguel - Presidential Suite,San Miguel - Standard Rate,1230.01,1537.51,0.0,0.0,0.0,0.0,0,0.0,0.0,1537.51,0,2,0,0,1,,,0,1537.51,false,"",false,0,307.5025,Room 107,"" +EXP-2153253510,2025-03-11,Hacienda San Angel,Expedia,,Isaac,De Hita Sánchez,dopdm302rc@m.expediapartnercentral.com,0 0 5529392377,,,,,,,,2025-03-13,2025-03-14,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 459.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $382.50 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENTMAR11/2025 +OK MARIANA MARCH11/2025",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,382.5,721.49,0.0,0.0,0.0,243.36,0.0,0.0,0.0,721.49,721.49,2,0,0,1,,,0,0.0,false,"",false,0,95.625,Room 122,2551-1 +LH25011145390137,2025-01-11,Hacienda San Angel,Extranet,,Michael G.,Hood,hood.michaelg@gmail.com,509.845.5150,,,,,,,,2025-03-14,2025-03-18,4,,,,,Cancelled,2025-01-11 15:24:47, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,2310.0,2864.4,0.0,0.0,0.0,0.0,0,0.0,0.0,2864.4,0,2,0,0,1,,,0,2864.4,false,"",false,0,554.4,Room 121,"" +EXP-X-394413197,2025-01-12,Hacienda San Angel,Expedia,,Jerry,Williamson,hhqt0tfwby@m.expediapartnercentral.com,1 919 6282298,,,,,,,,2025-03-14,2025-03-17,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,842.12, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAPREMIUMVIP.COM // +CONFIRMATION SENT JAN122025 // +CREDIT CARD INFORMATION OK// +RATE $ 511.70 USD + TAXES // +STAY MAR14-172025 // +SUITE VISTA DE SANTOS // +EXP VIP PREMIUM ADD $85 USD CREDIT F&B + UP-GRADE OR WINE BOTTLE // +SUBMITED JAN122025NGR//",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1535.1,2464.94,0.0,0.0,0.0,546.06,0.0,0.0,0.0,2464.94,2464.94,2,0,0,1,,,0,0.0,false,"",false,0,383.775,Room 121,"2562-1, 2562-2" +EXP-X-402889295,2025-01-25,Hacienda San Angel,Expedia,,Stuart,Emmrich,5dy6l8pcwq@m.expediapartnercentral.com,1 646 2834760,,,,,,,,2025-03-14,2025-03-17,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION TRHU EXP// +CONFIRMATION SENT ENE25 // +RATE $ 511.70 USD + TAXES // +CREDIT CARD OK INFORMATION AMEX // +STAY MAR 14- 17 2025 // +SUITE SAN JOSE // +NO PROMO // +ENE252025GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1535.1,1881.16,0.0,0.0,0.0,-37.72,0.0,0.0,0.0,1881.16,1918.88,1,0,0,1,,,0,-37.72,false,"",false,0,383.775,Room 122,2561-1 +EXP-X-427200994,2025-03-08,Hacienda San Angel,Expedia,,Fer Delgadillo,Ayala,1m2oycaekk@m.expediapartnercentral.com,376 868880,,,,,,,,2025-03-14,2025-03-16,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,260.24, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION BY EXPEDIA +RATE $525.10 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MARCH 07/2025 +OK MARIANA MARCH07/2025",,Cancelled,2025-03-11 09:46:14, Celestial - Royal Suite,Celestial - Standard Rate,1050.2,1312.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1312.75,0,2,0,0,1,,,0,1312.75,false,"",false,0,262.55,Room 103,"" +EXP-X-428917667,2025-03-12,Hacienda San Angel,Expedia,,Austin,Jessop,ajessoprn@gmail.com,0 0 16039522011,,,,,,,,2025-03-14,2025-03-15,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 371.52, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT MAR122025 // +CREDIT CARD INFORMATION OK // +RATE $309.60 USD + TAXES // +STAY MAR14-152025 // +SUITE SERAFIN // +SUBMITED MAR122025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,309.6,355.07,0.0,0.0,0.0,-31.93,0.0,0.0,0.0,355.07,387.0,1,0,0,1,,,0,-31.93,false,"",false,0,77.4,Room 110,"2554-1, 2554-2" +EXP-X-429220327,2025-03-14,Hacienda San Angel,Expedia,,Marilette,Brown,xprpdyx3tg@m.expediapartnercentral.com,44 790 4714533,,,,,,,,2025-03-14,2025-03-16,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,057.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $440.75 + TAXES +$85..00 USD// BOTTLE +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MARCH14/2025 +OK MARIANA MARCH14/2025 + +******************************* +RESERVATION MADE BY EXP +VIRTUAL CARD CHARGED $1,57.80 USD +GUEST DID NOT ARRIVE TO USE THE ROOM +NO SHOW +PENDING CHARGE TO GUEST OF 5% OF STAY $44.08 USD",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,881.5,1101.88,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1101.88,1057.8,1,0,0,1,,,0,44.08,false,"",false,0,220.375,Room 119,2553-1 +SMP-2025010437220292,2025-01-04,Hacienda San Angel,Simple Booking,,Sharon,Hills-Bonczyk,sharon.hillsbonczyk@gmail.com,+1612-709-4089,,,,,,,"",2025-03-15,2025-03-17,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN042025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 565 USD + TAXES // +STAY 16-17 MARCH2025// +SUITE ANGEL VIEW // +SUBMITED JAN042025NGR//",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1120.96,1401.2,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1401.2,1401.2,2,0,0,1,,,0,0.0,false,"",false,0,280.24,Room 106,2560-1 +EXP-X-399724529,2025-01-20,Hacienda San Angel,Expedia,,Stuart,Emmrich,e44inaq837@m.expediapartnercentral.com,1 646 2834760,,,,,,,,2025-03-15,2025-03-17,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA +RATE $509. 55 + TAXES +$85.00 USD ON FOOD & BEVERAGE// UPGRADE OR BOTTLE +CREDIT CARD INFO AMEX OK +CONFIRMATION SENT JANUARY20/2025 +OK MARIANA ZAVALA JANUARY20/2025",,Cancelled,2025-01-25 09:54:40, San Jose - Master Suite,San Jose - Standard Rate,1019.1,1273.88,0.0,0.0,0.0,0.0,0,0.0,0.0,1273.88,0,1,0,0,1,,,0,1273.88,false,"",false,0,254.775,Room 122,"" +SMP-2025022338311768,2025-02-23,Hacienda San Angel,Simple Booking,,CARRIE,O PANCAKE,myspiritfull@gmail.com,+1304-692-4112,,,,,,,"",2025-03-15,2025-03-16,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $410.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,410.0,815.13,0.0,0.0,0.0,302.63,0.0,0.0,0.0,815.13,815.13,2,0,0,1,,,0,0.0,false,"",false,0,102.5,Room 113,2559-1 +BDC-4523715915,2025-03-16,Hacienda San Angel,Booking.com,,Kayla,DeMars-Krentz,kdemar.911574@guest.booking.com,+1 306 581 0035,,,,.,,Canada,"",2025-03-15,2025-03-16,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR152025 // +CREDIT CARD INFORMATION OK // +RATE $ 360 USD + TAXES // +STAY MAR15-162025 // +SUITE GARDEN OF ANGELS // +SUBMITED MAR152025NGR //",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,360.0,554.44,0.0,0.0,0.0,104.44,0.0,0.0,0.0,554.44,554.44,2,0,0,1,,,0,0.0,false,"",false,0,90.0,Room 109,"2556-1, 2556-2, 2556-3" +MMS-OBH25010616413509-2705147,2025-01-06,Hacienda San Angel,Mr and Mrs Smith,,Jeff,Mackenzie,RESUMENOW@YAHOO.COM,,,,,,,,,2025-03-16,2025-03-18,2,,PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,,,Cancelled,2025-01-06 13:46:01,Angels Dome - Junior Suite,Angels Dome - Standard Rate,672.02,840.03,0.0,0.0,0.0,0.0,0,0.0,0.0,840.03,0,2,0,0,1,,,0,840.03,false,"",false,0,162.5856,Room 113,"" +EXP-X-390213077,2025-01-06,Hacienda San Angel,Expedia,,Michael,Marlow,x4cj0b5ndy@m.expediapartnercentral.com,0 0 46733182222,,,,,,,,2025-03-16,2025-03-19,3,,"Hotel Collect Booking, 1 King Bed, Non-Smoking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 85 US$ mat- och dryckeskredit per rum per vistelse","RESERVATION FROM EXPEDIA VIP +RATE $403.33 + TAXES +$85.00 USD AS CREDIT IN FOOD & BEVERAGE +CREDIT CARD AMEX OK +CONFIRMATION SENT ENE06/25 +OK MARIANA ENE06/25",,Cancelled,2025-03-13 15:19:01, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1210.0,1512.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1512.5,0,2,0,0,1,,,0,1512.5,false,"",false,0,302.5,Room 109,"" +EXP-X-423578429,2025-03-01,Hacienda San Angel,Expedia,,Heather,Nichols,g04ntmd0u0@m.expediapartnercentral.com,1 0 3034786845,,,,,,,,2025-03-16,2025-03-17,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 538.56, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT MAR02 // +RATE $ 448,8 USD + TAXES // +SOLVER DISCOUNT 10% // +CREDIT CAR OK VIRTUAL CARD FOR CHARGE // +SUITE MILAGROS // +STAY MAR 16- 17 2025 // +NO PROMO // +MAR022025GV",,Cancelled,2025-03-12 09:15:00, Milagros - Junior Suite,Milagros - Standard Rate,448.8,561.0,0.0,0.0,0.0,0.0,0,0.0,0.0,561.0,0,1,0,0,1,,,0,561.0,false,"",false,0,112.2,Room 102,"" +SMP-2025010437212268,2025-01-04,Hacienda San Angel,Simple Booking,,Stephanie,Szabo,szabo_s@hotmail.com,+1310-666-2313,,,,,,,"",2025-03-18,2025-03-21,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $470.13 + TAXES +NO PROMO + CREDIT CARD MASTER CARD CVV PENDING +CONFIRMATION SENT ENE04/2025 +OK MARIANA ENE04/2024",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1399.11,1916.49,0.0,0.0,0.0,167.6,0.0,0.0,0.0,1916.49,1916.49,2,0,0,1,,,0,0.0,false,"",false,0,349.7775,Room 107,2567-1 +SMP-2025020737961474,2025-02-07,Hacienda San Angel,Simple Booking,,Alex,Hickman,alex@chaletview.com,+15037780737,,,,,,,"",2025-03-18,2025-03-20,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $423.66 + TAXES +NO PROMO +CREDIT CARD AMEX CVV OK +CONFIRMATION SENT FREB06/2025 +OK MARIANA FREB06/2025",,Cancelled,2025-03-17 15:48:56, Angels View - Master Suite,Manual,1271.0,1588.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1588.75,1588.75,2,0,0,1,,,0,0.0,false,"",false,0,317.75,Room 106,"" +SMP-2025022338313546,2025-02-23,Hacienda San Angel,Simple Booking,,Douglas,Paley,dougpaley@gmail.com,+13057984949,,,,,,,"",2025-03-18,2025-03-20,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $630.00 + TAXES +NO PROMO +CREDIT CARD AMEX CVV PENING +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Cancelled,2025-03-04 10:36:48, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1260.0,1575.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1575.0,0,2,0,0,1,,,0,1575.0,false,"",false,0,315.0,Room 119,"" +EXP-X-420827532,2025-02-25,Hacienda San Angel,Expedia,,Elizabeth,Urenda,4od1la3w8k@m.expediapartnercentral.com,1 3364662,,,,,,,,2025-03-18,2025-03-20,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT FEB262025 // +CREDIT CARD INFORMATION OK // +RATE $ 441 USD + TAXES // +STAY MAR18-202025// +SUITE MILAGROS// +SUBMITED FEB262025NGR//",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,882.0,1448.69,0.0,0.0,0.0,346.19,0.0,0.0,0.0,1448.69,1448.69,2,0,0,1,,,0,0.0,false,"",false,0,220.5,Room 102,2566-1 +SMP-2025022738395247,2025-02-27,Hacienda San Angel,Simple Booking,,Lawrence,Ebringer,lawrence0002@yahoo.com,+16502245600,,,,,,,"",2025-03-19,2025-03-22,3,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB262025 // +CREDIT CARD INFORMATION OK// +RATE $ 407.26 USD + TAXES // +STAY MAR19-222025 // +SUITE GARDEN OF ANGELS // +SUBMITED FEB262025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1221.8,2049.06,0.0,0.0,0.0,521.81,0.0,0.0,0.0,2049.06,2049.06,2,0,0,1,,,0,0.0,false,"",false,0,305.45,Room 109,2568-1 +SMP-2025031238699197,2025-03-12,Hacienda San Angel,Simple Booking,,Bruce,Burgett,burgettmail@gmail.com,+12062264064,,,,,,,"",2025-03-19,2025-03-20,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR12 // +RATE $ 307.50 USD + TAXES // +CREDIT CARD INFORMATION VISA CVV PENDING // +SRECRET RATE // +SUITE SERAFIN // +STAY MAR19- 20 2025 // +MAR122025GV",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,307.5,402.11,0.0,0.0,0.0,17.73,0.0,0.0,0.0,402.11,402.11,2,0,0,1,,,0,0.0,false,"",false,0,76.875,Room 110,2565-1 +BDC-4820923100,2025-02-09,Hacienda San Angel,Booking.com,,Kaivan,Hashemi,kaivan_hashemi@hotmail.com,+44 7837 657663,,,,,,United Kingdom,"",2025-03-20,2025-03-25,5,,"My wife and I are looking forward to spending our 40th wedding anniversary at your lovely hotel. +Kind regards, +Dr Kaivan Hashemi, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT FEB09 // +CREDIT CARD INFORMATION OK MASTERCARD // +RATE $ 398.52 USD + TAXES // +SUITE MILAGROS // +STAY MAR 20- 25 2025 // +GENIUS DISCOUNT (10%) // +FEB092025GV",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1992.6,2506.69,0.0,0.0,0.0,15.94,0.0,0.0,0.0,2506.69,2506.69,2,0,0,1,,,0,0.0,false,"",false,0,498.15,Room 102,"2585-1, 2585-2" +LH25022046261486,2025-02-20,Hacienda San Angel,Extranet,,Elise,Friedman,elisefriedman@gmail.com,4153103414,,,,,,,,2025-03-20,2025-03-21,1,,"","DIRECT RESERVATION // +CONFIRMATION SENT FEB20 // +RATE $ 600 USD + TAXES // +NO PROMO // +SUITE VISTA DE SANTOS // +STAY MAR 20- 21 2025 +CREDIT CARD INFORMATION ON AMEX // +FEB202025GV",,Cancelled,2025-03-17 16:14:15, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,600.0,750.0,0.0,0.0,0.0,0.0,0,0.0,0.0,750.0,0,2,0,0,1,,,0,750.0,false,"",false,0,150.0,Room 121,"" +MMS-OBH25010418051804-2702956,2025-01-04,Hacienda San Angel,Mr and Mrs Smith,,David,Gershik,DZG830@OUTLOOK.COM,,,,,,,,,2025-03-21,2025-03-22,1,,PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $575 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT ENE04/2025 +OK MARIANA ENE04/2025 + + DO NO CHARGE ANYTHING TO THE GUEST",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,547.4,598.0,0.0,0.0,0.0,-86.25,0.0,0.0,0.0,598.0,598.0,2,0,0,1,,,0,0.0,false,"",false,0,136.85,Room 121,2569-1 +BDC-4713501413,2025-01-12,Hacienda San Angel,Booking.com,,Adalberto,Tejeda,atejed.878800@guest.booking.com,+1 415 608 7391,,,,,,United States,"",2025-03-21,2025-03-24,3,,"Approximate time of arrival: between 17:00 and 18:00, booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-01-12 16:41:09, Milagros - Junior Suite,Milagros - Standard Rate,1291.5,1601.46,0.0,0.0,0.0,0.0,0,0.0,0.0,1601.46,0,2,0,0,1,,,0,1601.46,false,"",false,0,309.96,Room 102,"" +LH25012945784583,2025-01-29,Hacienda San Angel,Extranet,,Lesley,Compoy,lesleycampoy@gmail.com,9178929960,,,,,,,,2025-03-21,2025-03-24,3,,"","DIRECT RESERVATION // +CONFIRMATION SENT ENE29 // +RATE $ 516.66 + TAXES // +NO PROMO // +SUITE SAN GABRIEL // +STAY MAR 21- 24 2025 // +ENE29205GV",,Cancelled,2025-02-02 18:08:27, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1550.0,1937.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1937.5,0,2,0,0,1,,,0,1937.5,false,"",false,0,387.5,Room 118,"" +SMP-2025013037783070,2025-01-30,Hacienda San Angel,Simple Booking,,Georgina,Maisto,jmaisto@arhaus.com,+14154124768,,,,,,,"",2025-03-21,2025-03-24,3,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE29 // +RATE $ 505 USD + TAXES // +NO PROMO // +SUITE MILAGROS // +STAY MAR 21- 24 2025 // +ENE292025GV",,Cancelled,2025-01-31 11:25:48, Milagros - Junior Suite,Milagros - Standard Rate,1515.0,1893.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1893.75,0,2,0,0,1,,,0,1893.75,false,"",false,0,378.75,Room 102,"" +SMP-2025013037783133,2025-01-30,Hacienda San Angel,Simple Booking,,jennifer,feinberg,jenna@feinberg5.com,+14155594307,,,,,,,"",2025-03-21,2025-03-23,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE29 // +RATE $ 510 USD + TAXES // +NO PROMO // +SUITE CROWN VIEW // +STAY MAR 21- 24 2025 // +ENE292025GV",,Cancelled,2025-03-10 20:15:02,Crown View - Junior Suite,Crown View - Standard Rate,1020.0,1275.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1275.0,0,2,0,0,1,,,0,1275.0,false,"",false,0,255.0,Room 112,"" +EXP-X-412191569,2025-02-13,Hacienda San Angel,Expedia,,Elise,Friedman,3uv9cscrt0@m.expediapartnercentral.com,1 415 3103414,,,,,,,,2025-03-21,2025-03-24,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT FEB13 // +RATE 473.73 USD + YAX // +NO CPROMO // +CREDIT CARD INFORMATION PM AMEX // +SILVER PROMOTION 10% DISCOUNT EXP // +STAY MAR 21- 24 2025 // +SUITE SAN GABRIEL // +FEB132025GV",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1421.2,1772.56,0.0,0.0,0.0,-3.94,0.0,0.0,0.0,1772.56,1776.5,1,0,0,1,,,0,-3.94,false,"",false,0,355.3,Room 118,2584-1 +SMP-2025012037572723,2025-01-20,Hacienda San Angel,Simple Booking,,Kelly,Robinson,Kellsbells35@hotmail.com,+971557540084,,,,,,United Arab Emirates,"",2025-03-22,2025-03-23,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $418.20 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT JANUARY20/2025 +OK MARIANA ZAVALA JANUARY20/2025 +ANGEL RATE",,Cancelled,2025-03-19 07:50:12, Garden of Angels - Junior Suite,Manual,418.2,522.75,0.0,0.0,0.0,0.0,0,0.0,0.0,522.75,0,2,0,0,1,,,0,522.75,false,"",false,0,104.55,Room 109,"" +BDC-4831931653,2025-01-22,Hacienda San Angel,Booking.com,,paul,patton,ppatto.895146@guest.booking.com,+1 415 269 1277,,,,,,United States,"",2025-03-22,2025-03-24,2,,"Approximate time of arrival: between 14:00 and 15:00 +This guest is interested in your airport shuttle service and would like to get more information from you., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT JAN222025 // +CREDIT CARD INFORMATION OK// +RATE $ 550 USD + TAXES // +STAY MAR22-242025 // +SUITE SAN JOSE// +SUBMITED JAN222025MARIANA//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1100.0,1632.47,0.0,0.0,0.0,257.47,0.0,0.0,0.0,1632.47,1632.47,2,0,0,1,,,0,0.0,false,"",false,0,275.0,Room 122,"2578-1, 2578-2" +SMP-2025031138660462,2025-03-11,Hacienda San Angel,Simple Booking,,Lindsay,Carmona,lindsay.carmona@gmail.com,+13108500432,,,,,,,"",2025-03-22,2025-03-24,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR 10 // +RATE $ 407.95 USD + TAXES // +NO PROMO // +SECRET RATE // +SUITE CROWN VIEW // +STAY MAR 22- 24 2025 // +MAR102025GV",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,815.9,1060.41,0.0,0.0,0.0,40.53,0.0,0.0,0.0,1060.41,1060.41,2,0,0,1,,,0,0.0,false,"",false,0,203.975,Room 112,2580-1 +LH25031946841235,2025-03-19,Hacienda San Angel,Extranet,,KELLY,ROBINSON,kellsbells35@hotmail.com,971557540084,,,,,,,,2025-03-22,2025-03-23,1,,"","RESERVATION THRU DIRECTA .COM // +CONFIRMATION SENT MAR192025 // +CREDIT CARD INFORMATION OK // +RATE $ 445 USD ANGEL RATE // +STAY MAR22-232025 // +SUITE GARDEN OF ANGELS // +SUBMITED MAR192025NGR // +COMP",,Checked-out,"", Garden of Angels - Junior Suite,Manual,445.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,2571-1 +EXP-2150407404,2025-02-11,Hacienda San Angel,Expedia,,Jennifer,Ippoliti,nubojl4d9a@m.expediapartnercentral.com,1 917 5363019,,,,,,,,2025-03-23,2025-03-24,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 540.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT FEB102025 // +CREDIT CARD INFORMATION OK // +RATE $ 450 USD + TAXES // +STAY MARCH22-242025 // +SUITE SERAFIN // +SUBMITED FEB102025NGR //",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,450.0,570.83,0.0,0.0,0.0,8.33,0.0,0.0,0.0,570.83,570.83,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 110,2579-1 +SMP-2025022638392460,2025-02-26,Hacienda San Angel,Simple Booking,,Elizabeth,Geier,geier.elizabeth@gmail.com,+14138844839,,,,,,,"",2025-03-23,2025-03-26,3,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB262025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 388.13 USD + TAXES // +STAY MAR23-272025 // +SUITE GARDEN OF ANGELS // +SUBMITED FEB262025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1164.41,1534.25,0.0,0.0,0.0,78.74,0.0,0.0,0.0,1534.25,1534.25,2,0,0,1,,,0,0.0,false,"",false,0,291.1025,Room 109,"2570-1, 2570-2" +BDC-4557418242,2025-03-13,Hacienda San Angel,Booking.com,,kelly,robinson,krobin.293666@guest.booking.com,+971 55 754 0084,,,,.,,United Arab Emirates,"",2025-03-23,2025-03-24,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR132025 // +CREDIT CARD INFORMATION OK // +RATE $ 427.50 USD + TAXES // +STAY MAR23-242025 // +SUITE ANGEL DOME // +SUBMITED MAR132025NGR //",,Cancelled,2025-03-17 15:17:14,Angels Dome - Junior Suite,Angels Dome - Standard Rate,427.5,534.38,0.0,0.0,0.0,0.0,0,0.0,0.0,534.38,0,2,0,0,1,,,0,534.38,false,"",false,0,106.875,Room 113,"" +EXP-2155679984,2025-03-15,Hacienda San Angel,Expedia,,Radhika,Chintalapally,9n8wump2xh@m.expediapartnercentral.com,1 734 3068293,,,,,,,,2025-03-23,2025-03-26,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.",,,Cancelled,2025-03-15 20:43:46, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1543.5,1929.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1929.38,0,2,0,0,1,,,0,1929.38,false,"",false,0,385.875,Room 119,"" +EXP-2155943284,2025-03-16,Hacienda San Angel,Expedia,,Erin,Tangen,2w5mkcfq2v@m.expediapartnercentral.com,1 623 3995918,,,,,,,,2025-03-23,2025-03-24,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 660.48, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIA PREM VIP.COM // +CONFIRMATION SENT MAR162025 // +CREDIT CARD INFORMATION OK // +RATE $550.40 USD + TAXES // +STAY MAR23-0242025// +SUITE RINCÓN// +SUBMITED MAR162025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,550.4,917.67,0.0,0.0,0.0,229.67,0.0,0.0,0.0,917.67,917.67,2,0,0,1,,,0,0.0,false,"",false,0,137.6,Room 119,"2577-1, 2577-2" +LH25031746806428,2025-03-17,Hacienda San Angel,Extranet,,KELLY,ROBINSON,kellsbells35@hotmail.com,+971557540084,,,,,,,,2025-03-23,2025-03-24,1,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT MAR172025 // +CREDIT CARD INFORMATION OK // +RATE $ 470 USD + TAXES // +STAY MAR23-242025 // +SUITE AD // +SUBMITED MAR172025NGR// +COMPED",,Checked-out,"",Angels Dome - Junior Suite,Manual,430.0,171.99,0.0,0.0,0.0,171.99,0.0,0.0,0.0,171.99,171.99,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 113,2583-1 +LH25031946857205,2025-03-19,Hacienda San Angel,Extranet,,Vanessa,Sanchez,vanessa@nessyswimwear.com,"",,,,,,,,2025-03-23,2025-03-24,1,,"","Nessy Swimwear Photo Shoot + +Trading for photos + +40% discount on all food and beverage + +Promises to be respectful of other hotel guests. Will be shooting in the room and around the venue. Keep one eye open on them and support as needed. This swimwear publication gets millions of views on social media. + +She moves to Celestial on the 24th.",,Checked-out,"", San Miguel - Presidential Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,1,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,"2576-1, 2576-2" +SMP-2025030638566041,2025-03-06,Hacienda San Angel,Simple Booking,,Jaime,Ostheimer,jaitimer@gmail.com,+12067180304,,,,,,,"",2025-03-24,2025-03-25,1,,"","RESERVATION THRU SB// +CONFIRMATION SENT MAR062025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 425 USD + TAXES // +STAY MAR24-252025 // +SUITE AD // +SUBMITED MAR062025NGR// + +ame exp cvv 5422",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,425.0,812.28,0.0,0.0,0.0,281.03,0.0,0.0,0.0,812.28,812.28,2,0,0,1,,,0,0.0,false,"",false,0,106.25,Room 113,"2586-1, 2586-2" +LH25031146664526,2025-03-11,Hacienda San Angel,Extranet,,Vanessa,Sanchez,vanessa@nessyswimwear.com,"",,,,,,,,2025-03-24,2025-03-26,2,,"","Nessy Swimwear Photo Shoot + +Trading for photos + + + +40% discount on all food and beverage + +Promises to be respectful of other hotel guests. Will be shooting in the room and around the venue. Keep one eye open on them and support as needed. This swimwear publication gets millions of views on social media.",,Checked-out,"", Celestial - Royal Suite,Manual,0.0,91.63,0.0,0.0,0.0,91.63,0.0,0.0,0.0,91.63,91.63,1,0,0,1,,,0,0.0,false,"",false,0,0,Room 103,2587-1 +EXP-2155938172,2025-03-16,Hacienda San Angel,Expedia,,Radhika,Chintalapally,nk1w6viut0@m.expediapartnercentral.com,1 734 3068293,,,,,,,,2025-03-24,2025-03-26,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.",,,Cancelled,2025-03-16 10:09:25, San Jose - Master Suite,San Jose - Standard Rate,882.0,1102.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1102.5,0,2,0,0,1,,,0,1102.5,false,"",false,0,220.5,Room 122,"" +EXP-2160897872,2025-03-23,Hacienda San Angel,Expedia,,NATHAN,WARNE,lyg3k8tjdk@m.expediapartnercentral.com,1 403 6295802,,,,,,,,2025-03-24,2025-03-25,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 432.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $360. 00 + TAXES +CREDIT CARD INFO OK +CONFIRMATION SENT MARCH23/2025 +OK MARIANA MARCH23/2025 + +************************** +San José, never arrive, +WERE CALLED BUT NEVER ANSWERED THE PHONE +THE RESERVATION CAME WITH EXPEDIA VIRTUAL CARD WHICH ALLOWS US TO CHARGE WITHOUT 5%.",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,360.0,450.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,450.0,432.0,2,0,0,1,,,0,18.0,false,"",false,0,90.0,Room 122,"" +SMP-2025010237163547,2025-01-02,Hacienda San Angel,Simple Booking,,John,Hajovsky,jhajo88@gmail.com,+15416109992,,,,,,,"",2025-03-26,2025-03-28,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN012025// +CREDIT CARD INFORMATION PENDIENT CVV // +RATE $ 557.50 USD + TAXES // +STAY MARCH26-282025// +SUITE SAN JOSE // +SUBMITED JAN012025NGR//",,Cancelled,2025-03-22 13:07:55, San Jose - Master Suite,San Jose - Standard Rate,1106.08,1412.77,0.0,0.0,0.0,30.17,0,0.0,0.0,1412.77,0,2,0,0,1,,,0,1412.77,false,"",false,0,276.52,Room 122,"" +EXP-X-404841682,2025-01-28,Hacienda San Angel,Expedia,,SHELLEY,MITCHELL,"",1 587 8922824,,,,,,,,2025-03-26,2025-03-28,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,117.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +RATE $438 USD + TAXES // +CREDIT CARD INFORMATIO OK, VIRTUAL CARD FOR CHARGE // +PROMOCION EXP BLUE 10% DISCOOUNT // +SUITE MILAGROS // +STAY MAR 25- 28 2025 // +ENE282025GV + +****** +SE MODIFICARON FECHAS +MAR 26- 28 2025",,Cancelled,2025-02-06 22:48:22, Milagros - Junior Suite,Milagros - Standard Rate,931.5,1164.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1164.38,0,2,0,0,1,,,0,1164.38,false,"",false,0,232.875,Room 102,"" +LH25032246912713,2025-03-22,Hacienda San Angel,Extranet,,John,Hajovsky,jhajo88@gmail.com,+15416109992,,,,,,United States of America,"",2025-03-26,2025-03-28,2,,"","DIRECT RESERVATION // +CONFIRMATION SENT MAR 22 // +RATE $ 447.50 USD + TAX // +SUITE SAN JOSE // +STAY MAR 26- 28 2025 // +NO PROMO // +CREDIT CARD INFO AMEX OK // +MAR222025GV",,Cancelled,2025-03-23 09:50:00, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,895.0,1118.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1118.75,0,2,0,0,1,,,0,1118.75,false,"",false,0,223.75,Room 121,"" +SMP-2025032238956139,2025-03-22,Hacienda San Angel,Simple Booking,,John,Hajovsky,jhajo88@gmail.com,+15416109992,,,,,,,"",2025-03-26,2025-03-28,2,,"","RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT MAR222025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 447.50 USD + TAXES // +STAY MAR26-282025 // +SUITE SAN JOSE // +SUBMITED MAR2220252NGR//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,895.0,1336.08,0.0,0.0,0.0,217.33,0.0,0.0,0.0,1336.08,1336.08,2,0,0,1,,,0,0.0,false,"",false,0,223.75,Room 122,"2589-1, 2589-2, 2589-3" +SMP-2025012737720974,2025-01-27,Hacienda San Angel,Simple Booking,,Timothy,McGhee,timothy.b.mcghee@gmail.com,+18474202507,,,,,,,"",2025-03-27,2025-04-03,7,,Please see email sent. I want to book with same agreement as my November visit,"RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN272025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 574.28 USD + TAXES // +STAYMAR27-APR032025 // +SUITE VISTA DE SANTOS// +SUBMITED JAN272025NGR//",,Cancelled,2025-01-27 16:21:05, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,4020.0,5025.0,0.0,0.0,0.0,0.0,0,0.0,0.0,5025.0,0,2,0,0,1,,,0,5025.0,false,"",false,0,1005.0,Room 121,"" +LH25012745735936,2025-01-27,Hacienda San Angel,Extranet,,TIMOTHY,MCGHEE,timothy.b.mcghee@gmail.com,"",,,,,,,,2025-03-27,2025-04-03,7,,"","RESERVATION DIRECTLY +RATE $587.14 +ANGEL'S RATE +CREDIT CARD INFO OK +CONFIRMATION SENT JANUARY 27/2025 +OK MARIANA ZAVALA JANUARY27/2025",,Cancelled,2025-01-28 20:41:01, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,4110.0,4110.0,0.0,0.0,0.0,0.0,0,0.0,0.0,4110.0,0,2,0,0,1,,,0,4110.0,false,"",false,0,1027.5,Room 121,"" +BDC-4712644057,2025-03-16,Hacienda San Angel,Booking.com,,Naomi,Maki,nmaki.803038@guest.booking.com,+1 727 460 1421,,,,,,United States,"",2025-03-27,2025-03-30,3,,"Approximate time of arrival: between 16:00 and 17:00 +This guest is interested in your airport shuttle service and would like to get more information from you. +Can a pregnancy pillow be provided? This is our baby moon :), booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR152025 // +CREDIT CARD INFORMATION OK // +RATE $ 418.50 USD + TAXES // +STAY MAR27-302025 // +SUITE GARDEN OF ANGEL // +SUBMITED MAR152005NGR//",,Cancelled,2025-03-21 12:08:56, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1255.5,1569.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1569.38,0,2,0,0,1,,,0,1569.38,false,"",false,0,313.875,Room 109,"" +BDC-4866320619,2025-01-15,Hacienda San Angel,Booking.com,,Laurie,Vanderheide,lvande.870083@guest.booking.com,+1 509 688 4495,,,,,,United States,"",2025-03-28,2025-03-31,3,,"Approximate time of arrival: between 04:00 and 05:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING.COM // +CONFIRMATION SENT ENE 16 // +RATE $ 409.5USD + TAXES // +CREDIT CARD INFORMATION OK VISA // +STAY MAR 28- 2025 2025 // +SUITE GARDEN OF ANGEL // +NO PROMO //",,Cancelled,2025-03-06 16:12:51, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1228.5,1545.45,0.0,0.0,0.0,9.82,0,0.0,0.0,1545.45,0,2,0,0,1,,,0,1545.45,false,"",false,0,307.125,Room 109,"" +SMP-2025030538525494,2025-03-05,Hacienda San Angel,Simple Booking,,cindy,nguyen,hello@cndsgn.com,+15044005021,,,,,,,"",2025-03-28,2025-04-01,4,,"","RESERVATIN FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR 04 // +CREDIT CARD VISA CVV PENDING // +RATE $ 401.80 USD + TAXES // +SECRET RATE // +SUITE MILAGROS // +STAY MAR 29- ABR 01 02025 // +NO PROMO // +MAR042025GV",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1705.41,2443.94,0.0,0.0,0.0,312.18,0.0,0.0,0.0,2443.94,2443.94,2,0,0,1,,,0,0.0,false,"",false,0,426.3525,Room 102,2600-1 +EXP-2159979092,2025-03-22,Hacienda San Angel,Expedia,,Richard,Craig,cu7xrh51fk@m.expediapartnercentral.com,1 562 5194803,,,,,,,,2025-03-28,2025-04-01,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION FROM EXPEDIA VIP +RATE $433.65 + TAXES +$85.00 USD TO USE ON FOOD &BEVERAGE +CREDIT CARD OK +CONFIRMATION SENT MARCH21/2025 +OK MARIANA MARCH 21/2025",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1734.6,2665.42,0.0,0.0,0.0,497.17,0.0,0.0,0.0,2665.42,2665.42,2,0,0,1,,,0,0.0,false,"",false,0,433.65,Room 103,2599-1 +MMS-OBH25032721012903-2790431,2025-03-27,Hacienda San Angel,Mr and Mrs Smith,,Michael,Thomson,MIKETHOMSON99@HOTMAIL.COM,3105281699,,,,,,,,2025-03-28,2025-03-31,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,789.98,1420.72,0.0,0.0,0.0,433.24,0.0,0.0,0.0,1420.72,1420.72,2,0,0,1,,,0,0.0,false,"",false,0,197.495,Room 109,2595-1 +LH25032747029865,2025-03-27,Hacienda San Angel,Extranet,,Joette,Gilbert,gatheringsinvail@gmail.com,9703765158,,,,,,,,2025-03-29,2025-03-30,1,,"","",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,415.0,518.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,518.75,518.75,2,0,0,1,,,0,0.0,false,"",false,0,103.75,Room 122,2593-1 +EXP-X-389443582,2025-01-05,Hacienda San Angel,Expedia,,Debra,Shatford,"",1 3233795799,,,,,,,,2025-03-30,2025-04-04,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,943.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT JAN052025 // +CREDIT CARD INFORMATION OK // +RATE $ 497.25 USD + TAXES // +STAY MAR31-APR042025 // +SUITE SAN JOSE// +SUBMITED JAN052025NGR//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,2452.5,3114.13,0.0,0.0,0.0,48.5,0.0,0.0,0.0,3114.13,3114.13,2,0,0,1,,,0,0.0,false,"",false,0,613.125,Room 122,2606-1 +SMP-2025022238300174,2025-02-22,Hacienda San Angel,Simple Booking,,Luzia,Dos Santos Grob,luziagrobdossantos@gmail.com,+12067144337,,,,,,,"",2025-03-30,2025-04-04,5,,Booking for my parents to celebrate my mom's 70th birthday,"RESERVATION FROM SIMPLE BOOKING +RATE $581.00+ TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB22/2025 +OK MARIANA SEND FEB22/2025",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,2905.0,3871.59,0.0,0.0,0.0,240.34,0.0,0.0,0.0,3871.59,3871.59,2,0,0,1,,,0,0.0,false,"",false,0,726.25,Room 121,2607-1 +SMP-2025033039140603,2025-03-30,Hacienda San Angel,Simple Booking,,Brad,Peik,bradpeik@gmail.com,4158198890,,,,,,,"",2025-03-30,2025-03-31,1,,"","LAST MINUTE RESERVATION FROM SIMPLE BOOKING +RATE $246.00 + TAXES + NO PROMO +CREDIT CARD OK +CONFIRMATION SEND MARCH30/2025 +OK MARIANA MARCH30/2025",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,246.0,493.44,0.0,0.0,0.0,185.94,0.0,0.0,0.0,493.44,493.44,2,0,0,1,,,0,0.0,false,"",false,0,61.5,Room 113,2596-1 +LH25022446341424,2025-02-24,Hacienda San Angel,Extranet,,Ines,Lara,ines@haciendasanangel.com,"",,,,,,,,2025-03-31,2025-04-02,2,,"","",,Cancelled,2025-02-24 13:55:08, Celestial - Royal Suite,Celestial - Package Rate,1075.5,1344.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1344.38,0,2,0,0,1,,,0,1344.38,false,"",false,0,268.875,Room 103,"" +LH25022746412428,2025-02-27,Hacienda San Angel,Extranet,,ELLEN,SULLIVAN,ellenasullivan14@gmail.com,"",,,,,,,,2025-03-31,2025-04-03,3,,"","",,Cancelled,2025-02-28 12:26:53,Angels Dome - Junior Suite,Angels Dome - Package Rate,1282.5,1603.13,0.0,0.0,0.0,0.0,0,0.0,0.0,1603.13,0,2,0,0,1,,,0,1603.13,false,"",false,0,320.625,Room 113,"" +LH25022846431320,2025-02-28,Hacienda San Angel,Extranet,,ELLEN,SULLIVAN,ellenasullivan14@gmail.com,4156068231,,,,,,,,2025-03-31,2025-04-03,3,,"","RESERVATION DIRECTLY +RATE $508.30 + TAXES +SENENITY PACKAGE +CREDIT CARD CVV OK +CONFIRMATION SENT FEB28/2025 +OK MARIANA FEB28/2025",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Package Rate,1300.5,2121.63,0.0,0.0,0.0,496.0,0.0,0.0,0.0,2121.63,2121.63,2,0,0,1,,,0,0.0,false,"",false,0,325.125,Room 113,2605-1 +LH25031746810155,2025-03-17,Hacienda San Angel,Extranet,,Alex,Hickman,alex@chaletview.com,+15037780737,,,,,,United States of America,"",2025-03-31,2025-04-02,2,,"","RESERVATION DIRECTLY +CREDIT FOR PAST RESERVATION SMP-2025020737961474 + + +CONFIRMATION SENT MARCH17/2025 +OK MARIANA MARC17/2025 + +Note he will be here until April 1st pretty early in the morning.",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,950.0,1478.13,0.0,0.0,0.0,290.63,0.0,0.0,0.0,1478.13,1478.13,2,0,0,1,,,0,0.0,false,"",false,0,237.5,Room 109,2601-1 +EXP-2158386450,2025-03-20,Hacienda San Angel,Expedia,,BRIAN SAEHONG,KIM,i2u0uorvxv@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-03-31,2025-04-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,171.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT MAR 19 // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +RATE $ 488.50 USD + TAX // +NO PORMO // +STAY MAR 31- ABR 02 2025 // +SUITE CELESTIAL //",,Cancelled,2025-03-20 10:18:01, Celestial - Royal Suite,Celestial - Standard Rate,976.5,1220.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1220.63,0,2,0,0,1,,,0,1220.63,false,"",false,0,244.125,Room 103,"" +LH25033147113589,2025-03-31,Hacienda San Angel,Extranet,,BRAD,PEIK,info@haciendasanangel.com,"",,,,,,,,2025-03-31,2025-04-01,1,,"","RESERVATION DIRECTLY +ANGEL'S RATE +COMPLEMENTARY +OK MARIANA ZAVALA MARCH31/2025 + + + GUEST WAS IN AD EXTENTED ON MORE NIGHT.",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,305.0,199.94,0.0,0.0,0.0,199.94,0.0,0.0,0.0,199.94,199.94,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 110,2597-1 +BDC-4724318064,2025-03-04,Hacienda San Angel,Booking.com,,Jeffrey,Hines,jhines.270008@guest.booking.com,+1 403 760 5907,,,,.,,Canada,"",2025-04-01,2025-04-03,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-03-30., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR042025 // +CREDIT CARD INFORMATION OK // +RATE $425.25 USD + TAXES // +STAY APR01-032025// +SUITE SERAFIN// +SUBMITED MAR042025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,850.5,1355.1,0.0,0.0,0.0,291.97,0.0,0.0,0.0,1355.1,1355.1,2,0,0,1,,,0,0.0,false,"",false,0,212.625,Room 110,2603-1 +EXP-X-396145551,2025-01-15,Hacienda San Angel,Expedia,,Ketan,Patel,30va7r1c8a@m.expediapartnercentral.com,1 0 8584495125,,,,,,,,2025-04-02,2025-04-06,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT JJAN152025// +CREDIT CARD INFORMATION OK // +RATE $ 421.30 USD + TAXES // +STAY ABR2-62025 // +SUITE GARDEN OF ANGELS// +SUBMITED JAN152025NGR //",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1685.2,2559.65,0.0,0.0,0.0,453.15,0.0,0.0,0.0,2559.65,2559.65,2,0,0,1,,,0,0.0,false,"",false,0,421.3,Room 109,"2614-1, 2614-2" +SMP-2025011837514607,2025-01-18,Hacienda San Angel,Simple Booking,,Simon,Menaker,simonmenaker@gmail.com,+17044257561,,,,,,,"",2025-04-02,2025-04-04,2,,We will be traveling to celebrate the birth of our first child in just a few months! Anything you can do to make our vacation extra special would be greatly appreciated. I would also like to notify the kitchen/restaurant staff that my wife has a gluten allergy. Thank you!,"RESERVATION FROM SIMPLE BOOKING +RATE $407.95 + TAXES +NO PROMO +CREDIT CARD VISA CVV OK +CONFIRMATION SENT ENE18/25 +OK MARIANA SENT ENE18/25",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,815.9,1637.39,0.0,0.0,0.0,617.51,0.0,0.0,0.0,1637.39,1637.39,2,0,0,1,,,0,0.0,false,"",false,0,203.975,Room 102,"2608-1, 2608-2" +EXP-X-423458313,2025-03-01,Hacienda San Angel,Expedia,,Michelle,Bodner,hqe35xpfum@m.expediapartnercentral.com,1 917 6978421,,,,,,,,2025-04-02,2025-04-03,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 777.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $648.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT MARCH1ST/2025 +OK MARIANA MARCH 1ST /2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,648.0,810.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,810.0,810.0,2,0,0,1,,,0,0.0,false,"",false,0,162.0,Room 107,2604-1 +LH25011445462506,2025-01-14,Hacienda San Angel,Extranet,,CAROLE & ALDEN,COATE,reservations@verana.com,4159875911,,,,,,,,2025-04-03,2025-04-06,3,,"",VERANA CXC,,Checked-out,"",Serafin - Junior Suite,Manual,1200.0,86.14,0.0,0.0,0.0,-1113.86,0.0,0.0,0.0,86.14,86.14,2,0,0,1,,,0,0.0,false,"",false,0,300.0,Room 110,2616-1 +LH25020345886937,2025-02-03,Hacienda San Angel,Extranet,,HILARY & BRIAN,COATE,reservations@verana.com,4159875911,,,,,,,,2025-04-03,2025-04-06,3,,"",VERANA CXC,,Checked-out,"",Crown View - Junior Suite,Manual,1200.0,43.07,0.0,0.0,0.0,-1156.93,0.0,0.0,0.0,43.07,43.07,2,0,0,1,,,0,0.0,false,"",false,0,300.0,Room 112,2615-1 +SMP-2025030138454284,2025-03-01,Hacienda San Angel,Simple Booking,,Stephanie,Zancolli,szancolli@indigoing.com,+19175628677,,,,,,,"",2025-04-03,2025-04-05,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT FEB 02 // +RATE $500 USD + TAX // +NO PROMO // +CREDIT CARD AMEX PENDIING CVV // +SUITE ANGEL DOME // +STAY ABR 03- 05 2025 // +FEB022025GV + +************************** +Solicita descuento AAA (10%)",,Cancelled,2025-03-18 13:10:57,Angels Dome - Junior Suite,Angels Dome - Standard Rate,1000.0,1125.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1125.0,0,2,0,0,1,,,0,1125.0,false,"",false,0,225.0,Room 113,"" +SMP-2025031838866356,2025-03-18,Hacienda San Angel,Simple Booking,,Stephanie,Zancolli,szancolli@indigoing.com,+19175628677,,,,,,,"",2025-04-03,2025-04-05,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $608.85+ TAXES +SECRET RATE + CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT MARCH18/2025 +OK MARIANA MARCH18/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1217.7,1895.65,0.0,0.0,0.0,373.52,0.0,0.0,0.0,1895.65,1895.65,2,0,0,1,,,0,0.0,false,"",false,0,304.425,Room 107,2612-1 +EXP-2161421827,2025-03-24,Hacienda San Angel,Expedia,,Ramon,Bandres,i1j5muuaat@m.expediapartnercentral.com,34 661 451044,,,,,,,,2025-04-03,2025-04-07,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION FROM EXPEDIA +RATE $393..82+ TAXES +Credit card visa ok +Confirmation sent March 24/2025 +Ok Mariana March24/2025",,Cancelled,2025-03-31 01:43:18,Angels Dome - Junior Suite,Angels Dome - Standard Rate,1575.3,1969.13,0.0,0.0,0.0,0.0,0,0.0,0.0,1969.13,0,2,0,0,1,,,0,1969.13,false,"",false,0,393.825,Room 113,"" +LH25040147142121,2025-04-01,Hacienda San Angel,Extranet,,gris,test,"","",,,,,,,,2025-04-03,2025-04-05,2,,"","",,Cancelled,2025-04-01 23:01:25,Angels Dome - Junior Suite,Angels Dome - Package Rate,684.0,1351.0,0.0,0.0,0.0,496.0,0,0.0,0.0,1351.0,0,2,0,0,1,,,0,1351.0,false,"",false,0,171.0,Room 113,"" +LH25040247151515,2025-04-02,Hacienda San Angel,Extranet,,ELLEN,SULLIVAN,ellenasullivan14@gmail.com,4156068231,,,,,,,,2025-04-03,2025-04-05,2,,"","",,Checked-out,"",Angels Dome - Junior Suite,Manual,684.0,1905.85,0.0,0.0,0.0,1050.85,0.0,0.0,0.0,1905.85,1905.85,2,0,0,1,,,0,0.0,false,"",false,0,171.0,Room 113,2613-1 +BDC-4941960787,2025-01-08,Hacienda San Angel,Booking.com,,Tyler,Weld,tweld.334116@guest.booking.com,+1 888 6447452,,1640 Home Road,,Great Barrington,,United States,01230,2025-04-05,2025-04-06,1,,smoking preference: Non-Smoking,"RESERVATION FROM BOOKING. COM +RATE $475.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT ENE08/25 +OK MARIANA ENE08/25",,Cancelled,2025-03-05 16:49:04,Angels Dome - Junior Suite,Angels Dome - Standard Rate,475.0,593.75,0.0,0.0,0.0,0.0,0,0.0,0.0,593.75,0,2,0,0,1,,,0,593.75,false,"",false,0,114.0,Room 113,"" +LH25013045797458,2025-01-30,Hacienda San Angel,Extranet,,Melanie / Ricardo,Conviser,melanie.conviser@gmail.com,3129273720,,,,,,,,2025-04-06,2025-04-09,3,,10% discount applied- Paula,"RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT JAN302025// +CREDIT CARD INFORMATION PENDIENT// +RATE $582 USD + TAXES // +STAY APR06-092025 // +SUITE SAN MIGUEL // +SUBMITED JAN302025NGR//",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Package Rate,1746.0,2939.17,0.0,0.0,0.0,756.67,0.0,0.0,0.0,2939.17,2939.17,2,0,0,1,,,0,0.0,false,"",false,0,436.5,Room 107,2621-1 +BDC-4635364536,2025-03-05,Hacienda San Angel,Booking.com,,Gabrielle,Sinnesberger,gsinne.478606@guest.booking.com,+1 403 710 0040,,,,,,Canada,"",2025-04-06,2025-04-08,2,,"Approximate time of arrival: between 12:00 and 13:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR04 // +RATE $465 USD + TAX // +CREDIT CARD VISA CVV PENDING // +SUITE GARDEN // +STAY ABR 06- 08 2025 // +NO PROMO // +MAR042025GV",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,930.0,1513.8,0.0,0.0,0.0,351.3,0.0,0.0,0.0,1513.8,1513.8,2,0,0,1,,,0,0.0,false,"",false,0,232.5,Room 109,2619-1 +SMP-2025032839099166,2025-03-28,Hacienda San Angel,Simple Booking,,Steven,Higgins,michael.p.ray@outlook.com,+16132204338,,,,,,Canada,"",2025-04-06,2025-04-09,3,,The guest arriving name is Steven Higgins,"RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR28 // +RATE $ 415 USD + TAX // +SUITE CROWN VIEW // +STAY ABR 02- 09 2025 // +NO PROMO // +CREDIT CARD INFORMATION OK VISA // +MAR282025GV",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,1245.0,1725.61,0.0,0.0,0.0,169.36,0.0,0.0,0.0,1725.61,1725.61,2,0,0,1,,,0,0.0,false,"",false,0,311.25,Room 112,2620-1 +SMP-2025030238466555,2025-03-02,Hacienda San Angel,Simple Booking,,James,McDaniel,jfmcd@mac.com,+52415 114 0811,,,,,,Mexico,"",2025-04-07,2025-04-10,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $392.23 + TAXES NO PROMO +NO PROMO +CREDIT CARD INFO CVV VISA PENDING +CONFIRMATION SENT MARCH02/2025 +OK MARIANA MARCH02/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1176.7,1646.62,0.0,0.0,0.0,175.74,0.0,0.0,0.0,1646.62,1646.62,2,0,0,1,,,0,0.0,false,"",false,0,294.175,Room 102,2623-1 +LH25040647242366,2025-04-06,Hacienda San Angel,Extranet,,Roxanna,Meyers,roxannam@csbsigns.com,+15054505859,,,,,,United States of America,"",2025-04-07,2025-04-10,3,,"","",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,965.0,1206.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1206.25,1206.25,2,0,0,1,,,0,0.0,false,"",false,0,241.25,Room 113,2622-1 +SMP-2025010237182639,2025-01-02,Hacienda San Angel,Simple Booking,,Frank,Weaver,raceefw@gmail.com,+1254 7443924,,,,,,,"",2025-04-08,2025-04-11,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 520 USD + TAXES // +STAY APR8-112025 // +SUITE ANGEL VIEW// +SUBMITED JAN022025NGR//",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1547.52,2835.29,0.0,0.0,0.0,900.89,0.0,0.0,0.0,2835.29,2835.29,2,0,0,1,,,0,0.0,false,"",false,0,386.88,Room 106,2625-1 +SMP-2025012737731628,2025-01-27,Hacienda San Angel,Simple Booking,,Jennifer,Grabot,grabo100@mail.chapman.edu,+19495472183,,,,,,,"",2025-04-09,2025-04-10,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE$364.90+ TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT JANUARY27/2025 +OK MARIANA ZAVALA JANUARY27/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,364.9,494.13,0.0,0.0,0.0,38.0,0.0,0.0,0.0,494.13,494.13,2,0,0,1,,,0,0.0,false,"",false,0,91.225,Room 109,2624-1 +EXP-2167027908,2025-04-01,Hacienda San Angel,Expedia,,LUKE,FAILLA,"",1 7188127892,,,,,,,,2025-04-09,2025-04-11,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 960.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $400.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SEND MARCH 31/2025 +OK MARIANA MARCH31/2025",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,800.0,1575.77,0.0,0.0,0.0,575.77,0.0,0.0,0.0,1575.77,1575.77,2,0,0,1,,,0,0.0,false,"",false,0,200.0,Room 110,2626-1 +SMP-2025012637708433,2025-01-26,Hacienda San Angel,Simple Booking,,Jennifer,Davis,jen.alaine.davis@gmail.com,16197872202,,,,,,,"",2025-04-10,2025-04-14,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE26 // +RATE $ 397.70 USD + TAXE // +CREDIT CARD INFORMATION VISA CVV PENDING // +SUITE GARDEN // +STAY APR 10- 14 2025 // +NO PROMO // +SECRET RATE // +ENE262025GV",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1590.82,2340.2,0.0,0.0,0.0,351.67,0.0,0.0,0.0,2340.2,2340.2,2,0,0,1,,,0,0.0,false,"",false,0,397.705,Room 109,2635-1 +SMP-2025022838436756,2025-02-28,Hacienda San Angel,Simple Booking,,Roxanna,Meyers,roxannam@csbsigns.com,+15054505859,,,,,,,"",2025-04-10,2025-04-11,1,,"","RESERVATION THRU SB .COM // +CONFIRMATION SENT FEB282025 // +CREDIT CARD INFORMATION PENDIENT CVV// +RATE $ 393.60 USD + TAXES // +STAY APR10-112025 // +SUITE MIL // +SUBMITED FEB282025NGR//",,Cancelled,2025-04-06 14:06:11, Milagros - Junior Suite,Milagros - Standard Rate,393.6,492.0,0.0,0.0,0.0,0.0,0,0.0,0.0,492.0,0,2,0,0,1,,,0,492.0,false,"",false,0,98.4,Room 102,"" +SMP-2025022838436809,2025-02-28,Hacienda San Angel,Simple Booking,,Roxanna,Meyers,roxannam@csbsigns.com,+15054505859,,,,,,United States of America,"",2025-04-10,2025-04-12,2,,"","RESERVATION THRU SB .COM // +CONFIRMATION SENT FEB282025 // +CREDIT CARD INFORMATION PENDIENT CVV// +RATE $ 393.60 USD + TAXES // +STAY APR10-122025 // +SUITE CV // +SUBMITED FEB282025NGR//",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,788.6,1463.47,0.0,0.0,0.0,477.72,0.0,0.0,0.0,1463.47,1463.47,2,0,0,1,,,0,0.0,false,"",false,0,197.15,Room 112,2628-1 +SMP-2025032939112663,2025-03-29,Hacienda San Angel,Simple Booking,,Dominique,Duncan-Wosik,dominique13@gmail.com,+17855507716,,,,,,,"",2025-04-10,2025-04-11,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR29 // +RATE 332.10 USD + TAX // +NO PROMO // +CREDIT CARD AMEX CVV PENDING // +SECRET RATE // +STAY ABR10-112025 // +SUITE ANGEL DOME // +MAR292025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,332.1,498.67,0.0,0.0,0.0,83.54,0.0,0.0,0.0,498.67,498.67,2,0,0,1,,,0,0.0,false,"",false,0,83.025,Room 113,"2627-1, 2627-2" +SMP-2025010537239058,2025-01-05,Hacienda San Angel,Simple Booking,,Jeanne,Davison,jeannefdavison@yahoo.com,+14356551131,,,,,,,"",2025-04-11,2025-04-13,2,,We are returning guests and are joining you for my 60th birthday (April 10) prior to my friends arriving on the 13th and us heading up to Punta Mita.,"RESERVATION FROM SIMPLE BOOKING +RATE $399.75 + TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT ENE05/25 +OK MARIANA ZAVA ENE05/25",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,793.1,1050.91,0.0,0.0,0.0,59.53,0.0,0.0,0.0,1050.91,1050.91,2,0,0,1,,,0,0.0,false,"",false,0,198.275,Room 102,2633-1 +SMP-2025013037783168,2025-01-30,Hacienda San Angel,Simple Booking,,Anne,Livingston,jalivingston@comcast.net,+12152055090,,,,,,,"",2025-04-11,2025-04-13,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE29 // +RATE $ 395.65 USD + TAXES // +NO PROMO // +SUITE ANGEL DOME // +STAY ABR 11- 13 2025 // +ENE292025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,791.3,1273.27,0.0,0.0,0.0,284.14,0.0,0.0,0.0,1273.27,1273.27,2,0,0,1,,,0,0.0,false,"",false,0,197.825,Room 113,2634-1 +BDC-4325566107,2025-02-24,Hacienda San Angel,Booking.com,,Greg,Lewis,glewis.465671@guest.booking.com,+1 561 479 8283,,,,,,United States,"",2025-04-11,2025-04-14,3,,"Viajo por trabajo y quizá utilice la tarjeta de crédito de la empresa. +Approximate time of arrival: between 14:00 and 15:00 +smoking preference: Non-Smoking","RESERVATION FROM BOOKING. COM +RATE $442.50 + TAXES +NO PROMO +CREDIT CARD INFO OK VISA +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Cancelled,2025-04-09 15:27:04,Serafin - Junior Suite,Serafin - Standard Rate,1327.5,1669.99,0.0,0.0,0.0,10.61,0.0,0.0,0.0,1669.99,1669.99,2,0,0,1,,,0,0.0,false,"",false,0,331.875,Room 110,"" +SMP-2025011937545229,2025-01-19,Hacienda San Angel,Simple Booking,,Brent,Neis,bneis17@gmail.com,+1573-1900,,,,,,,"",2025-04-12,2025-04-14,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE19 // +CREDIT CARD INFORMATION AMEX PENDING CVV // +RATE $ 414.10 USD + TAXES // +NO PROMO // +SECRET RATE // +SUITE CROWN VIEW // +STAY ABR 12- 14 2025 // +ENE192025GV",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,828.2,1035.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1035.25,1035.25,1,0,0,1,,,0,0.0,false,"",false,0,207.05,Room 112,2639-1 +EXP-2174662437,2025-04-11,Hacienda San Angel,Expedia,,Tamra,Tomlinson,mbsv2m3feh@m.expediapartnercentral.com,1 888 2545518,,,,,,,,2025-04-12,2025-04-13,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 475.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $396.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT APRIL11/25 +OK MARIANA APRIL11/25",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,396.0,495.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,495.0,495.0,2,0,0,1,,,0,0.0,false,"",false,0,99.0,Room 119,2631-1 +EXP-2174664612,2025-04-11,Hacienda San Angel,Expedia,,Morgan,Smith,a8mjyvotqq@m.expediapartnercentral.com,1 5125458584,,,,,,,,2025-04-12,2025-04-13,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 345.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $288.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO +CONFIRMATION SENT APRIL11/25 +OK MARIANA APRIL11/25",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,288.0,360.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,360.0,360.0,1,0,0,1,,,0,0.0,false,"",false,0,72.0,Room 110,2632-1 +BDC-4719582906,2025-04-12,Hacienda San Angel,Booking.com,,Brooke,Conaway,bconaw.201509@guest.booking.com,+1 713 876 7943,,,,.,,United States,"",2025-04-12,2025-04-13,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-04-12., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT APR122025// +CREDIT CARD INFORMATION OK// +RATE $375 USD + TAXES // +STAY APR12-132025 // +SUITE SAN GABRIEL // +SUBMITEDABR122025NGR //",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,375.0,690.04,0.0,0.0,0.0,221.29,0.0,0.0,0.0,690.04,690.04,2,0,0,1,,,0,0.0,false,"",false,0,93.75,Room 118,"2630-1, 2630-2" +EXP-2175454853,2025-04-12,Hacienda San Angel,Expedia,,Tamra,Tomlinson,myj4xvejru@m.expediapartnercentral.com,1 888 2545518,,,,,,,,2025-04-13,2025-04-14,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 480.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA .COM // +CONFIRMATION SENT APR122025 // +CREDIT CARD INFORMATION OK // +RATE $ 400.50 USD + TAXES // +STAY ABRI13-142025 // +SUITE RINCÓN OF ANGELS // +SUBMITED APR122025NGR //",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,400.5,557.63,0.0,0.0,0.0,57.0,0.0,0.0,0.0,557.63,557.63,2,0,0,1,,,0,0.0,false,"",false,0,100.125,Room 119,2637-1 +EXP-2175620898,2025-04-13,Hacienda San Angel,Expedia,,Morgan,Smith,v7d3y2q92w@m.expediapartnercentral.com,1 5125458584,,,,,,,,2025-04-13,2025-04-14,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 324.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR122025 // +CREDIT CARD INFORMATION OK // +RATE $ 270 USD + TAXES // +STAY APR13-142025 // +SUITE SERAFIN // +SUBMITED APR122025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,270.0,337.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,337.5,337.5,1,0,0,1,,,0,0.0,false,"",false,0,67.5,Room 110,2636-1 +SMP-2025030238470949,2025-03-02,Hacienda San Angel,Simple Booking,,Kyle,Peterson,kspeterson@gmail.com,+12158708845,,,,,,,"",2025-04-14,2025-04-17,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $474.23 USD + TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT MARCH02/2025 +OK MARIANA MARCH02/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1422.7,2262.32,0.0,0.0,0.0,483.94,0.0,0.0,0.0,2262.32,2262.32,2,0,0,1,,,0,0.0,false,"",false,0,355.675,Room 106,2643-1 +SMP-2025021838212890,2025-02-18,Hacienda San Angel,Simple Booking,,Connie,Anderson,aconnie03@gmail.com,+14804686535,,,,,,,"",2025-04-15,2025-04-17,2,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB182025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $582.205 USD + TAXES // +STAY APR15-172025 // +SUITE SAN MIGUEL // +SUBMITED FEB182025NGR//",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1164.41,2166.65,0.0,0.0,0.0,711.14,0.0,0.0,0.0,2166.65,2166.65,2,0,0,1,,,0,0.0,false,"",false,0,291.1025,Room 107,"2640-1, 2640-2" +LH25022646380510,2025-02-26,Hacienda San Angel,Extranet,,Mike,Babcock,miketbabcock@gmail.com,"",,,,,,,,2025-04-15,2025-04-17,2,,"","Firefighter co worker of Laura's. + +Angel's Rate for the room. + +50% discount on all food and beverages- Paula",,Checked-out,"",Crown View - Junior Suite,Manual,935.0,113.26,0.0,0.0,0.0,113.26,0.0,0.0,0.0,113.26,113.26,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 112,2644-1 +LH25032146890639,2025-03-21,Hacienda San Angel,Extranet,,Butch,De La Cruz,butchvd@hotmail.com,"",,,,,,,,2025-04-15,2025-04-18,3,,"","Flight Angel taking dogs to homes. Moves to Milagros on the 18th + +$75 is for staff 7%- nothing for me + +20% discount on food and beverage- Paula",,Checked-out,"",Angels Dome - Junior Suite,Manual,75.0,75.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,75.0,75.0,1,0,0,1,,,0,0.0,false,"",false,0,18.75,Room 113,2647-1 +BDC-4408676173,2025-03-31,Hacienda San Angel,Booking.com,,Kristine,Olson,kolson.392896@guest.booking.com,+1 847 687 4805,,,,,,United States,"",2025-04-15,2025-04-16,1,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $450.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT MARCH31/25 +OK MARIANA MARCH31/25",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,450.0,863.51,0.0,0.0,0.0,301.01,0.0,0.0,0.0,863.51,863.51,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 109,2642-1 +SMP-2025010437220704,2025-01-04,Hacienda San Angel,Simple Booking,,Chad,Cooper,Coop_20007@yahoo.com,+19495335380,,,,,,,"",2025-04-16,2025-04-17,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN042025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 500.20 USD + TAXES // +STAY 16-17APR2025 // +SUITE SAN MIGUEL// +SUBMITED JAN042025NGR//",,Cancelled,2025-01-10 16:41:02, San Miguel - Presidential Suite,San Miguel - Standard Rate,496.2,620.25,0.0,0.0,0.0,0.0,0,0.0,0.0,620.25,0,2,0,0,1,,,0,620.25,false,"",false,0,120.048,Room 107,"" +EXP-X-423790739,2025-03-02,Hacienda San Angel,Expedia,,lana,janes,qgr82aqd1j@m.expediapartnercentral.com,1 778 9556441,,,,,,,,2025-04-16,2025-04-22,6,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXP // +CONFIRMATION SENT FEB 02 // +RATE $ 441 USD + TAX // +NO PROMO // +CREDIT CARD VISA OK // +BLUE DISCOUNT 10% EXP // +SUITE MILAGROS // +STAY ABR 16- 22 2025 // +FEB022025GV",,Cancelled,2025-03-16 10:22:25, Milagros - Junior Suite,Milagros - Standard Rate,2646.0,3307.5,0.0,0.0,0.0,0.0,0,0.0,0.0,3307.5,0,2,0,0,1,,,0,3307.5,false,"",false,0,661.5,Room 102,"" +EXP-2174865345,2025-04-11,Hacienda San Angel,Expedia,,anushree,gupta,syv5s5fq9w@m.expediapartnercentral.com,0 0 6502766090,,,,,,,,2025-04-16,2025-04-18,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 811.68, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA .COM // +CONFIRMATION SENT APR112025 // +CREDIT CARD INFORMATION OK // +RATE $ 338.20 USD + TAXES // +STAY APR16-182025 // +SUITE SERAFIN // +SUBMITED APR112025NGR//",,Cancelled,2025-04-12 10:07:55,Serafin - Junior Suite,Serafin - Standard Rate,676.4,845.5,0.0,0.0,0.0,0.0,0,0.0,0.0,845.5,0,2,0,0,1,,,0,845.5,false,"",false,0,169.1,Room 110,"" +BDC-4664593703,2025-04-15,Hacienda San Angel,Booking.com,,Anushree,Gupta,agupta.683388@guest.booking.com,+1 650 276 6090,,,,.,,United States,"",2025-04-16,2025-04-18,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-04-14., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $288.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL 14/25 +OK MARIANA APRIL14/25",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,576.0,920.6,0.0,0.0,0.0,200.6,0.0,0.0,0.0,920.6,920.6,2,0,0,1,,,0,0.0,false,"",false,0,144.0,Room 110,2646-1 +EXP-X-388070222,2025-01-03,Hacienda San Angel,Expedia,,Penelope,Fain,j1mgk5w8bf@m.expediapartnercentral.com,1 0 5038103613,,,,,,,,2025-04-17,2025-04-21,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.",,,Cancelled,2025-01-02 23:48:29, Angels View - Master Suite,Angels View - Standard Rate,2025.0,2511.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2511.0,0,2,0,0,1,,,0,2511.0,false,"",false,0,486.0,Room 106,"" +EXP-X-388077089,2025-01-03,Hacienda San Angel,Expedia,,Penelope,Fain,lvtj566adk@m.expediapartnercentral.com,1 0 5038103613,,,,,,,,2025-04-17,2025-04-22,5,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION FROM EXPEDIA +RATE $546.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT DEC03/2024 +OK MARIANA DEC03/2024",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,2457.0,3496.21,0.0,0.0,0.0,424.96,0.0,0.0,0.0,3496.21,3496.21,2,0,0,1,,,0,0.0,false,"",false,0,614.25,Room 106,2663-1 +EXP-2178157720,2025-04-16,Hacienda San Angel,Expedia,,Maurice,St. Denis,lcoiflcorr@m.expediapartnercentral.com,1 780 9744038,,,,,,,,2025-04-17,2025-04-18,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 367.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT ABR16 // +RATE $ 306 USD + TAX // +BLUE PROMO EXP 10% DISCOUNT // +SUITE SAN GABRIEL // +STAY ABR 17- 18 2025 // +CREDIT CARD INFORMATION OK // +VIRTUAL CARD FOR CHARGE // +ABR162025GV",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,306.0,401.5,0.0,0.0,0.0,19.0,0.0,0.0,0.0,401.5,401.5,2,0,0,1,,,0,0.0,false,"",false,0,76.5,Room 118,2648-1 +BDC-4361107258,2025-02-27,Hacienda San Angel,Booking.com,,KARL,RUHL,kruhl.377503@guest.booking.com,+61 18553557625,,641 W Lake Street Suite 102,,Chicago,,Australia,60611,2025-04-18,2025-04-21,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-04-16., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING.COM +RATE $500.00 + TAXES +NO PROMO +CREDIT CARD MC CVV OK +CONFIRMATION SENT FEB27/2025 +OK MARIANA FEB27/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1500.0,2204.72,0.0,0.0,0.0,329.72,0.0,0.0,0.0,2204.72,2204.72,2,0,0,1,,,0,0.0,false,"",false,0,375.0,Room 109,"2659-1, 2659-2" +EXP-2153974903,2025-03-12,Hacienda San Angel,Expedia,,Heather,Perry,pd4svjqr1k@m.expediapartnercentral.com,1 0 3033594579,,,,,,,,2025-04-18,2025-04-19,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 528.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIPPREM.COM // +CONFIRMATION SENT MAR122025 // +CREDIT CARD INFORMATION OK// +RATE $ 440 USD + TAXES // +STAY APRIL18-192025 // +SUITE SERAFIN // +SUBMITED MAR122025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,440.0,851.78,0.0,0.0,0.0,301.78,0.0,0.0,0.0,851.78,851.78,2,0,0,1,,,0,0.0,false,"",false,0,110.0,Room 110,"2645-1, 2645-2" +LH25032146890693,2025-03-21,Hacienda San Angel,Extranet,,Butch,De La Cruz,butchvd@hotmail.com,"",,,,,,,,2025-04-18,2025-04-20,2,,"","Flight Angel taking dogs to homes. Moved from Angel's Dome on the 18th + +$50 is for staff 7%- nothing for me + +20% discount on food and beverage- Paula",,Checked-out,"", Milagros - Junior Suite,Manual,50.0,100.0,0.0,0.0,0.0,50.0,0.0,0.0,0.0,100.0,100.0,1,0,0,1,,,0,0.0,false,"",false,0,12.5,Room 102,2653-1 +SMP-2025032639053267,2025-03-26,Hacienda San Angel,Simple Booking,,Alison,Young,alisonyoungdesign@yahoo.com,+1512-771-0921,,,,,,,"",2025-04-18,2025-04-20,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $540.00 + TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT MARCH26/2025 +OK MARIANA MARCH26/2025",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1080.0,1741.53,0.0,0.0,0.0,391.53,0.0,0.0,0.0,1741.53,1741.53,2,0,0,1,,,0,0.0,false,"",false,0,270.0,Room 118,2652-1 +EXP-2175781736,2025-04-13,Hacienda San Angel,Expedia,,RYAN,BURNS,wl6rw76h0m@m.expediapartnercentral.com,86 18514039908,,,,,,,,2025-04-18,2025-04-20,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, AdditionalNotes: None, Remittance amount: 912.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA .COM // +CONFIRMATION SENT APR132025 // +CREDIT CARD INFORMATION OK // +RATE $ 380.25 USD + TAXES // +STAY APR18-202025 // +SUITE ANGEL DOME // +SUBMITED APR132025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,760.5,1088.64,0.0,0.0,0.0,138.01,0.0,0.0,0.0,1088.64,1088.64,2,0,0,1,,,0,0.0,false,"",false,0,190.125,Room 113,2656-1 +LH25041747489910,2025-04-17,Hacienda San Angel,Extranet,,Mike,Babcock,"","",,,,,,,,2025-04-18,2025-04-19,1,,"",50% discount on food and beverage- Paula,,Checked-out,"", Rincon de Angeles - Royal Suite,Manual,350.0,387.37,0.0,0.0,0.0,37.37,0.0,0.0,0.0,387.37,387.37,2,0,0,1,,,0,0.0,false,"",false,0,87.5,Room 119,2651-1 +LH25011045372462,2025-01-10,Hacienda San Angel,Extranet,,CHAD,COOPER,coop_20007@yahoo.com,9495335380,,,,,,,,2025-04-19,2025-04-20,1,,"","RESERVATION DIRECTLY +ANGEL'S RATE +CREDIT CRAD INFO OK +CONFIRMATION SENT ENE10/25 +OK MARIANA ENE10/25",,Cancelled,2025-02-15 21:49:53, San Miguel - Presidential Suite,San Miguel - Standard Rate,775.0,775.0,0.0,0.0,0.0,0.0,0,0.0,0.0,775.0,0,2,0,0,1,,,0,775.0,false,"",false,0,193.75,Room 107,"" +LH25040947309959,2025-04-09,Hacienda San Angel,Extranet,,Darcie,Imbert,imbertdarcie@gmail.com,"",,,,,,,,2025-04-19,2025-04-21,2,,"","Complimentary for a Condé Nast Traveler journalist + +No charge for food or beverage. No limited menu- she can have anything she wants of the standard menus + +Inform Miguel to pay $84 usd from hotel for the 7% for staff commission + +Journalist will be writing a review in the publication- Paula",,Checked-out,"", San Miguel - Presidential Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,2661-1 +BDC-4561653771,2025-04-19,Hacienda San Angel,Booking.com,,Gea,Carr,gcarr.209660@guest.booking.com,+1 408 218 4581,,,,,,United States,"",2025-04-19,2025-04-21,2,,smoking preference: Non-Smoking,"RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT APR192025 // +CREDIT CARD INFORMATION OK // +RATE $ 340 USD + TAXES // +STAY APR19-212025 // +SUITE CROWN VIEW & SERAFIN// +SUBMITED APR192025NGR//",,Checked-out,"","Crown View - Junior Suite,Serafin - Junior Suite","Crown View - Standard Rate,Serafin - Standard Rate",1360.0,2217.11,0.0,0.0,0.0,517.11,0.0,0.0,0.0,2217.11,2217.11,3,0,0,2,,,0,0.0,false,"",false,0,340.0,"Room 112, Room 110",2660-1 +SMP-2025032438995909,2025-03-24,Hacienda San Angel,Simple Booking,,Colleen,Clausen,smallclaus@gmail.com,+17735774289,,,,,,,"",2025-04-20,2025-04-25,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE 365.72 + TAXES +SECRET RATE +VISA CREDIT CARD CVV PENDING +CONFIRMATION SENT MARCH24/2025 +OK MARIANA MARCH24/2025",,Cancelled,2025-04-13 08:00:42,Crown View - Junior Suite,Crown View - Standard Rate,1828.6,2285.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2285.75,0,2,0,0,1,,,0,2285.75,false,"",false,0,457.15,Room 112,"" +BDC-4407901159,2025-04-06,Hacienda San Angel,Booking.com,,Katya,Belter,kbelte.820337@guest.booking.com,+1 781 996 9917,,,,.,,United States,"",2025-04-20,2025-04-24,4,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT APR052025 // +CREDIT CARD INFORMATION OK // +RATE $ 385.76 USD + TAXES // +STAY APR20-242025 // +SUITE MILAGROS // +SUBMITED APR052025NGR//",,Cancelled,2025-04-17 18:08:39, Milagros - Junior Suite,Milagros - Standard Rate,1543.05,1928.81,0.0,0.0,0.0,0.0,0,0.0,0.0,1928.81,0,2,0,0,1,,,0,1928.81,false,"",false,0,385.7625,Room 102,"" +LH25041747489053,2025-04-17,Hacienda San Angel,Extranet,,John,Fudela,jgfudeka@gmail.com,17819969917,,,,,,,,2025-04-20,2025-04-21,1,,"","DIRECT RESERVATION // +CONFIRMATION SENT ABR 17 // +RATE $ 296.22 USD + TAXES // +OK CREDIT CARD AMEX OK // +SUITE MILAGROS // +STAY ABR 20- 24 2025 // +ABR172025GV + + +THIS GUEST MOVED TO SM OK MZR",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,340.0,1481.13,0.0,0.0,0.0,1132.63,0.0,0.0,0.0,1481.13,1481.13,2,0,0,1,,,0,0.0,false,"",false,0,69.7,Room 102,2662-1 +LH25042047541268,2025-04-20,Hacienda San Angel,Extranet,,NO SOPHEA,SOPHEA,"",491709625126,,,,,,,,2025-04-20,2025-04-22,2,,"","RESERVATION THRU DIRECTA.COM // +CONFIRMATION SENT APR202025 // +CREDIT CARD INFORMATION OK// +RATE $ 440 USD + TAXES // +STAY APR20-222025 // +SUITE RINCÓN // +SUBMITED APR202025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,880.0,1304.36,0.0,0.0,0.0,204.36,0.0,0.0,0.0,1304.36,1304.36,2,0,0,1,,,0,0.0,false,"",false,0,220.0,Room 119,"2658-1, 2658-2" +LH25042147558954,2025-04-21,Hacienda San Angel,Extranet,,Suzanne Elizabeth,Martin,info@haciendasanangel.com,8623308474,,,,,,,,2025-04-21,2025-04-23,2,,"","",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,605.0,1157.1,0.0,0.0,0.0,400.85,0.0,0.0,0.0,1157.1,1157.1,2,0,0,1,,,0,0.0,false,"",false,0,151.25,Room 110,"2664-1, 2664-2" +LH25042147559934,2025-04-21,Hacienda San Angel,Extranet,,JOHN,FUDALA,"","",,,,,,,,2025-04-21,2025-04-24,3,,"",THE PAYMENT OF THIS RESERVATION IS AT MILAGROS ( APRIL 20// MOVES APRIL21ST) OK MZR,,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1445.0,226.87,0.0,0.0,0.0,226.87,0.0,0.0,0.0,226.87,226.87,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,2667-1 +LH25020645958631,2025-02-06,Hacienda San Angel,Extranet,,Debbie,Duhnam,"","",,,,,,,,2025-04-22,2025-04-26,4,,"","Yoga Retreat Participant- 1 of 6 +This 4 night reservation price includes: + +Airport Transportation + +1 massage + +4 Continental Breakfasts +4 Breakfasts from group menu for Yoga Retreat +2 Lunches from group menu for Yoga Retreat +3 Dinners from group menu for Yoga Retreat + +Alcohol NOT included",,Checked-out,"", Angels View - Master Suite,Manual,1827.2,2401.58,0.0,0.0,0.0,117.58,0.0,0.0,0.0,2401.58,2401.58,1,0,0,1,,,0,0.0,false,"",false,0,456.8,Room 106,2670-1 +LH25020645958737,2025-02-06,Hacienda San Angel,Extranet,,Wendi,Lawson,"","",,,,,,,,2025-04-22,2025-04-26,4,,"","Yoga Retreat Participant- 1 of 6 +This 4 night reservation price includes: + +Airport Transportation + +1 massage + +4 Continental Breakfasts +4 Breakfasts from group menu for Yoga Retreat +2 Lunches from group menu for Yoga Retreat +3 Dinners from group menu for Yoga Retreat + +Alcohol NOT included",,Checked-out,"", San Jose - Master Suite,Manual,1827.2,2429.23,0.0,0.0,0.0,145.23,0.0,0.0,0.0,2429.23,2429.23,1,0,0,1,,,0,0.0,false,"",false,0,456.8,Room 122,2673-1 +LH25020645958746,2025-02-06,Hacienda San Angel,Extranet,,Joanna,Cox,"","",,,,,,,,2025-04-22,2025-04-26,4,,"","Yoga Retreat Participant- 1 of 6 +This 4 night reservation price includes: + +Airport Transportation + +1 massage + +4 Continental Breakfasts +4 Breakfasts from group menu for Yoga Retreat +2 Lunches from group menu for Yoga Retreat +3 Dinners from group menu for Yoga Retreat + +Alcohol NOT included",,Checked-out,"", Vista de Santos - Master Suite,Manual,1827.2,2304.83,0.0,0.0,0.0,20.83,0.0,0.0,0.0,2304.83,2304.83,1,0,0,1,,,0,0.0,false,"",false,0,456.8,Room 121,2671-1 +LH25020645958772,2025-02-06,Hacienda San Angel,Extranet,,Shauna,Gray,"","",,,,,,,,2025-04-22,2025-04-26,4,,"","Yoga Retreat Participant- 1 of 6 +This 4 night reservation price includes: + +Airport Transportation + +1 massage + +4 Continental Breakfasts +4 Breakfasts from group menu for Yoga Retreat +2 Lunches from group menu for Yoga Retreat +3 Dinners from group menu for Yoga Retreat + +Alcohol NOT included",,Checked-out,"", Rincon de Angeles - Royal Suite,Manual,2025.6,2757.36,0.0,0.0,0.0,225.36,0.0,0.0,0.0,2757.36,2757.36,1,0,0,1,,,0,0.0,false,"",false,0,506.4,Room 119,2669-1 +LH25030346487160,2025-03-03,Hacienda San Angel,Extranet,,Carla,Barnes,"","",,,,,,,,2025-04-22,2025-04-26,4,,"","Yoga Retreat Participant- 1 of 6 +This 4 night reservation price includes: + +Airport Transportation + +1 massage + +4 Continental Breakfasts +4 Breakfasts from group menu for Yoga Retreat +2 Lunches from group menu for Yoga Retreat +3 Dinners from group menu for Yoga Retreat + +Alcohol NOT included",,Checked-out,"", Garden of Angels - Junior Suite,Manual,1628.8,2052.67,0.0,0.0,0.0,16.67,0.0,0.0,0.0,2052.67,2052.67,1,0,0,1,,,0,0.0,false,"",false,0,407.2,Room 109,2672-1 +LH25030346487437,2025-03-03,Hacienda San Angel,Extranet,,Lori,Washko,"","",,,,,,,,2025-04-22,2025-04-26,4,,"","Yoga Retreat LEADER +This 4 night reservation price includes: + +Airport Transportation + +1 massage + +4 Continental Breakfasts +4 Breakfasts from group menu for Yoga Retreat +2 Lunches from group menu for Yoga Retreat +3 Dinners from group menu for Yoga Retreat + +Alcohol NOT included",,Checked-out,"", San Gabriel - Junior Suite,Manual,1500.0,1940.38,0.0,0.0,0.0,65.38,0.0,0.0,0.0,1940.38,1940.38,1,0,0,1,,,0,0.0,false,"",false,0,375.0,Room 118,2674-1 +BDC-4884806384,2025-03-31,Hacienda San Angel,Booking.com,,Gilles,Pariseau,gparis.858470@guest.booking.com,+1 900 2049998823,,,,,,United States,"",2025-04-22,2025-04-23,1,,"Approximate time of arrival: between 15:00 and 16:00 +Hi...Just Curious...How far up the hill are the accommodations from the Malecon? Are the a lot of stairs? +Thank you, +Gilles, booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-03-30 22:20:50,Serafin - Junior Suite,Serafin - Standard Rate,427.5,534.38,0.0,0.0,0.0,0.0,0,0.0,0.0,534.38,0,1,0,0,1,,,0,534.38,false,"",false,0,106.875,Room 110,"" +BDC-4611168149,2025-04-01,Hacienda San Angel,Booking.com,,Regina,Maschler,rmasch.578553@guest.booking.com,+33787060116,,,,.,,United Kingdom,"",2025-04-23,2025-04-26,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FORM BOOKING.COM // +CONFIRMATION SENT ABR 01 // +RATE $ 392.85 USD + TAX // +CREDIT CARD INFO OK VISA // +SUITE SERAFIN // +STAY ABR 23- 25 2025 // +GENIUS DISCOUNT 10% // +ABR012025GV //",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,1178.55,1669.79,0.0,0.0,0.0,196.6,0.0,0.0,0.0,1669.79,1669.79,1,0,0,1,,,0,0.0,false,"",false,0,294.6375,Room 110,2676-1 +BDC-4540765757,2025-04-10,Hacienda San Angel,Booking.com,,LAURA LINDA BARBARA,NEGRE,lnegre.323010@guest.booking.com,+1 347 685 3663,,,,,,United States,"",2025-04-23,2025-04-24,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-04-21. +Approximate time of arrival: between 19:00 and 20:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATIONS FROM BOOKING +RATE $387.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT APRIL10/25 +OK MARIANA APRIL10/25",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,387.0,529.92,0.0,0.0,0.0,46.17,0.0,0.0,0.0,529.92,529.92,2,0,0,1,,,0,0.0,false,"",false,0,96.75,Room 113,2666-1 +SMP-2025041739541893,2025-04-17,Hacienda San Angel,Simple Booking,,Grace,Benson,gracepostbenson@gmail.com,3108504366,,,,,,,"",2025-04-23,2025-04-24,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR172025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 425 USD + TAXES // +STAY ABR23-242025 // +SUITE CROWN VIEW // +SUBMITED APR172025NGR//",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,425.0,559.55,0.0,0.0,0.0,28.3,0.0,0.0,0.0,559.55,559.55,2,0,0,1,,,0,0.0,false,"",false,0,106.25,Room 112,2665-1 +SMP-2025040239216029,2025-04-02,Hacienda San Angel,Simple Booking,,Kip,Cashmore,Kipcashmore@gmail.com,+18015403030,,,,,,,"",2025-04-24,2025-04-27,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 401.80 USD + TAXES // +STAY APR24-272025 // +SUITE ANGEL DOME // +SUBMITED APR2025NGR// + + +8015401550 contact guest",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1205.4,2289.04,0.0,0.0,0.0,782.29,0.0,0.0,0.0,2289.04,2289.04,2,0,0,1,,,0,0.0,false,"",false,0,301.35,Room 113,2679-1 +SMP-2025032639055004,2025-03-26,Hacienda San Angel,Simple Booking,,Robert,Arkin,Arkinlaw@yahoo.com,310-968-3630,,,,,,,"",2025-04-25,2025-04-28,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAR262025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $399.75 USD + TAXES // +STAY APR24-262025// +SUITE MILAGROS // +SUBMITED MAR262025NGR//",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1144.1,1837.44,0.0,0.0,0.0,407.31,0.0,0.0,0.0,1837.44,1837.44,2,0,0,1,,,0,0.0,false,"",false,0,286.025,Room 102,2680-1 +EXP-2165581621,2025-03-30,Hacienda San Angel,Expedia,,Dave,McCormick,r1yjscx3px@m.expediapartnercentral.com,1 253 2555847,,,,,,,,2025-04-25,2025-04-26,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 495.36, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA PREMIUM VIP +RATE $4412.80 + TAXES +$85.00 USD CREDIT ON FOOD & BEVERAGE // BOTTLE OR UPGRADE +CREDIT CARD INFO OK +CONFIRMATION SENT MARCH29/2025 +OK MARIANA MARCH29/2025",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,412.8,500.67,0.0,0.0,0.0,-15.33,0.0,0.0,0.0,500.67,516.0,2,0,0,1,,,0,-15.33,false,"",false,0,103.2,Room 112,"2668-1, 2668-2" +BDC-4796537716,2025-01-13,Hacienda San Angel,Booking.com,,Mary Jo,Stansbury,mstans.818425@guest.booking.com,+1 206 948 8377,,,,,,United States,"",2025-04-26,2025-04-30,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-04-24. +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT // +RATE $ 323.19 USD + TAXES // +NO PROMO // +SUITE VISTA DE SANTOS // +STAY ABR 26- 30 2025 // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +ENE122024GV",,Cancelled,2025-04-23 00:03:02, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1790.0,2233.92,0.0,0.0,0.0,-3.58,0,0.0,0.0,2233.92,0,2,0,0,1,,,0,2233.92,false,"",false,0,447.5,Room 121,"" +BDC-4680408892,2025-03-22,Hacienda San Angel,Booking.com,,Paula,Dukehart,pdukeh.856346@guest.booking.com,+1 703 216 7886,,,,.,,United States,"",2025-04-26,2025-05-01,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-04-24., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING-COM // +CONFIRMATION SENT MAR22 // +GENIUS DOSCOUNT 10% // +RATE $ 304.56 USD + TAX // +NO PROMO // +SUITE GARDEN OF ANGELS // +STAY ABR26-MAY012025 // +MAR222025GV",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1522.8,2314.53,0.0,0.0,0.0,411.03,0.0,0.0,0.0,2314.53,2314.53,2,0,0,1,,,0,0.0,false,"",false,0,380.7,Room 109,2689-1 +EXP-2164147819,2025-03-27,Hacienda San Angel,Expedia,,Dave,McCormick,47ue0bfcfp@m.expediapartnercentral.com,1 2532555847,,,,,,,,2025-04-26,2025-04-28,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 954.60, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT MAR27 // +CREDIT CARD OK VIRTUAL CARD FOR CHARGE // +RATE $397.75 UAS + TAX // +PROMOTION GOLD DISC 10% EXP // +RSVA EXP VIP PREMIUM // +SUITE CELESTIAL // +STAY ABR 26- 28 225 // +MAR272025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,795.5,1177.65,0.0,0.0,0.0,183.27,0.0,0.0,0.0,1177.65,1177.65,2,0,0,1,,,0,0.0,false,"",false,0,198.875,Room 103,2682-1 +SMP-2025032939118664,2025-03-29,Hacienda San Angel,Simple Booking,,Tracy,Loveridge,rhymingtracy@shaw.ca,+1780-906-3161,,,,,,Canada,T6C 1G2,2025-04-26,2025-05-03,7,,"20% discount on room, food and beverages. Tracy is a former flight angel.-Paula ok'd (note made by Natasha) + +CVV 374- Tracy gave me her zip code and postal code over Facebook.- Natasha","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR29 // +NO PORMO // +RATE $ 405 USD + TAX // +CREDIT CARD MASTER CARD CVV PENDING // +SUITE SANGABRIEL // +STAY ABR26- MAY 03 2025 // +MAR292025GV",,Cancelled,2025-03-31 21:43:06, San Gabriel - Junior Suite,San Gabriel - Standard Rate,2835.0,2835.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2835.0,0,2,0,0,1,,,0,2835.0,false,"",false,0,567.0,Room 118,"" +LH25033047088878,2025-03-30,Hacienda San Angel,Extranet,,Nathaniel,Doyno,n.doyno@gmail.com,5189655259,,,,,,,,2025-04-26,2025-04-29,3,,"","",,Checked-out,"", San Jose - Master Suite,Manual,1545.0,2350.19,0.0,0.0,0.0,418.94,0.0,0.0,0.0,2350.19,2350.19,2,0,0,1,,,0,0.0,false,"",false,0,386.25,Room 122,2683-1 +EXP-2179085806,2025-04-18,Hacienda San Angel,Expedia,,Minh,Dang,kquu9cxspd@m.expediapartnercentral.com,44 2080160509,,,,,,,,2025-04-26,2025-04-27,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 453.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT ABR 17 // +RATE $ 378 USD + TAXES // +VIRTUAL CARD FOR CHARGE // +SUITE CROWN VIEW // +STAY ABR 26- 27 2025 // +BLUE PORMO 10% DOSCOUNT // +ABR172025GV",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,378.0,652.42,0.0,0.0,0.0,179.92,0.0,0.0,0.0,652.42,652.42,2,0,0,1,,,0,0.0,false,"",false,0,94.5,Room 106,"2677-1, 2677-2" +LH25042347602134,2025-04-23,Hacienda San Angel,Extranet,,Mary Jo,Stansbury,maryjo@estansbury.com,+1 206 948 8377,,,,,,United States,"",2025-04-26,2025-04-30,4,,"","DIRECT RESERVATION // +CONFIRMATION SENT ABR23 // +RATE $425 USD + TAX // +NO PROMO // +CREDIT CARR VISA OK // +STAY ABR 26- 30 2025 // +SUITE VISTA DE SANTOS // +ABR232025GV",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1700.0,2649.56,0.0,0.0,0.0,524.56,0.0,0.0,0.0,2649.56,2649.56,2,0,0,1,,,0,0.0,false,"",false,0,425.0,Room 121,2684-1 +LH25042447628221,2025-04-24,Hacienda San Angel,Extranet,,Adam and Ashley,Carvajal,deslauriersashley@yahoo.com,"",,,,,,,,2025-04-26,2025-05-03,7,,"","Adam & Ashley and baby in the womb- + +COMPLEMENTARY SUITE",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,2485.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 110,2695-1 +SMP-2025030338476486,2025-03-03,Hacienda San Angel,Simple Booking,,Akshay,Nair,aksnair@gmail.com,+16504996256,,,,,,,"",2025-04-27,2025-04-30,3,,"","RESERVATION FROM SIMPLEBOOKINFG // +CONFIRMATION SENT FEB 03 // +RATE $ 436.67 USD + TAX // +NO PROMO // +CREDIT CARD INFO AMEX CVV // +SUITE ANGEL VIEW // +STAY ABR 27- 30 2025 // +MAR032025GV",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1310.0,1729.83,0.0,0.0,0.0,92.33,0.0,0.0,0.0,1729.83,1729.83,2,0,0,1,,,0,0.0,false,"",false,0,327.5,Room 106,"2685-1, 2685-2" +EXP-2183839719,2025-04-24,Hacienda San Angel,Expedia,,Douglas,Murdoch,blairmurdoch43@gmail.com,0 0 6044884747,,,,,,,,2025-04-27,2025-04-28,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 383.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $319.50 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL25/25 +OK MARIANA ZAVALA APRIL25/25",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,319.5,632.66,0.0,0.0,0.0,233.28,0.0,0.0,0.0,632.66,632.66,2,0,0,1,,,0,0.0,false,"",false,0,79.875,Room 112,2681-1 +SMP-2025022538346922,2025-02-25,Hacienda San Angel,Simple Booking,,Robert,Purtock,rpurtock@wi.rr.com,+14145813102,,,,,,,"",2025-04-28,2025-05-01,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $445.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV OK +CONFIRMATION SENT FEB24/2025 +OK MARIANA FEB24/2025",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1335.0,2239.13,0.0,0.0,0.0,570.38,0.0,0.0,0.0,2239.13,2239.13,2,0,0,1,,,0,0.0,false,"",false,0,333.75,Room 119,2688-1 +SMP-2025033039122154,2025-03-30,Hacienda San Angel,Simple Booking,,Lindsey,Johnson,lmross9@gmail.com,+17736004466,,,,,,,"",2025-04-28,2025-05-01,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $395.00 USD +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MARCH29/25 +OK MARIANA MARCH29/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1185.0,1918.16,0.0,0.0,0.0,436.91,0.0,0.0,0.0,1918.16,1918.16,2,0,0,1,,,0,0.0,false,"",false,0,296.25,Room 102,2691-1 +EXP-2185689563,2025-04-27,Hacienda San Angel,Expedia,,Leonardo,Ricagni,leonardoricagni@gmail.com,1 917 2250141,,,,,,,,2025-04-28,2025-04-30,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 726.24, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA +RATE $302.60 + TAXES +$85. 00 USD OF CREDIT ON FOOD & BEVERAGE +VIRTUAL CREDIT CARD INFO +CONFIRMATION SENT APRIL27/25 +OK MARIANA APRIL27/25",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,605.2,805.9,0.0,0.0,0.0,49.4,0.0,0.0,0.0,805.9,805.9,2,0,0,1,,,0,0.0,false,"",false,0,151.3,Room 112,2686-1 +EXP-X-407319788,2025-02-02,Hacienda San Angel,Expedia,,Stephanie,Schrader,"",1 5309066576,,,,,,,,2025-04-29,2025-05-03,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,549.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT FEB022025// +CREDIT CARD INFORMATION OK// +RATE $ 322.87 USD + TAXES // +STAY ABR29-MAY032025 // +SUITE CROWN VIEW// +SUBMITED FEB022025NGR//",,Cancelled,2025-02-22 19:58:02,Crown View - Junior Suite,Crown View - Standard Rate,1291.5,1614.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1614.38,0,1,0,0,1,,,0,1614.38,false,"",false,0,322.875,Room 112,"" +EXP-X-407983728,2025-02-03,Hacienda San Angel,Expedia,,Raymond,Martinez,xeh47kfgn8@m.expediapartnercentral.com,1 210 2649839,,,,,,,,2025-04-29,2025-05-03,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,898.88, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $395.60 + TAXES +$85.00 usd food & beverage// bottle or upgrade +CREDIT CARD INFO +CONFIRMATION SENT FEB 03/2025 +OK MARIANA ZAVALA FEB 03/2025",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1582.4,2177.3,0.0,0.0,0.0,199.3,0.0,0.0,0.0,2177.3,2177.3,2,0,0,1,,,0,0.0,false,"",false,0,395.6,Room 122,2694-1 +SMP-2025022838435203,2025-02-28,Hacienda San Angel,Simple Booking,,Greg,Young,gregryoung44@gmail.com,+19012182381,,,,,,,"",2025-04-29,2025-05-01,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMNATION SENT FEB28 // +RATE $ 373.10 USD + TAX // +CREDIT CARD INFORMATION AMEX PENDING CVV // +SUITE CELESTIAL // +STAY MAY 01- 03 2025 // +NO PROMO // +FEB282025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,746.2,932.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,932.75,932.75,2,0,0,1,,,0,0.0,false,"",false,0,186.55,Room 103,2687-1 +MMS-OBH25031919064403-2782491,2025-03-19,Hacienda San Angel,Mr and Mrs Smith,,Kate,Lucy,KATELUCY827@GMAIL.COM,,,,,,,,,2025-04-29,2025-05-01,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT MAR192025 // +CREDIT CARD INFORMATION OK // +RATE $ 318.26 USD + TAXES // +STAY APR29-MAY1ST2025 // +SUITE ANGEL DOME // +SUBMITED MAR192025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,636.53,1066.12,0.0,0.0,0.0,270.46,0.0,0.0,0.0,1066.12,1066.12,2,0,0,1,,,0,0.0,false,"",false,0,159.1325,Room 113,2690-1 +EXP-2154560314,2025-03-13,Hacienda San Angel,Expedia,,MARGO,ACKMAN,0b9m67ysy6@m.expediapartnercentral.com,1 414 9342099,,,,,,,,2025-04-30,2025-05-04,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,693.44, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT MAR132025 // +CREDIT CARD INFORMATION OK // +RATE $ 352.80 USD + TAXES // +STAY APR30-MAY042025 // +SUITE CROWN VIEW // +SUBMITED MAR132025NGR//",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,1411.2,2229.21,0.0,0.0,0.0,465.21,0.0,0.0,0.0,2229.21,2229.21,2,0,0,1,,,0,0.0,false,"",false,0,352.8,Room 112,2701-1 +EXP-2185995141,2025-04-28,Hacienda San Angel,Expedia,,Kumiko,Quanrud,gxxjslt6cr@m.expediapartnercentral.com,1 0 4087639118,,,,,,,,2025-04-30,2025-05-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, ***, Remittance amount: 856.56, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $356.90 + TAXES +VIRTUAL CREDIT CARD INFORMATION OK +$85.00 CREDIT ON FOOD & BEVERAGE // UPGRADE OR BOTTLE +CONFIRMATION SENT APIRL 28/25 +OK MARIANA APRIL28/25",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,713.8,1024.58,0.0,0.0,0.0,132.33,0.0,0.0,0.0,1024.58,1024.58,2,0,0,1,,,0,0.0,false,"",false,0,178.45,Room 121,2693-1 +SMP-2025011537457803,2025-01-15,Hacienda San Angel,Simple Booking,,Richard,Franceschini,raf61@yahoo.com,+13233333389,,,,,,,"",2025-05-01,2025-05-03,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE 16 // +RATE $347.74 USD + TAXES // +CREDIT CARD INFORMATION OK VISA CVV PENDING // +STAY MAY 01- 03 2025 // +SUITE ANGEL VIEW // +NO PROMO // +SECRET RATE //",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,695.49,975.36,0.0,0.0,0.0,106.0,0.0,0.0,0.0,975.36,975.36,2,0,0,1,,,0,0.0,false,"",false,0,173.8725,Room 106,2697-1 +LH25011645502278,2025-01-16,Hacienda San Angel,Extranet,,Rodedrick,Carter,joe@randacustomtravel.com,3107706434,,,,,,,,2025-05-01,2025-05-03,2,,"","DIRECT RESERVATION // +CONFIRMATION SENT ENE 16 // +RATE $350 USD + TAXES // +CREDIT CARD INFORMATION OK VISA // +STAY MAY 01- 03 2025 // +SUITE ANGEL DOME // +NO PROMO //",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,700.0,1370.34,0.0,0.0,0.0,495.34,0.0,0.0,0.0,1370.34,1370.34,1,0,0,1,,,0,0.0,false,"",false,0,175.0,Room 107,"2692-1, 2692-2, 2692-3" +SMP-2025022838435265,2025-02-28,Hacienda San Angel,Simple Booking,,Greg,Young,gregryoung44@gmail.com,+19012182381,,,,,,,"",2025-05-01,2025-05-03,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMNATION SENT FEB28 // +RATE $ 520 USD + TAX // +CREDIT CARD INFORMATION AMEX PENDING CVV // +SUITE RINCON DE ANGELES // +STAY MAY 01- 03 2025 // +NO PROMO // +FEB282025GV",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1040.0,1649.98,0.0,0.0,0.0,349.98,0.0,0.0,0.0,1649.98,1649.98,2,0,0,1,,,0,0.0,false,"",false,0,260.0,Room 119,2696-1 +SMP-2025021238071305,2025-02-12,Hacienda San Angel,Simple Booking,,Diana,Woody,dianalwoody@gmail.com,+18653868397,,,,,,,"",2025-05-02,2025-05-04,2,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB112025// +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 473.33 USD + TAXES // +STAY MAY2-52025 // +SUITE VS// +SUBMITED EB112025NGR//",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,975.0,1250.15,0.0,0.0,0.0,31.4,0.0,0.0,0.0,1250.15,1250.15,2,0,0,1,,,0,0.0,false,"",false,0,243.75,Room 121,2702-1 +SMP-2025010937330788,2025-01-09,Hacienda San Angel,Simple Booking,,Laura,Holubec,Holubec.laura@gmail.com,+19033409575,,,,,,,"",2025-05-03,2025-05-05,2,,Anniversary trip,"RESERVATION FROM SIMPLE BOOKING +RATE $301.35 + TAXES +NO PROMO +VIRTUAL CREDIT CARD CVV PENDING +CONFIRMATION SENT ENE09/25 +OK MARIANA ZAVALA ENE09/25 + +********************** +MILAGROS GUESTS REQUESTED ROOM CHANGE (UP-GRADE) TO CELESTIAL +PAID FOR UP-GRADE $ 379 USD 3 NTS +GUEST WILL RETURN MILAGGROS LAST NIGHT MAY8 + +FULL PAYMENT REMAINS IN ORIGINAL RESERVE (THIS ONE)",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,585.67,2242.03,0.0,0.0,0.0,1509.94,0.0,0.0,0.0,2242.03,2242.03,2,0,0,1,,,0,0.0,false,"",false,0,146.4175,Room 102,"" +SMP-2025011637469295,2025-01-16,Hacienda San Angel,Simple Booking,,Scott,Baker,sdbaker50@gmail.com,+17323712125,,,,,,,"",2025-05-03,2025-05-05,2,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT JAN152025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 445 USD + TAXES // +STAY MAY3-52025// +SUITE SAN JOSE // +SUBMITED JAN152025NGR//",,Cancelled,2025-03-07 10:30:21, San Jose - Master Suite,San Jose - Standard Rate,890.0,1112.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1112.5,0,2,0,0,1,,,0,1112.5,false,"",false,0,222.5,Room 122,"" +EXP-X-421800091,2025-02-27,Hacienda San Angel,Expedia,,Edward,Clinton,cqqa8ag2wr@m.expediapartnercentral.com,1 0 5104689955,,,,,,,,2025-05-03,2025-05-10,7,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXP.COM // +CONFIRMATION SENT FEB262025 // +CREDIT CARD INFORMATION OK // +RATE $ 351 USD + TAXES // +STAY MAY3-102025 // +SUITE GARDEN OF ANGELS // +SUBMITED FEB262025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,2457.0,3338.18,0.0,0.0,0.0,266.93,0.0,0.0,0.0,3338.18,3338.18,2,0,0,1,,,0,0.0,false,"",false,0,614.25,Room 109,2720-1 +SMP-2025041539493168,2025-04-14,Hacienda San Angel,Simple Booking,,ROB,KUENZI,robkenzi@outlook.com,+13234593426,,,,,,,"",2025-05-03,2025-05-07,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $436.25+ TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT APRIL14/25 +OK MARIANA APRIL14/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1745.0,3173.27,0.0,0.0,0.0,992.02,0.0,0.0,0.0,3173.27,3173.27,2,0,0,1,,,0,0.0,false,"",false,0,436.25,Room 122,2707-1 +EXP-2185308175,2025-04-27,Hacienda San Angel,Expedia,,Juan Daniel,Castillo Reyes,5dsdya07fw@m.expediapartnercentral.com,52 555 4526656,,,,,,,,2025-05-03,2025-05-04,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 415.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION OK // +RATE $ 346.50 USD + TAXES // +STAY MAY3-42025 // +SUITE ANGEL DOME // +SUBMITED APR272025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,346.5,464.8,0.0,0.0,0.0,31.67,0.0,0.0,0.0,464.8,464.8,2,0,0,1,,,0,0.0,false,"",false,0,86.625,Room 113,"2698-1, 2698-2" +EXP-2189536743,2025-05-02,Hacienda San Angel,Expedia,,Betsy,Royce Dean,69vwdeurvh@m.expediapartnercentral.com,0 0 6198239817,,,,,,,,2025-05-03,2025-05-04,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 410.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $342.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD +CONFIRMATION SENT MAY2ND /25 +OK MARIANA MAY2ND/25",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,342.0,449.03,0.0,0.0,0.0,21.53,0.0,0.0,0.0,449.03,449.03,2,0,0,1,,,0,0.0,false,"",false,0,85.5,Room 106,"2699-1, 2699-2" +SMP-2025032639033083,2025-03-26,Hacienda San Angel,Simple Booking,,Lisa,Raphael,LisaRaphael@gmail.com,+13152636833,,,,,,,"",2025-05-04,2025-05-06,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $416.15+ TAXES +SECRET RATE +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT MARCH26/2025 +OK MARIANA MARCH26/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,832.3,1344.38,0.0,0.0,0.0,304.0,0.0,0.0,0.0,1344.38,1344.38,2,0,0,1,,,0,0.0,false,"",false,0,208.075,Room 107,2706-1 +LH25020345886971,2025-02-03,Hacienda San Angel,Extranet,,Dean,Milano,"","",,,,,,,,2025-05-05,2025-05-07,2,,Angel's Rate,"Angel's Rate- Paula + +Long time restaurant guest from Chicago. Comes twice every year and always wishes he could stay in hotel but cannot afford so I worked this out with him. You still need card for incidentals. 20% discount on food and beverages- Paula",,Cancelled,2025-02-03 14:19:00,Crown View - Junior Suite,Manual,500.0,500.0,0.0,0.0,0.0,0.0,0,0.0,0.0,500.0,0,2,0,0,1,,,0,500.0,false,"",false,0,125.0,Room 112,"" +LH25020345887095,2025-02-03,Hacienda San Angel,Extranet,,Dean,Milano,deanguy@ameritech.net,"",,,,,,,,2025-05-05,2025-05-07,2,,"","Long time restaurant guest from Chicago. Comes twice every year and always wishes he could stay in hotel but cannot afford so I worked this out with him. + +You still need card for incidentals. 15% discount on food and beverages- Paula",,Checked-out,"",Crown View - Junior Suite,Manual,500.0,230.03,0.0,0.0,0.0,230.03,0.0,0.0,0.0,230.03,230.03,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 112,"2704-1, 2704-2" +LH25050547856544,2025-05-05,Hacienda San Angel,Extranet,,Laura,Holubec,Holubec.laura@gmail.com,+19033409575,,,,,,United States of America,"",2025-05-05,2025-05-08,3,,"","MILAGROS GUESTS REQUESTED ROOM CHANGE (UP-GRADE) +PAYMENT IN FULL + (ORIGINAL) IN MILAGROS +3 NOCHES M $1121.01 +UP-GRADES $379",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1200.0,378.99,0.0,0.0,0.0,-1121.01,0.0,0.0,0.0,378.99,378.99,2,0,0,1,,,0,0.0,false,"",false,0,300.0,Room 103,2710-1 +LH25050547858298,2025-05-05,Hacienda San Angel,Extranet,,ALEXIS,DE SELA,alexisdesela@me.com,2108349128,,,,,,,,2025-05-05,2025-05-08,3,,"","",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1025.0,1578.29,0.0,0.0,0.0,297.04,0.0,0.0,0.0,1578.29,1578.29,2,0,0,1,,,0,0.0,false,"",false,0,256.25,Room 118,"2709-1, 2709-2" +SMP-2025011637468649,2025-01-16,Hacienda San Angel,Simple Booking,,Michael,Hood,hood.michaelg@gmail.com,+15098455150,,,,,,,"",2025-05-06,2025-05-10,4,,This is for our 10th anniversary. I would love if there could be some flowers / pedals and some champagne in the room upon check in. I will gladly pay for this and can have it billed to the room if needed. Or please let me know if I need to pay in advance.,"RESERVATION THRU SB.COM // +CONFIRMATION SENT JAN152025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 482.50 USD + TAXES // +STAY MAY6-102025 // +SUITE RINCÓN OF ANGELS// +SUBMITED JAN152025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1930.0,3133.43,0.0,0.0,0.0,720.93,0.0,0.0,0.0,3133.43,3133.43,2,0,0,1,,,0,0.0,false,"",false,0,482.5,Room 119,2721-1 +EXP-2191724466,2025-05-06,Hacienda San Angel,Expedia,,ALEAH,WARRREN-TONG,46881ncba0@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-05-06,2025-05-07,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 324.00, Expedia Virtual Card will be activated from the day of Check-in.",,,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,270.0,337.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,337.5,337.5,2,0,0,1,,,0,0.0,false,"",false,0,67.5,Room 110,2708-1 +SMP-2025021738194110,2025-02-17,Hacienda San Angel,Simple Booking,,Michael,Thompson,mt7126@gmail.com,+19496835023,,,,,,,"",2025-05-07,2025-05-08,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $475.00 + TAXES +NO PROMO +CREDIT CARD INFO CVV PENDING +CONFIRMATION SENT FEB17/2025 +OK MARIANA FEB17/2025",,Cancelled,2025-03-28 08:05:32, Celestial - Royal Suite,Celestial - Standard Rate,475.0,593.75,0.0,0.0,0.0,0.0,0,0.0,0.0,593.75,0,2,0,0,1,,,0,593.75,false,"",false,0,118.75,Room 103,"" +LH25022646378675,2025-02-26,Hacienda San Angel,Extranet,,Nancy,Moody,njdmoody@gmail.com,"",,,,,,,,2025-05-07,2025-05-10,3,,"","RESERVATION DIRECTLY +RATE $291.66 + TAXES +NO PROMO +CREDIT CARD INFO OK +OK MARIANA FEB26/2025 +CONFIRMATION SENT FEB26/25 +OK MARIANA FEB26/25",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,1175.0,1468.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1468.75,1468.75,2,0,0,1,,,0,0.0,false,"",false,0,293.75,Room 112,"2719-1, 2719-2" +SMP-2025041539494313,2025-04-15,Hacienda San Angel,Simple Booking,,Jacqueline,Marra,jacqueline.marra@indagare.com,+19144203761,,,,,,,"",2025-05-07,2025-05-08,1,,I am a trave adivsor at Indagare Travel and am excited to see the property during my Nayarit scouting trip! I will be taking my mom as my guest.,"RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR152025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 319.80 USD + TAXES // +STAY MAY07-082025 // +SUITE ANGEL DOME // +SUBMITED APR152025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,319.8,437.75,0.0,0.0,0.0,38.0,0.0,0.0,0.0,437.75,437.75,2,0,0,1,,,0,0.0,false,"",false,0,79.95,Room 113,2712-1 +EXP-2185139171,2025-04-26,Hacienda San Angel,Expedia,,Nancy,Thompson,0wg3mdqqgp@m.expediapartnercentral.com,1 201 9064418,,,,,,,,2025-05-07,2025-05-08,1,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION OK // +RATE $ 450 USD + TAXES // +STAY MAY7-082025 // +SUITE CELESTIAL // +SUBMITED APR262025NGR//",,Cancelled,2025-05-02 12:02:37, Celestial - Royal Suite,Celestial - Standard Rate,450.0,562.5,0.0,0.0,0.0,0.0,0,0.0,0.0,562.5,0,2,0,0,1,,,0,562.5,false,"",false,0,112.5,Room 103,"" +LH25050547856826,2025-05-05,Hacienda San Angel,Extranet,,Laura,Holubec,Holubec.laura@gmail.com,+19033409575,,,,,,United States of America,"",2025-05-08,2025-05-09,1,,"","GUESTS REQUESTED CHANGE TO CELESTIAL +3 NIGHTS AVAILABLE +LAST NIGHT MAY8 RETURN AMILAGROS +FULL PAYMENT (ORIGINAL) ON MAY03 RESERVATION ON MILAGROS",,Checked-out,"", Milagros - Junior Suite,Manual,0.0,474.26,0.0,0.0,0.0,474.26,0.0,0.0,0.0,474.26,474.26,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 102,2715-1 +MMS-OBH25011122530108-2711659,2025-01-11,Hacienda San Angel,Mr and Mrs Smith,,James,Vogel,JAMVO98@GMAIL.COM,,,,,,,,,2025-05-09,2025-05-11,2,,PriceInformation : Tax is included at 19%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS// HYATT // +CONFIRMATION SENT JAN122025// +CREDIT CARD INFORMATION OK// +RATE $ 305.03 USD + TAXES // +STAY MAY9-112025 // +SUITE ANGEL VIEW // +SUBMITED JAN122025NGR//",,Cancelled,2025-04-21 22:26:01, Angels View - Master Suite,Angels View - Standard Rate,605.18,788.27,0.0,0.0,0.0,31.79,0,0.0,0.0,788.27,0,2,0,0,1,,,0,788.27,false,"",false,0,151.295,Room 106,"" +EXP-2181719190,2025-04-22,Hacienda San Angel,Expedia,,Rachit,Soni,godha.pranay@gmail.com,1 919 8001295,,,,,,,,2025-05-09,2025-05-12,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,293.60, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP +RATE $359.33 + TAXES +$85.00 CREDIT ON FOOD & BEVERAGE +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL22/25 +OK MARIANA APRIL22/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1078.0,1559.7,0.0,0.0,0.0,212.2,0.0,0.0,0.0,1559.7,1559.7,2,0,0,1,,,0,0.0,false,"",false,0,269.5,Room 122,"2717-1, 2717-2, 2717-3, 2717-4" +EXP-2181719980,2025-04-22,Hacienda San Angel,Expedia,,pranay,godha,godha.pranay@gmail.com,1 267 2506811,,,,,,,,2025-05-09,2025-05-12,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,195.23, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP +RATE $332.00 + TAXES +$85.00 CREDIT ON FOOD & BEVERAGE +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL22/25 +OK MARIANA APRIL22/2025",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,996.02,1571.03,0.0,0.0,0.0,326.0,0.0,0.0,0.0,1571.03,1571.03,2,0,1,1,,,0,0.0,false,"",false,0,249.005,Room 121,"2718-1, 2718-2, 2718-3, 2718-4" +LH25050547857816,2025-05-05,Hacienda San Angel,Extranet,,gris,test,"","",,,,,,,,2025-05-09,2025-05-10,1,,"","",,Cancelled,2025-05-05 12:26:43, Vista de Santos - Master Suite,Vista de Santos - Package Rate,337.5,917.88,0.0,0.0,0.0,496.0,0,0.0,0.0,917.88,0,2,0,0,1,,,0,917.88,false,"",false,0,84.375,Room 121,"" +EXP-2191530881,2025-05-05,Hacienda San Angel,Expedia,,edgar,onyango,ch4wrc0s6n@m.expediapartnercentral.com,52 322 3793185,,,,,,,,2025-05-09,2025-05-10,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 550.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT MAY052025 // +CREDIT CARD INFORMATION OK // +RATE $ 459 USD + TAXES // +STAY MAY09-102025 // +SUITE SAN MIGUEL // +SUBMITED MAY052025NGR//",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,459.0,645.95,0.0,0.0,0.0,72.2,0.0,0.0,0.0,645.95,645.95,2,0,0,1,,,0,0.0,false,"",false,0,114.75,Room 107,"2713-1, 2713-2, 2713-3, 2713-4" +SMP-2025022338314795,2025-02-23,Hacienda San Angel,Simple Booking,,Faith,Savage,msgchezmoi@icloud.com,+4407764182806,,,,,,,"",2025-05-10,2025-05-15,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE 4443.75 + TAXES +NO PROMO +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2250.0,3061.8,0.0,0.0,0.0,249.3,0.0,0.0,0.0,3061.8,3061.8,2,0,0,1,,,0,0.0,false,"",false,0,562.5,Room 119,2732-1 +LH25022646378716,2025-02-26,Hacienda San Angel,Extranet,,NANCY,MOODY,njdmoody@gmail.com,"",,,,,,,,2025-05-10,2025-05-13,3,,"","CREDIT FROM EXPEDIA RESERVATION 349358945 + + +27 DIC 2024",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,1005.0,680.15,0.0,0.0,0.0,680.15,0.0,0.0,0.0,680.15,680.15,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 112,"2728-1, 2728-2" +LH25030946631931,2025-03-09,Hacienda San Angel,Extranet,,Chelsea & Travis,Alterman,reservations@verana.com,845-520-0084,,,,,,,,2025-05-10,2025-05-12,2,,"",CXC VERANA,,Checked-out,"", Milagros - Junior Suite,Manual,640.0,285.45,0.0,0.0,0.0,285.45,0.0,0.0,0.0,285.45,285.45,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 102,2725-1 +SMP-2025041539493346,2025-04-15,Hacienda San Angel,Simple Booking,,Andrea,Siegman,andreasiegman@gmail.com,+13108495622,,,,,,Uruguay,"",2025-05-10,2025-05-12,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $401.80 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT APRIL14/25 +OK MARIANA APRIL14/25",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,803.6,1143.37,0.0,0.0,0.0,138.87,0.0,0.0,0.0,1143.37,1143.37,2,0,0,1,,,0,0.0,false,"",false,0,200.9,Room 107,2726-1 +SMP-2025031338721788,2025-03-13,Hacienda San Angel,Simple Booking,,Anthony,Bald,anthony.p.bald@gmail.com,+18023568270,,,,,,,"",2025-05-11,2025-05-13,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $303.40 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MARCH13/2025 +OK MARIANA MARCH13/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,606.81,975.9,0.0,0.0,0.0,217.39,0.0,0.0,0.0,975.9,975.9,2,0,0,1,,,0,0.0,false,"",false,0,151.7025,Room 109,"2722-1, 2722-2" +BDC-4496017209,2025-02-01,Hacienda San Angel,Booking.com,,Dominic,Hawkes,dhawke.183571@guest.booking.com,+44 7821 974007,,,,.,,United Kingdom,"",2025-05-12,2025-05-15,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING. COM +RATE $432.00 + TAXES +NO PROMO +CREDITR CARD INFO OK +CONFIRMATION SENT JANUARY 01/2025 +OK MARIANA JANUARY01/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1296.0,1759.58,0.0,0.0,0.0,139.58,0.0,0.0,0.0,1759.58,1759.58,1,0,0,1,,,0,0.0,false,"",false,0,324.0,Room 107,"2723-1, 2723-2" +LH25030246477401,2025-03-02,Hacienda San Angel,Extranet,,CHARLES N,WHITES JR,cnwhitejr@gmail.com,1713342978,,,,,,,,2025-05-12,2025-05-16,4,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT MARCH022025 // +CREDIT CARD INFORMATION OKO// +RATE $ 432.50 USD + TAXES // +STAY MAY12-162025 // +SUITE CELESTIAL// +SUBMITED MARCH022025NGR// +THEY WILL BRING THE AAA CARD TO GIVE THEM THE 10% OF DISCOUNT + +************** +CLIENTE LLAMAO PARA CAMNCELAR, TENDRA UNA CIRUGIA IMPORTANTE QUE NO LE PERMITIRA VIAJAR",,Cancelled,2025-04-01 15:32:38, Celestial - Royal Suite,Celestial - Standard Rate,1730.0,2162.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2162.5,0,2,0,0,1,,,0,2162.5,false,"",false,0,432.5,Room 103,"" +MMS-OB25030919103007-2771306,2025-03-09,Hacienda San Angel,Mr and Mrs Smith,,Patrick,Egan,eganpatrickm@gmail.com,+13477210249,,22 Utica Walk,,Breezy Point,,United States,11697,2025-05-12,2025-05-14,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT MAR092025 // +CREDIT CARD INFORMATION OK // +RATE $ 393.60 USD + TAXES // +STAY MAY12-142025 // +SUITE ANGEL VIEW // +SUBMITED MAR092025NGR//",,Cancelled,2025-04-30 16:51:11, Angels View - Master Suite,Angels View - Standard Rate,787.2,861.0,0.0,0.0,0.0,-123.0,0,0.0,0.0,861.0,0,2,0,0,1,,,0,861.0,false,"",false,0,196.8,Room 106,"" +SMP-2025042339683955,2025-04-23,Hacienda San Angel,Simple Booking,,Yevonne,Wieringa,Ydwieringa@gmail.com,+12819238543,,,,,,,"",2025-05-12,2025-05-15,3,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ABR 23 // +RATE $ 448.33 USD + TAX // +CREDIT CARD INFORMATION AMEX CVV PENDING // +NO PROMO // +SUITE CELESTIAL // +STAY MAY 12- 15 2025 // +ABR232025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1345.0,1681.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1681.25,1681.25,2,0,0,1,,,0,0.0,false,"",false,0,336.25,Room 103,2731-1 +EXP-2192240050,2025-05-06,Hacienda San Angel,Expedia,,Hoi Yi,Tam,infg66j1eu@m.expediapartnercentral.com,1 415 6277392,,,,,,,,2025-05-12,2025-05-13,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 405.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $337.50 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO +CONFIRMATION SENT MAY06/25 +OK MARIANA MAY06/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,337.5,612.13,0.0,0.0,0.0,190.25,0.0,0.0,0.0,612.13,612.13,2,0,0,1,,,0,0.0,false,"",false,0,84.375,Room 122,2727-1 +MMS-OBH25051322423502-2844479,2025-05-13,Hacienda San Angel,Mr and Mrs Smith,,Jeffery,Roberts,JGROBERTS@RLULAW.COM,,,,,,,,,2025-05-13,2025-05-14,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $288.00 + TAXES +HYATT +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT MAY13/25 +OK MARIANA MAY13/25",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,288.0,315.0,0.0,0.0,0.0,-45.0,0.0,0.0,0.0,315.0,315.0,2,0,0,1,,,0,0.0,false,"",false,0,72.0,Room 110,2730-1 +MMS-OBH25051322510003-2844484,2025-05-13,Hacienda San Angel,Mr and Mrs Smith,,Jeffery,Roberts,JGROBERTS@RLULAW.COM,,,,,,,,,2025-05-13,2025-05-14,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $288.00 + TAXES +HYATT +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT MAY13/25 +OK MARIANA MAY13/25",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,288.0,477.93,0.0,0.0,0.0,117.93,0.0,0.0,0.0,477.93,477.93,2,0,0,1,,,0,0.0,false,"",false,0,72.0,Room 113,2729-1 +EXP-X-419447205,2025-02-23,Hacienda San Angel,Expedia,,Michael,Thomas,t9nb36jft8@m.expediapartnercentral.com,1 0 2069633684,,,,,,,,2025-05-14,2025-05-16,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 864.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $360.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,720.0,1547.38,0.0,0.0,0.0,647.38,0.0,0.0,0.0,1547.38,1547.38,2,0,0,1,,,0,0.0,false,"",false,0,180.0,Room 122,2735-1 +EXP-2174825975,2025-04-11,Hacienda San Angel,Expedia,,Elena,Sanarina,wjgvegrqgw@m.expediapartnercentral.com,1 4156999034,,,,,,,,2025-05-14,2025-05-15,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 337.92, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT APR112025 // +CREDIT CARD INFORMATION OK // +RATE $ 281.60 USD + TAXES // +STAY MAY14-152025 // +SUITE MILAGROS // +SUBMITED APR112025NGR//",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,281.6,504.51,0.0,0.0,0.0,152.51,0.0,0.0,0.0,504.51,504.51,2,0,0,1,,,0,0.0,false,"",false,0,70.4,Room 102,2733-1 +LH25051248013748,2025-05-12,Hacienda San Angel,Extranet,,Yevonne,Wieringa,Ydwieringa@gmail.com,+12819238543,,,,,,United States of America,"",2025-05-15,2025-05-16,1,,"","RESERVATION DIRECTLY +RATE $400.00 + TAXES +NO PROMO +CREDIT CARD OK CONFIRMATION SENT MAY12/25 +OK MARIANA MAY12/25 + + + +THIS IS AN EXTENSION, GUEST ALREADY IN CELESTIAL",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,400.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,500.0,2,0,0,1,,,0,0.0,false,"",false,0,100.0,Room 103,2734-1 +EXP-2174200542,2025-04-11,Hacienda San Angel,Expedia,,Travis,Callahan,fdr1gou5if@m.expediapartnercentral.com,1 5123511817,,,,,,,,2025-05-16,2025-05-17,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 583.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR102025// +CREDIT CARD INFORMATION OK // +RATE $ 486 USD + TAXES // +STAY MAY16-172025 // +SUITE SAN JOSE // +SUBMITED APR102025NGR //",,Cancelled,2025-04-11 17:09:14, San Jose - Master Suite,San Jose - Standard Rate,486.0,607.5,0.0,0.0,0.0,0.0,0,0.0,0.0,607.5,0,2,0,0,1,,,0,607.5,false,"",false,0,121.5,Room 122,"" +LH25051248014145,2025-05-12,Hacienda San Angel,Extranet,,Yevonne,Wieringa,Ydwieringa@gmail.com,+12819238543,,,,,,United States of America,"",2025-05-16,2025-05-17,1,,"","RESERVATION DIRECTLY +RATE $330. 00 TAXES +CREDIT CARD INFO OK +CONFIRMATION SENT MAY12/25 +OK MARIANA MAY12/25",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,330.0,2781.89,0.0,0.0,0.0,2369.39,0.0,0.0,0.0,2781.89,2781.89,2,0,0,1,,,0,0.0,false,"",false,0,82.5,Room 110,"2736-1, 2736-2, 2736-3" +LH25020145849706,2025-02-01,Hacienda San Angel,Extranet,,VIVIEN & DAVID,BURCH,rhettburch@gmail.com,91775752063,,,,,,,,2025-05-19,2025-05-20,1,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT FEB012025 // +CREDIT CARD INFORMATION OK // +RATE $450 USD + TAXES // +STAY MAY19-202025 // +SUITE RINCON DE ANGELES// +SUBMITED FEB012025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,450.0,707.1,0.0,0.0,0.0,144.6,0.0,0.0,0.0,707.1,707.1,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 119,2754-1 +SMP-2025022338315018,2025-02-23,Hacienda San Angel,Simple Booking,,Ophilino,DACOSTA,ophilino@gmail.com,+19703148546,,,,,,,"",2025-05-19,2025-05-22,3,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT // +RATE $ 356.70 USD + TAX // +NO PROMO // +CREDIT CARD INFORMATION VISA VCC PENDING // +SECRET RATE // +SUITE ANGEL VIEW // +STAY MAY 19- 24 2025 // +***************** +Modifico rsva original // +Cambio de fecha de salida +Sytat May 19- 22 2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1070.1,2285.96,0.0,0.0,0.0,948.33,0.0,0.0,0.0,2285.96,2285.96,2,0,0,1,,,0,0.0,false,"",false,0,267.525,Room 106,2757-1 +LH25030746579412,2025-03-07,Hacienda San Angel,Extranet,,CHANDA PETERSON,BURCH,rhettburch@gmail.com,91775752063,,,,,,,,2025-05-19,2025-05-20,1,,"","RESERVATION THRU DIRECTA.COM // +CONFIRMATION SENT MAR072025// +CREDIT CARD INFORMATION OK // +RATE $415 USD + TAXES // +STAY MAY192025 // +SUITE SAN GABRIEL // +SUBMITED MAR072025NGR//",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,415.0,910.27,0.0,0.0,0.0,391.52,0.0,0.0,0.0,910.27,910.27,2,0,0,1,,,0,0.0,false,"",false,0,103.75,Room 118,2752-1 +SMP-2025030738587612,2025-03-07,Hacienda San Angel,Simple Booking,,Janet,Lansing,lansing.jan@gmail.com,+17144022082,,,,,,,"",2025-05-19,2025-05-20,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAR072025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $370 USD + TAXES // +STAY MAY19-202025 // +SUITE ANGEL DOME // +SUBMITED MAR072025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,370.0,573.61,0.0,0.0,0.0,111.11,0.0,0.0,0.0,573.61,573.61,1,0,0,1,,,0,0.0,false,"",false,0,92.5,Room 113,2750-1 +LH25030846600891,2025-03-08,Hacienda San Angel,Extranet,,CHANDA PETERSON,BURCH,rhettburch@gmail.com,91775752063,,,,,,,,2025-05-19,2025-05-20,1,,"","RESERVATION THRU DIRECT .COM // +CONFIRMATION SENT MAR082025// +CREDIT CARD INFORMATION OK // +RATE $ 470 USD + TAXES // +STAY MAY19-202025 // +SUITE VISTA DE SANTOS // +SUBMITED MARCH082025NGR//",,Checked-out,"", Vista de Santos - Master Suite,Manual,470.0,1442.57,0.0,0.0,0.0,855.07,0.0,0.0,0.0,1442.57,1442.57,2,0,0,1,,,0,0.0,false,"",false,0,117.5,Room 121,2751-1 +SMP-2025030938627452,2025-03-09,Hacienda San Angel,Simple Booking,,Todd,Phillips,todd.phillips@blumoana.com,8082647777,,,,,,,"",2025-05-19,2025-05-23,4,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAR092025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 324.92 USD + TAXES // +STAY MAY19-232025 // +SUITE GARDEN OF ANGELS // +SUBMITED MAR092025NGR//",,Cancelled,2025-03-15 11:52:06, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1299.71,1624.64,0.0,0.0,0.0,0.0,0,0.0,0.0,1624.64,0,2,0,0,1,,,0,1624.64,false,"",false,0,324.9275,Room 109,"" +SMP-2025031738832563,2025-03-17,Hacienda San Angel,Simple Booking,,Valmond,Romilly,arturo@mitierraholidays.com,+16048378410,,,,,,Canada,"",2025-05-19,2025-05-20,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $340.30 + TAXES +NO PROMO +CREDIT CARD INFO AMEX CVV PENDING +CONFIRMATION SENT MARCH17/2024 +OK MARIANA MARCH17/2024",,Cancelled,2025-03-18 11:11:33, Milagros - Junior Suite,Milagros - Standard Rate,340.3,425.38,0.0,0.0,0.0,0.0,0,0.0,0.0,425.38,0,2,0,0,1,,,0,425.38,false,"",false,0,85.075,Room 102,"" +EXP-2174807745,2025-04-11,Hacienda San Angel,Expedia,,Kimberly,Hartley,ynknv8ot88@m.expediapartnercentral.com,0 0 2146825346,,,,,,,,2025-05-19,2025-05-20,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 423.12, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAPREMIUMVIP.COM // +CONFIRMATION SENT APR112025 // +CREDIT CARD INFORMATION OK // +RATE $352.60 USD + TAXES // +STAY MAY19-202025 // +SUITE GARDEN OF ANGELS // +SUBMITED APR112025NGR//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,380.0,578.46,0.0,0.0,0.0,103.46,0.0,0.0,0.0,578.46,578.46,2,0,0,1,,,0,0.0,false,"",false,0,95.0,Room 122,"2749-1, 2749-2, 2749-3" +EXP-2174892453,2025-04-11,Hacienda San Angel,Expedia,,Travis,Callahan,scijylrygf@m.expediapartnercentral.com,1 512 3511817,,,,,,,,2025-05-19,2025-05-21,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 885.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR112025 // +CREDIT CARD INFORMATION OK // +RATE $ 369 USD + TAXES // +STAY MAY19-212025 // +SUITE MILAGROS // +SUBMITED APR112025NGR//",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,738.0,1123.59,0.0,0.0,0.0,201.09,0.0,0.0,0.0,1123.59,1123.59,2,0,0,1,,,0,0.0,false,"",false,0,184.5,Room 102,"2742-1, 2742-2" +LH25042547649806,2025-04-25,Hacienda San Angel,Extranet,,TAYLOR & KRISTEN,BURCH,rhettburch@gmail.com,"",,,,,,,,2025-05-19,2025-05-20,1,,"","RESERVATION DIRECTLY +RATE $475.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT APRIL25/25 +OK MARIANA APRIL25/25",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,475.0,1945.97,0.0,0.0,0.0,1352.22,0.0,0.0,0.0,1945.97,1945.97,2,0,0,1,,,0,0.0,false,"",false,0,118.75,Room 112,2753-1 +LH25042547649833,2025-04-25,Hacienda San Angel,Extranet,,VIVIEN & DAVIS,BURCH,rhettburch@gmail.com,91775752063,,,,,,,,2025-05-19,2025-05-20,1,,"","RESERVATION DIRECTLY +RATE $445.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT APRIL25/25 +OK MARIANA APRIL25/25",,Cancelled,2025-05-01 22:21:42,Serafin - Junior Suite,Serafin - Standard Rate,445.0,556.25,0.0,0.0,0.0,0.0,0,0.0,0.0,556.25,0,2,0,0,1,,,0,556.25,false,"",false,0,111.25,Room 110,"" +SMP-2025012337643878,2025-01-23,Hacienda San Angel,Simple Booking,,Paul,Moore,moore.paulc@gmail.com,+19186252525,,,,,,,"",2025-05-20,2025-05-25,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $459.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT ENE23/2025 +OK MARIANA ZAVALA ENE23/2025",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2295.0,3479.77,0.0,0.0,0.0,611.02,0.0,0.0,0.0,3479.77,3479.77,2,0,0,1,,,0,0.0,false,"",false,0,573.75,Room 119,2762-1 +SMP-2025031738831924,2025-03-17,Hacienda San Angel,Simple Booking,,Valmond,Romilly,arturo@mitierraholidays.com,+16048378410,,,,,,Canada,"",2025-05-20,2025-05-24,4,,"","RESERVATION FROM SIMPLE BOKKING +RATE $1600.00 + TAXES +NO PROMO +CREDIT CARD INFO CVV PENDING +CONFIRMATION SENT MARCH17/2025 +OK MARIANA MARCH17/2025",,Cancelled,2025-03-18 11:12:01, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1600.0,2000.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2000.0,0,2,0,0,1,,,0,2000.0,false,"",false,0,400.0,Room 118,"" +LH25031846823083,2025-03-18,Hacienda San Angel,Extranet,,VALMOND,ROMILY,arturo@mitierraholidays.com,6048378410,,,,,,,,2025-05-20,2025-05-24,4,,"","RESERVATION DIRECTLY +RATE $410.00 +CREDIT CARD INFO AMEX OK +CONFIRMATION SENT MARCH18/2025 +OK MARIANA MARCH18/2025 +DESCUENTO POR HUESPEDES REPETITIVOS",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1640.0,2220.66,0.0,0.0,0.0,580.66,0.0,0.0,0.0,2220.66,2220.66,2,0,0,1,,,0,0.0,false,"",false,0,328.0,Room 118,2759-1 +SMP-2025052140341835,2025-05-21,Hacienda San Angel,Simple Booking,,Scott,Arnell,S.arnell@yahoo.com,+16509606150,,,,,,,"",2025-05-20,2025-05-21,1,,"","",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,266.5,354.66,0.0,0.0,0.0,21.53,0.0,0.0,0.0,354.66,354.66,2,0,0,1,,,0,0.0,false,"",false,0,66.625,Room 109,"2756-1, 2756-2" +LH25050347811484,2025-05-03,Hacienda San Angel,Extranet,,test,test,"","",,,,,,,,2025-05-22,2025-05-24,2,,"","",,Cancelled,2025-05-03 08:10:58,Serafin - Junior Suite,Manual,1065.0,1331.25,0.0,0.0,0.0,0.0,0,0.0,0.0,1331.25,0.0,2,0,0,1,,,0,1331.25,false,"",false,0,266.25,Room 110,"" +MMS-OBH25052116062906-2852421,2025-05-21,Hacienda San Angel,Mr and Mrs Smith,,Donna,Leon,DONNALEON@SBCGLOBAL.NET,,,,,,,,,2025-05-22,2025-05-24,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // +CREDIT CARD INFORMATION OK VIRTUAL CARD // +RATE $234 USD +TAX // +SUITE ANGEL DOME // +STAY MAY 22- 24 2025 // +NO PROMO // +RESERVATION FORM HYATT // +MAY212025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,449.28,673.89,0.0,0.0,0.0,112.29,0.0,0.0,0.0,673.89,673.89,2,0,0,1,,,0,0.0,false,"",false,0,112.32,Room 113,2760-1 +LH25030546544339,2025-03-05,Hacienda San Angel,Extranet,,GRIS,TEST,"","",,,,,,,,2025-05-23,2025-05-27,4,,,,,Cancelled,2025-03-05 16:54:25, San Miguel - Presidential Suite,San Miguel - Package Rate,1863.0,2328.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2328.75,0,2,0,0,1,,,0,2328.75,false,"",false,0,465.75,Room 107,"" +LH25030646566807,2025-03-06,Hacienda San Angel,Extranet,,Huw,Dussy,"","",,,,,,,,2025-05-23,2025-05-27,4,,,,,Cancelled,2025-03-06 16:35:44, San Miguel - Presidential Suite,San Miguel - Package Rate,1863.0,2328.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2328.75,0,2,0,0,1,,,0,2328.75,false,"",false,0,465.75,Room 107,"" +SMP-2025030638571574,2025-03-06,Hacienda San Angel,Simple Booking,,Cynthia,Duffy,cynthiaduffy19@gmail.com,+14086036267,,,,,,,"",2025-05-23,2025-05-27,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $424.35 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MARCH06/2025 +OK MARIANA MARCH06/2025 + +cvv 609",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1697.41,2333.04,0.0,0.0,0.0,211.28,0.0,0.0,0.0,2333.04,2333.04,2,0,0,1,,,0,0.0,false,"",false,0,424.3525,Room 107,2768-1 +MMS-OBH25041017332806-2803963,2025-04-10,Hacienda San Angel,Mr and Mrs Smith,,Ryan,Priddy,RYANPRIDDYCSULB@GMAIL.COM,,,,,,,,,2025-05-23,2025-05-25,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $316.37 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL10/25 +OK MARIANA APRIL 10/25",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,632.74,861.89,0.0,0.0,0.0,70.96,0.0,0.0,0.0,861.89,861.89,1,0,0,1,,,0,0.0,false,"",false,0,158.185,Room 106,2763-1 +BDC-4637411045,2025-05-23,Hacienda San Angel,Booking.com,,Iliana,Cavazos,icavaz.562618@guest.booking.com,+1 956 243 7134,,,,,,United States,"",2025-05-23,2025-05-24,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-05-22. +Approximate time of arrival: between 14:00 and 15:00 +smoking preference: Non-Smoking","BOOKING.COM +MAY23-242025 +CC OK +$375 + TAX +SAN JOSE +MAY222025",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,375.0,471.75,0.0,0.0,0.0,3.0,0.0,0.0,0.0,471.75,471.75,2,0,0,1,,,0,0.0,false,"",false,0,93.75,Room 122,2758-1 +BDC-4449045869,2025-03-04,Hacienda San Angel,Booking.com,,Marinela,Reus,mreus.212975@guest.booking.com,+1 408 489 9770,,,,.,,United States,"",2025-05-24,2025-05-27,3,,"We’re celebrating my husband’s birthday. Would it be possible to make our stay more memorable? Thank you., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR042025 // +CREDIT CARD INFORMATION OK // +RATE $ 339.75 USD + TAXES // +STAY MAY24-262025 // +SUITE MILAGROS // +SUBMITED MAR042025NGR//",,Cancelled,2025-05-21 00:56:54, Milagros - Junior Suite,Milagros - Standard Rate,927.45,1166.73,0.0,0.0,0.0,7.42,0,0.0,0.0,1166.73,0,2,0,0,1,,,0,1166.73,false,"",false,0,231.8625,Room 102,"" +LH25050447843344,2025-05-04,Hacienda San Angel,Extranet,,JULIA,NAVRATIL,julia@thecenter.com,+14405542092,,,,,,,,2025-05-24,2025-05-27,3,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT MAY042025 // +CREDIT CARD INFORMATION OK // +RATE $410 USD + TAXES // +STAY MAY24-272025 // +SUITE ANGEL DOME // +SUBMITED MAY042025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1230.0,1785.17,0.0,0.0,0.0,247.67,0.0,0.0,0.0,1785.17,1785.17,2,0,0,1,,,0,0.0,false,"",false,0,307.5,Room 113,2770-1 +MMS-OBH25052121383406-2852714,2025-05-21,Hacienda San Angel,Mr and Mrs Smith,,Robyn,Newman,ROBYNRRSS@HOTMAIL.COM,,,,,,,,,2025-05-24,2025-05-25,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // +RATE $ 323.7 USD + TAXES // +SUITE CELESTIAL // +STAY MAY 24- 25 2025 // +CREDIT CARD OK VIRTUAL CARD PARA CARGO //",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,310.75,601.28,0.0,0.0,0.0,212.84,0.0,0.0,0.0,601.28,601.28,2,0,0,1,,,0,0.0,false,"",false,0,77.6875,Room 103,2761-1 +SMP-2025022438320569,2025-02-24,Hacienda San Angel,Simple Booking,,Mark,Allendorf,mdallendorf@gmail.com,+19252000632,,,,,,,"",2025-05-25,2025-05-28,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $369.00C+ TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1107.01,2208.88,0.0,0.0,0.0,825.12,0.0,0.0,0.0,2208.88,2208.88,2,0,0,1,,,0,0.0,false,"",false,0,276.7525,Room 103,"2772-1, 2772-2" +SMP-2025040839357402,2025-04-08,Hacienda San Angel,Simple Booking,,samuel,sterling,sam@ssanm.com,+15054018537,,,,,,,"",2025-05-25,2025-05-27,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR082025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 520 USD + TAXES // +STAY MAY25-272025 // +SUITE RINCÓN OF ANGELES // +SUBMITED APR082025NGR//",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1040.0,1398.81,0.0,0.0,0.0,98.81,0.0,0.0,0.0,1398.81,1398.81,2,0,0,1,,,0,0.0,false,"",false,0,260.0,Room 119,"2766-1, 2766-2" +LH25012645709769,2025-01-26,Hacienda San Angel,Extranet,,DEBBIE,CAROSELLA,debbie.carosella@gmail.com,3038194476,,,,,,,,2025-05-26,2025-05-27,1,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT JAN262025 // +CREDIT CARD INFORMATION OK// +RATE $ 350 USD + TAXES // +STAY MAY26-272025 // +SUITE GARDEN // +SUBMITED JAN262025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,350.0,556.56,0.0,0.0,0.0,119.06,0.0,0.0,0.0,556.56,556.56,2,0,0,1,,,0,0.0,false,"",false,0,87.5,Room 109,2769-1 +BDC-4561879146,2025-02-08,Hacienda San Angel,Booking.com,,Lucas,Pearson,lpears.196919@guest.booking.com,+1 714 856 8358,,,,.,,United States,"",2025-05-26,2025-06-02,7,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-05-24., booker_is_genius +smoking preference: Non-Smoking","RESERVARTION THRU EXPEDIA // +CONFIRMATION SENRT FEB08 // +CREDIT CARD OK, VIRTUAL CARD FOR CHARGE // +RATE 316.47 USD + TAXES // +GENIUS DISCOUNT 10% // +SUITE ANGEL VIEW // +STAY MAY 26- JUN 02 // +FEB08 2025GV",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,2215.35,3194.55,0.0,0.0,0.0,425.36,0.0,0.0,0.0,3194.55,3194.55,2,0,0,1,,,0,0.0,false,"",false,0,553.8375,Room 106,"2787-1, 2787-2" +SMP-2025031438749800,2025-03-14,Hacienda San Angel,Simple Booking,,Teresa,Ochoa de Gil,dgiloc@gmail.com,+16505449548,,,,,,,"",2025-05-26,2025-05-27,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $450.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMNATION SENT MARC14/2025 +OK MARIANA MARCH14/2025",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,450.0,562.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,562.5,562.5,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 122,2764-1 +EXP-2160925560,2025-03-23,Hacienda San Angel,Expedia,,Melissa,Raymond,36fhniu84j@m.expediapartnercentral.com,1 801 9715960,,,,,,,,2025-05-26,2025-05-27,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 402.48, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPVIPPREM.COM // +CONFIRMATION SENT MAR242025 // +CREDIT CARD INFORMATION OK // +RATE $ 335.40 USD + TAXES // +STAY MAY26-272025 // +SUITE CROWN VIEW // +SUBMITED MAR242025NGR//",,Cancelled,2025-05-23 10:09:33,Crown View - Junior Suite,Crown View - Standard Rate,335.4,419.25,0.0,0.0,0.0,0.0,0,0.0,0.0,419.25,0,2,0,0,1,,,0,419.25,false,"",false,0,83.85,Room 112,"" +EXP-2199330799,2025-05-16,Hacienda San Angel,Expedia,,LUCY,CHEN,5b3wsiq7ef@m.expediapartnercentral.com,34 871180461,,,,,,,,2025-05-26,2025-05-28,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 939.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $391.50 +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MAY16/25 +OK MARIANA MAY16/25",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,783.0,1019.28,0.0,0.0,0.0,40.53,0.0,0.0,0.0,1019.28,1019.28,2,0,0,1,,,0,0.0,false,"",false,0,195.75,Room 121,2771-1 +LH25052648324373,2025-05-26,Hacienda San Angel,Extranet,,Michael Jon,Watters,info@haciendasanangel.com,"",,,,,,,,2025-05-26,2025-05-27,1,,"","",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,340.0,425.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,425.0,425.0,2,0,0,1,,,0,0.0,false,"",false,0,85.0,Room 112,2767-1 +MMS-OBH25051304065401-2843403,2025-05-13,Hacienda San Angel,Mr and Mrs Smith,,Mary,Mell,MJMELL@COMCAST.NET,,,,,,,,,2025-05-27,2025-05-31,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $267.70 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MAY12/25 +OK MARIANA MAY12/25",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,1070.78,1563.75,0.0,0.0,0.0,225.27,0.0,0.0,0.0,1563.75,1563.75,2,0,0,1,,,0,0.0,false,"",false,0,267.695,Room 112,2778-1 +EXP-2158262486,2025-03-19,Hacienda San Angel,Expedia,,Jose,Pastor,xkabbc2mn8@m.expediapartnercentral.com,0 0 3105677069,,,,,,,,2025-05-28,2025-06-02,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 2 Double Beds, Non-Smoking, Remittance amount: 1,826.64, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION TRHU EXP // +CONFIRMATION SENT MAR19 // +RATE $ 304.44 USD + TAX // +PROMO EXP GOLD 10% DISC // +CREDIT CAR INFORMATION OK VIRTUAL CARD FOR CHARGE // +SUITE SAN GABRIEL // +STAY MAY 28- JUN 02 2025 // +MAR192025GV",,Cancelled,2025-05-05 17:02:02, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1522.2,1902.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1902.75,0,2,0,0,1,,,0,1902.75,false,"",false,0,380.55,Room 118,"" +SMP-2025043039840109,2025-04-30,Hacienda San Angel,Simple Booking,,Sands,McKinley,sands@capven.net,+12536864238,,,,,,,"",2025-05-28,2025-05-31,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE CELESTIAL $346.25 + TAXES +RATE $448.33 + TAXES +CREDIT CARD INFO AMEX CVV PENDING +CONFIRMATION SENT APRIL 30/2025 +OK MARIANA APRIL30/2025",,Checked-out,""," Celestial - Royal Suite, Vista de Santos - Master Suite","Celestial - Standard Rate,Vista de Santos - Standard Rate",2730.0,3658.5,0.0,0.0,0.0,246.0,0.0,0.0,0.0,3658.5,3658.5,2,0,0,2,,,0,0.0,false,"",false,0,682.5,"Room 103, Room 121",2779-1 +EXP-2200458160,2025-05-17,Hacienda San Angel,Expedia,,TANUS,SHIDID,wqm5h4x862@m.expediapartnercentral.com,34 871180461,,,,,,,,2025-05-28,2025-05-29,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 324.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT MAY 17 // +CREDIT CARD INFORMATION +RATE $ 270 USD + TAX // +NO PORMO // +SUITE SERAFIN // +STAY MAY 28- 29 2025 // +MAY172025GV",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,270.0,337.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,337.5,337.5,2,0,0,1,,,0,0.0,false,"",false,0,67.5,Room 110,"2773-1, 2773-2" +SMP-2025031338727619,2025-03-13,Hacienda San Angel,Simple Booking,,Chris,Baughman,chrisbaughmanjr@gmail.com,+19795751283,,,,,,,"",2025-05-29,2025-06-02,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $393.60+ TAXES +NO PROMO +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT MARC13/2025 +OK MARIANA MARCH13/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1574.4,2456.79,0.0,0.0,0.0,488.79,0.0,0.0,0.0,2456.79,2456.79,2,0,0,1,,,0,0.0,false,"",false,0,393.6,Room 107,"2765-1, 2765-2, 2765-3" +BDC-4389596956,2025-04-05,Hacienda San Angel,Booking.com,,Elisa,Marquez,emarqu.850951@guest.booking.com,+1 312 401 7001,,,,,,United States,"",2025-05-29,2025-05-31,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-05-27. +Approximate time of arrival: between 15:00 and 16:00 +Celebrando nuestro aniversario de bodas, booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $418.50 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT APRIL05/2025 +OK MARIANA APRIL05/25 + + +CELEBRATE ANNIVERSARY",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,837.0,1169.69,0.0,0.0,0.0,123.44,0.0,0.0,0.0,1169.69,1169.69,2,0,0,1,,,0,0.0,false,"",false,0,209.25,Room 119,"2776-1, 2776-2" +EXP-2170623509,2025-04-06,Hacienda San Angel,Expedia,,Cynthia,Ramos,ye75k03pfe@m.expediapartnercentral.com,1 510 2134563,,,,,,,,2025-05-29,2025-05-30,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 388.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT ARP052025 // +CREDIT CARD INFORMATION OK // +RATE $ 324 USD + TAXES // +STAY MAY29-302025 // +SUITE MILAGROS // +SUBMITED APR052025NGR//",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,324.0,320.0,0.0,0.0,0.0,-85.0,0.0,0.0,0.0,320.0,405.0,2,0,0,1,,,0,-85.0,false,"",false,0,81.0,Room 102,2774-1 +EXP-2186592426,2025-04-29,Hacienda San Angel,Expedia,,Ernest,Trujillo,evecx0aubb@m.expediapartnercentral.com,1 505 3209125,,,,,,,,2025-05-30,2025-05-31,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 491.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $409.50 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL 28/25 +OK MARIANA APRIL28/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,409.5,712.71,0.0,0.0,0.0,200.83,0.0,0.0,0.0,712.71,712.71,2,0,0,1,,,0,0.0,false,"",false,0,102.375,Room 122,2777-1 +LH25052848370562,2025-05-28,Hacienda San Angel,Extranet,,Adela,Micha Zaga,ines@haciendasanangel.com,"",,,,,,,,2025-05-30,2025-05-31,1,,"","Complimentary: Habitación con desayuno continental incluido. +- Con cargo a Fideicomiso – todo lo demás que soliciten. + +Fideicomiso de PV se encarga de sus gastos, A&B de ambas habitaciones, no ofrecer alcohol premium. +Es posible que quieran cenar hoy en el restaurante. +No solicitaron masajes* +la cuenta final será enviada a mi correo por favor + +Reportera / Conductora en GArden y Celestial +Hija de la conductora y Marido ( en Milagros y CV) +**Avisar de cambio de habitacion ( al parecer ya estan enterados pero para que no haya confusion) + +No solicitar tarjeta de credito. + +contacto de Fideicomiso: +JOel Ocampo +joel@visitpuertovallarta.com +322 1431917 + + +Therese y esposo llegan al aeropuerto a la 15:20. +Adela, llega via terrestre cerca de las 6 pm.",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,330.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,1,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,2781-1 +LH25052848370574,2025-05-28,Hacienda San Angel,Extranet,,Therese,Gotlib Micha,ines@haciendasanangel.com,"",,,,,,,,2025-05-30,2025-05-31,1,,"","Complimentary: Habitación con desayuno continental incluido. +- Con cargo a Fideicomiso – todo lo demás que soliciten. + +Fideicomiso de PV se encarga de sus gastos, A&B de ambas habitaciones, no ofrecer alcohol premium. +Es posible que quieran cenar hoy en el restaurante. +No solicitaron masajes* +la cuenta final será enviada a mi correo por favor + +Reportera / Conductora en GArden y Celestial +Hija de la conductora y Marido ( en Milagros y CV) +**Avisar de cambio de habitacion ( al parecer ya estan enterados pero para que no haya confusion) + +No solicitar tarjeta de credito. + +contacto de Fideicomiso: +JOel Ocampo +joel@visitpuertovallarta.com +322 1431917 + + +Therese y esposo llegan al aeropuerto a la 15:20. +Adela, llega via terrestre cerca de las 6 pm.",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,330.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 102,2780-1 +EXP-X-415821066,2025-02-18,Hacienda San Angel,Expedia,,Montague,Claybrook,lxn35qabci@m.expediapartnercentral.com,1 2156503146,,,,,,,,2025-05-31,2025-06-03,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,015.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP.COM // +CONFIRMATION SENT FEB182025// +CREDIT CARD INFORMATION OK// +RATE $282 USD + TAXES // +STAY MAY31-JUN022025 // +SUITE GARDEN // +SUBMITED FEB182025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,846.0,1079.03,0.0,0.0,0.0,21.53,0.0,0.0,0.0,1079.03,1079.03,1,0,0,1,,,0,0.0,false,"",false,0,211.5,Room 110,2790-1 +SMP-2025041039398966,2025-04-10,Hacienda San Angel,Simple Booking,,Michael,Waldman,MWaldman1@outlook.com,+16107454410,,,,,,,"",2025-05-31,2025-06-02,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $287.00 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT APRIL10/25 +OK MARIANA APRIL10/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,574.0,1117.15,0.0,0.0,0.0,399.65,0.0,0.0,0.0,1117.15,1117.15,2,0,0,1,,,0,0.0,false,"",false,0,143.5,Room 102,"2789-1, 2789-2" +EXP-2175798839,2025-04-13,Hacienda San Angel,Expedia,,Jeremy,Mickel,otp1u3hie2@m.expediapartnercentral.com,1 3462683081,,,,,,,,2025-05-31,2025-06-01,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 383.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR132025 // +CREDIT CARD INFORMATION OK // +RATE $ 319.50 USD + TAXES // +STAY MAY31-JUN012025 // +SUITE ANGEL DOME // +SUBMITED APR132025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,319.5,399.38,0.0,0.0,0.0,0.0,0.0,0.0,0.0,399.38,399.38,2,0,0,1,,,0,0.0,false,"",false,0,79.875,Room 113,"2783-1, 2783-2" +EXP-2175799353,2025-04-13,Hacienda San Angel,Expedia,,Jeremy,Mickel,lgh76bmhn1@m.expediapartnercentral.com,1 3462683081,,,,,,,,2025-05-31,2025-06-01,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 399.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR132025 // +CREDIT CARD INFORMATION OK // +RATE $ 333 USD + TAXES // +STAY MAY31-JUN012025 // +SUITE GARDEN OF ANGELS// +SUBMITED APR132025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,333.0,455.51,0.0,0.0,0.0,39.26,0.0,0.0,0.0,455.51,455.51,2,0,0,1,,,0,0.0,false,"",false,0,83.25,Room 109,"2782-1, 2782-2" +EXP-2175799758,2025-04-13,Hacienda San Angel,Expedia,,Jeremy,Mickel,72o3obmcl9@m.expediapartnercentral.com,1 3462683081,,,,,,,,2025-05-31,2025-06-01,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 399.60, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR132025 // +CREDIT CARD INFORMATION OK // +RATE $ 333 USD + TAXES // +STAY MAY31-JUN012025 // +SUITE CROWN VIEW// +SUBMITED APR132025NGR//",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,333.0,435.25,0.0,0.0,0.0,19.0,0.0,0.0,0.0,435.25,435.25,2,0,0,1,,,0,0.0,false,"",false,0,83.25,Room 112,2785-1 +BDC-4722235529,2025-05-07,Hacienda San Angel,Booking.com,,Patrick,Russel,prusse.162858@guest.booking.com,+61 415 348 030,,,,.,,Australia,"",2025-05-31,2025-06-02,2,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAY06 // +RATE $ 382.5 USD + TAX // +NO PROMO // +NO DISCOUNT // +SUITE SAN GABRIEL // +STAY MAY 31- JUN 02 2025 // +OK CREDIT CARD INFO FORCHARGE // +MAY062025GV",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,765.0,1290.4,0.0,0.0,0.0,334.15,0.0,0.0,0.0,1290.4,1290.4,1,0,0,1,,,0,0.0,false,"",false,0,191.25,Room 118,"2788-1, 2788-2" +LH25052848370309,2025-05-28,Hacienda San Angel,Extranet,,Adela,Micha Zaga,ines@haciendasanangel.com,"",,,,,,,,2025-05-31,2025-06-02,2,,"","Complimentary: Habitación con desayuno continental incluido. +- Con cargo a Fideicomiso – todo lo demás que soliciten. + +Fideicomiso de PV se encarga de sus gastos, A&B de ambas habitaciones, no ofrecer alcohol premium. +Es posible que quieran cenar hoy en el restaurante. +No solicitaron masajes* +la cuenta final será enviada a mi correo por favor + +Reportera / Conductora en GArden y Celestial +Hija de la conductora y Marido ( en Milagros y CV) +**Avisar de cambio de habitacion ( al parecer ya estan enterados pero para que no haya confusion) + +No solicitar tarjeta de credito. + +contacto de Fideicomiso: +JOel Ocampo +joel@visitpuertovallarta.com +322 1431917 + + +Therese y esposo llegan al aeropuerto a la 15:20. +Adela, llega via terrestre cerca de las 6 pm.",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,800.0,150.13,0.0,0.0,0.0,150.13,0,0.0,0.0,150.13,0,1,0,0,1,,,0,150.13,false,"",false,0,0,Room 103,"2786-1, 2786-2, 2786-3" +LH25052848370449,2025-05-28,Hacienda San Angel,Extranet,,Therese,Gotlib Micha,ines@haciendasanangel.com,"",,,,,,,,2025-05-31,2025-06-01,1,,"","Complimentary: Habitación con desayuno continental incluido. +- Con cargo a Fideicomiso – todo lo demás que soliciten. + +Fideicomiso de PV se encarga de sus gastos, A&B de ambas habitaciones, no ofrecer alcohol premium. +Es posible que quieran cenar hoy en el restaurante. +No solicitaron masajes* +la cuenta final será enviada a mi correo por favor + +Reportera / Conductora en GArden y Celestial +Hija de la conductora y Marido ( en Milagros y CV) +**Avisar de cambio de habitacion ( al parecer ya estan enterados pero para que no haya confusion) + +No solicitar tarjeta de credito. + +contacto de Fideicomiso: +JOel Ocampo +joel@visitpuertovallarta.com +322 1431917 + + +Therese y esposo llegan al aeropuerto a la 15:20. +Adela, llega via terrestre cerca de las 6 pm.",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,380.0,48.13,0.0,0.0,0.0,48.13,0,0.0,0.0,48.13,0,2,0,0,1,,,0,48.13,false,"",false,0,0,Room 121,"2784-1, 2784-2, 2784-3" +EXP-X-402379465,2025-01-24,Hacienda San Angel,Expedia,,RACHEL,BAXTER,0pnlkg7j7r@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-02,2025-06-06,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,532.16, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT JAN242025// +CREDIT CARD INFORMATION OK// +RATE $ 319.20 USD + TAXES // +STAY JUN02-062025// +SUITE // ANGEL VIEW +SUBMITED // JAN252025NGR",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1276.8,1907.43,0.0,0.0,0.0,311.43,0.0,0.0,0.0,1907.43,1907.43,2,0,0,1,,,0,0.0,false,"",false,0,319.2,Room 106,2796-1 +SMP-2025031538771147,2025-03-15,Hacienda San Angel,Simple Booking,,Todd,Phillips,todd.phillips@blumoana.com,8082647777,,,,,,,"",2025-06-02,2025-06-06,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR 15 // +RATE $ 344.40 USD + TAX // +CREDIT CARD INFORMATION MASTERCARD, CVV PENDING // +NO PROMO // +SECRET RATE // +SUITE CELESTIAL // +STAY JUN 02- 06 2025 // +MAR152025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1377.6,2045.8,0.0,0.0,0.0,323.8,0.0,0.0,0.0,2045.8,2045.8,2,0,0,1,,,0,0.0,false,"",false,0,344.4,Room 103,2795-1 +SMP-2025051240141578,2025-05-12,Hacienda San Angel,Simple Booking,,masoud,bashirtash,bashirtashm@yahoo.com,+16612044855,,,,,,,"",2025-06-02,2025-06-04,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $410.00 + TAXES +SECRET RATE +CREDIT CARD MC CVV PENDING +CONFIRMATION SENT MAY12/25 +OK MARIANA MAY12/25",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,820.0,2033.88,0.0,0.0,0.0,1008.88,0.0,0.0,0.0,2033.88,2033.88,1,0,0,1,,,0,0.0,false,"",false,0,205.0,Room 107,2792-1 +SMP-2025051240141700,2025-05-12,Hacienda San Angel,Simple Booking,,masoud,bashirtash,bashirtashm@yahoo.com,+16612044855,,,,,,,"",2025-06-02,2025-06-04,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $248.05 + TAXES +SECRET RATE +CREDIT CARC MC CVV PENDING +CONFIRMATION SENT MAY12/25 +OK MARIANA MAY12/25",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,496.1,674.53,0.0,0.0,0.0,54.4,0.0,0.0,0.0,674.53,674.53,1,0,0,1,,,0,0.0,false,"",false,0,124.025,Room 113,2791-1 +MMS-OBH25051609124203-2846970,2025-05-16,Hacienda San Angel,Mr and Mrs Smith,,Maureen,Eldridge,MAUREENEELDRIDGE@GMAIL.COM,,,,,,,,,2025-06-02,2025-06-05,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $320.40 +TAXES +HYATT +VIRTUAL CREDIT CARD +CONFIRMATION SENT MAY16/25 +OK MARIANA MAY16/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,961.2,1245.72,0.0,0.0,0.0,44.22,0.0,0.0,0.0,1245.72,1245.72,2,0,0,1,,,1051.3,0.0,false,"",false,0,240.3,Room 122,2793-1 +SMP-2025052140358995,2025-05-21,Hacienda San Angel,Simple Booking,,Ting yun,Cheng,ashleycheng1998@gmail.com,+19096786169,,,,,,Taiwan,"",2025-06-02,2025-06-06,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $266..50 + TAXES +SECRET RATE +CREDIT CARD INFO OK +CONFIRMATION SENT MAY21/2025 +OK MARIANA + + + +ON MAY 25 SHE CLLED TO MOVE TO SAN GABRIEL SUITE, THIS RESERVATION WAS ORGINALLY TO GARDEN //OK MARIANA + +ARRIVED 4 PAX WE CHARGE $100.00 P/ PERSON P/ NIGHT +LAST NIGHT WILL ONLY STAY 3 PAX",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1066.01,2631.13,0.0,0.0,0.0,1298.62,0.0,0.0,0.0,2631.13,2631.13,2,0,0,1,,,0,0.0,false,"",false,0,266.5025,Room 118,2797-1 +MMS-OBH25050402105108-2833937,2025-05-04,Hacienda San Angel,Mr and Mrs Smith,,Phillip,Small,PHIL@PWSMALL.COM,,,,,,,,,2025-06-03,2025-06-04,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH + RATE $280.80 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MAY03/25 +OK MARIANA MAY03/25",,Cancelled,2025-05-04 09:15:55, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,280.8,365.63,0.0,0.0,0.0,14.63,0,0.0,0.0,365.63,0,2,0,0,1,,,0,365.63,false,"",false,0,70.2,Room 121,"" +MMS-OBH25050416173201-2834383,2025-05-04,Hacienda San Angel,Mr and Mrs Smith,,Phillip,Small,PHIL@PWSMALL.COM,,,,,,,,,2025-06-04,2025-06-05,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $329.47 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +OK MARIANA MAY04/25",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,329.47,429.0,0.0,0.0,0.0,17.16,0.0,0.0,0.0,429.0,429.0,2,0,0,1,,,0,0.0,false,"",false,0,82.3675,Room 119,2794-1 +EXP-2200312750,2025-05-17,Hacienda San Angel,Expedia,,MARC,FRANKEL,"",1 5033188204,,,,,,,,2025-06-04,2025-06-10,6,,"Hotel Collect Booking, 2 Double Beds, Non-Smoking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXP // +CONFIRMATION SENT MAY 17 // +RATE $ 306.75 USD + TAX +PROMO BLUE DISCOUNT 10% // +CREDIT CARD INFORMATION OK AMEX // +SUITE SAN GABRIEL // +STAY JUN 04- 10 2025 // +MAY172025GV",,Cancelled,2025-05-23 10:57:05, San Gabriel - Junior Suite,San Gabriel - Standard Rate,1840.5,2300.63,0.0,0.0,0.0,0.0,0,0.0,0.0,2300.63,0,2,0,0,1,,,0,2300.63,false,"",false,0,460.125,Room 118,"" +EXP-2204906768,2025-05-23,Hacienda San Angel,Expedia,,MARC,FRANKEL,"",1 5033188204,,,,,,,,2025-06-04,2025-06-08,4,,"Hotel Collect Booking, 1 King Bed, Non-Smoking, Hotel Collect Booking Collect Payment From Guest.","EXPEDIA +JUN04-082025 +CC OK +$298.12 + TAX +MILAGROS +MAY23-052025 NGR",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1192.5,1729.63,0.0,0.0,0.0,239.0,0.0,0.0,0.0,1729.63,1729.63,2,0,0,1,,,0,0.0,false,"",false,0,298.125,Room 102,2799-1 +BDC-4765602812,2025-04-04,Hacienda San Angel,Booking.com,,priscilla,cardenas,pcarde.142973@guest.booking.com,+1 310 948 4711,,,,.,,United States,"",2025-06-05,2025-06-08,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $364.50 + TAXES + NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT ARPIL04/2025 +OK MARIANA APRIL04/25",,Cancelled,2025-04-07 14:41:22, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1093.5,1366.88,0.0,0.0,0.0,0.0,0,0.0,0.0,1366.88,0,2,0,0,1,,,0,1366.88,false,"",false,0,273.375,Room 121,"" +SMP-2025042039612428,2025-04-20,Hacienda San Angel,Simple Booking,,Ernie,Florez,florezconsulting@gmail.com,+15103182484,,,,,,,"",2025-06-05,2025-06-08,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $440.00 + TAXES +NO PROMO +CREDIT CARD INFO AMEX CCVV PENDING +CONFIRMATION SENT APRIL20/25 +OK MARIANA ZAVALA APRIL20/25",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1320.0,2273.46,0.0,0.0,0.0,623.46,0.0,0.0,0.0,2273.46,2273.46,2,0,0,1,,,0,0.0,false,"",false,0,330.0,Room 119,2798-1 +MMS-OBH25050219490906-2832827,2025-05-02,Hacienda San Angel,Mr and Mrs Smith,,James,Jenkins,JJENKINS32@GMAIL.COM,,,,,,,,,2025-06-05,2025-06-11,6,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $ 282.67 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +COMFIRMATION SENT MAY02/25 +OK MARIANA MAY02/25",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1696.03,2708.15,0.0,0.0,0.0,588.11,0.0,0.0,0.0,2708.15,2708.15,1,0,0,1,,,0,0.0,false,"",false,0,424.0075,Room 121,2809-1 +LH25030946622579,2025-03-09,Hacienda San Angel,Extranet,,Paul,Gomez,pgomez100@msn.com,322 173 9753,,,,,,,,2025-06-06,2025-06-08,2,,"","GIFT CERTIFICATE SPCA PV VALID FOR: + +2 NIGHT STAY IN A SERAPHIN SUITE +1 DINNER FOR 2 PEOPLE +VALUED IN $2,000 USD + +RESERVED BY +MAR092025NGR",,Cancelled,2025-05-13 17:29:38, Angels View - Master Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 106,"" +EXP-2166123225,2025-03-31,Hacienda San Angel,Expedia,,Alba Elizabeth,Sandoval,ydqeadl2qk@m.expediapartnercentral.com,1 818 4694958,,,,,,,,2025-06-06,2025-06-09,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,296.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $360.00 + TAXES +NO PROMO +CREDIT CARD OK +CONFRIMATION SENT MARCH30/25 +OK MARIANA MARCH30/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1080.0,1350.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1350.0,1350.0,2,0,0,1,,,0,0.0,false,"",false,0,270.0,Room 122,2803-1 +EXP-X-427513026,2025-03-08,Hacienda San Angel,Expedia,,MADELEINE,DIBIASI,3ncva5us48@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-07,2025-06-08,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 324.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT MAR082025 // +CREDIT CARD INFORMATION OK// +RATE $ 270 USD + TAXES // +STAY JUN7-082025 // +SUITE ANGEL DOME // +SUBMITED MAR082025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,270.0,452.37,0.0,0.0,0.0,114.87,0.0,0.0,0.0,452.37,452.37,2,0,0,1,,,0,0.0,false,"",false,0,67.5,Room 113,2801-1 +EXP-2152245984,2025-03-08,Hacienda San Angel,Expedia,,MADELEINE,DIBIASI,5fxrqhi6vf@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-07,2025-06-08,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 324.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT MAR082025 // +CREDIT CARD INFORMATION OK// +RATE $ 270 USD + TAXES // +STAY JUN7-082025 // +SUITE SERAFIN // +SUBMITED MAR082025NGR//",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,270.0,337.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,337.5,337.5,1,0,0,1,,,0,0.0,false,"",false,0,67.5,Room 110,2800-1 +EXP-X-406425279,2025-01-31,Hacienda San Angel,Expedia,,ROSENDO,TREJO-VEGA,rru3tuuts7@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-08,2025-06-11,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,451.52, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $ 403.20 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT FEBRUARY 1ST/2025 +OK MARIANA FEBRUARY1ST/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1209.6,1533.53,0.0,0.0,0.0,21.53,0.0,0.0,0.0,1533.53,1533.53,2,0,0,1,,,0,0.0,false,"",false,0,302.4,Room 107,2808-1 +EXP-2193885432,2025-05-08,Hacienda San Angel,Expedia,,Parmis,Khodadoustan,1p9k69k5w8@m.expediapartnercentral.com,1 651 4440433,,,,,,,,2025-06-08,2025-06-11,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATIO THRU EXP // +CONFIRMATION SENT MAY 8 // +CREDIT CARD INFO VISA OK // +RATE $ 293.7 USD + TAX // +SUITE CROWN VIEW // +STAY JUN 08- 112025 // +PROMOTIONMOVIL SPECIAL 11% // +MAY082025GV",,Cancelled,2025-06-05 12:32:22,Crown View - Junior Suite,Crown View - Standard Rate,881.1,1101.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1101.38,0,2,0,0,1,,,0,1101.38,false,"",false,0,220.275,Room 112,"" +EXP-2198565625,2025-05-15,Hacienda San Angel,Expedia,,UJJWAL,THUKRAL,sgqnjjxlke@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-08,2025-06-10,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 864.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $360.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD INFO +CONFIRMATION SENT MAY15/25 +OK MARIANA MAY15/25",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,720.0,946.53,0.0,0.0,0.0,46.53,0.0,0.0,0.0,946.53,946.53,2,0,0,1,,,0,0.0,false,"",false,0,180.0,Room 103,"2802-1, 2802-2" +SMP-2025052840540254,2025-05-28,Hacienda San Angel,Simple Booking,,Barry,Burns,bmbwiz@gmail.com,+13107339767,,,,,,,"",2025-06-08,2025-06-09,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $311.60+ TAXES +SECRET RATE +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT MAY28/25 +OK MARIANA MAY28/25",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,311.6,411.03,0.0,0.0,0.0,21.53,0.0,0.0,0.0,411.03,411.03,1,0,0,1,,,0,0.0,false,"",false,0,77.9,Room 106,2804-1 +SMP-2025052840540321,2025-05-28,Hacienda San Angel,Simple Booking,,Matthew,Mesher,matthewmesher@gmail.com,+18183174917,,,,,,,"",2025-06-08,2025-06-09,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $305.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV VISA PENDING +CONFIRMATION SENT MAY28/25 +OK MARIANA MAY28/25",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,305.0,381.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,381.25,381.25,2,0,0,1,,,0,0.0,false,"",false,0,76.25,Room 113,2806-1 +SMP-2025060440723877,2025-06-04,Hacienda San Angel,Simple Booking,,shaan,mistry,shaan.mistry@gmail.com,+4407730551404,,,,,,United Kingdom,"",2025-06-08,2025-06-09,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT JUN 04 // +CREDIT CARD INFORMATION AMEX PENDING CVV // +RATE 4 305 USD + TAX // +SUITE SERAFIN // +STAY JUN 08-09 2025 // +NO PROMO // +JUN042025GV",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,305.0,381.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,381.25,381.25,1,0,0,1,,,0,0.0,false,"",false,0,76.25,Room 110,2805-1 +EXP-2169847864,2025-04-04,Hacienda San Angel,Expedia,,James,Godin,pxl3fblrxl@m.expediapartnercentral.com,1 203 5981173,,,,,,,,2025-06-10,2025-06-15,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,381.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $396.90+ TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT APRIL04/2025 +OK MARIANA APRIL04/25",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1984.5,2674.85,0.0,0.0,0.0,194.22,0.0,0.0,0.0,2674.85,2674.85,2,0,0,1,,,0,0.0,false,"",false,0,496.125,Room 119,2814-1 +EXP-2206208689,2025-05-25,Hacienda San Angel,Expedia,,Maria,Tovares,mn6vbf9244@m.expediapartnercentral.com,1 562 5443661,,,,,,,,2025-06-10,2025-06-13,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,150.03, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIAVIP +SERAFIN SUITE +JUN10-132025 +CC OK +$251.11 + TAX +MAY252025NGR",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,958.36,1331.23,0.0,0.0,0.0,133.28,0.0,0.0,0.0,1331.23,1331.23,1,0,0,1,,,0,0.0,false,"",false,0,239.59,Room 106,"2807-1, 2807-2" +SMP-2025041139424639,2025-04-11,Hacienda San Angel,Simple Booking,,Pfeiffer,Bloecker,p.bloecker@gmail.com,+12063542422,,,,,,,"",2025-06-11,2025-06-14,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $393.60 + TAXES +SECRET RATE +CREDIT CARD CVV AMEX PENDING +CONFIRMATION SENT APRIL11/25 +OK MARIANA APRIL11/25",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1180.8,2325.25,0.0,0.0,0.0,849.25,0.0,0.0,0.0,2325.25,2325.25,2,0,0,1,,,0,0.0,false,"",false,0,295.2,Room 107,"2811-1, 2811-2" +LH25051548086537,2025-05-15,Hacienda San Angel,Extranet,,Daniela,Vazquez,daniela.vazquez.1b@gmail.com,+523221600765,,,,,,,,2025-06-13,2025-06-15,2,,"","La capella exchange 2 nights +ok Inés + +habitacion con desayuno continental incluido +Cualquier otro consumo tiene costo. 15% OFF en F&B",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,655.0,176.85,0.0,0.0,0.0,176.85,0.0,0.0,0.0,176.85,176.85,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 112,2812-1 +BDC-6232333572,2025-05-31,Hacienda San Angel,Booking.com,,Katherine,Mayo,kmayo.339979@guest.booking.com,+44 7795 818602,,,,.,,United Kingdom,"",2025-06-13,2025-06-14,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-06-11., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $270.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MAY05/25 +OK MARIANA MAY31/25",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,270.0,339.66,0.0,0.0,0.0,2.16,0.0,0.0,0.0,339.66,339.66,2,0,0,1,,,0,0.0,false,"",false,0,67.5,Room 110,2810-1 +LH25060248478406,2025-06-02,Hacienda San Angel,Extranet,,Catherine,Davis,catdavis@telus.net,4035104904,,,,,,,,2025-06-13,2025-06-15,2,,"","DIRECT RESERVATION // +CONFIRMATION SENT JUN02 // +RATE $ $375 // +SUITE SAN JOSE // +STAY JUN 13- 15 2025 // +JUN022025GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,750.0,168.99,0.0,0.0,0.0,168.99,0.0,0.0,0.0,168.99,168.99,1,0,0,1,,,0,0.0,false,"",false,0,0,Room 122,2815-1 +SMP-2025033139141362,2025-03-30,Hacienda San Angel,Simple Booking,,Edward,Stuenkel,edstuenkel@gmail.com,+17342237887,,,,,,,"",2025-06-14,2025-06-20,6,,"","RESERVATION FROM SIMPLE BOOKING +RATE $$420.00 + TAXES +SECRET RATE +CREDIT CARD CVV PENDING +CONFIRMATION SENT MARCH30/25 +OK MARIANA MARCH30/25",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,2520.0,3518.97,0.0,0.0,0.0,368.97,0.0,0.0,0.0,3518.97,3518.97,2,0,0,1,,,0,0.0,false,"",false,0,630.0,Room 103,2823-1 +EXP-2215325669,2025-06-06,Hacienda San Angel,Expedia,,MICHAEL,MADRIZ,eqh3w56yhr@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-14,2025-06-17,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,506.60, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA +JUN14-172025 +CC OK +$418.50 USD + TAX +SAN MIGUEL +JUN062025NGR",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1255.5,1992.25,0.0,0.0,0.0,422.87,0.0,0.0,0.0,1992.25,1992.25,2,0,0,1,,,0,0.0,false,"",false,0,313.875,Room 107,2817-1 +SMP-2025061340962884,2025-06-13,Hacienda San Angel,Simple Booking,,Dave,Moore,dave@altsrc.net,+15033339856,,,,,,,"",2025-06-14,2025-06-15,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $325.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD VIS CVV PENDING +CONFIRMATION SENT JUNE13/2025 +OK MARIANA JUNE13/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,325.0,406.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,406.25,406.25,2,0,0,1,,,0,0.0,false,"",false,0,81.25,Room 109,"2813-1, 2813-2" +EXP-2195300109,2025-05-11,Hacienda San Angel,Expedia,,RICHARD,CHIPMAN,"",1 4088237706,,,,,,,,2025-06-15,2025-06-16,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 345.60, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA.COM +JUN15-162025 +$288 + TAX +CREDIT CARD OK +GARDEN OF ANGELS +MAY102025NGR",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,288.0,501.33,0.0,0.0,0.0,141.33,0.0,0.0,0.0,501.33,501.33,2,0,0,1,,,0,0.0,false,"",false,0,72.0,Room 109,2816-1 +EXP-2218735860,2025-06-11,Hacienda San Angel,Expedia,,Peter,Bazeli,h2n5qgo0q4@m.expediapartnercentral.com,86 020 89447863,,,,,,,,2025-06-17,2025-06-19,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 950.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT JUN11 // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +RATE $ 396 USD +TAX // +DISCOUNT 10% EXP BLUE PROMO // +EXP VIP // +SUITE RINCON DE ANGELES // +STAY JUN 17- 19 2025 // +JUN112025GV",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,792.0,1025.8,0.0,0.0,0.0,35.8,0.0,0.0,0.0,1025.8,1025.8,1,0,0,1,,,0,0.0,false,"",false,0,198.0,Room 119,"2819-1, 2819-2, 2819-3" +SMP-2025022038241686,2025-02-20,Hacienda San Angel,Simple Booking,,Catherine,Duchene,csduchene@gmail.com,+16235237598,,,,,,,"",2025-06-18,2025-06-19,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $311.60 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT FEB20/2025 +OK MARIANA FEB20/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,311.6,427.7,0.0,0.0,0.0,38.2,0.0,0.0,0.0,427.7,427.7,2,0,0,1,,,0,0.0,false,"",false,0,77.9,Room 106,2822-1 +EXP-2184744183,2025-04-26,Hacienda San Angel,Expedia,,Patricia,Lee,6wudjx1vfa@m.expediapartnercentral.com,1 9492920790,,,,,,,,2025-06-18,2025-06-23,5,,"Hotel Collect Booking, *********, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAPREMIUMVIP.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION OK // +RATE $ 323.36 USD + TAXES // +STAY JUN18-232025 // +SUITE VISTA DE SANTOS // +SUBMITED APR262025NGR//",,Checked-out,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1616.8,2337.63,0.0,0.0,0.0,316.63,0.0,0.0,0.0,2337.63,2337.63,2,0,0,1,,,0,0.0,false,"",false,0,404.2,Room 121,"2830-1, 2830-2" +EXP-2207630251,2025-05-27,Hacienda San Angel,Expedia,,Thomas,Wolfe,uxk63qvfnu@m.expediapartnercentral.com,1 925 7843839,,,,,,,,2025-06-18,2025-06-21,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 984.29, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA +RATE $273.41+ TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MAY27/25 +OK MARIANA MAY27/25",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,820.25,1068.37,0.0,0.0,0.0,43.06,0.0,0.0,0.0,1068.37,1068.37,1,0,0,1,,,0,0.0,false,"",false,0,205.0625,Room 109,"2820-1, 2820-2" +SMP-2025011337393217,2025-01-12,Hacienda San Angel,Simple Booking,,Allison,Harding,allisoncharding@gmail.com,+15033027405,,,,,,,"",2025-06-19,2025-06-25,6,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JAN122025 // +CREDIT CARD INFORMATION CVV PENDING// +RATE $ 393.59 USD + TAXES // +STAY JUN19-252025 // +SUITE SAN MIGUEL// +SUBMITED JAN122025NGR//",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2342.69,3256.17,0.0,0.0,0.0,327.81,0.0,0.0,0.0,3256.17,3256.17,2,0,0,1,,,0,0.0,false,"",false,0,585.6725,Room 107,"2835-1, 2835-2" +EXP-X-396809325,2025-01-16,Hacienda San Angel,Expedia,,Jess,Friedman,aefgsfpcjy@m.expediapartnercentral.com,1 800 8400032,,,,,,,,2025-06-19,2025-06-23,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,285.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP.COM // +CONFIRMATION SENT JAN152025// +CREDIT CARD INFORMATION OK // +RATE $ 267.75 USD + TAXES // +STAY JUN19-232025 // +SUITE ANGEL DOME // +SUBMITED JAN152025NGR//",,Checked-out,"",Crown View - Junior Suite,Manual,1071.0,1518.98,0.0,0.0,0.0,180.23,0.0,0.0,0.0,1518.98,1518.98,2,0,0,1,,,0,0.0,false,"",false,0,267.75,Room 112,"2821-1, 2821-2" +EXP-2220133987,2025-06-13,Hacienda San Angel,Expedia,,Ryan,Rubin,ku6gcsjrw5@m.expediapartnercentral.com,1 888 2545518,,,,,,,,2025-06-20,2025-06-22,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 707.40, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA +JUN122025 +CC OK +$294.75 USD +TAX +JUN20-222025 +MILAGROS +JUN122025NGR",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,589.5,796.62,0.0,0.0,0.0,59.74,0.0,0.0,0.0,796.62,796.62,2,0,0,1,,,0,0.0,false,"",false,0,147.375,Room 102,2826-1 +SMP-2025061841077545,2025-06-18,Hacienda San Angel,Simple Booking,,kathryn lynn,adcock,adcock.lynn@gmail.com,+12504029962,,,,,,,"",2025-06-20,2025-06-23,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $328.00 USD + TAXES +SECRET RATE +CREDIT CARD MASETR CARD OK +CONFIRMATION SENT JUNE17/25 +OK MARIANA JUNE17/25",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,984.0,1230.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1230.0,1230.0,2,0,0,1,,,0,0.0,false,"",false,0,246.0,Room 103,2828-1 +EXP-2224155155,2025-06-18,Hacienda San Angel,Expedia,,Valeria,Rodriguez Garcia,j9wqmjlytu@m.expediapartnercentral.com,0 0 8136431080,,,,,,,,2025-06-20,2025-06-22,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 950.40, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA +JUN182025 +JUN20-222025 +RINCÓN OF ANGELS +$396 USD + TAX +CC OK +JUN182025NGR",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,792.0,1329.8,0.0,0.0,0.0,339.8,0.0,0.0,0.0,1329.8,1329.8,2,0,0,1,,,0,0.0,false,"",false,0,198.0,Room 119,"2825-1, 2825-2" +BDC-4889547750,2025-05-01,Hacienda San Angel,Booking.com,,David,Gonzales,dgonza.136749@guest.booking.com,+1 619 247 5312,,,,.,,United States,"",2025-06-21,2025-06-24,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-06-19., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAY 01 // +RATE $ 309.17 USD + TAX // +GENIUS DISCOUNT 10% // +VIRTUAL CARD FOR CHARGE // +SUITE ANGELS VIEW // +STAY JUN 21- 24 2025 // +MAY012025GV",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,927.45,1209.8,0.0,0.0,0.0,50.49,0.0,0.0,0.0,1209.8,1209.8,2,0,0,1,,,0,0.0,false,"",false,0,231.8625,Room 106,"2832-1, 2832-2, 2832-3, 2832-4" +SMP-2025060140637071,2025-06-01,Hacienda San Angel,Simple Booking,,Carey,Eskesen,carey.eskesen@gmail.com,+13032576681,,,,,,,"",2025-06-21,2025-06-22,1,,"","SIMPLEBOOKING.COM +JUN012025 +CREDIT CARD CVV PENDIENT +GARDEN OF ANGELS +$266.50 USD + TAX +JUN21-222025 +JUN012025NGR",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,266.5,355.93,0.0,0.0,0.0,22.8,0.0,0.0,0.0,355.93,355.93,2,0,0,1,,,0,0.0,false,"",false,0,66.625,Room 109,2827-1 +EXP-2213207195,2025-06-04,Hacienda San Angel,Expedia,,ROSIO,SANCHEZ,"",1 8327661841,,,,,,,,2025-06-21,2025-06-23,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 815.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +RATE $339.75 USD + TAX // +VIRTUAL CARD FOR CHARGE // +BLUE DISCOUNT 10% // +SUITE SAN JOSE // +STAY JUN 21- 23 2025 // +JUN222025GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,679.5,849.38,0.0,0.0,0.0,0.0,0.0,0.0,0.0,849.38,849.38,2,0,0,1,,,0,0.0,false,"",false,0,169.875,Room 122,2829-1 +EXP-2212155588,2025-06-02,Hacienda San Angel,Expedia,,Martin,Romero,ok558jbcq5@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-06-22,2025-06-23,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 356.40, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $297.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SEND JUNE02/2025 +OK MARIANA JUNE02/25",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,297.0,449.78,0.0,0.0,0.0,78.53,0.0,0.0,0.0,449.78,449.78,2,0,0,1,,,0,0.0,false,"",false,0,74.25,Room 102,2831-1 +BDC-5065028899,2025-06-22,Hacienda San Angel,Booking.com,,Nataly,Rodriguez,nrodri.614792@guest.booking.com,+1 512 945 2151,,,,.,,United States,"",2025-06-22,2025-06-24,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-06-22., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JUN22 // +CREDIT CARD OK VIRTUAL CARD FOR CHARGE // +LAST MINUTE BOOOKING // +RATE $ 306 USD + TAXES // +GENIUS DISCOUNT 10% // +STAY JUN 22- 24 2025 // +SUITE ANGEL DOME // +JUN222025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,612.0,769.9,0.0,0.0,0.0,4.9,0.0,0.0,0.0,769.9,769.9,2,0,0,1,,,0,0.0,false,"",false,0,153.0,Room 113,2833-1 +SMP-2025061440983111,2025-06-14,Hacienda San Angel,Simple Booking,,Tracee,Hancock,Tmc7816@gmail.com,+12163465169,,,,,,,"",2025-06-23,2025-06-26,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $329.36+ TAXES +NO PROMO +CREDIT CARD MC CVV PENDING +CONFIRMATION SENT JUNE14/25 +OK MARIANA JUNE14/25",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,988.1,1553.13,0.0,0.0,0.0,318.0,0.0,0.0,0.0,1553.13,1553.13,2,0,0,1,,,0,0.0,false,"",false,0,247.025,Room 103,2836-1 +SMP-2025060440698421,2025-06-03,Hacienda San Angel,Simple Booking,,Israel,Velasquez,corkylb@icloud.com,+15622093128,,,,,,,"",2025-06-24,2025-06-28,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT JUN03 // +RATE $ 375 USD + TAXES // +NO PROMO // +SUITE SAN JOSE // +STAY JUN 24- 28 2025 // +JUN032025GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1500.0,2232.01,0.0,0.0,0.0,357.01,0.0,0.0,0.0,2232.01,2232.01,2,0,0,1,,,0,0.0,false,"",false,0,375.0,Room 122,2837-1 +BDC-6074704984,2025-06-24,Hacienda San Angel,Booking.com,,Nataly,Rodriguez,natlorenzo95@gmail.com,+1 512 945 2151,,,,.,,United States,"",2025-06-24,2025-06-25,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-06-23., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JUN23 // +CREDIT CARD OK VIRTUAL CARD FOR CHARGE // +LAST MINUTE BOOOKING // +RATE $ 306 USD + TAXES // +GENIUS DISCOUNT 10% // +STAY JUN 24- 25 2025 // +SUITE ANGEL DOME // +JUN232025NGR",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,306.0,950.4,0.0,0.0,0.0,567.9,0.0,0.0,0.0,950.4,950.4,2,0,0,1,,,0,0.0,false,"",false,0,76.5,Room 113,"2834-1, 2834-2, 2834-3" +EXP-2223592501,2025-06-17,Hacienda San Angel,Expedia,,Jacqueline,Ward,11yy3e5c7f@m.expediapartnercentral.com,1 6023951995,,,,,,,,2025-06-26,2025-06-29,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,145.01, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $318.06 + TAXES +NO PROMO +VIRTUAL CREDIT CARD +CONFIRMATION SENT JUNE17/25 +OK MARIANA JUNE17/25",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,954.18,1300.4,0.0,0.0,0.0,107.67,0.0,0.0,0.0,1300.4,1300.4,2,0,0,1,,,0,0.0,false,"",false,0,238.545,Room 106,2839-1 +MMS-OBH25050122142808-2830849,2025-05-01,Hacienda San Angel,Mr and Mrs Smith,,Kimberley,Dilley,KJD27_99@YAHOO.COM,,,,,,,,,2025-06-27,2025-06-30,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMRS.COM // +CONFIRMATION SENT MAY022025 // +CREDIT CARD INFORMATION OK // +RATE $ 239.61 USD + TAXES // +STAYJUN27-302025 // +SUITE GARDEN OF ANGELS // +SUBMITED MAY022025NGR //",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,718.85,1428.19,0.0,0.0,0.0,529.63,0.0,0.0,0.0,1428.19,1428.19,2,0,0,1,,,0,0.0,false,"",false,0,179.7125,Room 109,2842-1 +MMS-OBH25061219080800-2874662,2025-06-12,Hacienda San Angel,Mr and Mrs Smith,,Steven,Strozza,STEVENSTROZZA@GMAIL.COM,,,,,,,,,2025-06-27,2025-06-29,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $256.32 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE06/25 +OK MARIANA JUNE06/25",,Cancelled,2025-06-19 03:21:03,Angels Dome - Junior Suite,Angels Dome - Standard Rate,512.64,560.7,0.0,0.0,0.0,-80.1,0,0.0,0.0,560.7,0,2,0,0,1,,,0,560.7,false,"",false,0,128.16,Room 113,"" +MMS-OBH25062719581900-2889625,2025-06-27,Hacienda San Angel,Mr and Mrs Smith,,Franco,Saspe,FSASPE@GMAIL.COM,,,,,,,,,2025-06-27,2025-06-28,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,247.1,387.22,0.0,0.0,0.0,78.34,0.0,0.0,0.0,387.22,387.22,2,0,0,1,,,0,0.0,false,"",false,0,61.775,Room 102,2838-1 +EXP-2183115150,2025-04-24,Hacienda San Angel,Expedia,,Jamie,Marlow,6v170cp5gs@m.expediapartnercentral.com,1 217 8530048,,,,,,,,2025-06-28,2025-06-29,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 432.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR23-2025 // +CREDIT CARD INFORMATION OK // +RATE $ 360 USD + TAXES // +STAY JUN28-292025 // +SUITE CELESTIAL // +SUBMITED APR232025NGR//",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,360.0,471.53,0.0,0.0,0.0,21.53,0.0,0.0,0.0,471.53,471.53,2,0,0,1,,,0,0.0,false,"",false,0,90.0,Room 103,2841-1 +BDC-4539946644,2025-05-10,Hacienda San Angel,Booking.com,,Akira,Yoshimura,ayoshi.884825@guest.booking.com,+52 472 127 1886,,,,,,Mexico,"",2025-06-28,2025-06-29,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-06-26. +Approximate time of arrival: between 15:00 and 16:00, booker_is_genius +smoking preference: Non-Smoking","BOOKING.COM +MAY092025 +JUN28-292025 +SAN JOSE MASTER SUITE +ROOM RATE $375 USD + TAX +CREDIT CARD OK +CONFIRMATION MAY092025NGR",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,375.0,471.75,0.0,0.0,0.0,3.0,0.0,0.0,0.0,471.75,471.75,2,0,0,1,,,0,0.0,false,"",false,0,93.75,Room 122,2840-1 +LH25031646786487,2025-03-16,Hacienda San Angel,Extranet,,ALEXA,BILL,"","",,,,,,,,2025-06-29,2025-07-04,5,,,,,Cancelled,2025-03-16 18:59:05,Crown View - Junior Suite,Crown View - Package Rate,1440.0,1800.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1800.0,0,2,0,0,1,,,0,1800.0,false,"",false,0,360.0,Room 112,"" +BDC-4938448272,2025-04-23,Hacienda San Angel,Booking.com,,George,Sellner,gselln.751790@guest.booking.com,+1 808 634 5264,,,,,,United States,"",2025-06-29,2025-07-02,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-06-27. +Me and my wife are celebrating our 20th Wedding anniversary, booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING.COM // +CONFIRMATION SENT ABR 23 // +RATE $ 498.33 USD + TAX // +VIRTUAL CARD FOR CHARGE // +NO PROMO // +SUITE SAN MIGUEL // +STAY JUN 29 JUL 02 2025 // +ABR232025GV",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1480.0,2206.12,0.0,0.0,0.0,356.12,0.0,0.0,0.0,2206.12,2206.12,2,0,0,1,,,0,0.0,false,"",false,0,370.0,Room 107,2844-1 +SMP-2025031238705787,2025-03-12,Hacienda San Angel,Simple Booking,,Allen,Wing,mrallenwing@gmail.com,+12152188647,,,,,,,"",2025-06-30,2025-07-02,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR12 // +NO PORMO // +CREDIT CARD INFORMATION VISA CVV PENDING // +SUITE AV / S G+STAY JUN 30- JUL 02 2025 +RATE AV $311.60 USD + TAX // +RATE SG $ 345 USD + TAX // +SECRET RATE // +MAR122025GV",,Checked-out,""," Angels View - Master Suite, San Gabriel - Junior Suite","Angels View - Standard Rate,San Gabriel - Standard Rate",1313.2,2266.43,0.0,0.0,0.0,624.93,0.0,0.0,0.0,2266.43,2266.43,4,0,0,2,,,0,0.0,false,"",false,0,328.3,"Room 106, Room 118",2843-1 +EXP-2220011838,2025-06-13,Hacienda San Angel,Expedia,,Hillary,Lehr,9600t86bb8@m.expediapartnercentral.com,0 0 4152839503,,,,,,,,2025-06-30,2025-07-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 681.12, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay",,,Cancelled,2025-06-12 18:51:35,Crown View - Junior Suite,Crown View - Standard Rate,567.6,709.5,0.0,0.0,0.0,0.0,0,0.0,0.0,709.5,0,2,0,0,1,,,0,709.5,false,"",false,0,141.9,Room 112,"" +EXP-2220056147,2025-06-13,Hacienda San Angel,Expedia,,Hillary,Lehr,cn0sg2e9q0@m.expediapartnercentral.com,1 888 2545518,,,,,,,,2025-06-30,2025-07-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 864.00, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA +JUN122025 +JUN30-JULY2025 +CC OK +$360 USD + TAX +CELESTIAL SUITE +JUN122025NGR",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,720.0,1045.2,0.0,0.0,0.0,145.2,0.0,0.0,0.0,1045.2,1045.2,2,0,0,1,,,0,0.0,false,"",false,0,180.0,Room 103,2845-1 +LH25061348726543,2025-06-13,Hacienda San Angel,Extranet,,Murphy,Perng,murphy@matterofwine.com,"",,,,,,,,2025-07-02,2025-07-05,3,,"","This room rate was steeply discounted for this Travel Agent and her husband on their babymoon. 3 Nights for the price of 2 plus a 20% discount. + +No discounts on food or beverage. + +She promised good tips for service. Please tell me if this is not what happens.- Paula",,Checked-out,"", Angels View - Master Suite,Manual,612.0,840.07,0.0,0.0,0.0,75.07,0.0,0.0,0.0,840.07,840.07,2,0,0,1,,,0,0.0,false,"",false,0,153.0,Room 106,2846-1 +EXP-X-419429433,2025-02-23,Hacienda San Angel,Expedia,,MATTHEW T,BESMER,nqyhutsmyg@m.expediapartnercentral.com,1 877 5171344,,,,,,,,2025-07-03,2025-07-04,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 361.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE 301.50 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT FEB23/2025 +OK MARIANA FEB23/2025",,Cancelled,2025-04-28 12:59:38, Milagros - Junior Suite,Milagros - Standard Rate,301.5,376.88,0.0,0.0,0.0,0.0,0,0.0,0.0,376.88,0,2,0,0,1,,,0,376.88,false,"",false,0,75.375,Room 102,"" +BDC-4690645622,2025-05-14,Hacienda San Angel,Booking.com,,William,Waters,wwater.213795@guest.booking.com,+1 253 279 7828,,,,.,,United States,"",2025-07-03,2025-07-06,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $450.00 + TAXES +NO PROMO +CREDIT XCARD VISA CVV OK +CONFIRMATION SENT MAY13/2025 +OK MARIANA MAY13/25 + +************************ +CAMBIO ED HAB A CELESTIAL +RATE $ 434.76 USD + TAX",,Checked-out,"", San Miguel - Presidential Suite,Manual,1296.0,1740.93,0.0,0.0,0.0,120.93,0.0,0.0,0.0,1740.93,1740.93,2,0,0,1,,,0,0.0,false,"",false,0,324.0,Room 107,2848-1 +EXP-X-419429902,2025-02-23,Hacienda San Angel,Expedia,,Matthew,Besmer,r72gwhnb32@m.expediapartnercentral.com,1 559 4036367,,,,,,,,2025-07-04,2025-07-06,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 715.56, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $298.15 + NO PROMO +VIRTUAL CREDIT CARD INFO OK +CONFIRMATION SEN FEB23/2025 +OK MARIANA FEB23/2025",,Cancelled,2025-04-27 19:40:46, Milagros - Junior Suite,Milagros - Standard Rate,596.3,745.38,0.0,0.0,0.0,0.0,0,0.0,0.0,745.38,0,2,0,0,1,,,0,745.38,false,"",false,0,149.075,Room 102,"" +EXP-2193731869,2025-05-08,Hacienda San Angel,Expedia,,Alexandra,Mcguire,bl9a6uxggo@m.expediapartnercentral.com,86 021 60781960,,,,,,,,2025-07-04,2025-07-08,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,630.80, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATIO THRU EXP // +CINFIRMATION SENT MAY 8 // +CREDIT CARD INFO MASTER CARD OK // +RATE $ 339.75 USD + TAX // +SUITE SAB JOSE // +STAY JUL 4- 8 2025 // +PROMOTION BLUE DISCOUNT 10% // +MAY082025GV",,Cancelled,2025-06-28 20:21:50, San Jose - Master Suite,San Jose - Standard Rate,1359.0,1698.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1698.75,0,2,0,0,1,,,0,1698.75,false,"",false,0,339.75,Room 122,"" +BDC-4312583772,2025-05-19,Hacienda San Angel,Booking.com,,Roderick,Samonte,rsamon.894104@guest.booking.com,+1 510 674 5601,,,,.,,United States,"",2025-07-04,2025-07-08,4,,"booker_is_genius +smoking preference: Non-Smoking","BOOKING.COM +$308.81 + TAX +JULY04-082025 +ANGEL VIEW +MAY192025NGR",,Cancelled,2025-06-02 23:58:51, Angels View - Master Suite,Angels View - Standard Rate,1235.25,1553.94,0.0,0.0,0.0,9.88,0,0.0,0.0,1553.94,0,2,0,0,1,,,0,1553.94,false,"",false,0,308.8125,Room 106,"" +MMS-OB25052616022700-2857108,2025-05-26,Hacienda San Angel,Mr and Mrs Smith,,Lourdes,Debarry,lourdesd@btinternet.com,+447887567113,,x,,,,United Kingdom,x,2025-07-04,2025-07-11,7,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS // +RATE $ 261.68 USD + TAX // +15% DOSCOUNT MMS // +CREDIT CARD INFORMATION OK VIRTUAL CAR FOR CHARGE // +CHARGE TO GUEST 5% $91.59 USD // +SUITE ANGEL DOME // +STAY JULIO 4- 11 2025 // +MAY262025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1758.48,2382.97,0.0,0.0,0.0,184.87,0.0,0.0,0.0,2382.97,2382.97,2,0,0,1,,,0,0.0,false,"",false,0,439.62,Room 113,2855-1 +EXP-2221813015,2025-06-15,Hacienda San Angel,Expedia,,Guillermo,Torres,21qjwu1ejo@m.expediapartnercentral.com,1 214 2887686,,,,,,,,2025-07-04,2025-07-06,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","EXPEDIA VIP +JUN152025 +$387.20 USD + TAX +RINCÓN OF ANGELS +JULY04-062025 +JUN1520265NGR",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,774.4,883.0,0.0,0.0,0.0,-85.0,0.0,0.0,0.0,883.0,968.0,2,0,0,1,,,0,-85.0,false,"",false,0,193.6,Room 119,2847-1 +EXP-X-426509868,2025-03-06,Hacienda San Angel,Expedia,,ALEXANDRA,MCGUIRE,"",1 8135057771,,,,,,,,2025-07-05,2025-07-09,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,728.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP.COM // +CONFIRMATION SENT MAR062025// +CREDIT CARD INFORMATION OK // +RATE $ 360 USD + TAXES // +STAY JUL5-092025// +SUITE SJ // +SUBMITED MAR062025NGR//",,Cancelled,2025-05-07 12:21:17, San Jose - Master Suite,San Jose - Standard Rate,1440.0,1800.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1800.0,0,2,0,0,1,,,0,1800.0,false,"",false,0,360.0,Room 122,"" +EXP-2199140650,2025-05-15,Hacienda San Angel,Expedia,,Angela,Garcia,fditxjkmev@m.expediapartnercentral.com,1 2133007029,,,,,,,,2025-07-05,2025-07-07,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, close to second room under the name Angela Garcia, Remittance amount: 696.60, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA AGENCIA +MAY1505205 +CREDIT CARD OK +JUL05-072025 +MAY152025NGR",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,580.5,853.46,0.0,0.0,0.0,127.83,0.0,0.0,0.0,853.46,853.46,1,0,0,1,,,0,0.0,false,"",false,0,145.125,Room 109,2850-1 +EXP-2199141978,2025-05-15,Hacienda San Angel,Expedia,,Angela,Garcia,ltj797uk1h@m.expediapartnercentral.com,1 2133007029,,,,,,,,2025-07-05,2025-07-07,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 707.40, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA AGENCIA +MAY1505205 +CREDIT CARD OK +JUL05-072025 +MAY152025NGR",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,589.5,736.88,0.0,0.0,0.0,0.0,0.0,0.0,0.0,736.88,736.88,1,0,0,1,,,0,0.0,false,"",false,0,147.375,Room 112,2852-1 +SMP-2025062341204935,2025-06-22,Hacienda San Angel,Simple Booking,,Aileen,Morgan,songfemme@gmail.com,+19175823456,,,,,,,"",2025-07-06,2025-07-07,1,,"","SIMPLEBOOKING.COM +SAN MIGUEL PRESIDENTIAL SUITE +$410 USD + TAX +AAA CARD 10% DISCOUNT +JUL06-072025 +CCV PENDIENT +JUN222025NGR",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,410.0,925.3,0.0,0.0,0.0,412.8,0.0,0.0,0.0,925.3,925.3,2,0,0,1,,,0,0.0,false,"",false,0,102.5,Room 107,"2851-1, 2851-2" +EXP-2237058427,2025-07-05,Hacienda San Angel,Expedia,,TEGAN,CAMDEN,heuyt3hvji@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-07-06,2025-07-07,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 367.20, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION FROM EXPEDIA +RATE $306.00 + TAXES +NO PORMO +VIRTUAL CREDIT CARD +CONFIRMATION SENT JULY05/25 +OK MARIANA ZAVALA JULY05/25",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,306.0,670.57,0.0,0.0,0.0,288.07,0.0,0.0,0.0,670.57,670.57,2,0,0,1,,,0,0.0,false,"",false,0,76.5,Room 102,2849-1 +SMP-2025070641571491,2025-07-06,Hacienda San Angel,Simple Booking,,daniel,Gu,danielhirogu@gmail.com,+19256635637,,,,,,,"",2025-07-06,2025-07-08,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $393.60 + TAXES +SECRET RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATIONSENT JULY06/25 +OK MARIANA JULY05/2025",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,787.2,1125.99,0.0,0.0,0.0,141.99,0.0,0.0,0.0,1125.99,1125.99,2,0,0,1,,,0,0.0,false,"",false,0,196.8,Room 103,2853-1 +SMP-2025062741348449,2025-06-27,Hacienda San Angel,Simple Booking,,Fadi,Rabbat,rabbatfadi@hotmail.com,+19737800221,,,,,,,"",2025-07-07,2025-07-11,4,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JUN272025 // +CREDIT CARD INFORMATION OK // +RATE $380 USD + TAXES // +STAY JULY7-102025 // +SUITE SAN GABRIEL // +SUBMITED JUN272025NGR // + +*************** + +SOLICITO CAMBIO DE HAB +SUITE SERAFIN // +SRATE $ 301.66 USD + TAX",,Cancelled,2025-07-02 09:15:51,Serafin - Junior Suite,Serafin - Standard Rate,1205.0,1506.25,0.0,0.0,0.0,0.0,0,0.0,0.0,1506.25,0,2,0,0,1,,,0,1506.25,false,"",false,0,301.25,Room 110,"" +EXP-2235143961,2025-07-03,Hacienda San Angel,Expedia,,Aurora,Perez,krvibnpn1n@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-07-08,2025-07-09,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 540.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION FROM EXPEDIA +RATE $450.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY 2ND/2025 +OK MARIANA JULY20NS/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,450.0,1230.63,0.0,0.0,0.0,668.13,0.0,0.0,0.0,1230.63,1230.63,2,0,0,1,,,0,0.0,false,"",false,0,112.5,Room 107,"2854-1, 2854-2" +MMS-OBH25052606102507-2856596,2025-05-26,Hacienda San Angel,Mr and Mrs Smith,,Omar,Castillo,OFCASTILLO1@GMAIL.COM,,,,,,,,,2025-07-09,2025-07-13,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +RATE $ 292.50 USD + TAX // +RESERVATION FROM HYATT // +SUITE VISTA DE SANTOS // +STAY JUL 09- 013 2025 // +MAY262025GV",,Cancelled,2025-05-26 18:15:54, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1123.2,1462.5,0.0,0.0,0.0,58.5,0,0.0,0.0,1462.5,0,2,0,0,1,,,0,1462.5,false,"",false,0,280.8,Room 121,"" +LH25063049104401,2025-06-30,Hacienda San Angel,Extranet,,Fadi,Rabbat,rabbatfadi@hotmail.com,+19737800221,,,,,,United States of America,"",2025-07-10,2025-07-11,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JUN302025 // +CREDIT CARD INFORMATION OK // +RATE $300 USD + TAXES // +STAY JULY10-112025 // +SUITE SERAFÍN // +SUBMITED JUN302025NGR //",,Cancelled,2025-06-30 13:49:40,Serafin - Junior Suite,Serafin - Standard Rate,300.0,375.0,0.0,0.0,0.0,0.0,0,0.0,0.0,375.0,0,2,0,0,1,,,0,375.0,false,"",false,0,75.0,Room 110,"" +MMS-OBH25052600534907-2856455,2025-05-25,Hacienda San Angel,Mr and Mrs Smith,,D,Riess,127600WES@GMAIL.COM,,,,,,,,,2025-07-11,2025-07-14,3,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +GST AWARE OF CANCEL AND PAYMENT POLICY PLEASE BE AWARE THAT CANCELLATIONS MADE LESS THAN 48 HOURS BEFORE ARRIVAL WILL INCUR A CHARGE IN FULL.|FULL AMOUNT OF BOOKING WILL BE TAKEN AT THE TIME OF BOOKING.","RESERVATION FROM MR. SMITH +RATE $377.36 + TAXES +PROMO; HYATT +VIRTUAL CREDIT CARD +CONFIRMATION OK MAY25/25 +OK MARIANA MAY25/25",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1132.08,1349.14,0.0,0.0,0.0,-65.96,0.0,0.0,0.0,1349.14,1349.14,2,0,0,1,,,0,0.0,false,"",false,0,283.02,Room 119,2859-1 +MMS-OBH25052600553604-2856457,2025-05-25,Hacienda San Angel,Mr and Mrs Smith,,D,Riess,127600WES@GMAIL.COM,,,,,,,,,2025-07-11,2025-07-14,3,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +GST AWARE OF CANCEL AND PAYMENT POLICY PLEASE BE AWARE THAT CANCELLATIONS MADE LESS THAN 48 HOURS BEFORE ARRIVAL WILL INCUR A CHARGE IN FULL.|FULL AMOUNT OF BOOKING WILL BE TAKEN AT THE TIME OF BOOKING.","RESERVATION FROM MR. & MRES. SMITH +RATE $343.18+ TAXES +PROMO; HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION OK 25/05/25 +OK MARIANA 25/05/25",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1029.55,1687.41,0.0,0.0,0.0,400.47,0.0,0.0,0.0,1687.41,1687.41,1,0,0,1,,,0,0.0,false,"",false,0,257.3875,Room 103,"2858-1, 2858-2, 2858-3" +SMP-2025063041399065,2025-06-30,Hacienda San Angel,Simple Booking,,Nicole,M,nm10917@gmail.com,+1949-226-9771,,,,,,,"",2025-07-12,2025-07-14,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $262.40 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JUNE29/25 +OK MARIANA JUNE29/25",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,524.8,821.47,0.0,0.0,0.0,165.47,0.0,0.0,0.0,821.47,821.47,1,0,0,1,,,0,0.0,false,"",false,0,131.2,Room 109,2856-1 +MMS-OBH25071107105907-2903049,2025-07-11,Hacienda San Angel,Mr and Mrs Smith,,Quanlai,Li,LIQUANLAI1995@GMAIL.COM,,,,,,,,,2025-07-12,2025-07-14,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT JULY112025 // +CREDIT CARD INFORMATION OK // +RATE $ 256.32 USD + TAXES // +STAY JULY12-142025 // +SUITE SERAFÍN // +SUBMITED JULY112025NGR //",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,512.64,567.9,0.0,0.0,0.0,-72.9,0.0,0.0,0.0,567.9,567.9,2,0,0,1,,,0,0.0,false,"",false,0,128.16,Room 110,2857-1 +EXP-2205186065,2025-05-24,Hacienda San Angel,Expedia,,Miguel Angel,Rodriguez,kt24ygdcnq@m.expediapartnercentral.com,1 805 7204277,,,,,,,,2025-07-14,2025-07-15,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 432.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT MAY223 // +CREDIT CARD INFORMATION OK MASTERCARD // +RATE $ 360 USD + TAX // +BLUE DISCOUNT 10% // +SUITE CELESTIAL // +STAY JUL 14- 15 2025 // +MAY232025GV",,Cancelled,2025-07-12 03:46:39, Celestial - Royal Suite,Celestial - Standard Rate,360.0,450.0,0.0,0.0,0.0,0.0,0,0.0,0.0,450.0,0,2,0,0,1,,,0,450.0,false,"",false,0,90.0,Room 103,"" +MMS-OBH25060305191302-2864915,2025-06-03,Hacienda San Angel,Mr and Mrs Smith,,Steve,Witting,WITTINGSTEVE@GMAIL.COM,,,,,,,,,2025-07-17,2025-07-18,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $326.40 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENTJUNE06/25 +OK MARIANA JUNE06/25",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,326.4,357.0,0.0,0.0,0.0,-51.0,0.0,0.0,0.0,357.0,357.0,3,0,0,1,,,0,0.0,false,"",false,0,81.6,Room 118,2860-1 +LH25062949086650,2025-06-29,Hacienda San Angel,Extranet,,Rico,Amigo,rrico.1017@gmail.com,"",,,,,,,,2025-07-17,2025-07-20,3,,Angel's Rate,"ANNIVERSARY - please give the same amenities we do for paying guests. + +This is a dear acquaintance. No charge for anything. He promises to take good care of staff. Please tell me if he does not. + +He might try to pay $30 usd a day, if he does accept it but do not charge if he does not offer. If he does, it all goes to staff as the 7%. + +I told him minimum $5 a day for camarista. + +His primo y su esposa are staying here the last night as well to give him and his wife a ride to their home in El Grullo. He wants to pay for them. + +Please arrange VIP transportation for Rico and his wife on the day of arrival Alaska Airline Flight #1368 at 2:51pm- Paula",,Checked-out,"", San Miguel - Presidential Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,2862-1 +SMP-2025063041425324,2025-06-30,Hacienda San Angel,Simple Booking,,Amy,O'Brien,amy.y.obrien1@gmail.com,+13032046936,,,,,,,"",2025-07-17,2025-07-21,4,,"IF the Presidential Suite opens up, PLEASE PLEASE PLEASE let us know. Thank you!","RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT JUN302025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 480 USD + TAXES // +STAY JULY17-212025 // +SUITE CELESTIAL SUITE // +SUBMITED JUN302025NGR //",,Cancelled,2025-07-01 19:51:23, Celestial - Royal Suite,Celestial - Standard Rate,1920.0,2400.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2400.0,0,2,0,0,1,,,0,2400.0,false,"",false,0,480.0,Room 103,"" +MMS-OBH25060402520905-2866020,2025-06-04,Hacienda San Angel,Mr and Mrs Smith,,Steve,Witting,WITTINGSTEVE@GMAIL.COM,,,,,,,,,2025-07-18,2025-07-20,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION TRHU MMS // +RATE $ 241.8 USD + TAX // +NO PROMO // +VIRTUAL CARD FOR CHARGE // +SUITE ANGEL DOME // +STAY JUL 18- 20 2025 // +JUN032025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,464.26,769.38,0.0,0.0,0.0,189.05,0.0,0.0,0.0,769.38,769.38,2,0,0,1,,,0,0.0,false,"",false,0,116.065,Room 113,2861-1 +EXP-2244516905,2025-07-15,Hacienda San Angel,Expedia,,SERBAN,GIUROIU,r29vmch0oq@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-07-18,2025-07-22,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,900.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION THRU EXP // +CONFIRMATION SENT JUL15 // +RATE $ 396 USD + TAXES // +PROMO BLUE 10% DISCOUNT // +SUITE SAN JOSE // +STAY JUL 18- 22 205 // +VIRTUAL CARD FOR CHARGE // +JUL152025GV",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1584.0,1980.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1980.0,1980.0,2,0,0,1,,,0,0.0,false,"",false,0,396.0,Room 122,2867-1 +LH25062949086787,2025-06-29,Hacienda San Angel,Extranet,,Primo,de Rico,rrico.1017@gmail.com,"",,,,,,,,2025-07-19,2025-07-20,1,,Angel's Rate,"Primo de Rico in SM- No charge for anything + +Rico will pay $30 usd for staff 7% commission",,Checked-out,"", Vista de Santos - Master Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 121,2863-1 +LH25071949573380,2025-07-19,Hacienda San Angel,Extranet,,JORDAN JR,BURL EDSEL,BURLJR@GMAIL.COM,+17605180175,,,,,,,,2025-07-19,2025-07-20,1,,"","RESERVATION THRU DIRECTA.COM // +CONFIRMATION SENT JULY192025 // +CREDIT CARD INFORMATION OK // +RATE $ 320 USD + TAXES // +STAY JULY19-202025 // +SUITE GARDEN OF ANGELS // +SUBMITED JULY192025NGR//",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,320.0,400.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,400.0,400.0,1,0,0,1,,,0,0.0,false,"",false,0,80.0,Room 109,2864-1 +EXP-2218823323,2025-06-11,Hacienda San Angel,Expedia,,BLAIR,MILNE,t3pqvnfvvd@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-07-21,2025-07-26,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 2,234.77, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXP // +CONFIRMATION SENT JUN11 // +RATE $ 372.46 USD +TAX // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +MLOS 3 PACKAGE PROMO // +SUITE CELESTIAL // +STAY JUL 21- 26 2025 // +JUN112025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1862.31,2622.49,0.0,0.0,0.0,294.6,0.0,0.0,0.0,2622.49,2622.49,2,0,0,1,,,0,0.0,false,"",false,0,465.5775,Room 103,"2865-1, 2865-2" +EXP-2242040141,2025-07-11,Hacienda San Angel,Expedia,,Melissa,Raymond,gvgpuqihcb@m.expediapartnercentral.com,1 8019715960,,,,,,,,2025-07-21,2025-07-23,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 652.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXP // +CONFIRMATION SENT JUL 11 // +RATE $ 272 USD + TAX // +PROMO:MID YEARSALE 2025 // +SUITE GARDEN OF ANGELS // +STAY JUL 21- 23 2025 // +VIRTUAL CARD FOR CHARGE // +JUL112025GV",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,544.0,699.33,0.0,0.0,0.0,19.33,0.0,0.0,0.0,699.33,680.0,1,0,0,1,,,0,19.33,false,"",false,0,136.0,Room 109,"2866-1, 2866-2, 2866-3" +EXP-2208714540,2025-05-28,Hacienda San Angel,Expedia,,Burl,Jordan,owinw3663y@m.expediapartnercentral.com,1 7605180175,,,,,,,,2025-07-23,2025-07-29,6,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","EXPEDIA.COM +JUL23-292025 +CC OK +$374.54 + TAX +ANGEL VIEW +MAY282025NGR",,Cancelled,2025-07-15 07:02:38, Angels View - Master Suite,Angels View - Standard Rate,2247.25,2809.06,0.0,0.0,0.0,0.0,0,0.0,0.0,2809.06,0,1,0,0,1,,,0,2809.06,false,"",false,0,561.8125,Room 106,"" +EXP-2212938464,2025-06-03,Hacienda San Angel,Expedia,,Bijan,Massoumi,jamw0ksr3w@m.expediapartnercentral.com,+16507964427,,,,,,,,2025-07-23,2025-07-26,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,516.64, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA +JUN23-262025 +CC OK +SAN MIGUEL SUITE +JUN032025NGR + +************************************ +GUESTS DECIDED TO LEAVE THE ROOM BECAUSE THE AIR CONDITIONING WAS NOT SUFFICIENT FOR THEIR COMFORT. THE NIGHT BEFORE DEPARTURE, THEY RETURNED, USED THE ROOM, AND HAD DINNER. +CHECKED OUT JULY 25. NO EXTRA CHARGES WERE AUTHORIZED. OK, INES.",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1263.87,1701.1,0.0,0.0,0.0,121.26,0.0,0.0,0.0,1701.1,1579.84,2,0,0,1,,,0,121.26,false,"",false,0,315.9675,Room 107,"2868-1, 2868-2" +MMS-OBH25070422331906-2896923,2025-07-04,Hacienda San Angel,Mr and Mrs Smith,,Hanna,Kernazhytskaya,ANYA.V.KERN@GMAIL.COM,,,,,,,,,2025-07-23,2025-07-25,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $280.75 + TAXES +HYATT +VIRTUAL CREDIT CARD +CONFIRMATION SENT JULY04/2025 +OK MARIANA JULY04/2025",,Cancelled,2025-07-21 11:55:53,Angels Dome - Junior Suite,Angels Dome - Standard Rate,561.6,731.25,0.0,0.0,0.0,29.25,0.0,0.0,0.0,731.25,731.25,1,0,0,1,,,0,0.0,false,"",false,0,140.4,Room 113,"" +LH25072249642084,2025-07-22,Hacienda San Angel,Extranet,,MELISSA,RAYMOND,"","",,,,,,,,2025-07-23,2025-07-24,1,,"","RESERVATION DIRECTLY +SAME RATE THEY HAVE FROM PAST RESERVATION OK INES +OK MARIANA JULY22/25",,Checked-out,"", Garden of Angels - Junior Suite,Manual,272.0,751.61,0.0,0.0,0.0,411.61,0,0.0,0.0,751.61,0,2,0,0,1,,,0,751.61,false,"",false,0,68.0,Room 109,2870-1 +EXP-2250604623,2025-07-22,Hacienda San Angel,Expedia,,Francisco,Hernandez,hhnpr2p4lq@m.expediapartnercentral.com,1 0 9096846532,,,,,,,,2025-07-23,2025-07-26,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,362.24, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1135.2,1426.13,0.0,0.0,0.0,7.13,0.0,0.0,0.0,1426.13,1426.13,2,0,0,1,,,0,0.0,false,"",false,0,283.8,Room 106,2873-1 +MMS-OBH25072222522403-2915228,2025-07-22,Hacienda San Angel,Mr and Mrs Smith,,Hanna,Kernazhytskaya,ANYA.V.KERN@GMAIL.COM,,,,,,,,,2025-07-23,2025-07-24,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE$ 258.34 +VIRTUCAL CRETI CARD +CONFIRMATION SENT JULY22/25 +OK GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,258.34,336.38,0.0,0.0,0.0,13.45,0.0,0.0,0.0,336.38,336.38,1,0,0,1,,,0,0.0,false,"",false,0,64.585,Room 113,"2869-1, 2869-2" +MMS-OBH25072407053502-2916425,2025-07-24,Hacienda San Angel,Mr and Mrs Smith,,Hanna,Kernazhytskaya,ANYA.V.KERN@GMAIL.COM,,,,,,,,,2025-07-24,2025-07-25,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $307.20 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY24/2025 +OK MARIANA JULY24/2025",,Checked-out,"",Angels Dome - Junior Suite,Manual,307.2,357.53,0.0,0.0,0.0,-26.47,0.0,0.0,0.0,357.53,357.53,1,0,0,1,,,0,0.0,false,"",false,0,76.8,Room 113,2871-1 +MMS-OBH25051903110306-2849691,2025-05-19,Hacienda San Angel,Mr and Mrs Smith,,Hanna,Kernazhytskaya,ANYA.V.KERN@GMAIL.COM,,,,,,,,,2025-07-25,2025-07-27,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // +HYATT // +RATE $ 287.03 USD + TAX // +VURTUAL CARD FOR CHARGE // +SUITE $ ANGEL DONE // +STAY jUL 25-27 2025 //",,Cancelled,2025-07-04 15:31:17,Angels Dome - Junior Suite,Angels Dome - Standard Rate,551.09,602.76,0.0,0.0,0.0,-86.1,0,0.0,0.0,602.76,0,1,0,0,1,,,0,602.76,false,"",false,0,137.7725,Room 113,"" +LH25070949323879,2025-07-09,Hacienda San Angel,Extranet,,Jake,Naughton,jake@jakenaughton.com,"",,,,,,,,2025-07-25,2025-07-26,1,,Angel's Rate,"NYTimes photographer- No charges for anything. + +He moves to Celestial the next night. Here for a total of 2 nights. + +Support with staging as requested by Tasha please- Paula",,Checked-out,"", Garden of Angels - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,2877-1 +EXP-2252196866,2025-07-24,Hacienda San Angel,Expedia,,Jeffrey,Nolte,twxik5nyph@m.expediapartnercentral.com,1 0 6317749060,,,,,,,,2025-07-25,2025-07-28,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,057.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPEDIAPREMIUMVIP .COM // +CONFIRMATION SENT JULY242025 // +CREDIT CARD INFORMATION OK // +RATE $ 293.83 USD + TAXES // +STAY JULY25-282025 // +SUITE ANGEL DOME // +SUBMITEDJULY242025NGR //",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,881.5,1154.66,0.0,0.0,0.0,52.78,0.0,0.0,0.0,1154.66,1154.66,1,0,0,1,,,0,0.0,false,"",false,0,220.375,Room 113,"2872-1, 2872-2" +EXP-2218407695,2025-06-11,Hacienda San Angel,Expedia,,Aidan,Wahl,9ga8glxn96@m.expediapartnercentral.com,1 602 7619744,,,,,,,,2025-07-26,2025-07-27,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 372.60, Expedia Virtual Card will be activated from the day of Check-in.","EXPEDIA +JUN102025 +CVV OK +$310.50 USD + TAX +JULY26-272025 +SERAFÍN +JUN102025NGR",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,310.5,541.96,0.0,0.0,0.0,153.83,0.0,0.0,0.0,541.96,541.96,2,0,0,1,,,0,0.0,false,"",false,0,77.625,Room 110,"2874-1, 2874-2" +LH25070949323807,2025-07-09,Hacienda San Angel,Extranet,,Jake,Naughton,jake@jakenaughton.com,"",,,,,,,,2025-07-26,2025-07-27,1,,Angel's Rate,"NYTimes photographer- No charges for anything. + +He does need transportation TO the airport when he checks out only; he does not need it to arrive. I will pay for his transportation to the airport. + +Support with staging as requested by Tasha please- Paula",,Checked-out,"", Garden of Angels - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 109,2876-1 +LH25072449700685,2025-07-24,Hacienda San Angel,Extranet,,Heinz Legler and,Veronique Lievre,reservations@verana.com,322 227 5420,,,,,,,,2025-07-26,2025-07-27,1,,"",CORTESÍA PARA DUEÑOS DE VERANA OK PAULA // NGR,,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,360.0,120.33,0.0,0.0,0.0,120.33,0.0,0.0,0.0,120.33,120.33,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 112,2875-1 +EXP-2228086230,2025-06-24,Hacienda San Angel,Expedia,,Josh,Harvey-White,p4kbn1aqmk@m.expediapartnercentral.com,0 0 12139321616,,,,,,,,2025-07-27,2025-07-29,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,066.56, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay|1 Free beverage per person for 2 (once per stay)","EXPEDIAVIP.COM +SAN MIGUEL PRESIDENTIAL SUITE +$444.40 USD + TAX +JUL27-292025 +JUN232025NGR +ADD $85 USD FOR FOOD AND BEVERAGE",,Cancelled,2025-06-26 14:07:02, San Miguel - Presidential Suite,San Miguel - Standard Rate,888.8,1111.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1111.0,0,2,0,0,1,,,0,1111.0,false,"",false,0,222.2,Room 107,"" +EXP-2230393455,2025-06-26,Hacienda San Angel,Expedia,,Josh,Harvey-White,hbmtrylo96@m.expediapartnercentral.com,1 213 9321616,,,,,,,,2025-07-27,2025-07-29,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,030.20, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: 1 Free beverage per person for 2 (once per stay),USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT JUN262025 // +CREDIT CARD INFORMATION OK // +RATE $ 429.25 USD + TAXES // +STAY JULY27-292025 // +SUITE SAN MIGUEL // +SUBMITED JUN262025NGR// +ADD $85 USD F & B",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,858.5,1275.58,0.0,0.0,0.0,202.45,0.0,0.0,0.0,1275.58,1275.58,2,0,0,1,,,0,0.0,false,"",false,0,214.625,Room 107,"2878-1, 2878-2" +LH25070349181728,2025-07-03,Hacienda San Angel,Extranet,,Stephen,Adams,stephenpadams@gmail.com,+18608300048,,,,,,,,2025-07-27,2025-07-29,2,,"","RESERVATION DIRECTLY +RATE$_ 280.00 + TAXES +NO PROMO +VISA CREDIT CARD INFO OK +CONFIRMATION SENT JULY03/2025 +OK MARIANA JULY03/2025 + + + + + + + + +vendran dos adultos y 2 niños 10 y 7 años, reservaron dos habitaciones untos, ok Paula + +cvv 918",,Cancelled,2025-07-21 10:51:14,"Angels Dome - Junior Suite,Crown View - Junior Suite","Manual,Manual",1120.0,1400.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1400.0,0,4,0,0,2,,,0,1400.0,false,"",false,0,280.0,"Room 113, Room 112","" +LH25072449690663,2025-07-24,Hacienda San Angel,Extranet,,MELISSA,RAYMOND,"",8019715960,,,,,,,,2025-07-28,2025-07-29,1,,"","RESERVATION DIRECTLY +RATE $320.00 TAXES +15% OK INES THEY WERE LAST WEEK SAME ROM +CREDIT CARD AMEX OK +OK MARIANA 24/2025",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,320.0,340.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,340.0,340.0,2,0,0,1,,,0,0.0,false,"",false,0,68.0,Room 109,2880-1 +MMS-OBH25042703013503-2823952,2025-04-27,Hacienda San Angel,Mr and Mrs Smith,,Craig,Scholla,CRAIGSCHOLLA@AOL.COM,,,,,,,,,2025-07-29,2025-07-30,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT APR262025 // +CREDIT CARD INFORMATION OK // +RATE $ 436.80 USD + TAXES // +STAY JULY29-302025 // +SUITE CELSTIAL SUITE // +SUBMITED APR242025NGR//",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,436.8,614.97,0.0,0.0,0.0,68.97,0.0,0.0,0.0,614.97,614.97,1,0,0,1,,,0,0.0,false,"",false,0,109.2,Room 103,"2879-1, 2879-2" +LH25072949814741,2025-07-29,Hacienda San Angel,Extranet,,Eliane,Giroux,eliane.giroux@gmail.com,5147098774,,,,,,,,2025-07-29,2025-08-03,5,,"","DIRECT RESWERVATION // +RATE $440 USD + TAX *// +COFIRMATION SENT // +CREDIT CARD OK // +NO PROMO // +STAY JUL29- AGO03 2025 // +SUITE ANGEL VIEW // +JUL292025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,2200.0,3632.4,0.0,0.0,0.0,882.4,0.0,0.0,0.0,3632.4,3632.4,2,0,0,1,,,0,0.0,false,"",false,0,550.0,Room 106,"2883-1, 2883-2, 2883-3" +SMP-2025052840532821,2025-05-28,Hacienda San Angel,Simple Booking,,Robert,Otero,robert4495@gmail.com,+17192144495,,,,,,,"",2025-07-30,2025-08-02,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $411.37 + TAXES +SECRET RATE +VIRTUAL CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MAY28/25 +OK MARIANA MAY28/25",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1234.1,2041.25,0.0,0.0,0.0,498.62,0.0,0.0,0.0,2041.25,2041.25,2,0,0,1,,,0,0.0,false,"",false,0,308.525,Room 107,"2881-1, 2881-2" +MMS-OBH25070503184904-2897020,2025-07-05,Hacienda San Angel,Mr and Mrs Smith,,Kyle,Rolnick,KROLNICK@GMAIL.COM,,,,,,,,,2025-07-30,2025-08-02,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $247.10 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY04/2025 +OK MARIANA JULY04/2025",,Cancelled,2025-07-05 14:55:59, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,741.31,965.25,0.0,0.0,0.0,38.61,0,0.0,0.0,965.25,0,2,0,0,1,,,0,965.25,false,"",false,0,185.3275,Room 109,"" +MMS-OBH25042519391903-2822789,2025-04-25,Hacienda San Angel,Mr and Mrs Smith,,Craig,Scholla,CRAIGSCHOLLA@AOL.COM,,,,,,,,,2025-07-31,2025-08-01,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $417.60 + TAXES +WORLD OF HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT APRIL25/25 +OK MARIANA APRIL25/25",,Cancelled,2025-04-26 20:01:00, Celestial - Royal Suite,Celestial - Standard Rate,417.6,456.75,0.0,0.0,0.0,-65.25,0,0.0,0.0,456.75,0,2,0,0,1,,,0,456.75,false,"",false,0,104.4,Room 103,"" +EXP-2173996237,2025-04-10,Hacienda San Angel,Expedia,,Armenia,Leal,gdpa6s4wyn@m.expediapartnercentral.com,1 210 8874589,,,,,,,,2025-08-01,2025-08-06,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,863.84, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIA VIP.COM // +CONFIRMATION SENT APR102025 // +CREDIT CARD INFORMATION OK // +RATE $ 310.64 USD + TAXES // +STAY AGO01-062025 // +SUITE SERAFIN // +SUBMITED APR102025NGR//",,Cancelled,2025-04-11 03:37:57,Serafin - Junior Suite,Serafin - Standard Rate,1553.2,1941.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1941.5,0,2,0,0,1,,,0,1941.5,false,"",false,0,388.3,Room 110,"" +SMP-2025070441518779,2025-07-03,Hacienda San Angel,Simple Booking,,Joshua,walters,josh@jcwaltersesq.com,+19162028968,,,,,,,"",2025-08-02,2025-08-03,1,,If you can arrange to have some flowers in the room upon arrival that would be apprecaited.,"RESERVATION FROM SIMPLE BOOKING +RATE $410.00 + TAXES +SECRET RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT JULY03/2025 +OK MARIANA JULY03/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,410.0,512.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,512.5,512.5,2,0,0,1,,,0,0.0,false,"",false,0,102.5,Room 107,2882-1 +SMP-2025031438754680,2025-03-14,Hacienda San Angel,Simple Booking,,Ryan,Buresh,bureshryan@gmail.com,+16192063160,,,,,,,"",2025-08-03,2025-08-06,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAR142025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $395 USD + TAXES // +STAY AGO3-062025 // +SUITE ANGEL VIEW // +SUBMITED MAR142025NGR//",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1185.0,1529.58,0.0,0.0,0.0,48.33,0.0,0.0,0.0,1529.58,1529.58,2,0,0,1,,,0,0.0,false,"",false,0,296.25,Room 106,2888-1 +SMP-2025070441545720,2025-07-04,Hacienda San Angel,Simple Booking,,Joshua,walters,josh@jcwaltersesq.com,+19162028968,,,,,,,"",2025-08-03,2025-08-04,1,,"","",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,405.9,1095.64,0.0,0.0,0.0,588.26,0.0,0.0,0.0,1095.64,1095.64,2,0,0,1,,,0,0.0,false,"",false,0,101.475,Room 107,2884-1 +LH25072949814770,2025-07-29,Hacienda San Angel,Extranet,,Eliane,Giroux,eliane.goroux@gmail.com,5147098774,,,,,,,,2025-08-03,2025-08-05,2,,"","RESERVATION DIRECTLY +RATE $362.50 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT JULY29/2025 +OK MARIANA JULY29/2025",,Cancelled,2025-07-31 14:25:21,Crown View - Junior Suite,Crown View - Standard Rate,725.0,906.25,0.0,0.0,0.0,0.0,0,0.0,0.0,906.25,0,2,0,0,1,,,0,906.25,false,"",false,0,181.25,Room 112,"" +SMP-2025073042259362,2025-07-30,Hacienda San Angel,Simple Booking,,Daisy,Parker,daisyparker@me.com,+13322137491,,,,,,,"",2025-08-03,2025-08-05,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JULY302025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $274.70 USD + TAXES // +STAY AUG03-052025 // +SUITE MILAGROS // +SUBMITED JULY302025NGR //",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,549.4,793.51,0.0,0.0,0.0,106.76,0.0,0.0,0.0,793.51,793.51,2,0,0,1,,,0,0.0,false,"",false,0,137.35,Room 102,"2887-1, 2887-2, 2887-3" +BDC-6489597147,2025-07-31,Hacienda San Angel,Booking.com,,Joakim,Lehmkhul,joakimk.lehmkhul@gmail.com,+52 322 190 0948,,,,,,Mexico,"",2025-08-04,2025-08-05,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-08-02., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING. COM +RATE $330.00+ TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY31/2025 +OK MARIANA JULY31/2025",,Checked-out,""," Garden of Angels - Junior Suite,Angels Dome - Junior Suite","Garden of Angels - Standard Rate,Angels Dome - Standard Rate",660.0,868.28,0.0,0.0,0.0,43.28,0.0,0.0,0.0,868.28,868.28,2,0,0,2,,,0,0.0,false,"",false,0,165.0,"Room 109, Room 113","2885-1, 2885-2" +EXP-2259846908,2025-08-04,Hacienda San Angel,Expedia,,Joshua,Davis,s133ba4o26@m.expediapartnercentral.com,1 5037562267,,,,,,,,2025-08-04,2025-08-05,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 388.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA +RATE $324.00 + TAXES +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT AUGUS08/2025 +OK MARIANA AUGUST 08/2025",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,324.0,557.61,0.0,0.0,0.0,152.61,0.0,0.0,0.0,557.61,557.61,2,0,0,1,,,0,0.0,false,"",false,0,81.0,Room 112,2886-1 +SMP-2025030238460894,2025-03-02,Hacienda San Angel,Simple Booking,,Rex,Yamamoto,hiroorex@hotmail.com,+16506295762,,,,,,,"",2025-08-05,2025-08-08,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $393.60 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MARCH02/2025 +OK MARIANA MARCH02/2025",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1180.8,1604.61,0.0,0.0,0.0,128.61,0.0,0.0,0.0,1604.61,1604.61,2,0,0,1,,,0,0.0,false,"",false,0,295.2,Room 107,"2889-1, 2889-2" +SMP-2025051940286979,2025-05-18,Hacienda San Angel,Simple Booking,,Lauren,J,lhagspiel92@gmail.com,+14348068614,,,,,,,"",2025-08-05,2025-08-09,4,,"","SIMPLEBOOKING.COM +AUG05-092025 +GARDEN OF ANGELS +$336.25 + TAX +MAY152025NGR",,Checked-out,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1345.0,2188.83,0.0,0.0,0.0,507.58,0.0,0.0,0.0,2188.83,2188.83,2,0,0,1,,,0,0.0,false,"",false,0,336.25,Room 109,2890-1 +SMP-2025031838860685,2025-03-18,Hacienda San Angel,Simple Booking,,Laura,Persun,laurajpersun@gmail.com,+17172654035,,,,,,,"",2025-08-06,2025-08-11,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $282.90 + TAXES + +SECRET RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT MARCH18/2025 +OK MARIANA MARCH18/2025",,Checked-out,"",Crown View - Junior Suite,Crown View - Standard Rate,1414.51,2021.14,0.0,0.0,0.0,253.0,0.0,0.0,0.0,2021.14,2021.14,2,0,0,1,,,0,0.0,false,"",false,0,353.6275,Room 112,2892-1 +MMS-OBH25070518171508-2897569,2025-07-05,Hacienda San Angel,Mr and Mrs Smith,,Joshua,Luke,JDLUKE87@GMAIL.COM,,,,,,,,,2025-08-06,2025-08-10,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $359.43 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY05/25 +OK MARIANA JULY05/25",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1437.7,2180.87,0.0,0.0,0.0,383.74,0.0,0.0,0.0,2180.87,2180.87,1,0,0,1,,,0,0.0,false,"",false,0,359.425,Room 103,2891-1 +MMS-OBH25070823110003-2900837,2025-07-08,Hacienda San Angel,Mr and Mrs Smith,,Jason,Coffey,JCOFFEY2006@HOTMAIL.COM,,,,,,,,,2025-08-08,2025-08-11,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS // HYATT // +CONFIRMATION SENT // +RATE $ 391.60 USD + TAX // +VIRTUAL CARD FOR CHARGE// +SUITE ANGELS VIEW // +STAY AGO 08- 11 2025 // +PROMO: SMITH SCLUSIVE MEMBER DISCOUNT // +JUL082025GV + +ORIGINAL RESERVATION AV, ACCEPTED TO MOVE TO RINCON, NO CHANGE ON RATE. INES + +ALLLERGIC TO DOWN / no poner almohadas o cubres de plumas",,Checked-out,"", Rincon de Angeles - Royal Suite,Manual,1127.81,1579.15,0.0,0.0,0.0,169.39,0.0,0.0,0.0,1579.15,1579.15,2,0,0,1,,,0,0.0,false,"",false,0,281.9525,Room 119,2893-1 +EXP-2149967986,2025-02-09,Hacienda San Angel,Expedia,,Saul,Tawil,w92mpr1ssr@m.expediapartnercentral.com,0 0 5567079763,,,,,,,,2025-08-10,2025-08-23,13,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 4,406.64, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: Crédito de USD85 para alimentos y bebidas (por hab., por estancia)","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $282.00 + TAXES +$85.00 CREDIT ON FOOD & BEVERAGE// BOTTLE OR UPGRRADE +CREDIT CARD INFO OK +CONFIRMATION SENT FEB08/2025 +OK MARIANA FEB08/2025",,Cancelled,2025-02-10 16:42:21,Crown View - Junior Suite,Crown View - Standard Rate,3672.2,4590.25,0.0,0.0,0.0,0.0,0,0.0,0.0,4590.25,0,2,0,0,1,,,0,4590.25,false,"",false,0,918.05,Room 112,"" +BDC-6352090126,2025-07-25,Hacienda San Angel,Booking.com,,Kacey,Currington,kcurri.716210@guest.booking.com,+1 214 802 8902,,,,,,United States,"",2025-08-10,2025-08-12,2,,"Approximate time of arrival: between 10:00 and 11:00 +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JULY252025 // +CREDIT CARD INFORMATION OK // +RATE $ 500 USD + TAXES // +STAY AUG 10-122025 // +SUITE SAN MIGUEL // +SUBMITED JULY252025NGR //",,Cancelled,2025-07-31 13:11:14, San Miguel - Presidential Suite,San Miguel - Standard Rate,1000.0,1250.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1250.0,0,2,0,0,1,,,0,1250.0,false,"",false,0,250.0,Room 107,"" +LH25073149861700,2025-07-31,Hacienda San Angel,Extranet,,KACEY,CURRINGTON,kcurrington@intexelectric.com,1 214 802 8902,,,,,,,,2025-08-10,2025-08-12,2,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT JULY312025 // +CREDIT CARD INFORMATION OK // +RATE $ 400 USD + TAXES // +STAY AUG 10-122025 // +SUITE CELESTIAL // +SUBMITED JULY312025NGR // + +RESRVACION ORIGINAL EN SM, SE CANCELO Y SE LE DIO TAFIFA DE 400 POR TRABAJOS EN ALBERCA",,Checked-out,"", Celestial - Royal Suite,Manual,800.0,1209.0,0.0,0.0,0.0,209.0,0.0,0.0,0.0,1209.0,1209.0,2,0,0,1,,,0,0.0,false,"",false,0,200.0,Room 103,2894-1 +EXP-2186789890,2025-04-29,Hacienda San Angel,Expedia,,MARIO,NOGUE SOLE,8do5om4eci@m.expediapartnercentral.com,34 971 434050,,,,,,,,2025-08-13,2025-08-16,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 914.01, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATTION THRU EXP // +CONFIRMATION SENT ABR29 // +RATE $ 253.89 USD + TAX // +PACKAGE MLO3 // +VIRTUAL CARD FOR CHARGE // +SUITE ANGEL DOME // +STAY AGO 13- 16 2025 // +ABR292025GV",,Checked-out,"", Milagros - Junior Suite,Manual,761.67,1221.76,0.0,0.0,0.0,269.67,0.0,0.0,0.0,1221.76,1221.76,2,0,0,1,,,0,0.0,false,"",false,0,190.4175,Room 102,"2895-1, 2895-2" +EXP-2234288259,2025-07-02,Hacienda San Angel,Expedia,,Mauricio,Gomez,spwm1boxyx@m.expediapartnercentral.com,1 0 8326613552,,,,,,,,2025-08-13,2025-08-16,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION TRHU EXP // +CONFIRMATION SENT JUL02 // +RATE $ 425 USD + TAX // +EXP VIP PREMIUM // +PROMO EXP: MID YEAR SALE 2025 // +SUITE SAN MIGUEL // +STAY AGO 13- 16 2025 // +JUL022025GV",,Cancelled,2025-08-02 09:06:39, San Miguel - Presidential Suite,San Miguel - Standard Rate,1275.0,1593.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1593.75,0,2,0,0,1,,,0,1593.75,false,"",false,0,318.75,Room 107,"" +MMS-OBH25071916263606-2911708,2025-07-19,Hacienda San Angel,Mr and Mrs Smith,,Niklas,Lowry,NIK.LOWRY@PROTONMAIL.COM,,,,,,,,,2025-08-13,2025-08-17,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $263.95 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY19/2025 +OK MARIANA JULY19/2025",,Cancelled,2025-08-10 20:00:59, Milagros - Junior Suite,Milagros - Standard Rate,1055.81,1374.75,0.0,0.0,0.0,54.99,0,0.0,0.0,1374.75,0,2,0,0,1,,,0,1374.75,false,"",false,0,263.9525,Room 102,"" +LH25080449953348,2025-08-04,Hacienda San Angel,Extranet,,Mauricio,Gomez,mauricio.gomez@championx.com,"",,,,,,,,2025-08-13,2025-08-16,3,,"","DIRECT RESERVATION // +CONFIRMATION SENT AGO04// +CREDIT CARD INFO OK // +NO PROMO // +RATE $ 384 USD + TAXES // +DESC 20% OK INES // +SUITE CELESTIAL // +STAY AGO 13- 16 2025 // +AGO042025GV",,Checked-out,"", Celestial - Royal Suite,Celestial - Standard Rate,1440.0,1583.6,0.0,0.0,0.0,143.6,0.0,0.0,0.0,1583.6,1583.6,2,0,0,1,,,0,0.0,false,"",false,0,288.0,Room 103,2896-1 +SMP-2025042139636243,2025-04-21,Hacienda San Angel,Simple Booking,,Susan,Crawford Barns,sandgbarns@sbcglobal.net,+19184932602,,,,,,,"",2025-08-16,2025-08-19,3,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ABR 21 // +RATE $ 317.07 USD + TAXES // +NO PROMO // +CREDIT CARD INFORMATION VISA CVV PENDING // +SECRET RATE // +SUITE ANGEL VIEW // +STAY AGO 16- 19 2025 // +ABR212025GV",,Cancelled,2025-07-30 08:20:36, Angels View - Master Suite,Angels View - Standard Rate,951.21,1189.01,0.0,0.0,0.0,0.0,0,0.0,0.0,1189.01,0,2,0,0,1,,,0,1189.01,false,"",false,0,237.8025,Room 106,"" +BDC-4410854480,2025-03-11,Hacienda San Angel,Booking.com,,joanna,aston,jaston.341862@guest.booking.com,+1 650 215 0338,,,,,,United States,"",2025-08-19,2025-08-20,1,,"booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-03-17 10:56:59,Serafin - Junior Suite,Serafin - Standard Rate,288.0,360.0,0.0,0.0,0.0,0.0,0,0.0,0.0,360.0,0,2,0,0,1,,,0,360.0,false,"",false,0,72.0,Room 110,"" +SMP-2025082042798370,2025-08-20,Hacienda San Angel,Simple Booking,,Brian,Sutherland,briansantabarbara@gmail.com,+1805-245-6130,,,,,,,"",2025-08-21,2025-08-23,2,,We are currently staying in at an AirBnd in Zona Romántica and need to check out at 11:00. We are hoping for an early check-in. Celebrating our one-year anniversary.,"RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT AGO202025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 295.20 USD + TAXES // +STAY AGO21-222025 // +SUITE CROWN VIEW // +SUBMITED AGO202025NGR // + +Daily rate paid after upgrade in total for Rincon was $460 per night.- Paula",,Checked-out,"", Rincon de Angeles - Royal Suite,Manual,920.2,1891.24,0.0,0.0,0.0,740.99,0.0,0.0,0.0,1891.24,1891.24,2,0,0,1,,,0,0.0,false,"",false,0,230.05,Room 119,2897-1 +MMS-OBH25071605074100-2908246,2025-07-16,Hacienda San Angel,Mr and Mrs Smith,,Ronaldo,Carvalho,RONALDOCARVALHO@COCA-COLA.COM,,,,,,,,,2025-08-22,2025-08-24,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. SMITH +RATE $245.23 + TAXES +HYATT +VIRTUAL CREDIT CARD +CONFIRMATION SENT JULY 17/2025 +OK MARIANA JULY17/2025",,Cancelled,2025-07-17 11:15:55, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,490.46,638.63,0.0,0.0,0.0,25.55,0,0.0,0.0,638.63,0,2,0,0,1,,,0,638.63,false,"",false,0,122.615,Room 109,"" +SMP-2025081142560405,2025-08-11,Hacienda San Angel,Simple Booking,,Jack,Zhang,jxz8072@hotmail.com,+15854890169,,,,,,,"",2025-08-23,2025-08-26,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT AUG102025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 440 USD + TAXES // +STAY AUG23-262025 // +SUITE SAN JOSE // +SUBMITED AUG102025NGR//",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,1320.0,1906.2,0.0,0.0,0.0,256.2,0.0,0.0,0.0,1906.2,1906.2,2,0,0,1,,,0,0.0,false,"",false,0,330.0,Room 122,2898-1 +SMP-2025080942515685,2025-08-09,Hacienda San Angel,Simple Booking,,KRISTELL,MELENDEZ,kristell.melendez@effem.com,+526643314154,,,,,,Mexico,"",2025-08-27,2025-08-28,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $270.60 + TAXES +SECRET RATE +AMEX CVV PENDING +CONFIRMATION SENT AUG09/2025 +OK MARIANA AUG09/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,270.6,338.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,338.25,338.25,2,0,0,1,,,0,0.0,false,"",false,0,67.65,Room 102,2900-1 +SMP-2025082742952100,2025-08-27,Hacienda San Angel,Simple Booking,,Robert,Tabak,rob_tabak@yahoo.com,+15176142336,,,,,,,"",2025-08-27,2025-08-28,1,,Extra pillows please,"RESERVATION FROM SIMPLE BOOKING +RATE $440.00 + TAXES +NO PROMO +INFOC REDIT CARD OK +CONFIRMATION SENT 27/08/25 +OK MARIANA 27/08/25",,Checked-out,"", San Jose - Master Suite,San Jose - Standard Rate,440.0,661.47,0.0,0.0,0.0,111.47,0.0,0.0,0.0,661.47,661.47,2,0,0,1,,,0,0.0,false,"",false,0,110.0,Room 122,2899-1 +LH25053148439776,2025-05-31,Hacienda San Angel,Extranet,,LEAH,BELL,lkatbell@gmail.com,+19852854202,,,,,,,,2025-08-28,2025-09-01,4,,"","THIS RESERVATION WAS MAID IN SEPTEMBER 11-2023 +IT WAS CANCELED BECAUSE THEY HAD AN ACCIDENT AND WE GIVE THEM A CREDIT FOR $1,821.31 USD, SAME QUANTITY THAT THEY PAID, NOW THEY WANT TO USE THEIR CREDIT IN THIS RESERVATION, WE ARE DISCOUNT THE CREDIT AND THEY NEED TO PAY THE BALANCE FOR THE EXTRA NIGHT. + +DIRECT +MAY312025 +CC OK +AUG28-SEP012025 +RINCÓN OF ANGELS +MAY212025NGR + +NOTE: BECAUSE OF POOL WORK THEY AGREED TO MOVE TO ANGELS VIEW FROM RINCON. PAYMENT ARRANGEMENTS DO NOT CHANGE. KEEP THE SAME AS IS IN THE NOTES AND ALREADY APPLIED TO THE CURRENT BALANCE- PAULA + +MOVED THEM BACK TO RINCON, SINCE WE CHANGED PLANES ON POOL RENOVATION- INES + +WE SWITCH THE ROOM FOR CELESTIAL SUITE BECAUSE RINCÓN AIR CONDITIONER START TO LEAK A LOT OF WATER NGR",,Checked-out,"", Celestial - Royal Suite,Manual,1760.0,752.15,0.0,0.0,0.0,373.4,0.0,0.0,0.0,752.15,752.15,2,0,0,1,,,0,0.0,false,"",false,0,75.75,Room 103,"2903-1, 2903-2" +EXP-2260682607,2025-08-05,Hacienda San Angel,Expedia,,PEDRO,TOSTADO,oed7nhlnr5@m.expediapartnercentral.com,52 664 5181871,,,,,,,,2025-08-28,2025-09-01,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,382.40, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 bebida gratis para 2 (por persona, una vez por estancia)""","RESERVATION FROM EXPEDIA +RATE $288.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT AUG04/2025 +OK MARIANA AUG04/2025 + +SUITE GARDEN // +STAY AGO 28- SEP 01 20252 // +********************************************* +GUEST AGREES TO CHANGE ROOM TO CV FOR POOL MAINTENANCE SAN ANGEL",,Checked-out,"",Crown View - Junior Suite,Manual,1152.0,1460.26,0.0,0.0,0.0,20.26,0.0,0.0,0.0,1460.26,1460.26,2,0,0,1,,,0,0.0,false,"",false,0,288.0,Room 112,"2901-1, 2901-2" +EXP-2229627612,2025-06-25,Hacienda San Angel,Expedia,,Martin Augustus,Rowe,ygpkx6sf9b@m.expediapartnercentral.com,1 417 8729063,,,,,,,,2025-08-31,2025-09-04,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,008.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: 1 Free beverage per person for 2 (once per stay),USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT JUN25205 // +CREDIT CARD INFORMATION OK // +RATE $ 418.50 USD + TAXES // +STAY AGO31-SEP042025 // +SUITE SAN MIGUEL PRESIDENTIALS UITE // +SUBMITED JUN252025NGR // +ADD $85 USD FOR FOOD & BEVERAGE",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1674.0,2111.57,0.0,0.0,0.0,19.07,0.0,0.0,0.0,2111.57,2111.57,2,0,0,1,,,0,0.0,false,"",false,0,418.5,Room 107,"2902-1, 2902-2" +BDC-5598685040,2025-08-31,Hacienda San Angel,Booking.com,,Nora,Gomez Basulto,nbasul.971929@guest.booking.com,+1 469 675 9003,,3010 Lyndon B Johnson Fwy,,Dallas,,United States,75234-7770,2025-08-31,2025-09-01,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-08-31., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT AUG312025 // +CREDIT CARD INFORMATION OK // +RATE $ 300 USD + TAXES // +STAY AUG31-SEP012025 // +SUITE SERAFÍN// +SUBMITED AUG312025NGR// + + + WAS NO SHOW",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,300.0,375.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,375.0,375.0,2,0,0,1,,,0,0.0,false,"",false,0,75.0,Room 110,"" +MMS-OBH25090216301100-2957482,2025-09-02,Hacienda San Angel,Mr and Mrs Smith,,Leon,Evans,LEON.ALEXANDER.EVANS@GMAIL.COM,,,,,,,,,2025-09-02,2025-09-04,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,509.18,663.0,0.0,0.0,0.0,26.52,0.0,0.0,0.0,663.0,663.0,2,0,0,1,,,0,0.0,false,"",false,0,127.295,Room 102,2904-1 +EXP-2259818231,2025-08-03,Hacienda San Angel,Expedia,,Nicole,Dennis,c3498qw78m@m.expediapartnercentral.com,1 3109857404,,,,,,,,2025-09-03,2025-09-07,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA +RATE $414.00+ TAXES +NO POROMO +VISA CREDIT CARD OK +CONFIRMATION SENT AUGUST 03/2025 +OK MARIANA AUGUST03/2025",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1656.0,2263.67,0.0,0.0,0.0,193.67,0.0,0.0,0.0,2263.67,2263.67,2,0,0,1,,,0,0.0,false,"",false,0,414.0,Room 119,2906-1 +MMS-OBH25082923313802-2954059,2025-08-29,Hacienda San Angel,Mr and Mrs Smith,,Kimberley,Dilley,KJD27_99@YAHOO.COM,,,,,,,,,2025-09-03,2025-09-05,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT AUG292025 // +CREDIT CARD INFORMATION OK // +RATE $256.32 USD + TAXES // +STAY SEP03-052025// +SUITE SERAFÍN // +SUBMITED AUG292025NGR //",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,512.64,826.56,0.0,0.0,0.0,185.76,0.0,0.0,0.0,826.56,826.56,2,0,0,1,,,0,0.0,false,"",false,0,128.16,Room 110,2905-1 +MMS-OBH25030118522809-2763279,2025-03-01,Hacienda San Angel,Mr and Mrs Smith,,Heidi,Swisshelm,HEIDIGRIDER@YAHOO.COM,,,,,,,,,2025-09-04,2025-09-07,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS// +CONFIRMATION SENT FEB 02 // +RATE $ 328.90 USD + TAX // +NO PROMO // +CREDIT CARD OINFORMATION OK VIRTUAL CARD FOR CHARGE // +SUITE CELESTIAL // +STAY SEP 04- 07 2025 // +FEB022025GV",,Cancelled,2025-06-04 09:55:57, Celestial - Royal Suite,Celestial - Standard Rate,947.23,1184.04,0.0,0.0,0.0,0.0,0,0.0,0.0,1184.04,0,2,0,0,1,,,0,1184.04,false,"",false,0,236.8075,Room 103,"" +EXP-X-412070261,2025-02-13,Hacienda San Angel,Expedia,,Brittney,Valdez,3e6jeeq492@m.expediapartnercentral.com,1 909 4144230,,,,,,,,2025-09-06,2025-09-10,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT FEB132025// +CREDIT CARD INFORMATION OK// +RATE $ 344.25 USD + TAXES // +STAY SEP6-102025// +SUITE ANGEL VIEW// +SUBMITED FEB132025NGR//",,Cancelled,2025-07-20 17:11:48, Angels View - Master Suite,Angels View - Standard Rate,1377.0,1721.25,0.0,0.0,0.0,0.0,0,0.0,0.0,1721.25,0,2,0,0,1,,,0,1721.25,false,"",false,0,344.25,Room 106,"" +SMP-2025060940831178,2025-06-09,Hacienda San Angel,Simple Booking,,Lauren,Balsiger,lauren.balsiger@gmail.com,+15034816160,,,,,,,"",2025-09-06,2025-09-10,4,,"","SIMPLEBOOKING +SEP6-102025 +$375 USD + TAX +CVV PENDIENT +JUN082025NGR + +ORGINAL RESERVATION SJ MOVED TO CELESTIAL AT NO COST, POOL REPAIR.",,Checked-out,"", Celestial - Royal Suite,Manual,1500.0,2397.92,0.0,0.0,0.0,522.92,0.0,0.0,0.0,2397.92,2397.92,2,0,0,1,,,0,0.0,false,"",false,0,375.0,Room 103,2908-1 +MMS-OBH25081704523103-2941343,2025-08-17,Hacienda San Angel,Mr and Mrs Smith,,Justin,Arthur,ARTJUSTIN@GMAIL.COM,,,,,,,,,2025-09-06,2025-09-07,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT AUG162025 // +CREDIT CARD INFORMATION OK // +RATE $ 307.20 USD + TAXES // +STAY SEP06-072025 // +SUITE GARDEN OF ANGELS // +SUBMITED AUG162025NGR //",,Cancelled,2025-09-03 18:15:50, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,307.2,336.0,0.0,0.0,0.0,-48.0,0,0.0,0.0,336.0,0,2,0,0,1,,,0,336.0,false,"",false,0,76.8,Room 109,"" +EXP-2278165282,2025-08-28,Hacienda San Angel,Expedia,,NANCY,THOMPSON,y02lwx3h6v@m.expediapartnercentral.com,1 2019064418,,,,,,,,2025-09-08,2025-09-09,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 454.08, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $378. 40 + TAXES +$85.00 USD AS CREDIT AT THE REST. +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT AUG28/2025 +OK MARIANA AUG28/2025",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,378.4,550.4,0.0,0.0,0.0,77.4,0.0,0.0,0.0,550.4,550.4,2,0,0,1,,,0,0.0,false,"",false,0,94.6,Room 106,2907-1 +EXP-2286790413,2025-09-10,Hacienda San Angel,Expedia,,Irene,Restrepo,eq9iac786t@m.expediapartnercentral.com,1 0 3054988800,,,,,,,,2025-09-12,2025-09-13,1,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXP // +CONFIRMATION SENT SEP09 //",,Cancelled,2025-09-09 21:26:14, Angels View - Master Suite,Angels View - Standard Rate,396.0,495.0,0.0,0.0,0.0,0.0,0,0.0,0.0,495.0,0,2,0,0,1,,,0,495.0,false,"",false,0,99.0,Room 106,"" +SMP-2025082842954044,2025-08-28,Hacienda San Angel,Simple Booking,,Juan,Romo Zermeno,juanromo@sbcglobal.net,+525102059067,,,,,,Mexico,"",2025-09-13,2025-09-16,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT AUG272025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 503.33 USD + TAXES // +STAY SEP13-162025// +SUITE SAN MIGUEL // +SUBMITED AUG272025NGR //",,Cancelled,2025-09-08 10:48:22, San Miguel - Presidential Suite,San Miguel - Standard Rate,1510.0,1887.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1887.5,0,2,0,0,1,,,0,1887.5,false,"",false,0,377.5,Room 107,"" +SMP-2025082842954099,2025-08-28,Hacienda San Angel,Simple Booking,,Juan,Romo Zermeno,juanromo@sbcglobal.net,+525102059067,,,,,,Mexico,"",2025-09-13,2025-09-16,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT AUG272025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 360.80 USD + TAXES // +STAY SEP13-162025// +SUITE ANGEL VIEW // +SUBMITED AUG272025NGR //",,Cancelled,2025-09-08 10:50:37, Angels View - Master Suite,Angels View - Standard Rate,1082.4,1353.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1353.0,0,2,0,0,1,,,0,1353.0,false,"",false,0,270.6,Room 106,"" +BDC-4846183651,2025-04-09,Hacienda San Angel,Booking.com,,David,Keif,dkeif.804795@guest.booking.com,+1 310 397 5882,,,,.,,United States,"",2025-09-14,2025-09-19,5,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $243.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT APRIL09/25 +OK MARIANA APRIL09/25",,Cancelled,2025-07-05 10:46:55,Serafin - Junior Suite,Serafin - Standard Rate,1215.0,1518.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1518.75,0,2,0,0,1,,,0,1518.75,false,"",false,0,303.75,Room 110,"" +BDC-6037981947,2025-07-05,Hacienda San Angel,Booking.com,,David,Keif,dkeif.199995@guest.booking.com,+1 310 397 5882,,,,.,,United States,"",2025-09-15,2025-09-20,5,,"booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-07-05 12:01:31, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1304.1,1630.13,0.0,0.0,0.0,0.0,0,0.0,0.0,1630.13,0,2,0,0,1,,,0,1630.13,false,"",false,0,326.025,Room 109,"" +BDC-5186122896,2025-07-05,Hacienda San Angel,Booking.com,,David,Keif,dkeif.359776@guest.booking.com,+1 310 397 5882,,,,.,,United States,"",2025-09-15,2025-09-20,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-09-13., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING.COM +RATE $243.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY05/2025 +OK MARIANA JULY05/2025",,Checked-out,"",Serafin - Junior Suite,Serafin - Standard Rate,1215.0,2480.32,0.0,0.0,0.0,961.57,0.0,0.0,0.0,2480.32,2480.32,2,0,0,1,,,0,0.0,false,"",false,0,303.75,Room 110,2909-1 +LH25091550927530,2025-09-15,Hacienda San Angel,Extranet,,test,test,"","",,,,,,,,2025-09-15,2025-09-16,1,,"","",,Cancelled,2025-09-15 12:12:19, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,460.0,675.0,0.0,0.0,0.0,100.0,0,0.0,0.0,675.0,0.0,2,0,0,1,,,0,675.0,false,"",false,0,115.0,Room 119,"" +MMS-OBH25060818334506-2870327,2025-06-08,Hacienda San Angel,Mr and Mrs Smith,,Philip,Dorin,HANSHIROSAN@GMAIL.COM,,,,,,,,,2025-09-17,2025-09-21,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $284.54 +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE08/25 +OK MARIANA JUNE08/25",,Checked-out,"", San Miguel - Presidential Suite,Manual,1138.18,2238.01,0.0,0.0,0.0,815.28,0.0,0.0,0.0,2238.01,2238.01,2,0,0,1,,,0,0.0,false,"",false,0,284.545,Room 107,2913-1 +LH25091650959773,2025-09-16,Hacienda San Angel,Extranet,,Paulina,Ruiz,info@haciendasanangel.com,"",,,,,,,,2025-09-18,2025-09-21,3,,"","DIRECT RESERVATION // +SPECIAL RATE FOR FIDEICOISO DE TURISMO // +PREMIOS ARIEL // +SUITE CELESTAL + STAY SEP 18- 21 202 // +RATE $ 312 USD + TAX // +PIF +SEP162025GV",,Checked-out,"", Celestial - Royal Suite,Manual,936.0,1170.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1170.0,1170.0,2,0,0,1,,,0,0.0,false,"",false,0,234.0,Room 103,2911-1 +LH25091650959811,2025-09-16,Hacienda San Angel,Extranet,,Francisco Jose,Garza,info@haciendasanangel.com,"",,,,,,,,2025-09-18,2025-09-21,3,,"","DIRECT RESERVATION // +SPECIAL RATE FOR FIDEICOISO DE TURISMO // +PREMIOS ARIEL // +SUITE ANGEL VIEW // + STAY SEP 18- 21 202 // +RATE $ 286.6 USD + TAX // +PIF +SEP162025GV",,Checked-out,"", Angels View - Master Suite,Manual,856.8,1092.53,0.0,0.0,0.0,21.53,0.0,0.0,0.0,1092.53,1092.53,2,0,0,1,,,0,0.0,false,"",false,0,214.2,Room 106,"2912-1, 2912-2" +LH25091650959860,2025-09-16,Hacienda San Angel,Extranet,,Michelle,Rodriguez,info@haciendasanangel.com,"",,,,,,,,2025-09-18,2025-09-21,3,,"","DIRECT RESERVATION // +SPECIAL RATE FOR FIDEICOISO DE TURISMO // +PREMIOS ARIEL // +SUITE MILAGROS // + STAY SEP 18- 21 202 // +RATE $ 220.8 USD + TAX // +PIF +SEP162025GV",,Checked-out,"", Milagros - Junior Suite,Manual,662.4,986.7,0.0,0.0,0.0,158.7,0.0,0.0,0.0,986.7,986.7,2,0,0,1,,,0,0.0,false,"",false,0,165.6,Room 102,2915-1 +LH25091650959869,2025-09-16,Hacienda San Angel,Extranet,,Erick,Martinez Gomez,info@haciendasanangel.com,"",,,,,,,,2025-09-18,2025-09-21,3,,"","DIRECT RESERVATION // +SPECIAL RATE FOR FIDEICOISO DE TURISMO // +PREMIOS ARIEL // +SUITE GARDEN OF ANGELS // + STAY SEP 18- 21 202 // +RATE $ 220.8 USD + TAX // +PIF +SEP162025GV",,Checked-out,"", Garden of Angels - Junior Suite,Manual,662.4,828.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,828.0,828.0,2,0,0,1,,,0,0.0,false,"",false,0,165.6,Room 109,2914-1 +EXP-2291681622,2025-09-17,Hacienda San Angel,Expedia,,Angelica,Avila,g7il01yn8c@m.expediapartnercentral.com,0 0 3339680927,,,,,,,,2025-09-19,2025-09-20,1,,"Hotel Collect Booking, 2 Double Beds, Non-Smoking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT SEP172025 // +CREDIT CARD INFORMATION OK // +RATE $ 342 USD + TAXES // +STAY SEP19-202025 // +SUITE SAN GABRIEL // +SUBMITED SEP172025NGR//",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,342.0,427.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,427.5,427.5,2,0,0,1,,,0,0.0,false,"",false,0,85.5,Room 118,2910-1 +LH25060648578286,2025-06-06,Hacienda San Angel,Extranet,,Mariana,Test,"","",,,,,,,,2025-09-21,2025-09-26,5,,,,,Cancelled,2025-06-06 15:42:56,Crown View - Junior Suite,Crown View - Package Rate,1485.0,1856.25,0.0,0.0,0.0,0.0,0,0.0,0.0,1856.25,0,2,0,0,1,,,0,1856.25,false,"",false,0,371.25,Room 112,"" +MMS-OBH25070406060104-2896167,2025-07-04,Hacienda San Angel,Mr and Mrs Smith,,Philip,Dorin,HANSHIROSAN@GMAIL.COM,,,,,,,,,2025-09-21,2025-09-22,1,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +Late checkout if possible would be great","RESERVATION FROM MR. SMITH +RATE $329.47 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY04/25 +OK MARIANA JULY04/25",,Checked-out,"", San Miguel - Presidential Suite,Manual,329.47,1194.74,0.0,0.0,0.0,782.9,0.0,0.0,0.0,1194.74,1194.74,2,0,0,1,,,0,0.0,false,"",false,0,82.3675,Room 107,2916-1 +LH25082050350192,2025-08-20,Hacienda San Angel,Extranet,,Shaun,Richards,s.richards@f1s.com,403.615.4165,,,,,,,,2025-09-21,2025-09-22,1,,,,,Cancelled,2025-08-20 21:31:51, Celestial - Royal Suite,Celestial - Standard Rate,480.0,600.0,0.0,0.0,0.0,0.0,0,0.0,0.0,600.0,0,2,0,0,1,,,0,600.0,false,"",false,0,120.0,Room 103,"" +MMS-OBH25070908241404-2901044,2025-07-09,Hacienda San Angel,Mr and Mrs Smith,,Martha,Doyle,MARTHA.DOYLE@REGENCE.COM,,,,,,,,,2025-09-22,2025-09-27,5,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS .COM // +CONFIRMATION SENT JULY092025// +CREDIT CARD INFORMATION OK // +RATE $ 393 USD + TAXES // +STAY SEP22-272025 // +SUITE RINCÓN OF ANGELS / CHANGED TO SAN MIGUEL // +SUBMITED JULY092025NGR//",,Checked-out,"", San Miguel - Presidential Suite,Manual,1965.12,2826.95,0.0,0.0,0.0,370.55,0.0,0.0,0.0,2826.95,2826.95,1,0,0,1,,,0,0.0,false,"",false,0,491.28,Room 107,"2918-1, 2918-2" +MMS-OBH25070722560404-2899689,2025-07-07,Hacienda San Angel,Mr and Mrs Smith,,Brian,Oakey,BPOAKEY@SMCM.EDU,,,,,,,,,2025-09-24,2025-09-26,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT JULY072025 // +CREDIT CARD INFORMATION OK // +RATE $290.14 USD + TAXES // +STAY SEP24-262025 // +SUITE ANGEL DOME// +SUBMITED JULY072025NGR//",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,580.99,721.58,0.0,0.0,0.0,-4.66,0.0,0.0,0.0,721.58,721.58,1,0,0,1,,,0,0.0,false,"",false,0,145.2475,Room 113,2917-1 +MMS-OBH25070915335504-2901484,2025-07-09,Hacienda San Angel,Mr and Mrs Smith,,Adam,Grimm,GRIMM.ADAM24@GMAIL.COM,,,,,,,,,2025-09-24,2025-09-28,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT JULY092025 // +CREDIT CARD INFORMATION OK// +RATE $ 439.29 USD + TAXES // +STAY SEP24-272025// +SUITE ANGEL VIEW // +SUBMITED JULY092025NGR //",,Checked-out,"", Angels View - Master Suite,Angels View - Standard Rate,1317.89,2028.18,0.0,0.0,0.0,380.82,0.0,0.0,0.0,2028.18,2028.18,2,0,0,1,,,0,0.0,false,"",false,0,329.4725,Room 106,2921-1 +SMP-2025083043012413,2025-08-30,Hacienda San Angel,Simple Booking,,Italo Eduardo,Guerra,edward.guerra@som.com,+525514001450,,,,,,Mexico,"",2025-09-24,2025-09-28,4,,"","RESERVATION FROM SIMPLEBOOKING// +CONFIRMATION SENT AGO 30 // +RATE $ 265.48 USD + TAX // +OK INFO CREDIT ARD MARTERCARD PENDING CVV // +NO PROMO // +SECRET RATE $ // +SUITE GARDEN- CHANGE ROOM TO SAN GABRIEL // +STAY SEP 24- 28 2025 // +AGO302025GV",,Checked-out,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1520.0,1623.65,0.0,0.0,0.0,-276.35,0.0,0.0,0.0,1623.65,1623.65,2,0,0,1,,,0,0.0,false,"",false,0,380.0,Room 118,2919-1 +SMP-2025090143033552,2025-09-01,Hacienda San Angel,Simple Booking,,Ronald,Brower,stbrower208@gmail.com,+19499030811,,,,,,,"",2025-09-25,2025-09-29,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $366.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT AUG31/2025 +OK MARIANA31/2025",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,1490.0,2796.86,0.0,0.0,0.0,934.36,0.0,0.0,0.0,2796.86,2796.86,2,0,0,1,,,0,0.0,false,"",false,0,372.5,Room 102,"2923-1, 2923-2" +LH25092651173360,2025-09-26,Hacienda San Angel,Extranet,,DEVIN,BURSTEIN,devinjai@gmail.com,9176275966,,,,,,,,2025-09-26,2025-09-28,2,,"","RESERVATION DIRECTLY +RATE $ 0 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMAION SENT SEP26/2025 +OK MARIANA SEP26/2025 + +ANGEL RATE",,Checked-out,"", San Jose - Master Suite,Manual,0.0,54.47,0.0,0.0,0.0,54.47,0.0,0.0,0.0,54.47,54.47,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 122,2922-1 +EXP-2262941751,2025-08-07,Hacienda San Angel,Expedia,,DELANE,SWANK,"",1 7073376492,,,,,,,,2025-09-27,2025-09-29,2,,"Hotel Collect Booking, 1 King Bed, Non-Smoking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXP // +RATE $ 450 USD + TAXES // +CREDIT CARD INFORMATION OK AMEX // +BLUE PROMOTION EXP DISCOUNT 10% // +SUITE SAN MIGUEL // +STAY SEP 27- 29 2025 // +AGO072025GV",,Checked-out,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,900.0,1365.6,0.0,0.0,0.0,240.6,0.0,0.0,0.0,1365.6,1365.6,2,0,0,1,,,0,0.0,false,"",false,0,225.0,Room 107,2924-1 +EXP-2294359361,2025-09-20,Hacienda San Angel,Expedia,,RICHARD,CHIPMAN,,1 4088237706,,,,,,,,2025-09-27,2025-09-28,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 453.60, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""",,,Cancelled,2025-09-20 17:41:47, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,378.0,472.5,0.0,0.0,0.0,0.0,0,0.0,0.0,472.5,0,2,0,0,1,,,0,472.5,false,"",false,0,94.5,Room 121,"" +EXP-2294368880,2025-09-20,Hacienda San Angel,Expedia,,Richard,Chpiman,s512qc86j4@m.expediapartnercentral.com,1 0 4088237706,,,,,,,,2025-09-27,2025-09-28,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 485.76, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA VIP +RATE $404.80 + TAXES +$85.00 CREDIT ONF FOOD & BEVERAGE +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP20/2025 +OK MARIANA SEP20/2025",,Checked-out,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,404.8,526.0,0.0,0.0,0.0,20.0,0.0,0.0,0.0,526.0,526.0,2,0,0,1,,,0,0.0,false,"",false,0,101.2,Room 119,2920-1 +MMS-OBH25090521283800-2960985,2025-09-05,Hacienda San Angel,Mr and Mrs Smith,,Jinna,Caples,JUPAIK@GMAIL.COM,,,,,,,,,2025-09-28,2025-09-30,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS / HIATT // +VIRTUAL CARD FOR CHARGE // +RATE $ 304.08 USD + TAX // +NO PROMO // +SUITE ANGEL DOME // +STAY SEP 28- OCT 01 2025 // +SEP052025GV + + +THEY MADE UPGRADE 2 NIGHTS ON AV AND ON MORE NIGHT ON SM",,Checked-out,"", Angels View - Master Suite,Manual,585.26,1067.86,0.0,0.0,0.0,336.28,0.0,0.0,0.0,1067.86,1067.86,2,0,0,1,,,0,0.0,false,"",false,0,146.315,Room 106,2925-1 +BDC-5805218731,2025-06-21,Hacienda San Angel,Booking.com,,Paula,Dukehart,pdukeh.729506@guest.booking.com,+1 703 216 7886,,,,,,United States,"",2025-09-29,2025-10-03,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-09-27., booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-06-21 07:27:10,Serafin - Junior Suite,Serafin - Standard Rate,1183.5,1479.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1479.38,0,2,0,0,1,,,0,1479.38,false,"",false,0,295.875,Room 110,"" +BDC-6750330232,2025-06-21,Hacienda San Angel,Booking.com,,Paula,Dukehart,pdukeh.866536@guest.booking.com,+1 703 216 7886,,,,,,United States,"",2025-09-29,2025-10-01,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-09-27. +Approximate time of arrival: between 16:00 and 17:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JUN21 // +RATE $ 272.25 USD + TAXES // +CREDIT CARD INFO OK, VIRTUAL CARD FOR CHARGE // +PROMO GENIUS DISCOUNT 10% // +SUITE SERAFIN // +STAY SEP 29- OCT 01 2025 // +JUN212025GV",,Cancelled,2025-08-17 05:44:56,Serafin - Junior Suite,Serafin - Standard Rate,544.5,684.98,0.0,0.0,0.0,4.35,0,0.0,0.0,684.98,0,2,0,0,1,,,0,684.98,false,"",false,0,136.125,Room 110,"" +SMP-2025072642137731,2025-07-26,Hacienda San Angel,Simple Booking,,Paula,Dukehart,pauladukehart@gmail.com,+1703-216-7886,,,,,,,"",2025-09-29,2025-10-01,2,,"","RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT JULY252025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 425 USD + TAXES // +STAY SEP29-OCT012025 // +SUITE MILAGROS // +SUBMITED JULY252025NGR //",,Checked-out,"", Milagros - Junior Suite,Milagros - Standard Rate,680.0,1195.98,0.0,0.0,0.0,345.98,0.0,0.0,0.0,1195.98,1195.98,2,0,0,1,,,0,0.0,false,"",false,0,170.0,Room 102,"2927-1, 2927-2" +MMS-OBH25042314093507-2820069,2025-04-23,Hacienda San Angel,Mr and Mrs Smith,,Dawn,Hammon,DNHAMMON@GMAIL.COM,,,,,,,,,2025-09-30,2025-10-02,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // +FROM HYATT // +CONFIRMATION SENT ABR 23 // +RATE $ 273 USD + TAX // +VIRTUAL CARD FOR CHARGE // +NO PROMO // +SUITE MILAGROS // +STAY SEP 30- OCT 02 2025 // +ABR232025GV",,Cancelled,2025-04-24 18:01:10, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,524.16,682.5,0.0,0.0,0.0,27.3,0,0.0,0.0,682.5,0,2,0,0,1,,,0,682.5,false,"",false,0,131.04,Room 109,"" +MMS-OBH25042314442206-2820114,2025-04-23,Hacienda San Angel,Mr and Mrs Smith,,Heather,Mcgowan,HEATHERMCGOWAN50@GMAIL.COM,,,,,,,,,2025-09-30,2025-10-02,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // +FROM HYATT // +CONFIRMATION SENT ABR 23 // +RATE $ 273 USD + TAX // +VIRTUAL CARD FOR CHARGE // +NO PROMO // +SUITE GARDEN OF ANGEL // +STAY SEP 30- OCT 02 2025 // +ABR232025GV",,Cancelled,2025-04-24 09:21:04, Milagros - Junior Suite,Milagros - Standard Rate,524.16,682.5,0.0,0.0,0.0,27.3,0,0.0,0.0,682.5,0,2,0,0,1,,,0,682.5,false,"",false,0,131.04,Room 102,"" +EXP-2182938485,2025-04-23,Hacienda San Angel,Expedia,,DAWN,HAMMON,9eupu65oni@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-09-30,2025-10-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 918.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXP // +CONFIRMATION SENT ABR 23 // +CREDIT CARD INFO OK // +RATE $ 382.50 USD + TAX // +VIRTUAL CARD FOR CHARGE //BLUE PROMO EXP 10% DISCOUNT // +SUITE SAN JOSE // +STAY SEP 30- OCT 02 2025 // +ABR232025GV",,Cancelled,2025-08-02 13:56:42, San Jose - Master Suite,San Jose - Standard Rate,765.0,956.25,0.0,0.0,0.0,0.0,0,0.0,0.0,956.25,0,2,0,0,1,,,0,956.25,false,"",false,0,191.25,Room 122,"" +EXP-2183454183,2025-04-24,Hacienda San Angel,Expedia,,DAWN,HAMMON,dho0ed0yfb@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-09-30,2025-10-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 934.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $389.25 + TAXES +NO PROMO +VIRUTAL CREDIT CARD OK +CONFIRMATION APRIL24/25 +OK MARIANA APRIL24/25",,Cancelled,2025-08-02 14:01:51, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,778.5,973.13,0.0,0.0,0.0,0.0,0,0.0,0.0,973.13,0,2,0,0,1,,,0,973.13,false,"",false,0,194.625,Room 121,"" +EXP-2257785086,2025-08-01,Hacienda San Angel,Expedia,,Peter,Drozdoff,1u7jos3ied@m.expediapartnercentral.com,1 0 7605608436,,,,,,,,2025-09-30,2025-10-06,6,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,987.64, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $414. 95 + TAXES +UPGRADE OR BOTLLE + $85.00 CREDIT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY30/2025 +OK MARIANA JULY30/2025",,Cancelled,2025-09-23 11:21:04, Angels View - Master Suite,Angels View - Standard Rate,2489.7,3112.13,0.0,0.0,0.0,0.0,0,0.0,0.0,3112.13,0,2,0,0,1,,,0,3112.13,false,"",false,0,622.425,Room 106,"" +EXP-2257785920,2025-08-01,Hacienda San Angel,Expedia,,Peter,Drozdoff,h99vgreyxm@m.expediapartnercentral.com,1 0 7605608436,,,,,,,,2025-09-30,2025-10-06,6,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 3,128.70, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $434.54 + TAXES +UPGRADE OR BOTLLE + $85.00 AS A CREDIT +VIRTUAL CREDIT CARD OK +CONFRIMATION SENT JULY31/2025 +OK MARIANA JULY31/2025",,Checked-in,"", Celestial - Royal Suite,Celestial - Standard Rate,2607.25,3567.94,0.0,0.0,0.0,308.88,0.0,0.0,0.0,3567.94,3259.06,2,0,0,1,,,0,308.88,false,"",false,0,651.8125,Room 103,"" +LH25092851213580,2025-09-28,Hacienda San Angel,Extranet,,JINNA,CAPLES,"","",,,,,,,,2025-09-30,2025-10-01,1,,"",THIS RESERVATION IS PAID IN THE THE ONE ON AV,,Checked-out,"", San Miguel - Presidential Suite,Manual,0.0,515.95,0.0,0.0,0.0,515.95,0.0,0.0,0.0,515.95,515.95,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,2928-1 +BDC-4719508675,2025-04-13,Hacienda San Angel,Booking.com,,Becky,Slama,bslama.272912@guest.booking.com,+1 408 406 6142,,,,,,United States,"",2025-10-02,2025-10-04,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-09-30. +Approximate time of arrival: between 16:00 and 17:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT ABR13 // +RATE $ 339.75 USD + TAX // +CREDIT CARD OK, VIRTUAL CARD FOR CHARGE // +SUITE ANGEL DOME // +STAY OCT 02- 04 2025 // +GENIUS DISCOUNT 10% BOOKING.COM // +ABR132025GV",,Checked-out,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,679.5,1138.7,0.0,0.0,0.0,289.32,0.0,0.0,0.0,1138.7,1138.7,2,0,0,1,,,0,0.0,false,"",false,0,169.875,Room 113,2930-1 +SMP-2025061440971908,2025-06-13,Hacienda San Angel,Simple Booking,,Jonathan,Aills,jsaills@att.net,+17135173611,,,,,,,"",2025-10-02,2025-10-06,4,,"","SIMPLEBOOKING +JUN132025 +CC PENDIENT CVV +$515 USD + TAX +SAN MIGUEL +JUN132025NGR",,Checked-in,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2060.0,2705.94,0.0,0.0,0.0,130.94,0.0,0.0,0.0,2705.94,2575.0,2,0,0,1,,,0,130.94,false,"",false,0,515.0,Room 107,"" +SMP-2025061440971942,2025-06-13,Hacienda San Angel,Simple Booking,,Jonathan,Aills,jsaills@att.net,+17135173611,,,,,,,"",2025-10-02,2025-10-06,4,,"","SIMPLEBOOKING +JUN132025 +CC PENDIENT CVV +$366.25 USD + TAX +GARDEN OF ANGELS +JUN132025NGR",,Checked-in,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1465.0,1831.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1831.25,1831.25,2,0,0,1,,,0,0.0,false,"",false,0,366.25,Room 109,"" +SMP-2025080342367776,2025-08-03,Hacienda San Angel,Simple Booking,,Brittany,Hyman,bdtaylor85@gmail.com,+1832-875-3843,,,,,,United States of America,"",2025-10-02,2025-10-05,3,,Celebrating 40th birthday on October 4,"RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT AGO03 // +NO PROMO // +RATE $ 388.13 USD + TAX // +SECRET RATE // +SUITE CROWN VIEW // +STAY OCT 02- 05 2025 // +CREDIT CARD INFORMATION VISA CVV ok // +AGO032025GV",,Checked-in,"",Crown View - Junior Suite,Crown View - Standard Rate,1164.41,1498.57,0.0,0.0,0.0,43.06,0.0,0.0,0.0,1498.57,1455.51,2,0,0,1,,,0,43.06,false,"",false,0,291.1025,Room 112,2929-1 +BDC-4472761902,2025-01-10,Hacienda San Angel,Booking.com,,alexyz,gutierrez,agutie.335088@guest.booking.com,+1 575 513 8353,,,,,,United States,"",2025-10-03,2025-10-08,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-10-01. +smoking preference: Non-Smoking",,,Cancelled,2025-01-10 05:34:08, San Jose - Master Suite,San Jose - Standard Rate,2295.0,2845.8,0.0,0.0,0.0,0.0,0,0.0,0.0,2845.8,0,2,0,0,1,,,0,2845.8,false,"",false,0,550.8,Room 122,"" +EXP-2273504451,2025-08-22,Hacienda San Angel,Expedia,,Héctor Damián,Carrillo Ramírez,eeijipiwks@m.expediapartnercentral.com,0 0 3318620661,,,,,,,,2025-10-04,2025-10-06,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,112.40, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: 1 bebida gratis para 2 (por persona, una vez por estancia)","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT AUG222025 // +CREDIT CARD INFORMATION OK // +RATE $ 463.50 USD + TAXES // +STAY OCT4-62025 // +SUITE RINCÓN OF ANGELS // +SUBMITED AUG222025NGR //",,Checked-in,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,927.0,1158.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1158.75,1112.4,2,0,0,1,,,0,46.35,false,"",false,0,231.75,Room 119,"" +LH25100251308964,2025-10-02,Hacienda San Angel,Extranet,,Azael,Sandoval,pegsteley@gmail.com,322-228-8090,,,,,,,,2025-10-04,2025-10-05,1,,"",This is a regular guest of the restaurant that has made a reservation for an employee of hers as a thank you to him. Azael is the guest. The email on file is Peg Steley and she is the woman paying for the room.- Natasha,,Checked-in,"", Angels View - Master Suite,Manual,305.0,312.63,0.0,0.0,0.0,0.0,0.0,0.0,0.0,312.63,312.63,2,0,0,1,,,0,0.0,false,"",false,0,62.525,Room 106,"" +SMP-2025100543677052,2025-10-05,Hacienda San Angel,Simple Booking,,gwbowler,Bowler,gwbowler@gmail.com,+16199161172,,,,,,,"",2025-10-05,2025-10-08,3,,"",,,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,844.6,1055.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1055.75,0,2,0,0,1,,,0,1055.75,false,"",false,0,211.15,Room 113,"" +LH25051548089605,2025-05-15,Hacienda San Angel,Extranet,,Paul,Gomez,pgomez100@msn.com,322 173 9753,,,,,,,,2025-10-06,2025-10-08,2,,"","GIFT CERTIFICATE FOR $2,000 USD 2 NIGHT STAY IN SERAPHIM SUITE +SPCA PV",,Cancelled,2025-08-29 13:32:14, Angels View - Master Suite,Angels View - Standard Rate,860.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 106,"" +EXP-2190782293,2025-05-05,Hacienda San Angel,Expedia,,Augustine,Cheng,d4h00dxv9w@m.expediapartnercentral.com,1 0 4807475443,,,,,,,,2025-10-09,2025-10-12,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIPPREMIUM.COM // +CONFIRMATION SENT MAY042025 // +CREDIT CARD INFORMATION OK // +RATE $454.36 USD + TAXES // +STAY OCT09122025 // +SUITE SAN MIGUEL // +SUBMITED MAY042025NGR//",,Cancelled,2025-05-12 11:44:04, San Miguel - Presidential Suite,San Miguel - Standard Rate,1363.1,1703.88,0.0,0.0,0.0,0.0,0,0.0,0.0,1703.88,0,2,0,0,1,,,0,1703.88,false,"",false,0,340.775,Room 107,"" +SMP-2025092143435429,2025-09-21,Hacienda San Angel,Simple Booking,,Thomas,Ryan,thosryandesign@mac.com,+1323-842-4783,,,,,,,"",2025-10-09,2025-10-13,4,,I've stayed many times with y'all and looking forward to coming back!,"RESERVATION FROM SIMPLE BOOKING +RATE $462.50 + TAXES +BEST AVAILABLE RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT SEP20/2025 +OK MARIANA SEP20/2025",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,1850.0,2312.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2312.5,0,2,0,0,1,,,0,2312.5,false,"",false,0,462.5,Room 122,"" +SMP-2025052040337434,2025-05-20,Hacienda San Angel,Simple Booking,,Sean,Bartmasser,bartmasser@gmail.com,+15107252210,,,,,,,"",2025-10-10,2025-10-13,3,,Celebrating my wife's Birthday :),"SIMPLEBOOKING.COM +OCT10-132025 +$456.66 + TAX +CVV & ZC PENDIENT +MAY202025NGR",,Cancelled,2025-09-19 20:17:15, Angels View - Master Suite,Angels View - Standard Rate,1370.0,1712.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1712.5,0,2,0,0,1,,,0,1712.5,false,"",false,0,342.5,Room 106,"" +MMS-OB25090221575303-2957795,2025-09-02,Hacienda San Angel,Mr and Mrs Smith,,Shawna,Hickel,shawna.hickel@gmail.com,19072978567,,10212 Valley Park Dr,,Anchorage,Anchorage,United States,99507-7319,2025-10-10,2025-10-15,5,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $327.24 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP02/2025 +OK MARIANA SEP02/2025",,Cancelled,2025-09-26 17:00:57, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1636.18,1789.58,0.0,0.0,0.0,-255.65,0,0.0,0.0,1789.58,0,2,0,0,1,,,0,1789.58,false,"",false,0,409.045,Room 109,"" +BDC-5355782448,2025-09-26,Hacienda San Angel,Booking.com,,Shawna,Hickel,shicke.453606@guest.booking.com,+1 907 297 8567,,,,.,,United States,"",2025-10-10,2025-10-14,4,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $370. 17 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT SEP26/2025 +OK MARIANA SEP26/25",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1651.5,2079.19,0.0,0.0,0.0,14.81,0,0.0,0.0,2079.19,0,2,0,0,1,,,0,2079.19,false,"",false,0,412.875,Room 106,"" +EXP-X-421751379,2025-02-27,Hacienda San Angel,Expedia,,Shalini,Sharp,7bqbu3i5g9@m.expediapartnercentral.com,0 0 9173281087,,,,,,,,2025-10-11,2025-10-13,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 2 Double Beds, Non-Smoking, Remittance amount: 887.04, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT FEB262025 // +CREDIT CARD INFORMATION OK // +RATE $ 369.60 USD + TAXES // +STAY OCT11-132025 // +SUITE SAN GABRIEL // +SUBMITED FEB262025NGR//",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,739.2,924.0,0.0,0.0,0.0,0.0,0,0.0,0.0,924.0,0,2,0,0,1,,,0,924.0,false,"",false,0,184.8,Room 118,"" +SMP-2025071841922620,2025-07-17,Hacienda San Angel,Simple Booking,,Bob,Faircloth,bob.faircloth@gmail.com,+13108928683,,,,,,,"",2025-10-11,2025-10-13,2,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JULY172025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 442.80 USD + TAXES // +STAY OCT11-132025 // +SUITE CELESTIAL // +SUBMITED JULY172025NGR//",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,885.6,1107.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1107.0,0,2,0,0,1,,,0,1107.0,false,"",false,0,221.4,Room 103,"" +SMP-2025071841937074,2025-07-18,Hacienda San Angel,Simple Booking,,Bryan,Kehoe,bryan_kehoe@nihonkohden.com,+17276435605,,,,,,,"",2025-10-11,2025-10-13,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $321.85 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JULY18/2025 +OK MARIANA JULY18/2025 + + +UPGRADE FROM GA TO RA DIFFERENCE P/N $209.00 TAXES INCLUDED ( APLLY THE SECRET RATE DISCCOUNT) OK MARIANA JYLU22/2025",,Confirmed,"", Rincon de Angeles - Royal Suite,Manual,643.7,1222.63,0.0,0.0,0.0,418.0,0,0.0,0.0,1222.63,0,2,0,0,1,,,0,1222.63,false,"",false,0,160.925,Room 119,"" +SMP-2025080442371353,2025-08-03,Hacienda San Angel,Simple Booking,,Mark,Callender,callendm@tcd.ie,+16466479387,,,,,,,"",2025-10-11,2025-10-14,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $ 343.03 + TAXES +SECRET RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SEND AUG03/2025 +OK MARIANA AUG03/2025",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1029.1,1286.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1286.38,0,2,0,0,1,,,0,1286.38,false,"",false,0,257.275,Room 113,"" +EXP-2238583914,2025-07-07,Hacienda San Angel,Expedia,,MAX,BAUCUS,ywnxi6fcps@m.expediapartnercentral.com,44 20 39293737,,,,,,,,2025-10-12,2025-10-13,1,,"Hotel Collect Booking, 1 Queen Bed, Non-Smoking, We would like to bring our 5 pound well behaved dog. He is a Yorkie Poo so he doesnot shed and is hyperallergenic., Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""",,,Cancelled,2025-07-07 15:02:49,Angels Dome - Junior Suite,Angels Dome - Standard Rate,391.5,489.38,0.0,0.0,0.0,0.0,0,0.0,0.0,489.38,0,2,0,0,1,,,0,489.38,false,"",false,0,97.875,Room 113,"" +SMP-2025070741637425,2025-07-07,Hacienda San Angel,Simple Booking,,Melodee,Hanes,msmelda1@gmail.com,+1202870-8818,,,,,,,"",2025-10-12,2025-10-13,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JULY072025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 483.80 USD + TAXES // +STAY OCT12-132025 // +SUITE SAN MIGUEL PRESIDENTIAL SUITE // +SUBMITED JULY072025NGR//",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,483.8,604.75,0.0,0.0,0.0,0.0,0,0.0,0.0,604.75,0,2,0,0,1,,,0,604.75,false,"",false,0,120.95,Room 107,"" +EXP-X-417700024,2025-02-21,Hacienda San Angel,Expedia,,Anthony,Glaser,dyuwsmcl4x@m.expediapartnercentral.com,1 843 8146200,,,,,,,,2025-10-13,2025-10-20,7,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +EXP VIP PREMIUM // +$85 USD CREDIT & UP-GRADE OR BOTTLE OF WINE // +CREDIT CARD INFORMATION OK VISA // +CONFIRMATION SENT FEB20 // +PROMOTION GOLD 10% DISCOUNT // +SUITE ANGEL DOME // +STAY OCT 13- 20 2025 // +FEB202025GV",,Cancelled,2025-02-21 12:03:47,Angels Dome - Junior Suite,Angels Dome - Standard Rate,2360.7,2950.88,0.0,0.0,0.0,0.0,0,0.0,0.0,2950.88,0,2,0,0,1,,,0,2950.88,false,"",false,0,590.175,Room 113,"" +LH25081450199221,2025-08-14,Hacienda San Angel,Extranet,,Emily,Chourre,"","",,,,,,,,2025-10-13,2025-10-21,8,,Angel's Rate,"Family friend + +No charge for anything. She will tip staff well. The $280 is the 7% for staff; be sure Miguel knows please- Paula",,Confirmed,"",Serafin - Junior Suite,Manual,280.0,280.0,0.0,0.0,0.0,0.0,0,0.0,0.0,280.0,0,1,0,0,1,,,0,280.0,false,"",false,0,70.0,Room 110,"" +EXP-X-409559696,2025-02-07,Hacienda San Angel,Expedia,,John,OBrien,lant110o7t@m.expediapartnercentral.com,0 0 9364992975,,,,,,,,2025-10-14,2025-10-15,1,,"Hotel Collect Booking, 1 King Bed, Non-Smoking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIP.COM // +CONFIRMATION SENT FEB072025// +CREDIT CARD INFORMATION OK// +RATE $ 409.20 USD + TAXES // +STAY OCT14-152025 // +SUITE SAN JOSE // +SUBMITED FEB72025NGR//",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,409.2,511.5,0.0,0.0,0.0,0.0,0,0.0,0.0,511.5,0,2,0,0,1,,,0,511.5,false,"",false,0,102.3,Room 122,"" +MMS-OB25090511051106-2960399,2025-09-05,Hacienda San Angel,Mr and Mrs Smith,,Kate,Parsons,kate.parsons@live.co.uk,+447572950835,,6 Novello Street,,London,,United Kingdom,SW6 4JB,2025-10-14,2025-10-17,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT SEP052025// +CREDIT CARD INFORMATION OK // +RATE $ 321.82 USD + TAXES // +STAY OCT14-172025 // +SUITE ANGEL DOME // +SUBMITED SEP052025NGR//",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,965.47,1055.99,0.0,0.0,0.0,-150.85,0,0.0,0.0,1055.99,0,2,0,0,1,,,0,1055.99,false,"",false,0,241.3675,Room 113,"" +SMP-2025090543146496,2025-09-05,Hacienda San Angel,Simple Booking,,Leah,Dailey,jdailey63@hotmail.com,+12516895133,,,,,,,"",2025-10-15,2025-10-19,4,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT SEP052025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 334.15 USD + TAXES // +STAY JOCT15-192025 // +SUITE MILAGROS // +SUBMITED SEP052025NGR//",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,1336.6,1670.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1670.75,0,2,0,0,1,,,0,1670.75,false,"",false,0,334.15,Room 102,"" +SMP-2025073042260552,2025-07-30,Hacienda San Angel,Simple Booking,,Dan,Eisenhardt,daneisenhardt@gmail.com,+17783844549,,,,,,Canada,"",2025-10-16,2025-10-19,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JULY302025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $535 USD + TAXES // +STAY OCT16-192025 // +SUITE SAN MIGUEL // +SUBMITED JULY302025NGR//",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1605.0,2006.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2006.25,0,2,0,0,1,,,0,2006.25,false,"",false,0,401.25,Room 107,"" +BDC-6317942031,2025-08-17,Hacienda San Angel,Booking.com,,Arnaud,De boer,aboer.896291@guest.booking.com,+1 669 304 7323,,,,.,,United States,"",2025-10-17,2025-10-22,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-10-15., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT AUG172025// +CREDIT CARD INFORMATION OK // +RATE $ 310.23 USD + TAXES // +STAY OCT17-222025 // +SUITE GARDEN OF ANGELS // +SUBMITED AGO172025NGR //",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1551.15,1951.35,0.0,0.0,0.0,12.41,0,0.0,0.0,1951.35,0,2,0,0,1,,,0,1951.35,false,"",false,0,387.7875,Room 109,"" +EXP-2290548240,2025-09-15,Hacienda San Angel,Expedia,,DANIEL,YUFA,10a7hmn105@m.expediapartnercentral.com,1 414 9342099,,,,,,,,2025-10-20,2025-10-22,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,058.40, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION FROM EXPEDIA +RATE $441.00 USD + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP15/2025 +OK MARIANA SEP15/2025",,Cancelled,2025-09-15 20:05:55, Celestial - Royal Suite,Celestial - Standard Rate,882.0,1102.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1102.5,0,2,0,0,1,,,0,1102.5,false,"",false,0,220.5,Room 103,"" +SMP-2025091643343413,2025-09-16,Hacienda San Angel,Simple Booking,,Daniel,Yufa,dalina4u@gmail.com,+18476096956,,,,,,,"",2025-10-20,2025-10-22,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $405.90 + TAXES +SECRET RATE +VISA CREDIT CARD CVV PENDING +CONFIRMATION SENT SEP15/2025 +OK MARIANA SEP15/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,811.8,1014.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1014.75,0,2,0,0,1,,,0,1014.75,false,"",false,0,202.95,Room 103,"" +SMP-2025042239664381,2025-04-22,Hacienda San Angel,Simple Booking,,Rina,Tinozzi,wedalert@yahoo.com,+14152598915,,,,,,,"",2025-10-23,2025-10-24,1,,"we're the Bride and groom, booking the presidential one day early!","RESERVATION FROM SIMPLE BOOKING +RATE 4455.10 + TAXES +SECRET RATE +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT APRIL22/25 +OK MARIANA APRIL22/25",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,455.1,568.88,0.0,0.0,0.0,0.0,0,0.0,0.0,568.88,0,2,0,0,1,,,0,568.88,false,"",false,0,113.775,Room 107,"" +EXP-2182181665,2025-04-22,Hacienda San Angel,Expedia,,Karmin,Sanderson,be9k6bifdi@m.expediapartnercentral.com,1 0 4152727779,,,,,,,,2025-10-23,2025-10-24,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, ***, Remittance amount: 517.44, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP +RATE $431.20 + TAXES +$85.00 CREDIT ON FOOD & BEVERAGE +VIRTUAL CREDIT CARD +CONFIRMATION SENT APRIL22/25 +OK MARIANA APRIL22/25",,Cancelled,2025-04-23 09:18:58, San Jose - Master Suite,San Jose - Standard Rate,431.2,539.0,0.0,0.0,0.0,0.0,0,0.0,0.0,539.0,0,2,0,0,1,,,0,539.0,false,"",false,0,107.8,Room 122,"" +LH25042847703151,2025-04-28,Hacienda San Angel,Extranet,,Rina y Rob // PETTER NAPOLLI,Tinozzi/Sharman,"","",,,,,,,,2025-10-23,2025-10-24,1,,"","RESERVATION DIRECTLY +RATE $490.00 + TAXES +NO PROMO +CREDIT CARD INFO CVV OK +CONFIRMATION SENT APRIL28/25 +OK MARIANA APRIL28/25",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,490.0,612.5,0.0,0.0,0.0,0.0,0,0.0,0.0,612.5,0,2,0,0,1,,,0,612.5,false,"",false,0,122.5,Room 122,"" +SMP-2025050539951642,2025-05-05,Hacienda San Angel,Simple Booking,,Rina,Tinozzi,rinabirdy@gmail.com,+14152598915,,,,,,,"",2025-10-23,2025-10-24,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAY42025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 319.80 USD + TAXES // +STAY OCT23-242025 // +SUITE SERAFÍN // +SUBMITED MAY42025NGR//",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,319.8,399.75,0.0,0.0,0.0,0.0,0,0.0,0.0,399.75,0,1,0,0,1,,,0,399.75,false,"",false,0,79.95,Room 110,"" +SMP-2025050539974201,2025-05-05,Hacienda San Angel,Simple Booking,,Peter,Baum,junkster3@myastound.net,+14155334728,,,,,,,"",2025-10-23,2025-10-24,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAY05 // +SECRET RATE // +RATE $ 401.80 USD + TAX // +CREDIT CARD INFORMATION VISA PENDING CVV // +NO RPOMO // +SUITE ANGEL VIEW // +STAY OCT 23- 24 2025 // +MAY052025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,401.8,502.25,0.0,0.0,0.0,0.0,0,0.0,0.0,502.25,0,2,0,0,1,,,0,502.25,false,"",false,0,100.45,Room 106,"" +SMP-2025051740260760,2025-05-17,Hacienda San Angel,Simple Booking,,Jen,Pezman Forshan,jennypezman@gmail.com,+14152504390,,,,,,,"",2025-10-23,2025-10-24,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAY 17 // +RATE $ 414.10 USD + TAX // +SECRET RATE // +CREDIT CARD INFORMATION VISA PENDING CVV // +NO PROMO // +SUITE CELESTIAL // +STAY OCT 23- 24 2025 // +MAY172025GV",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,414.1,517.63,0.0,0.0,0.0,0.0,0,0.0,0.0,517.63,0,2,0,0,1,,,0,517.63,false,"",false,0,103.525,Room 103,"" +SMP-2025052340415873,2025-05-23,Hacienda San Angel,Simple Booking,,Rina,Tinozzi,rinabirdy@gmail.com,+14152598915,,,,,,,"",2025-10-23,2025-10-24,1,,Part of the Sharman wedding party for the upcoming weekend.,"SIMPLEBOOKING.COM +OCT23-242025 +CVV PENDIENT +$440 + TAX +SAN GABRIEL +MAY232025NGR",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,440.0,550.0,0.0,0.0,0.0,0.0,0,0.0,0.0,550.0,0,2,0,0,1,,,0,550.0,false,"",false,0,110.0,Room 118,"" +SMP-2025052340415925,2025-05-23,Hacienda San Angel,Simple Booking,,Rina,Tinozzi,rinabirdy@gmail.com,+14152598915,,,,,,,"",2025-10-23,2025-10-24,1,,guests of the Sharman Wedding this upcoming weekend.,"SIMPLEBOOKING.COM +OCT23-242025 +CVV PENDIENT +$540 + TAX +RINCÓN DE ANGELES +MAY232025NGR",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,540.0,675.0,0.0,0.0,0.0,0.0,0,0.0,0.0,675.0,0,2,0,0,1,,,0,675.0,false,"",false,0,135.0,Room 119,"" +SMP-2025052340416380,2025-05-23,Hacienda San Angel,Simple Booking,,Carole Van Haaften,Lizarraga,carole@designartistry.com,+14157175581,,,,,,,"",2025-10-23,2025-10-24,1,,"","RESERVATION FROM SIMPLEBOOKINFG // +CONFIRMATION SENT MAY 23 // +RATE $ 520 USD + TAX // +NO PROMO // +CREDIT CARD INFORMATION AMEX OK // +SUITE VISTA DE SANTOS // +STAY OCT 23- 24 2025 // +MAY232025GV",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,520.0,650.0,0.0,0.0,0.0,0.0,0,0.0,0.0,650.0,0,2,0,0,1,,,0,650.0,false,"",false,0,130.0,Room 121,"" +LH25060448525635,2025-06-04,Hacienda San Angel,Extranet,,David,Wolf,DWolfe@marcusmillichap.com,510-388-1633,,,,,,,,2025-10-23,2025-10-24,1,,"","DIRECT RESERVATION // +CONFIRMATION SENT JUN04 // +RATE $ 440 USD // +SUITE ANGEL DOME // +STAY OCT 23- 24 2025 // +CREDIT CARD INFORMATION OK // +JUN042025GV // + +ANGEL RATE",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,440.0,440.0,0.0,0.0,0.0,0.0,0,0.0,0.0,440.0,0,2,0,0,1,,,0,440.0,false,"",false,0,88.0,Room 113,"" +EXP-2292866236,2025-09-18,Hacienda San Angel,Expedia,,Krista,Lee,48s0wk9vn6@m.expediapartnercentral.com,1 0 4159523725,,,,,,,,2025-10-23,2025-10-24,1,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXP // +CONFIRMATION SENT SEP 18 // +ARTE $ 378.40 USD + TAX // +PK INFO CREDIT CARD VISA // +PROMOCION GOLD FABCED MOD10% // +SUITE GARDEN OF ANGEL // +STAY OCT 23- 24 2025 // +SEP182025GV",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,378.4,473.0,0.0,0.0,0.0,0.0,0,0.0,0.0,473.0,0,2,0,0,1,,,0,473.0,false,"",false,0,94.6,Room 109,"" +BDC-6341196287,2025-10-04,Hacienda San Angel,Booking.com,,Kate,O’Neil,koneil.413450@guest.booking.com,+1 425 749 8818,,,,,,United States,"",2025-10-23,2025-10-24,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-10-21., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT OCT042025 // +CREDIT CARD INFORMATION OK // +RATE $ 510 USD + TAXES // +STAY OCT23-242025 // +SUITE MILAGROS // +SUBMITED OCT042025NGR//",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,510.0,637.5,0.0,0.0,0.0,0.0,0,0.0,0.0,637.5,0,2,0,0,1,,,0,637.5,false,"",false,0,127.5,Room 102,"" +LH25032747024965,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", San Miguel - Presidential Suite,Manual,796.5,995.63,0.0,0.0,0.0,0.0,0,0.0,0.0,995.63,0,2,0,0,1,,,0,995.63,false,"",false,0,199.125,Room 107,"" +LH25032747024991,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", Celestial - Royal Suite,Manual,760.5,950.63,0.0,0.0,0.0,0.0,0,0.0,0.0,950.63,0,2,0,0,1,,,0,950.63,false,"",false,0,190.125,Room 103,"" +LH25032747025003,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", Rincon de Angeles - Royal Suite,Manual,771.5,964.38,0.0,0.0,0.0,0.0,0,0.0,0.0,964.38,0,2,0,0,1,,,0,964.38,false,"",false,0,192.875,Room 119,"" +LH25032747025015,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", Angels View - Master Suite,Manual,741.5,926.88,0.0,0.0,0.0,0.0,0,0.0,0.0,926.88,0,2,0,0,1,,,0,926.88,false,"",false,0,185.375,Room 106,"" +LH25032747026782,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", San Jose - Master Suite,Manual,751.5,939.38,0.0,0.0,0.0,0.0,0,0.0,0.0,939.38,0,2,0,0,1,,,0,939.38,false,"",false,0,187.875,Room 122,"" +LH25032747026791,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", Vista de Santos - Master Suite,Manual,751.5,939.38,0.0,0.0,0.0,0.0,0,0.0,0.0,939.38,0,2,0,0,1,,,0,939.38,false,"",false,0,187.875,Room 121,"" +LH25032747026815,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","SIMPLEBOOKING.COM +OCT23-242025 +CVV PENDIENT +$693 + TAX +SAN GABRIEL +MAY232025",,Confirmed,"", San Gabriel - Junior Suite,Manual,689.5,861.88,0.0,0.0,0.0,0.0,0,0.0,0.0,861.88,0,2,0,0,1,,,0,861.88,false,"",false,0,172.375,Room 118,"" +LH25032747026819,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", Milagros - Junior Suite,Manual,661.5,826.88,0.0,0.0,0.0,0.0,0,0.0,0.0,826.88,0,2,0,0,1,,,0,826.88,false,"",false,0,165.375,Room 102,"" +LH25032747026826,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"", Garden of Angels - Junior Suite,Manual,661.5,826.88,0.0,0.0,0.0,0.0,0,0.0,0.0,826.88,0,2,0,0,1,,,0,826.88,false,"",false,0,165.375,Room 109,"" +LH25032747026833,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"",Angels Dome - Junior Suite,Manual,619.5,774.38,0.0,0.0,0.0,0.0,0,0.0,0.0,774.38,0,2,0,0,1,,,0,774.38,false,"",false,0,154.875,Room 113,"" +LH25032747026869,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"",Crown View - Junior Suite,Manual,661.5,826.88,0.0,0.0,0.0,0.0,0,0.0,0.0,826.88,0,2,0,0,1,,,0,826.88,false,"",false,0,165.375,Room 112,"" +LH25032747026873,2025-03-27,Hacienda San Angel,Extranet,,Rina y Rob,Tinozzi/Sharman,"","",,,,,,,,2025-10-24,2025-10-26,2,,"","",,Confirmed,"",Serafin - Junior Suite,Manual,661.5,826.88,0.0,0.0,0.0,0.0,0,0.0,0.0,826.88,0,2,0,0,1,,,0,826.88,false,"",false,0,165.375,Room 110,"" +SMP-2025050539974234,2025-05-05,Hacienda San Angel,Simple Booking,,Peter,Baum,junkster3@myastound.net,+14155334728,,,,,,,"",2025-10-26,2025-10-27,1,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAY05 // +SECRET RATE // +RATE $ 397.70 USD + TAX // +CREDIT CARD INFORMATION VISA PENDING CVV // +NO RPOMO // +SUITE ANGEL VIEW // +STAY OCT 226-27 2025 // +MAY052025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,397.7,497.13,0.0,0.0,0.0,0.0,0,0.0,0.0,497.13,0,2,0,0,1,,,0,497.13,false,"",false,0,99.425,Room 106,"" +EXP-2218958934,2025-06-11,Hacienda San Angel,Expedia,,Rick,Stoeker,5v4spp5ptp@m.expediapartnercentral.com,1 9176766736,,,,,,,,2025-10-26,2025-10-28,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT JUN11 // +RATE $ 365.20 USD +TAX // +DISCOUNT 10% EXP SILVER PROMO // +CREDIT CARD INFORMATION OK VISA // +EXP VIP // +SUITE GARDEN // +STAY OCT 26- 28 2025 // +JUN112025GV",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,730.4,913.0,0.0,0.0,0.0,0.0,0,0.0,0.0,913.0,0,2,0,0,1,,,0,913.0,false,"",false,0,182.6,Room 109,"" +MMS-OBH25070718145902-2899432,2025-07-07,Hacienda San Angel,Mr and Mrs Smith,,Raymond,Smith,RKENDALLS@YAHOO.COM,,,,,,,,,2025-10-26,2025-11-01,6,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out + TRAVEL WITH 2 FRENCH BULLDOGS DUE TO DIABETES.","RESERVAION FROM MR. & MRS. SMITH +RATE $343.20 TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY07/2025 +OK MARIANA JULY 07/2025",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,2059.2,2681.25,0.0,0.0,0.0,107.25,0,0.0,0.0,2681.25,0,2,0,0,1,,,0,2681.25,false,"",false,0,514.8,Room 102,"" +LH25091550935592,2025-09-15,Hacienda San Angel,Extranet,,WILLIAM,REID,gswarrior.31@gmail.com,601-543-3234,,,,,,,,2025-10-26,2025-10-27,1,,"","RESERVATION DIRECTLY +RATE $505.00 + TAXES +RESPECT SECRET RATE +CREDIT CARD VISA OK +CONFIRMATION SENT SEP15/2025 +OK MARIANA SEP15/2025 + +THEY COME WITH THE SHARMAN WEDDING, THE FIRST 2 NIGHTS THEY WILL STAY AT MILAGROS",,Confirmed,"", Celestial - Royal Suite,Manual,505.0,517.63,0.0,0.0,0.0,0.0,0,0.0,0.0,517.63,0,2,0,0,1,,,0,517.63,false,"",false,0,103.525,Room 103,"" +SMP-2025041539493200,2025-04-14,Hacienda San Angel,Simple Booking,,Ruth,Haney,ruthhaney@gmail.com,+12069998086,,,,,,,"",2025-10-27,2025-10-29,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $496.10 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +COFIRMATION SENT APRIL14/25 +OK MARIANA APRIL14/25 + +NO EARLY CHECKIN POSSIBLE. WE WILL BE FILMING FROM 2:15pm- 2:45pm- Paula",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,992.21,1240.26,0.0,0.0,0.0,0.0,0,0.0,0.0,1240.26,0,2,0,0,1,,,0,1240.26,false,"",false,0,248.0525,Room 107,"" +SMP-2025033039139044,2025-03-30,Hacienda San Angel,Simple Booking,,Ruth,Haney,ruthhaney@gmail.com,+12069998086,,,,,,,"",2025-10-29,2025-11-03,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $554.32 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MARCH30/2025 +OK MARIANA MARCH630/2025",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2771.62,3464.53,0.0,0.0,0.0,0.0,0,0.0,0.0,3464.53,0,2,0,0,1,,,0,3464.53,false,"",false,0,692.905,Room 107,"" +SMP-2025050239907174,2025-05-02,Hacienda San Angel,Simple Booking,,Mario,Romiti,marioromitidr@icloud.com,+19172258900,,,,,,,"",2025-10-29,2025-11-01,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAY022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 446.90 USD + TAXES // +STAY OCT29-NOV012025 // +SUITE CELESTIAL SUITE // +SUBMITEDMAY022025NGR //",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1340.7,1675.88,0.0,0.0,0.0,0.0,0,0.0,0.0,1675.88,0,2,0,0,1,,,0,1675.88,false,"",false,0,335.175,Room 103,"" +MMS-OBH25062020512102-2882835,2025-06-20,Hacienda San Angel,Mr and Mrs Smith,,Raymond,Smith,RKENDALLS@YAHOO.COM,,,,,,,,,2025-10-30,2025-11-04,5,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +Travel with 2 French Bulldogs- 13 kg each",,,Cancelled,2025-06-20 14:16:02, Milagros - Junior Suite,Milagros - Standard Rate,1898.2,2372.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2372.75,0,2,0,0,1,,,0,2372.75,false,"",false,0,474.55,Room 102,"" +SMP-2025081442661998,2025-08-14,Hacienda San Angel,Simple Booking,,Christina,Gonzales,Christina_gonzales4@yahoo.com,+18326432711,,,,,,,"",2025-10-30,2025-11-04,5,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT AGO14 // +NO PROMO // +CREDIT CARD INFORMATION AMEX PENDING CVV // +RATE $ 369 USD + TAX // +SECRET RATE // +SUITE GARDEN // +STAY OCT 30- NOV 04 2025 // +AGO142025GV",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1845.01,2306.26,0.0,0.0,0.0,0.0,0,0.0,0.0,2306.26,0,2,0,0,1,,,0,2306.26,false,"",false,0,461.2525,Room 109,"" +EXP-X-414004989,2025-02-15,Hacienda San Angel,Expedia,,Ruby,Richards,61yd1pfxm3@m.expediapartnercentral.com,0 0 3037662222,,,,,,,,2025-10-31,2025-11-03,3,,"Hotel Collect Booking, 1 King Bed, Non-Smoking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: $85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAVIPPREM .COM // +CONFIRMATION SENT FEB152025// +CREDIT CARD INFORMATION OK// +RATE $ 475.86 USD + TAXES // +STAY OCT31-3NOV 2025// +SUITE SAN JOSE// +SUBMITED FEB152025NGR//",,Cancelled,2025-02-23 16:06:33, San Jose - Master Suite,San Jose - Standard Rate,1427.6,1784.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1784.5,0,1,0,0,1,,,0,1784.5,false,"",false,0,356.9,Room 122,"" +BDC-5165091156,2025-06-13,Hacienda San Angel,Booking.com,,Susan,Seidel,sseide.186004@guest.booking.com,+1 470 997 6878,,,,,,United States,"",2025-10-31,2025-11-04,4,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $576.66 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE 13/25 +OK MARIANA JUNE13/25",,Cancelled,2025-07-20 12:57:12, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2330.0,2912.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2912.5,0,2,0,0,1,,,0,2912.5,false,"",false,0,582.5,Room 119,"" +EXP-2294144225,2025-09-20,Hacienda San Angel,Expedia,,Melinda,Teachey,j1vd0jbpbu@m.expediapartnercentral.com,1 8287737881,,,,,,,,2025-10-31,2025-11-02,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,267.20, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPEVIP.COM // +CONFIRMATION SENT SEP202025// +CREDIT CARD INFORMATION OK // +RATE $ 528 USD + TAXES // +STAY OCT31-NOV022025 // +SUITE SAN JOSE // +SUBMITED SEP202025NGR//",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,1056.0,1320.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1320.0,0,2,0,0,1,,,0,1320.0,false,"",false,0,264.0,Room 122,"" +EXP-2294228847,2025-09-20,Hacienda San Angel,Expedia,,Mohsin,mortada,b54cn66mrw@m.expediapartnercentral.com,1 6577990715,,,,,,,,2025-10-31,2025-11-03,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,795.20, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPVIP.COM // +CONFIRMATION SENT SEP2025 // +CREDIT CARD INFORMATION OK // +RATE $498.66 USD + TAXES // +STAY OCT31-NOV032025 // +SUITE VISTA DE SANTOS // +SUBMITED SEP2025NGR //",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1496.0,1870.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1870.0,0,2,0,0,1,,,0,1870.0,false,"",false,0,374.0,Room 121,"" +LH25090850770334,2025-09-08,Hacienda San Angel,Extranet,,AARON,FREEMAN,aaronfreeman47@gmail.com,2068894176,,,,,,,,2025-11-01,2025-11-03,2,,"","RESERVATION DIRECTLY +RATE $577.50 + TAXES +NO PROMO +CREDIT CARD INFO AMEX OK +CONFIRMATION SENT SEP08/2025 +OK MARIANA SEP08/2025",,Cancelled,2025-09-08 14:19:00, Angels View - Master Suite,Angels View - Standard Rate,1155.0,1443.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1443.75,0,2,0,0,1,,,0,1443.75,false,"",false,0,288.75,Room 106,"" +SMP-2025091143249500,2025-09-11,Hacienda San Angel,Simple Booking,,Becky,Detering,beckydetering@mac.com,+15419537114,,,,,,,"",2025-11-01,2025-11-02,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT SEP102025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 505.95 USD + TAXES // +STAY NOV1-022025 // +SUITE RINCÓN & ANGEL VIEW // +SUBMITED SEP102025NGR//",,Confirmed,""," Rincon de Angeles - Royal Suite, Angels View - Master Suite","Rincon de Angeles - Standard Rate,Angels View - Standard Rate",1011.9,1264.88,0.0,0.0,0.0,0.0,0,0.0,0.0,1264.88,0,4,0,0,2,,,0,1264.88,false,"",false,0,252.975,"Room 119, Room 106","" +BDC-4725592247,2025-01-27,Hacienda San Angel,Booking.com,,Naureen,Jenkins,njenki.102542@guest.booking.com,+1 508 735 2979,,,,,,United States,"",2025-11-02,2025-11-09,7,,"Approximate time of arrival: between 16:00 and 17:00 +This is our 53rd anniversary., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT ENE26 // +CREDIT CARD INFORMATION OK AMEX // +NO PROMO // +RATE $ 721.12 USD + TAXES // +GENIUS DISCOUNT // +SUITE GARDEN // +STAY NOV 02- 09 2025 // +ENE262025GV",,Cancelled,2025-05-03 10:16:59, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,2884.5,3605.63,0.0,0.0,0.0,0.0,0,0.0,0.0,3605.63,0,2,0,0,1,,,0,3605.63,false,"",false,0,721.125,Room 109,"" +SMP-2025071341777170,2025-07-13,Hacienda San Angel,Simple Booking,,Cindy,Rodriguez,cinsiar@gmail.com,+19715067875,,,,,,,"",2025-11-02,2025-11-05,3,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT JUL 12 // +RATE $ 531.63 USD + TAX // +NO PROMO // +SECRET RATE // +CREDIT CARD INFORMATION MASTERCARD CVV PENDING // +SUITE CELESTIAL // +STAY NOV 02- 05 2025 // +JUL122025GV",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1594.9,1993.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1993.63,0,2,0,0,1,,,0,1993.63,false,"",false,0,398.725,Room 103,"" +BDC-4465904944,2025-04-26,Hacienda San Angel,Booking.com,,Claudia,Quiroz,cquiro.522873@guest.booking.com,+56 9 9543 3910,,,,,,Chile,"",2025-11-03,2025-11-06,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION OK // +RATE $ 403.50 USD + TAXES // +STAY NOV03-062025 // +SUITE SERAFIN // +SUBMITED APR262025NGR//",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,1210.5,1513.13,0.0,0.0,0.0,0.0,0,0.0,0.0,1513.13,0,1,0,0,1,,,0,1513.13,false,"",false,0,302.625,Room 110,"" +BDC-4545966276,2025-04-26,Hacienda San Angel,Booking.com,,Marcelo,Oller,moller.184774@guest.booking.com,+34 615 04 62 02,,,,.,,Spain,"",2025-11-03,2025-11-06,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION OK // +RATE $ 363.15 USD + TAXES // +STAY NOV03-062025 // +SUITE ANGEL DOME // +SUBMITED APR272025NGR//",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1089.45,1361.81,0.0,0.0,0.0,0.0,0,0.0,0.0,1361.81,0,1,0,0,1,,,0,1361.81,false,"",false,0,272.3625,Room 113,"" +LH25071449451448,2025-07-14,Hacienda San Angel,Extranet,,John,Kurowski,jkurowsk@gmail.com,"",,,,,,,,2025-11-03,2025-11-06,3,,"","Firefighter co-worker of my daughter Laura + +50% discount on all food and beverages- Paula",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1840.0,920.0,0.0,0.0,0.0,0.0,0,0.0,0.0,920.0,0,2,0,0,1,,,0,920.0,false,"",false,0,230.0,Room 106,"" +EXP-2294218723,2025-09-20,Hacienda San Angel,Expedia,,Mohsin,mortada,8jbnwf38bx@m.expediapartnercentral.com,1 6577990715,,,,,,,,2025-11-03,2025-11-06,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,001.12, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPVIP .COM // +CONFIRMATION SENT SEP202025// +CREDIT CARD INFORMATION OK// +RATE $555.86 USD + TAXES // +STAY NOV03-062025 // +SUITE RINCÓN OF ANGELS// +SUBMITED SEP202025NGR //",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1667.6,2084.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2084.5,0,2,0,0,1,,,0,2084.5,false,"",false,0,416.9,Room 119,"" +SMP-2025030238456062,2025-03-02,Hacienda San Angel,Simple Booking,,Diana,Wurn,Dianawurn@gmail.com,+12068504330,,,,,,,"",2025-11-04,2025-11-09,5,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT FEB 02 // +RATE $ 371.46 USD + TAX // +NO PROMO // +CREDIT CARD AMEX PENDIING CVV // +SUITE MILAGROS // +STAY NOV 04- 09 2025 // +FEB022025GV",,Cancelled,2025-03-04 12:34:10, Milagros - Junior Suite,Milagros - Standard Rate,1857.31,2321.64,0.0,0.0,0.0,0.0,0,0.0,0.0,2321.64,0,2,0,0,1,,,0,2321.64,false,"",false,0,464.3275,Room 102,"" +SMP-2025030438519518,2025-03-04,Hacienda San Angel,Simple Booking,,Diana,Wurn,Dianawurn@gmail.com,+12068504330,,,,,,,"",2025-11-04,2025-11-09,5,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR04 // +RATE $522.34 USD + TAX // +SECRET RATE // +CREDIT CARD VISA CVV PENDING // +SUITE SAN MIGUEL // +STAY NOV 04- 09 2025 // +NO PROMO // +MAR042025GV",,Cancelled,2025-10-02 11:00:45, San Miguel - Presidential Suite,San Miguel - Standard Rate,2611.71,3264.64,0.0,0.0,0.0,0.0,0,0.0,0.0,3264.64,0,2,0,0,1,,,0,3264.64,false,"",false,0,652.9275,Room 107,"" +SMP-2025092343471727,2025-09-23,Hacienda San Angel,Simple Booking,,Rosa,Mariona,rosa.gomez@sanjuan.edu,+19166637799,,,,,,,"",2025-11-04,2025-11-05,1,,"","RESERVATIN FROM SIMPLE BOOKING +RATE $426.40 + TAXES +SECRET RATE +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT SEP23/2025 +OK MARIANA SEP23/2025",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,426.4,533.0,0.0,0.0,0.0,0.0,0,0.0,0.0,533.0,0,2,0,0,1,,,0,533.0,false,"",false,0,106.6,Room 112,"" +EXP-2297415680,2025-09-25,Hacienda San Angel,Expedia,,Chenxing,Huang,edd4vdqbty@m.expediapartnercentral.com,1 0 7323257168,,,,,,,,2025-11-04,2025-11-07,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXP // +CONFIRMATION SENT SEP25 // +RATE $538.50 USD + TAX // +SUITE SAN JOSE // +STAY NOV 04- 07 2025 // +PROMOTION BLUE 10% // +SEP252025GV",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,1615.5,2019.38,0.0,0.0,0.0,0.0,0,0.0,0.0,2019.38,0,2,0,0,1,,,0,2019.38,false,"",false,0,403.875,Room 122,"" +MMS-OBH25092518271307-2979782,2025-09-25,Hacienda San Angel,Mr and Mrs Smith,,Carlos,Dios,CARLOS.DEDIOS10@YAHOO.COM,,,,,,,,,2025-11-04,2025-11-07,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // HYATT // +VIRTUAL CARD FOR CHARGE // +RATE $ 416 USD + TAX // +SUITE SAN GABRIEL // +STAY NOV 04- 05 2025 // +NO PROMO // +SEP252025GV",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1198.08,1560.0,0.0,0.0,0.0,62.4,0,0.0,0.0,1560.0,0,1,0,0,1,,,0,1560.0,false,"",false,0,299.52,Room 118,"" +LH25091550931192,2025-09-15,Hacienda San Angel,Extranet,,Helga,Gruber,GruberHelga48@gmail.com,"",,,,,,,,2025-11-05,2025-11-09,4,,Angel's Rate,"No charge for anything- Long time friends- Helga and Debbie + +Let me know how they tip when they leave. + +Please ask Miguel to pay staff commission from my pocket.",,Confirmed,"", Vista de Santos - Master Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 121,"" +LH25091550931339,2025-09-15,Hacienda San Angel,Extranet,,raye,La,Laraye45@gmail.com,"",,,,,,,,2025-11-05,2025-11-09,4,,"","Visiting with my friend, Helga in VS. +$25 per day is for staff commission (7%) Nothing for me. + +I do not know the last name but the couple is Laraye and Wendy. +Take card for incidentals at check in but no charge before check in. +20% discount on food and beverages- Paula",,Confirmed,"", Garden of Angels - Junior Suite,Manual,100.0,100.0,0.0,0.0,0.0,0.0,0,0.0,0.0,100.0,0,2,0,0,1,,,0,100.0,false,"",false,0,25.0,Room 109,"" +BDC-5066584207,2025-06-01,Hacienda San Angel,Booking.com,,Cassie,Delaney,cdelan.288670@guest.booking.com,+1 250 682 2186,,,,,,Canada,"",2025-11-06,2025-11-07,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-11-04. +Approximate time of arrival: between 07:00 and 08:00 +This guest is interested in your airport shuttle service and would like to get more information from you., booker_is_genius +smoking preference: Non-Smoking","BOOKING.COM +MAY312025 +NOV06-072025 +CC OK +$387 USD + TAX +ANGEL DOME SUITE +MAY312025NGR",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,387.0,483.75,0.0,0.0,0.0,0.0,0,0.0,0.0,483.75,0,2,0,0,1,,,0,483.75,false,"",false,0,96.75,Room 113,"" +EXP-2296226408,2025-09-23,Hacienda San Angel,Expedia,,LOREN,LONG,21xv7aks7o@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-11-06,2025-11-07,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 615.60, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION FROM EXPEDIA +RATE $513.00+ TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP23/2025 +OK MARIANA SEP23/2025",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,513.0,641.25,0.0,0.0,0.0,0.0,0,0.0,0.0,641.25,0,1,0,0,1,,,0,641.25,false,"",false,0,128.25,Room 106,"" +MMS-OBH25050816235803-2839123,2025-05-08,Hacienda San Angel,Mr and Mrs Smith,,Amanda,Mosley,AMOSLEY0405@GMAIL.COM,,,,,,,,,2025-11-07,2025-11-10,3,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +This will be our first time to ever visit Puerto Vallarta and our 10 year wedding anniversary. Anything extra or upgraded would be most appreciated and a special part of our trip. Thanks so much and can't wait to see the property!","RESERVATION FROM MR. & MRES. SMITH +RATE $400.60 + TAXES +HYATT +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MAY08/25 +OK MARIANA MAY08/25",,Cancelled,2025-09-04 16:35:54, Angels View - Master Suite,Angels View - Standard Rate,1201.82,1564.88,0.0,0.0,0.0,62.6,0,0.0,0.0,1564.88,0,2,0,0,1,,,0,1564.88,false,"",false,0,300.455,Room 106,"" +MMS-OBH25083102002100-2954833,2025-08-31,Hacienda San Angel,Mr and Mrs Smith,,Bryan,Djerroud,BRYANDJERROUD@YAHOO.COM,,,,,,,,,2025-11-07,2025-11-11,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS .COM // +CONFIRMATION SENT AUG302025 // +CREDIT CARD INFORMATION OK // +RATE $446.42 USD + TAXES // +STAY NOV7-112025 // +SUITE CROWN VIEW // +SUBMITED AUG302025NGR//",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,1785.7,1953.12,0.0,0.0,0.0,-279.01,0,0.0,0.0,1953.12,0,1,0,0,1,,,0,1953.12,false,"",false,0,446.425,Room 112,"" +SMP-2025022238298447,2025-02-22,Hacienda San Angel,Simple Booking,,Catherine,Ash,piccadillyproducer@gmail.com,+14164581275,,,,,,Canada,"",2025-11-08,2025-11-12,4,,"","RESERVATION THRU SB.COM // +CONFIRMATION SENT FEB222025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 460.22 USD + TAXES // +STAY NOV20-122025 // +SUITE CELESTIAL // +SUBMITED FEB222025NGR// +CVV 126",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1840.91,2301.14,0.0,0.0,0.0,0.0,0,0.0,0.0,2301.14,0,2,0,0,1,,,0,2301.14,false,"",false,0,460.2275,Room 103,"" +EXP-2174821452,2025-04-11,Hacienda San Angel,Expedia,,Laura,Bakan,u8swr38y5n@m.expediapartnercentral.com,1 604 8055578,,,,,,,,2025-11-08,2025-11-15,7,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT APR112025 // +CREDIT CARD INFORMATION OK // +RATE $ 491.14 USD + TAXES // +STAY NOV8-152025 // +SUITE SAN JOSE // +SUBMITED APR112025NGR//",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,3438.0,4297.5,0.0,0.0,0.0,0.0,0,0.0,0.0,4297.5,0,2,0,0,1,,,0,4297.5,false,"",false,0,859.5,Room 122,"" +MMS-OBH25083006334302-2954204,2025-08-30,Hacienda San Angel,Mr and Mrs Smith,,Mark,Hoebich,PRONTOMARCO@GMAIL.COM,,,,,,,,,2025-11-08,2025-11-11,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $474.19 + TAXES +HYATT +VIRTUAL CREDIT CARD +CONFIRMATION SENT AUG30/2025 +OK MARIANA AUG30/2025 + + +3 PAX",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1422.58,1555.94,0.0,0.0,0.0,-222.29,0,0.0,0.0,1555.94,0,3,0,0,1,,,0,1555.94,false,"",false,0,355.645,Room 118,"" +MMS-OBH25092703431906-2980918,2025-09-27,Hacienda San Angel,Mr and Mrs Smith,,Kim,Nguyen,KIMNGUYEN007@GMAIL.COM,,,,,,,,,2025-11-09,2025-11-11,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT SEP262025// +CREDIT CARD INFORMATION OK // +RATE $ 407.97 USD + TAXES // +STAY NOV09-112025 // +SUITE ANGEL DOME // +SUBMITED SEP262025NGR //",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,815.95,892.45,0.0,0.0,0.0,-127.49,0,0.0,0.0,892.45,0,2,0,0,1,,,0,892.45,false,"",false,0,203.9875,Room 113,"" +BDC-6429280019,2025-10-02,Hacienda San Angel,Booking.com,,ALENNA,SEBBEN,asebbe.347405@guest.booking.com,+1 773 501 9979,,,,,,United States,"",2025-11-10,2025-11-12,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-11-08. +Approximate time of arrival: between 14:00 and 15:00 +This guest is interested in your airport shuttle service and would like to get more information from you., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT OCT022025 // +CREDIT CARD INFORMATION OK // +RATE $ 533.25 USD + TAXES // +STAY NOV10-122025 // +SUITE ANGEL VIEW // +SUBMITED OCT022025NGR//",,Cancelled,2025-10-02 20:24:35, Angels View - Master Suite,Angels View - Standard Rate,1066.5,1333.13,0.0,0.0,0.0,0.0,0,0.0,0.0,1333.13,0,2,0,0,1,,,0,1333.13,false,"",false,0,266.625,Room 106,"" +EXP-X-399251164,2025-01-19,Hacienda San Angel,Expedia,,Janet,Short,0xe4onmhg4@m.expediapartnercentral.com,1 5105044220,,,,,,,,2025-11-11,2025-11-14,3,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $521.73 + TAXES +$85.00 CREDIT ON FOOD AND BEVERAGE// UPGRADE OR BOTLLE +CREDIT CARD INFO OK +CONFIRMATION SENT JANUARY19/2025 +OK MARIANA JANUARY19/2025",,Cancelled,2025-08-28 15:06:16, San Miguel - Presidential Suite,San Miguel - Standard Rate,1565.2,1956.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1956.5,0,2,0,0,1,,,0,1956.5,false,"",false,0,391.3,Room 107,"" +SMP-2025041439468038,2025-04-14,Hacienda San Angel,Simple Booking,,Chris,Thiele,tallbro@gmail.com,+16046844506,,,,,,Canada,"",2025-11-11,2025-11-14,3,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR142025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 378.57 USD + TAXES // +STAY NOV11-142025 // +SUITE GARDEN OF ANGELS // +SUBMITED APR142025NGR//",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1135.71,1419.64,0.0,0.0,0.0,0.0,0,0.0,0.0,1419.64,0,2,0,0,1,,,0,1419.64,false,"",false,0,283.9275,Room 109,"" +MMS-OBH25071723470202-2910110,2025-07-17,Hacienda San Angel,Mr and Mrs Smith,,Jennifer,Lai,JENLAIMD@GMAIL.COM,,,,,,,,,2025-11-11,2025-11-13,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS .COM // +CONFIRMATION SENT JULY172025 // +CREDIT CARD INFORMATION OK // +RATE $ 378.07 USD + TAXES // +STAY NOV11-132025 // +SUITE SERAFIN // +SUBMITED JULY172025NGR//",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,756.14,827.03,0.0,0.0,0.0,-118.15,0,0.0,0.0,827.03,0,2,0,0,1,,,0,827.03,false,"",false,0,189.035,Room 110,"" +MMS-OBH25082701544102-2951177,2025-08-27,Hacienda San Angel,Mr and Mrs Smith,,Jamie,Cornejo,JAMIE.CORNEJO@GMAIL.COM,,,,,,,,,2025-11-11,2025-11-12,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS / HYATT // +RATE $ 417.30 USD + TAX // +VIRTUAL CARD FOR CHARGE // +SUITE CROWN VIEW // +STAY NOV 11- 12 2025 // +NO PROMO // +AGO262025GV",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,400.61,521.63,0.0,0.0,0.0,20.87,0,0.0,0.0,521.63,0,1,0,0,1,,,0,521.63,false,"",false,0,100.1525,Room 112,"" +EXP-2209370112,2025-05-29,Hacienda San Angel,Expedia,,Sarah,Heames,sogpl6r3ev@m.expediapartnercentral.com,0 0 4066401441,,,,,,,,2025-11-13,2025-11-14,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 598.56, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: $85 food and beverage credit per room, per stay","EXPEDIAPREMIUMVIP.COM +MAY292025 +$498.80 USD + TAX +ANGEL VIEW SUITE +NOV13-142025 +29MAY2025NGR",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,498.8,623.5,0.0,0.0,0.0,0.0,0,0.0,0.0,623.5,0,2,0,0,1,,,0,623.5,false,"",false,0,124.7,Room 106,"" +LH25072449690320,2025-07-24,Hacienda San Angel,Extranet,,GREG,KONECNY,gjkonecny@att.net,6308864387,,,,,,,,2025-11-13,2025-11-16,3,,"","RESERVATION DIRECTLY +RATE $621.60 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT JULY24/2025 +OK MARIANA JULY24/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1910.0,2387.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2387.5,0,2,0,0,1,,,0,2387.5,false,"",false,0,477.5,Room 103,"" +LH25072449690354,2025-07-24,Hacienda San Angel,Extranet,,GREG,KONECNY,gjkonecny@att.net,6308864387,,,,,,,,2025-11-13,2025-11-16,3,,"","RESERVATION DIRECTLY +RATE $593.33 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT JULY24/2025 +OK MARIANA JULY24/2025",,Cancelled,2025-08-20 11:14:42, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1845.0,2306.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2306.25,0,2,0,0,1,,,0,2306.25,false,"",false,0,461.25,Room 119,"" +LH25072449690387,2025-07-24,Hacienda San Angel,Extranet,,GREG,KONECNY,gjkonecny@att.net,6308864387,,,,,,,,2025-11-13,2025-11-16,3,,"","RESERVATION DIRECTLY +RATE $491.16 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT JULY24/2025 +OK MARIANA JULY/2025",,Cancelled,2025-08-20 11:13:56, Milagros - Junior Suite,Milagros - Standard Rate,1525.0,1906.25,0.0,0.0,0.0,0.0,0,0.0,0.0,1906.25,0,2,0,0,1,,,0,1906.25,false,"",false,0,381.25,Room 102,"" +SMP-2025080742460290,2025-08-07,Hacienda San Angel,Simple Booking,,ALEXANDER,KHAYAT,A.KHAYAT@OUTLOOK.COM,+19494265940,,,,,,,"",2025-11-13,2025-11-16,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $389.50 + TAXES +SECRET RATE + CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT AUG06/2025 +OK MARIANA AUG06/2025",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,1168.51,1460.64,0.0,0.0,0.0,0.0,0,0.0,0.0,1460.64,0,2,0,0,1,,,0,1460.64,false,"",false,0,292.1275,Room 110,"" +LH25080750040769,2025-08-07,Hacienda San Angel,Extranet,,GREG,KONECNY,gjkonecny@att.net,6308864387,,,,,,,,2025-11-13,2025-11-14,1,,"","RESERVATION DIRECTLY +RATE $530.00 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT AUG07/2025 +OK MARIANA AUG07/2025",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,530.0,662.5,0.0,0.0,0.0,0.0,0,0.0,0.0,662.5,0,2,0,0,1,,,0,662.5,false,"",false,0,132.5,Room 112,"" +EXP-2284962001,2025-09-07,Hacienda San Angel,Expedia,,CHASE,JENSEN,riya43s0ve@m.expediapartnercentral.com,86 021 60781960,,,,,,,,2025-11-13,2025-11-17,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,234.77, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""2 人免费饮料(每人每次住宿一份)""","RESERVATION FROM EXPEDIA +RATE $465.58 + TAXES +VIRTUAL CREDIR CARD INFO +NO PROMO +CONFIRMATION SEND SEP09/2025 +OK MARIANA SEP09/2025",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,1862.31,2327.89,0.0,0.0,0.0,0.0,0,0.0,0.0,2327.89,0,2,0,0,1,,,0,2327.89,false,"",false,0,465.5775,Room 102,"" +LH25072449690292,2025-07-24,Hacienda San Angel,Extranet,,GREG,KONECNY,gjkonecny@att.net,"",,,,,,,,2025-11-14,2025-11-16,2,,"","RESERVATION DIRECTLY +RATE $638.33 + TAXES +NO PROMO +CREDIT CARD INFO VISA OK +CONFIRMATION SENT JULY24/2025 + + +COMINF WITH 3 MORE ROOMS",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1290.0,1612.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1612.5,0,2,0,0,1,,,0,1612.5,false,"",false,0,322.5,Room 107,"" +SMP-2025080942528275,2025-08-09,Hacienda San Angel,Simple Booking,,Jessica,Hovick,jahovick@gmail.com,+12023170848,,,,,,,"",2025-11-14,2025-11-15,1,,"","RESERVATION FROM SIMPLE BOOKING +RATE $430.50 + ATXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT AUG009/2025 +OK MARIANA AUG09/2025",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,430.5,538.13,0.0,0.0,0.0,0.0,0,0.0,0.0,538.13,0,2,0,0,1,,,0,538.13,false,"",false,0,107.625,Room 109,"" +MMS-OBH25090304574604-2958039,2025-09-03,Hacienda San Angel,Mr and Mrs Smith,,Edgardo,Canales,CANALES.EDGARDO@GMAIL.COM,,,,,,,,,2025-11-14,2025-11-16,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $546.82+ TAXES +HYATT +VIRTUAL CREDIT CARD +CONFIRMATION SENT SEPT09/2025 +OK MARIANA SEPT09/2025",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1093.63,1196.16,0.0,0.0,0.0,-170.88,0,0.0,0.0,1196.16,0,1,0,0,1,,,0,1196.16,false,"",false,0,273.4075,Room 106,"" +LH25073049829232,2025-07-30,Hacienda San Angel,Extranet,,SUSAN & GEORGE,CROWFORD BARNS,sandgbarns@sbcglobal.net,+19184932602,,,,,,,,2025-11-15,2025-11-18,3,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT JULY302025// +CREDIT CARD INFORMATION OK // +RATE $ 600 USD + TAXES // +STAY NOV15-182025 // +SUITE SAN JOSE // +SUBMITED JULY302025NGR //",,Cancelled,2025-09-16 12:25:18, San Jose - Master Suite,San Jose - Standard Rate,1800.0,2250.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2250.0,0,2,0,0,1,,,0,2250.0,false,"",false,0,450.0,Room 122,"" +SMP-2025081542679883,2025-08-15,Hacienda San Angel,Simple Booking,,cara,manion,cara.nicole.manion@gmail.com,+12039487937,,,,,,,"",2025-11-15,2025-11-17,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $507.50+ TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT AUG08/2025 +OK MARIANA AUG08/2025",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1300.0,1625.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1625.0,0,2,0,0,1,,,0,1625.0,false,"",false,0,325.0,Room 119,"" +EXP-2288756348,2025-09-12,Hacienda San Angel,Expedia,,Kerrie,Lamont,sp57ljvqlc@m.expediapartnercentral.com,1 213 4078988,,,,,,,,2025-11-15,2025-11-17,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay),USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT SEP12 // +CREDIT CAR OK FOR CHARGE // +RATE 528 USD + TAX // +EXP SILVER FENCED MOD 10% DISCOUNT // +SUITE VISTA DE SANTOS // +STAY NOV 15- 17 2025 // +SEP122025GV",,Cancelled,2025-09-14 13:35:51, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1056.0,1320.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1320.0,0,2,0,0,1,,,0,1320.0,false,"",false,0,264.0,Room 121,"" +MMS-OBH25093004223207-2983439,2025-09-30,Hacienda San Angel,Mr and Mrs Smith,,James,Owen,JIMMYON@MAC.COM,,,,,,,,,2025-11-15,2025-11-17,2,,"PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out +Romantic getaway, very rare indeed...Anything you can do is appreciated! Jim and Angie","RESERVATION FROM MR. & MRES. SMITH +HYATT +RATE $368.55+ TAXES +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP29/2025 +OK MARIANA SEP29/2025",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,707.62,921.39,0.0,0.0,0.0,36.86,0,0.0,0.0,921.39,0,2,0,0,1,,,0,921.39,false,"",false,0,176.905,Room 109,"" +SMP-2025051940288455,2025-05-19,Hacienda San Angel,Simple Booking,,WILL,JENKINS,wjenkins@carolina.rr.com,+17045768032,,,,,,,"",2025-11-16,2025-11-22,6,,"","SIMPLEBOOKING.COM +$429.82 + TAX +NOV16-222025 +ANGEL VIEW +MAY192025NGR",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,2578.9,3223.63,0.0,0.0,0.0,0.0,0,0.0,0.0,3223.63,0,2,0,0,1,,,0,3223.63,false,"",false,0,644.725,Room 106,"" +EXP-2290798239,2025-09-16,Hacienda San Angel,Expedia,,Lisa,Bruton,3i455ad4kv@m.expediapartnercentral.com,86 755 82628521,,,,,,,,2025-11-17,2025-11-21,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,322.00, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""2 人免费饮料(每人每次住宿一份)""","RESERVATION FROM EXPEDIA +RATE $483.75 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP15/2025 +OK MARIANA SEP15/2025",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1935.0,2418.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2418.75,0,2,0,0,1,,,0,2418.75,false,"",false,0,483.75,Room 121,"" +EXP-2155081894,2025-03-14,Hacienda San Angel,Expedia,,Michael,Karras,mpcvuamedt@m.expediapartnercentral.com,1 801 8349689,,,,,,,,2025-11-19,2025-11-21,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,151.04, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP +RATE $479.60 + TAXES +$85.00 CREDIT ON FOOF & BEVERAGE +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT MARCH14/2025 +OK MARIANA MARCH14/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,959.2,1199.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1199.0,0,2,0,0,1,,,0,1199.0,false,"",false,0,239.8,Room 103,"" +LH25040547215983,2025-04-05,Hacienda San Angel,Extranet,,John,Curley,jcurleyauctions@gmail.com,"",,,,,,,,2025-11-21,2025-11-23,2,,"","Hosting - Angel's Rate- SULA Society will pay. + +$60 is the 7% for staff + +$10 is for Camarista + +No discounts on food and beverage. You still collect open voucher at check in- Paula + + +OK HAB PAGADA EN EFECTIVO USD // OK INFO A MIGUEL",,Confirmed,"", Garden of Angels - Junior Suite,Manual,70.0,70.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,70.0,70.0,2,0,0,1,,,0,0.0,false,"",false,0,17.5,Room 109,2775-1 +EXP-2190887349,2025-05-05,Hacienda San Angel,Expedia,,BRIAN,GRILL,wsion2j10a@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-11-21,2025-11-25,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,586.32, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT MAY42025// +CREDIT CARD INFORMATION OK // +RATE $ 538.81 USD + TAXES // +STAY NOV21-252025 // +SUITE SAN MIGUEL // +SUBMITED MAY042025NGR//",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2155.26,2694.08,0.0,0.0,0.0,0.0,0,0.0,0.0,2694.08,0,2,0,0,1,,,0,2694.08,false,"",false,0,538.815,Room 107,"" +LH25070549228930,2025-07-05,Hacienda San Angel,Extranet,,Michael and Erin,Avon,reservations@verana.com,484 832 6872,,,,,,,,2025-11-21,2025-11-22,1,,"","CXC VERANA +CLEBRAN ANIVERSARIO + + +CONFIRMATION SENT TO VERANA JULY05/2025 +OK MARIANA LULY05/2025",,Confirmed,"", Milagros - Junior Suite,Manual,320.0,400.0,0.0,0.0,0.0,0.0,0,0.0,0.0,400.0,0,2,0,0,1,,,0,400.0,false,"",false,0,80.0,Room 102,"" +LH25093051253872,2025-09-30,Hacienda San Angel,Extranet,,Peter,Klug,alma@journeymexico.com,322 225 9821,,,,,,,,2025-11-21,2025-11-22,1,,"","DIRECT RESERVATION // +AGENCIA JOURNEY // +NOT COMMISSIONABLE // +DISCOUNTED 20% // +RATE $492 USD + TAX // +SUITE SAN JOSE // +STAY NOV 21- 22 2025 // +SEP302025GV + +CREDIT CARD INFORMATION PENDING. _____ FOR SECURE +TRANSFER TO BE MADE FOR PAYMENT OF STAY.",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,615.0,615.0,0.0,0.0,0.0,0.0,0,0.0,0.0,615.0,0,1,0,0,1,,,0,615.0,false,"",false,0,123.0,Room 122,"" +LH25060148459534,2025-06-01,Hacienda San Angel,Extranet,,KRISTA,GAETA,kristagaeta@gmail.com,"",,,,,,,,2025-11-22,2025-11-25,3,,"","THEY HAVE A CERTIFICATE: +SF LGBT FUNDRISER +Valid for: +3 Nights in the Hacienda San Angel Luxury Boutique Hotel $100 Credit in onsite gourmet restaurant Value: $2,500 USD Expires March 30, 2026 Not applicable to blackout dates +Voucher HSA31012025MZR + + +CONFIRMATION SENT JUNE1ST/2025 +OK MARIANA JUNE 1ST/2025",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1360.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 113,"" +LH25092051044031,2025-09-20,Hacienda San Angel,Extranet,,Timothy,Ricker,tim@timrickerinteriors.com,+16126700700,,,,,,United States of America,"",2025-11-22,2025-11-28,6,,"","RESERVATION DIRECTLY +RATE $614.16 + TAXES +NO PROMO +CREDIT CARD INFO MC OK +CONFIRMATION SENT SEP20/2025 +OK MARIANA SEP20/2025",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,3685.0,4606.25,0.0,0.0,0.0,0.0,0,0.0,0.0,4606.25,0,2,0,0,1,,,0,4606.25,false,"",false,0,921.25,Room 121,"" +SMP-2025050840044700,2025-05-08,Hacienda San Angel,Simple Booking,,Sarah,Briggs,sarahhbriggs@gmail.com,+18029895277,,,,,,,"",2025-11-23,2025-11-24,1,,This is the first night of our honeymoon. We are coming back for the last night on the 28th.,"RESERVATION FROM SIMPLE BOOKING +RATE $485.00 + BTAXES +NO PROMO +CREDIT CARD MS CVV PENDING +CONFIRMATION SENT MAY08/25 +OK MARIANA MAY08/25",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,485.0,606.25,0.0,0.0,0.0,0.0,0,0.0,0.0,606.25,0,2,0,0,1,,,0,606.25,false,"",false,0,121.25,Room 102,"" +EXP-2271640989,2025-08-19,Hacienda San Angel,Expedia,,Alison,Foy-Vigneault,lmuwa461ew@m.expediapartnercentral.com,1 514 9233033,,,,,,,,2025-11-24,2025-11-30,6,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION FROM EXPEDIA +RATE $594.00 + TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT AUG19/2025 +OK MARIANA AUG19/2025",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,3564.0,4455.0,0.0,0.0,0.0,0.0,0,0.0,0.0,4455.0,0,2,0,0,1,,,0,4455.0,false,"",false,0,891.0,Room 119,"" +LH25050747898975,2025-05-07,Hacienda San Angel,Extranet,,ROGER,WESTPHAL,rogerwestphal5@gmail.com,"",,,,,,,,2025-11-25,2025-11-29,4,,"","DIRECT RESERVATION // +CONFIRMATION SENT MAY07 // +RESERVATION HAS CREDIT FOR RESERVATION PREVIOUSLY CANCELLED IN MAY $ 2,933.75 // +NO PROMO // +OK CREDIT CARD INFO // +SUITE CELESTIAL // +STAY NOV 25- 29 2025 // +MAY072025GV",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,2470.0,153.75,0.0,0.0,0.0,-2933.75,0,0.0,0.0,153.75,0,2,0,0,1,,,0,153.75,false,"",false,0,617.5,Room 103,"" +BDC-4846228944,2025-03-12,Hacienda San Angel,Booking.com,,Roling,Kathryn,rkathr.295444@guest.booking.com,+1 917 887 6174,,,,.,,United States,"",2025-11-26,2025-11-30,4,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT MAR12 // +RATE $ 397.91 USD + TAXES // +GENIUS DISCOUNT 10% // +CREDIT CARD INFORMATION OKMASTERCARD // +NO PROMO // +SUITE CROWN VIEW // +STAY NOV 26- 30 2025 // +MAR122025GV",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,1591.65,2002.3,0.0,0.0,0.0,12.74,0,0.0,0.0,2002.3,0,2,0,0,1,,,0,2002.3,false,"",false,0,397.9125,Room 112,"" +EXP-2277511376,2025-08-27,Hacienda San Angel,Expedia,,JASON,MITCHELL,2a7woea70k@m.expediapartnercentral.com,1 403 9921467,,,,,,,,2025-11-26,2025-11-30,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,764.80, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT AUG272025 // +CREDIT CARD INFORMATION OK // +RATE $ 576 USD + TAXES // +STAY NOV26-302025 // +SUITE SAN JOSE // +SUBMITED AUG272025NGR//",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,2304.0,2880.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2880.0,0,2,0,0,1,,,0,2880.0,false,"",false,0,576.0,Room 122,"" +SMP-2025092743555138,2025-09-27,Hacienda San Angel,Simple Booking,,Matthew,Roberts,mroberts@landmarkenviro.com,+13038981042,,,,,,,"",2025-11-26,2025-11-29,3,,"",,,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,1735.0,2168.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2168.75,0,2,0,0,1,,,0,2168.75,false,"",false,0,433.75,Room 102,"" +BDC-5849937934,2025-09-14,Hacienda San Angel,Booking.com,,katharine,salem,ksalem.588663@guest.booking.com,+44 7786 262992,,,,.,,United Kingdom,"",2025-11-27,2025-11-30,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-11-25., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT SEP132025 // +CREDIT CARD INFORMATION OK // +RATE $ 518.40 USD + TAXES // +STAY NOV27-302025 // +SUITE ANGEL VIEW // +SUBMITED SEP132025NGR//",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1555.2,1944.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1944.0,0,2,0,0,1,,,0,1944.0,false,"",false,0,388.8,Room 106,"" +SMP-2025050840029592,2025-05-08,Hacienda San Angel,Simple Booking,,Sarah,Briggs,sarahhbriggs@gmail.com,+18029895277,,,,,,,"",2025-11-28,2025-11-29,1,,this will be the last night of our honeymoon!,"RESERVATION FROM SIMPLE BOOKING // +CONFIRMATION SENT MAY 07 // +CREDIT CAR MASTERCARD CVV PENDING // +NO PROMO // +SUITE MILAGROS // +STAY NOV 28- 29 20 25 // +MAY072025GV",,Cancelled,2025-05-19 07:55:34, Milagros - Junior Suite,Milagros - Standard Rate,550.0,687.5,0.0,0.0,0.0,0.0,0,0.0,0.0,687.5,0,2,0,0,1,,,0,687.5,false,"",false,0,137.5,Room 102,"" +LH25051948159313,2025-05-19,Hacienda San Angel,Extranet,,BRIGGS,SARAH,sarahhbriggs@gmail.com,8029895277,,,,,,,,2025-11-28,2025-11-29,1,,"","DIRECT +NOV28-292025 +$690 + TAX +RINCON +MAY192025NGR",,Cancelled,2025-07-23 12:51:50, Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,690.0,862.5,0.0,0.0,0.0,0.0,0,0.0,0.0,862.5,0,2,0,0,1,,,0,862.5,false,"",false,0,172.5,Room 119,"" +LH25092051044051,2025-09-20,Hacienda San Angel,Extranet,,Timothy,Ricker,tim@timrickerinteriors.com,+16126700700,,,,,,United States of America,"",2025-11-28,2025-11-29,1,,"","RESERVATION DIRECTLY +RATE $540.00 + TAXES +NO PROMO +CREDIT CARD INFO MC OK +CONFIRMATION SENT SEP20/2025 +OK MARIANA SEP20/2025",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,540.0,675.0,0.0,0.0,0.0,0.0,0,0.0,0.0,675.0,0,2,0,0,1,,,0,675.0,false,"",false,0,135.0,Room 113,"" +LH25093051253928,2025-09-30,Hacienda San Angel,Extranet,,Peter,Klug,alma@journeymexico.com,322 225 9821,,,,,,,,2025-11-28,2025-12-01,3,,"","DIRECT RESERVATION // +AGENCIA JOURNEY // +NOT COMMISSIONABLE // +DISCOUNTED 20% // +RATE $492 USD + TAX // +SUITE VISTA DE SANTOS // +STAY NOV 28- DIC 01 2025 // +SEP302025GV + +CREDIT CARD INFORMATION PENDING. _____ FOR SECURE +TRANSFER TO BE MADE FOR PAYMENT OF STAY.",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,1860.0,1860.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1860.0,0,1,0,0,1,,,0,1860.0,false,"",false,0,372.0,Room 121,"" +SMP-2025081242609971,2025-08-12,Hacienda San Angel,Simple Booking,,Brian,League,bleague@me.com,+12134791660,,,,,,,"",2025-11-29,2025-12-02,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $554.87+TAXES +SECRET RATE +CREDIT CARD AMX CVV PENDING +CONFIRMATION SENT AUG12/2025 +OK MARIANA AUG12/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1664.6,2080.75,0.0,0.0,0.0,0.0,0,0.0,0.0,2080.75,0,2,0,0,1,,,0,2080.75,false,"",false,0,416.15,Room 103,"" +SMP-2025092643539518,2025-09-26,Hacienda San Angel,Simple Booking,,David,Bryant,dfraserbryant@gmail.com,+14153705518,,,,,,,"",2025-11-29,2025-12-01,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $485.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD INFO VISA CVV PENDING +CONFIRMATION SENT SEP26/2025 +OK MARIANA SEP26/2025",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,970.0,1212.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1212.5,0,2,0,0,1,,,0,1212.5,false,"",false,0,242.5,Room 110,"" +MMS-OBH25071000130800-2901949,2025-07-09,Hacienda San Angel,Mr and Mrs Smith,,Nabiel,Shawa,SUSIESHAWA@GMAIL.COM,,,,,,,,,2025-11-30,2025-12-02,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION TRHU MMS / HYEATT // +RATE $ 469.48 USD + TAXES // +PROMO: SMITH SCLUSIVE: MEMBERS DISCOUNT // +SUITE ANGELS DOME // +STAY NIV30- DIC 01 2025 // +VIRTUAL CARD FOR CHARGE // +JUL092025GV + + *** VIENE CON CACHORROS, FAVOR DE RETIRAR ALFOMBRAS",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,901.39,985.9,0.0,0.0,0.0,-140.84,0,0.0,0.0,985.9,0,1,0,0,1,,,0,985.9,false,"",false,0,225.3475,Room 113,"" +BDC-6429244211,2025-10-01,Hacienda San Angel,Booking.com,,Debra,Selland,dsella.242038@guest.booking.com,+1 206 355 9778,,,,.,,United States,"",2025-11-30,2025-12-01,1,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-11-28., booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-10-01 08:25:18, San Jose - Master Suite,San Jose - Standard Rate,640.0,800.0,0.0,0.0,0.0,0.0,0,0.0,0.0,800.0,0,2,0,0,1,,,0,800.0,false,"",false,0,160.0,Room 122,"" +BDC-6380588235,2025-10-01,Hacienda San Angel,Booking.com,,Debra,Selland,dsella.203851@guest.booking.com,+1 206 355 9778,,,,.,,United States,"",2025-11-30,2025-12-02,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-11-28., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT OCT012025// +CREDIT CARD INFORMATION OK // +RATE $ 660 USD + TAXES // +STAY NOV30-DEC022025 // +SUITE RINCÓN OF ANGELS // +SUBMITED OCT012025NGR //",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,1320.0,1650.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1650.0,0,2,0,0,1,,,0,1650.0,false,"",false,0,330.0,Room 119,"" +SMP-2025062741336029,2025-06-27,Hacienda San Angel,Simple Booking,,kipp,mueller,kipp@lakebreezeskilodge.com,+18303051500,,,,,,,"",2025-12-01,2025-12-03,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT JUN 27 // +CREDIT CARD INFORMATION AMEX CVV PENDING // +RATE $ 524.80 USD + TAXES // +NO PROPMO // +SECRET RATE // +SUITE ANGELS VIEW // +STAY DIC 01- 03 2025 // +JUN272025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1049.6,1312.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1312.0,0,2,0,0,1,,,0,1312.0,false,"",false,0,262.4,Room 106,"" +BDC-6461490031,2025-08-25,Hacienda San Angel,Booking.com,,katharine,salem,ksalem.360647@guest.booking.com,+44 7786 262992,,,,.,,United Kingdom,"",2025-12-01,2025-12-04,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-11-29., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT AGO24 // +VIRTUAL CARD FOR CHARGE // +RATE $ 465.75 USD + TAX // +GENIUS DOSCOUNT 10% // +SUITE CROWN VIEW // +STAY DIC 01- 04 2025 // +AGO24082025GV",,Cancelled,2025-09-24 00:10:54,Crown View - Junior Suite,Crown View - Standard Rate,1397.25,1746.56,0.0,0.0,0.0,0.0,0,0.0,0.0,1746.56,0,2,0,0,1,,,0,1746.56,false,"",false,0,349.3125,Room 112,"" +SMP-2025032238955269,2025-03-22,Hacienda San Angel,Simple Booking,,Mark,Clark,mdcmd59@gmail.com,+12317501257,,,,,,,"",2025-12-02,2025-12-06,4,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAR222025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $488.72 USD + TAXES // +STAY DEC2-72025 // +SUITE CELESTIAL // +SUBMITED MAR222025NGR//",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1943.41,2429.26,0.0,0.0,0.0,0.0,0,0.0,0.0,2429.26,0,2,0,0,1,,,0,2429.26,false,"",false,0,485.8525,Room 103,"" +LH25040647248171,2025-04-06,Hacienda San Angel,Extranet,,Amy,Welch,"","",,,,,,,,2025-12-02,2025-12-04,2,,Auction Donation,"PEACE Gift Certificate- Get credit card for incidentals at check in + +3 Night Stay +Includes Continental Breakfast +One Dinner for 2 + +Gift Certificate will have a value on it...IGNORE!!! They did not get a $3,000 gift certificate. That is a value number for bidding at the auction they won it at. All this certificate entitles them to is a 3 night stay and one dinner.- Paula + +RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT APR062025 // +CREDIT CARD INFORMATION NO NECESARY until check in// +RATE $ 0 USD + TAXES // +STAY NOV18-DEC012025 // +SUITE SERAFIN // +SUBMITED APR062025PAULANGR//",,Confirmed,"",Serafin - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 110,"" +SMP-2025081942751913,2025-08-19,Hacienda San Angel,Simple Booking,,Matthew,Bainer,mbainer@bainerlawfirm.com,+14159488199,,,,,,,"",2025-12-02,2025-12-05,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $635.00+ TAXES +BEST AVAILABLE RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT AUG18/2025 +OK MARIANA AUG18/2025",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,1905.0,2381.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2381.25,0,2,0,0,1,,,0,2381.25,false,"",false,0,476.25,Room 122,"" +LH25090250630742,2025-09-02,Hacienda San Angel,Extranet,,David,Gersham,davidgriffingershman@gmail.com,"",,,,,,,,2025-12-02,2025-12-06,4,,Angel's Rate,"This is another collaboration with a photographer to acquire more photos and a video for marketing + +Room is free + +Please give commission 7% to my staff from my pocket- tell Miguel +Also tell me if he does not leave propinas for staff. + +Food and Beverage Full Price",,Confirmed,"",Angels Dome - Junior Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,1,0,0,1,,,0,0.0,false,"",false,0,0,Room 113,"" +SMP-2025032539031406,2025-03-25,Hacienda San Angel,Simple Booking,,Kirby,Allison,theallisons0510@gmail.com,+17138980157,,,,,,,"",2025-12-03,2025-12-04,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT MAR252025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $640 USD + TAXES // +STAY DEN03-042025 // +SUITE RINCÓN DE ÁNGELES // +SUBMITED MAR252025NGR //",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,640.0,800.0,0.0,0.0,0.0,0.0,0,0.0,0.0,800.0,0,2,0,0,1,,,0,800.0,false,"",false,0,160.0,Room 119,"" +SMP-2025042239666027,2025-04-22,Hacienda San Angel,Simple Booking,,Thomas,Rosato,trosato@me.com,+16462864138,,,,,,,"",2025-12-03,2025-12-10,7,,"","RESERVATION FROM SIMPLE BOOKING +RATE $ 570.49 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT APRIL22/25 +OK MARIANA APRIL22/25",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3993.42,4991.78,0.0,0.0,0.0,0.0,0,0.0,0.0,4991.78,0,2,0,0,1,,,0,4991.78,false,"",false,0,998.355,Room 107,"" +LH25082750506663,2025-08-27,Hacienda San Angel,Extranet,,Grant,Gingrich,grant.gingrich@hotmail.com,6057303958,,,,,,,,2025-12-03,2025-12-04,1,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT AUG272025// +CREDIT CARD INFORMATION OK // +RATE $ 570 USD + TAXES // +STAY DEC03-042025 // +SUITE GARDEN OF ANGELS // +SUBMITED AUG272025NGR //",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,570.0,712.5,0.0,0.0,0.0,0.0,0,0.0,0.0,712.5,0,2,0,0,1,,,0,712.5,false,"",false,0,142.5,Room 109,"" +MMS-OBH25081918520902-2944081,2025-08-19,Hacienda San Angel,Mr and Mrs Smith,,Amy,Martell,AMARTELL@HELMSBRISCOE.COM,,,,,,,,,2025-12-04,2025-12-05,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MR. & MRS. SMITH +RATE $419.33 + TAXES +HYATT +CREDIT CARD MC CVV PENDING +CONFIRMATION SENT AUG19/2025 +OK MARIANA AUG19/2025",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,419.33,524.16,0.0,0.0,0.0,0.0,0,0.0,0.0,524.16,0,1,0,0,1,,,0,524.16,false,"",false,0,104.8325,Room 102,"" +BDC-6721820925,2025-09-06,Hacienda San Angel,Booking.com,,Tadsarin,Stacey,tstace.899885@guest.booking.com,+1 360 624 6006,,,,.,,United States,"",2025-12-04,2025-12-07,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-02., booker_is_genius +smoking preference: Non-Smoking","RESERVATION TRU BOOKING.COM // +CONFIRMATION SENT SEP 05 // +VIRTUAL CARD FOR CHARGE // +RATE $ 464.40 USD + TAX // +GENIUS DISCOUNT 10% // +SUITE GARDEN OF ANGELS // +STAY DIC 04- 07 2025 // +SEP062025GV",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1393.2,1741.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1741.5,0,2,0,0,1,,,0,1741.5,false,"",false,0,348.3,Room 109,"" +EXP-2221984178,2025-06-15,Hacienda San Angel,Expedia,,Melanie,Baskette,1saavhuh43@m.expediapartnercentral.com,1 856 6307593,,,,,,,,2025-12-05,2025-12-07,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION FROM EXPEDIA +RATE $556.25+ TAXES +NO PROMO +CREDIT CARD INFO OK +CONFIRMATION SENT JUNE15/25 +OK MARIANA JUNE 15/25",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1112.5,1390.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1390.63,0,2,0,0,1,,,0,1390.63,false,"",false,0,278.125,Room 106,"" +SMP-2025072442109055,2025-07-24,Hacienda San Angel,Simple Booking,,Heather,Nelson-Melidonian,nelsonhrae@gmail.com,+19515336445,,,,,,,"",2025-12-05,2025-12-09,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $655.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JULY24/2025 +OK MARIANA JULY24/2025",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2620.0,3275.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3275.0,0,2,0,0,1,,,0,3275.0,false,"",false,0,655.0,Room 119,"" +MMS-OBH25091221442004-2968143,2025-09-12,Hacienda San Angel,Mr and Mrs Smith,,Robert,Hopson,ROBERT@ROBERTHOPSONGROUP.COM,,,,,,,,,2025-12-08,2025-12-11,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION FROM MMS // +RATE $ 401.70 USD + TAX // +VIRTUAL CARD FOR CHARGE // +NO PROMO // +SUITE GARDEN OF ANGELS // +STAY DIC 08- 0 11 2025 // +SEP122025GV",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1156.9,1506.38,0.0,0.0,0.0,60.25,0,0.0,0.0,1506.38,0,2,0,0,1,,,0,1506.38,false,"",false,0,289.225,Room 109,"" +SMP-2025011537465201,2025-01-15,Hacienda San Angel,Simple Booking,,Joe,Freeman,jennifersfreeman@comcast.net,+13039080902,,,,,,,"",2025-12-09,2025-12-12,3,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE 16 // +RATE $ 483.33 USD + TAXES // +CREDIT CARD INFORMATION OK VISA CVV PENDING // +STAY DEC 09- 12 2025 // +SUITE SAN GABRIEL // +NO PROMO //",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1450.0,1812.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1812.5,0,2,0,0,1,,,0,1812.5,false,"",false,0,362.5,Room 118,"" +SMP-2025011637468650,2025-01-16,Hacienda San Angel,Simple Booking,,Steve,Peterson,sjp1650@gmail.com,+13033563432,,,,,,,"",2025-12-09,2025-12-11,2,,"","RESERVATION THRU SB .COM // +CONFIRMATION SENT JAN152025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 428.45 USD + TAXES // +STAY DEC9-112025// +SUITE ANGEL VIEW// +SUBMITED JAN152025NGR//",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,856.9,1071.13,0.0,0.0,0.0,0.0,0,0.0,0.0,1071.13,0,2,0,0,1,,,0,1071.13,false,"",false,0,214.225,Room 106,"" +EXP-2265037035,2025-08-10,Hacienda San Angel,Expedia,,Lauren,Sharp,m5b8x7bisj@m.expediapartnercentral.com,1 888 2545518,,,,,,,,2025-12-09,2025-12-11,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 1,436.46, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION FROM EXPEDIA +RATE $598.53 +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT AUG10/2025 +OK MARIANA AUG10/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1197.05,1496.31,0.0,0.0,0.0,0.0,0,0.0,0.0,1496.31,0,2,0,0,1,,,0,1496.31,false,"",false,0,299.2625,Room 103,"" +SMP-2025080242322466,2025-08-02,Hacienda San Angel,Simple Booking,,Margo,Ackman,margoackman@gmail.com,+13037158777,,,,,,,"",2025-12-11,2025-12-14,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $455.10 + taxes +SECRET RATE +VISA CREDIT CARD CVV PENDING +CONFIRMATION SENT AUG08/2025 +PK MARIANA AUG08/2025",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,1365.3,1706.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1706.63,0,2,0,0,1,,,0,1706.63,false,"",false,0,341.325,Room 102,"" +BDC-5035157266,2025-06-04,Hacienda San Angel,Booking.com,,Madaleine,Shields,mshiel.239255@guest.booking.com,+1 650 474 9718,,,,.,,United States,"",2025-12-12,2025-12-16,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-10., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $382.72 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE06/25 +OK MARIANA JUNE06/25",,Cancelled,2025-06-04 19:40:55, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1530.9,1913.63,0.0,0.0,0.0,0.0,0,0.0,0.0,1913.63,0,2,0,0,1,,,0,1913.63,false,"",false,0,382.725,Room 109,"" +BDC-6488951643,2025-06-05,Hacienda San Angel,Booking.com,,Madaleine,Shields,mshiel.670867@guest.booking.com,+1 650 474 9718,,,,,,United States,"",2025-12-12,2025-12-16,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-10., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $397.91+ TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE06/25 +OK MARIANA JUNE06/25",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1591.65,1989.56,0.0,0.0,0.0,0.0,0,0.0,0.0,1989.56,0,2,0,0,1,,,0,1989.56,false,"",false,0,397.9125,Room 109,"" +BDC-6721460660,2025-06-09,Hacienda San Angel,Booking.com,,Madaleine,Shields,mshiel.958582@guest.booking.com,+1 650 474 9718,,,,,,United States,"",2025-12-12,2025-12-16,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-10., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $454.83 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE09/25 +OK MARIANAJUNE09/25",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1891.35,2364.19,0.0,0.0,0.0,0.0,0,0.0,0.0,2364.19,0,2,0,0,1,,,0,2364.19,false,"",false,0,472.8375,Room 106,"" +SMP-2025082842954780,2025-08-28,Hacienda San Angel,Simple Booking,,Sojern,Ghost,grace.cheung@sojern.com,+6512341234,,,,,,Singapore,"",2025-12-12,2025-12-13,1,,"",,,Cancelled,2025-08-27 21:40:05,Serafin - Junior Suite,Serafin - Standard Rate,500.0,625.0,0.0,0.0,0.0,0.0,0,0.0,0.0,625.0,0,2,0,0,1,,,0,625.0,false,"",false,0,125.0,Room 110,"" +SMP-2025100243642943,2025-10-02,Hacienda San Angel,Simple Booking,,Katherine,Cass,krc53spam@gmail.com,+16287774696,,,,,,,"",2025-12-12,2025-12-16,4,,This is planned as a romantic getaway,"RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT OC022025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 557.60 USD + TAXES // +STAY DEC12-162025 // +SUITE CELESTIAL SUITE // +SUBMITED OCT022025NGR//",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,2230.4,2788.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2788.0,0,2,0,0,1,,,0,2788.0,false,"",false,0,557.6,Room 103,"" +SMP-2025082942975849,2025-08-28,Hacienda San Angel,Simple Booking,,Neal,Ambrose,tnambrose88@gmail.com,+13609411248,,,,,,,"",2025-12-13,2025-12-19,6,,"","RESERVATION THRU SIMIPLEBOOKING.COM // +CONFIRMATION SENT AUG282025 // +CREDIT CARD INFORMATION CVV PENDIENT// +RATE $ 429.81 USD + TAXES // +STAY DEC13-192025 // +SUITE ANGEL DOME // +SUBMITED AUG282025NGR//",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,2578.91,3223.64,0.0,0.0,0.0,0.0,0,0.0,0.0,3223.64,0,2,0,0,1,,,0,3223.64,false,"",false,0,644.7275,Room 113,"" +EXP-2152397788,2025-03-09,Hacienda San Angel,Expedia,,CHERYL,SASSCER,5xwq37vu7c@m.expediapartnercentral.com,1 305 6664063,,,,,,,,2025-12-15,2025-12-21,6,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 3,283.20, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT MAR092025// +CREDIT CARD INFORMATION OK // +RATE $ 456 USD + TAXES // +STAY DEC15-212025 // +SUITE MILAGROS // +SUBMITED MAR092025NGR//",,Cancelled,2025-05-15 12:16:19, Milagros - Junior Suite,Milagros - Standard Rate,2736.0,3420.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3420.0,0,2,0,0,1,,,0,3420.0,false,"",false,0,684.0,Room 102,"" +BDC-4512439703,2025-05-01,Hacienda San Angel,Booking.com,,Madaleine,Shields,mshiel.485635@guest.booking.com,+1 650 474 9718,,,,,,United States,"",2025-12-16,2025-12-22,6,,"Approximate time of arrival: between 17:00 and 18:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT ABR 30 // +RATE $ 446 USD + TAX // +CREDIT CARD INFORMATION OK VISA // +GENIUS DICOUNT 10% // +SUITE GARDEN OF ANGELS // +STAY DIC 16- 22 2025 // +ABR302025GV",,Cancelled,2025-06-04 19:38:44, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,2673.0,3362.63,0.0,0.0,0.0,21.38,0,0.0,0.0,3362.63,0,2,0,0,1,,,0,3362.63,false,"",false,0,668.25,Room 109,"" +SMP-2025092743554722,2025-09-27,Hacienda San Angel,Simple Booking,,Brad,Hayes,bhayes4891@gmail.com,+13604204891,,,,,,,"",2025-12-19,2025-12-22,3,,"",,,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,2030.0,2537.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2537.5,0,2,0,0,1,,,0,2537.5,false,"",false,0,507.5,Room 106,"" +MMS-OBH25070702003400-2898678,2025-07-07,Hacienda San Angel,Mr and Mrs Smith,,Trent,Boarnet,TRENT@TRENTBOARNET.COM,,,,,,,,,2025-12-20,2025-12-27,7,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS // +RATE $ 615.09 USD + TAXES // +NO PROMO // +VIRTUAL CARD FOR CHARGE // +SUITE RINCON DE ANGELES // +STAY DIC 20- 27 2025 // +JUL062025GV",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,4133.36,5382.0,0.0,0.0,0.0,215.3,0,0.0,0.0,5382.0,0,2,0,0,1,,,0,5382.0,false,"",false,0,1033.34,Room 119,"" +EXP-X-419813838,2025-02-24,Hacienda San Angel,Expedia,,LOUISE,FORD,kyey02m7xq@m.expediapartnercentral.com,1 0 6464690364,,,,,,,,2025-12-21,2026-01-04,14,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest.","RESERVATION THRU EXP // +CONFRIMATION SENT FEB 24 // +RATE $ 540 USD + TAX // +CREDIT CARD INFORMATION OK AMEX // +SUITE SAN JOSE // +STAY DIC 21- ENE 04 // +PROMO BLUE EXP 10% DESC // +FEB242024GV",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,7560.0,9450.0,0.0,0.0,0.0,0.0,0,0.0,0.0,9450.0,0,2,0,0,1,,,0,9450.0,false,"",false,0,1890.0,Room 122,"" +SMP-2025052040334439,2025-05-20,Hacienda San Angel,Simple Booking,,larry,Sullivan,larrysull@icloud.com,+12505169104,,,,,,Canada,"",2025-12-21,2025-12-26,5,,"","SIMPLEBOOKING.COM +DEC.21-262025 +CELESTIAL SUITE +$639.60 + TAX +PENDIENT CVV & ZC +MAY202025NGR",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,3198.0,3997.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3997.5,1998.75,2,0,0,1,,,0,1998.75,false,"",false,0,799.5,Room 103,"" +SMP-2025091343292976,2025-09-13,Hacienda San Angel,Simple Booking,,Daryl,Shoptaugh,DarylShoptaugh@gmail.com,+4407444277586,,,,,,United Kingdom,"",2025-12-21,2025-12-28,7,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT SEP13 // +RATE CV $630 AD $600 G $630 USD + TAX // +CREDIT CARD INFO AMEX CVV PEND // +NO PROMO // +DEPOSIT 50% // +SUITE AD / CV / G // +STAY DIC 21- 28 2025 // +sep132025gv",,Cancelled,2025-09-14 14:54:08,"Crown View - Junior Suite,Angels Dome - Junior Suite, Garden of Angels - Junior Suite","Crown View - Standard Rate,Angels Dome - Standard Rate,Garden of Angels - Standard Rate",13020.0,16275.0,0.0,0.0,0.0,0.0,0,0.0,0.0,16275.0,0,6,0,0,3,,,0,16275.0,false,"",false,0,3255.0,"Room 112, Room 113, Room 109","" +LH25092851206014,2025-09-28,Hacienda San Angel,Extranet,,Timothy,Ricker,tim@timrickerinteriors.com,+16126700700,,,,,,United States of America,"",2025-12-22,2025-12-29,7,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT SEP282025// +CREDIT CARD INFORMATION OK // +RATE $ 870 USD + TAXES // +STAY DEC22- 292025 // +SUITE SAN MIGUEL // +SUBMITED SEP282025NGR// +THIS RESERVATION HAS AN EXTENSION TO ANGEL VIEW",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,6090.0,7612.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,7612.5,3806.25,2,0,0,1,,,0,3806.25,false,"",false,0,1522.5,Room 107,"" +EXP-X-406779786,2025-02-01,Hacienda San Angel,Expedia,,Gwyneth,Parker,vs7ly683yo@m.expediapartnercentral.com,1 2068172229,,,,,,,,2025-12-23,2025-12-29,6,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $464.40 +$85.00 USD CREDIT//BOTTLE OR UPGRADE +CREDIT CARD INFO OK +CONFIRMATION SENT FEBRUARY 1ST/2025 +OK MARIANA FEBRUARY1ST/2025",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,2786.4,3483.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3483.0,0,1,0,0,1,,,0,3483.0,false,"",false,0,696.6,Room 118,"" +SMP-2025042939833638,2025-04-29,Hacienda San Angel,Simple Booking,,MARK,COX,macslegend@gmail.com,+15753131634,,,,,,,"",2025-12-23,2025-12-26,3,,"","RESERVATTION FROM SIMPLEBOOKING // +CONFIRMATION SENT ABR29 // +RATE $ 615 USD + TAX // +NO PROMO // +CREDIT CARD VISA CVV PENDING // +SEVRET RATE // +HOLIDAY SEASSON RESERVATION CHARGE 50% // +SUITE ANGEL VIEW // +STAY DEC 23- 29 2025 // +ABR292025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1845.0,2306.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2306.25,1153.13,2,0,0,1,,,1153.13,1153.12,false,"",false,0,461.25,Room 106,"" +MMS-OBH25081323133801-2938302,2025-08-13,Hacienda San Angel,Mr and Mrs Smith,,Johnny,Pedrotti,JWADEP@HOTMAIL.COM,,,,,,,,,2025-12-23,2025-12-30,7,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS / HYATT // +RATE $ 667.5 USD + TAX // +VIRTUAL CARD FOR CHARGE // +SUITE VISTAS DE SANTOS // +STAY DIC 23- 0 2025 // +MEMBER DISCOUNT // +AGO132025GV",,Cancelled,2025-08-25 12:40:59, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,4485.6,5607.0,0.0,0.0,0.0,0.0,0,0.0,0.0,5607.0,0,2,0,0,1,,,0,5607.0,false,"",false,0,1121.4,Room 121,"" +MMS-OBH25082519503402-2949698,2025-08-25,Hacienda San Angel,Mr and Mrs Smith,,Johnny,Pedrotti,JWADEP@HOTMAIL.COM,,,,,,,,,2025-12-23,2025-12-28,5,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT AUG252025// +CREDIT CARD INFORMATION OK // +RATE $ 640.80 USD + TAXES // +STAY DEC23-282025 // +SUITE VISTA DE SANTOS // +SUBMITED AUG252025NGR//",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,3204.0,3504.38,0.0,0.0,0.0,-500.62,0,0.0,0.0,3504.38,0,2,0,0,1,,,0,3504.38,false,"",false,0,801.0,Room 121,"" +BDC-5165729215,2025-09-08,Hacienda San Angel,Booking.com,,Tomczyk,Steven,tsteve.510891@guest.booking.com,+1 303 818 3646,,,,,,United States,"",2025-12-23,2025-12-28,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-21., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT SEP072025 // +CREDIT CARD INFORMATION OK // +RATE $ 567 USD + TAXES // +STAY DEC22-272025 // +SUITE GARDEN OF ANGELS // +SUBMITED SEP072025NGR //",,Cancelled,2025-09-10 15:52:48, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,2835.0,3543.75,0.0,0.0,0.0,0.0,0,0.0,0.0,3543.75,0,2,0,0,1,,,0,3543.75,false,"",false,0,708.75,Room 109,"" +EXP-X-388842523,2025-01-04,Hacienda San Angel,Expedia,,Gwyneth,Parker,ln01ekn3p2@m.expediapartnercentral.com,1 2068172229,,,,,,,,2025-12-24,2025-12-31,7,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP +RATE $464.28 + TAXES +$85.00 USD ON CREDIT// UPGRADE OR BOTLLE +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT ENE04/2025 +OK MARIANA ENE04/2025",,Cancelled,2025-02-01 06:49:03, San Gabriel - Junior Suite,San Gabriel - Standard Rate,3250.8,4063.5,0.0,0.0,0.0,0.0,0,0.0,0.0,4063.5,0,2,0,0,1,,,0,4063.5,false,"",false,0,780.192,Room 118,"" +EXP-2202760275,2025-05-20,Hacienda San Angel,Expedia,,Maria,Dubov,6l915cqwgq@m.expediapartnercentral.com,1 847 3221326,,,,,,,,2025-12-24,2025-12-29,5,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay",,,Cancelled,2025-05-20 17:51:00, Vista de Santos - Master Suite,Vista de Santos - Standard Rate,3300.0,4125.0,0.0,0.0,0.0,0.0,0,0.0,0.0,4125.0,0,2,0,0,1,,,0,4125.0,false,"",false,0,825.0,Room 121,"" +BDC-6715071181,2025-05-25,Hacienda San Angel,Booking.com,,Alida,Camper,acampe.228618@guest.booking.com,+1 202 255 0360,,,,,,United States,"",2025-12-24,2025-12-26,2,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-22. +We request a rollaway bed in one of the rooms please., booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-05-25 14:51:06,"Serafin - Junior Suite,Angels Dome - Junior Suite","Serafin - Standard Rate,Angels Dome - Standard Rate",2160.0,2700.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2700.0,0,4,0,0,2,,,0,2700.0,false,"",false,0,540.0,"Room 110, Room 113","" +BDC-4847422825,2025-01-24,Hacienda San Angel,Booking.com,,Steven,Green,sgreen.150334@guest.booking.com,+1 416 356 1232,,,,,,Canada,"",2025-12-25,2026-01-01,7,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-23., booker_is_genius +smoking preference: Non-Smoking",,,Cancelled,2025-01-23 19:36:42,"Serafin - Junior Suite,Crown View - Junior Suite,Angels Dome - Junior Suite","Serafin - Standard Rate,Crown View - Standard Rate,Angels Dome - Standard Rate",9576.0,11970.0,0.0,0.0,0.0,0.0,0,0.0,0.0,11970.0,0,5,0,0,3,,,0,11970.0,false,"",false,0,2394.0,"Room 110, Room 112, Room 113","" +BDC-6728291227,2025-07-16,Hacienda San Angel,Booking.com,,Timothy,Murphy,tmurph.459912@guest.booking.com,+1 203 564 0799,,"30 08 Prudential Tower, 19 Cecil St",,bangkok,,United States,N/A,2025-12-25,2025-12-28,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-23. +AdditionalNotes: None +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $870.00 USD + TAXES +HOLIDAY SEASON +VIRTUAL CREDIT CARD +CONFIRMATION SENT JULY15/2025 +OK MARIANA JULY15/2025",,Cancelled,2025-08-07 20:18:38, San Miguel - Presidential Suite,San Miguel - Standard Rate,2610.0,3262.5,0.0,0.0,0.0,0.0,0,0.0,0.0,3262.5,0,2,0,0,1,,,0,3262.5,false,"",false,0,652.5,Room 107,"" +BDC-4410051498,2025-03-27,Hacienda San Angel,Booking.com,,Mary,Asma,masma.276001@guest.booking.com,+1 407 592 0833,,,,,,United States,"",2025-12-26,2025-12-30,4,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $468.00 + TAXES +NO PROMO +CREDIT CARD CVV OK +CONFIRMATION SENT MARCH27/2024 +OK MARIAN MAARCH27/2025",,Cancelled,2025-09-24 10:42:51, Milagros - Junior Suite,Milagros - Standard Rate,1872.0,2340.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2340.0,0,2,0,0,1,,,0,2340.0,false,"",false,0,468.0,Room 102,"" +LH25070449209575,2025-07-04,Hacienda San Angel,Extranet,,ALISSE,KINGSLEY,alissethemuse@aol.com,+12137092582,,,,,,,,2025-12-26,2025-12-28,2,,"","RESERVATION DIRECTLY +RATE $600.00 TAXES +HOLIDAY SEASON +CREDIT CARD INFO AMEX OK +CONFIRMATION SETN JULY04/25 +OK MARIANA JULY04/25 + + +cvv 330 + +MS. Alisse uses a cane, might need a stole to reach the bed!... NOTES!!!",,Confirmed,"",Serafin - Junior Suite,Serafin - Holiday Rate,1200.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1500.0,750.0,2,0,0,1,,,0,750.0,false,"",false,0,300.0,Room 110,"" +MMS-OBH25100318290902-2986936,2025-10-03,Hacienda San Angel,Mr and Mrs Smith,,Stephen,Cocco,COCCOSTEVE@GMAIL.COM,,,,,,,,,2025-12-26,2025-12-30,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT OCT032025 // +CREDIT CARD INFORMATION OK // +RATE $ 538.27 USD + TAXES // +STAY DEC26-302025 // +SUITE MILAGROS // +SUBMITED OCT032025NGR//",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,2153.09,2354.94,0.0,0.0,0.0,-336.42,0,0.0,0.0,2354.94,0,2,0,0,1,,,0,2354.94,false,"",false,0,538.2725,Room 102,"" +BDC-4840203369,2025-01-03,Hacienda San Angel,Booking.com,,Nam,Lee,nlee.107730@guest.booking.com,+1 206 8548279,,,,.,,United States,"",2025-12-27,2026-01-02,6,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JAN032025 // +CREDIT CARD INFORMATION OK // +RATE $ 421.20 USD + TAXES // +STAY DEC272025-JAN22026 // +SUITE MILAGROS // +SUBMITED JAN032025NGR//",,Cancelled,2025-01-25 18:52:42, Milagros - Junior Suite,Milagros - Standard Rate,2527.2,3159.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3159.0,0,2,0,0,1,,,0,3159.0,false,"",false,0,606.528,Room 102,"" +SMP-2025012637688202,2025-01-26,Hacienda San Angel,Simple Booking,,Nam,Lee,Kchenrylee@gmail.com,+12068548279,,,,,,,"",2025-12-27,2025-12-29,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT ENE25 // +RATE $ 475.60 USD + TAX // +NO PROMO //+SECRET RATE // +CREDIT CARD INFORMATION VISA PENDING CVV // +SUITE ANGEL VIEW // +STAY DIC 27- 29 2025 // +ENE252025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,951.2,1189.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1189.0,594.5,2,0,0,1,,,0,594.5,false,"",false,0,237.8,Room 106,"" +MMS-OBH25090901460103-2964056,2025-09-09,Hacienda San Angel,Mr and Mrs Smith,,Matthew,Patsky,MPATSKY@COMCAST.NET,,,,,,,,,2025-12-27,2025-12-28,1,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT SEP082025 // +CREDIT CARD INFORMATION OK // +RATE $ 606.53 USD + TAXES // +STAY DEC27-282025 // +SUITE RINCÓN OF ANGELS // +SUBMITED SEP082025NGR//",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,606.53,789.75,0.0,0.0,0.0,31.59,0,0.0,0.0,789.75,0,2,0,0,1,,,0,789.75,false,"",false,0,151.6325,Room 119,"" +BDC-4326004992,2025-01-29,Hacienda San Angel,Booking.com,,Thomas,Gard,tgard.183667@guest.booking.com,+1 925 348 3931,,,,,,United States,"",2025-12-28,2026-01-01,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-26., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT ENE29 // +RATE $ 780 USD + TAXES // +NO PROMO // +SUITE SAN MIGUEL // +STAY DIC 28- ENE 01 2025 // +ENE292025GV",,Cancelled,2025-06-30 16:22:53, San Miguel - Presidential Suite,San Miguel - Standard Rate,3120.0,3900.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3900.0,0,2,0,0,1,,,0,3900.0,false,"",false,0,780.0,Room 107,"" +SMP-2025041139426305,2025-04-11,Hacienda San Angel,Simple Booking,,Ann & Alex,Robertson,aaarober@shaw.ca,+12506500157,,,,,,Canada,"",2025-12-28,2026-01-03,6,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR112025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 640 USD + TAXES // +STAY DEC282025-JAN032026 // +SUITE RINCÓN DE ANGELES // +SUBMITED APR112025NGR//",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,3840.0,4800.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,4800.0,2400.0,2,0,0,1,,,0,2400.0,false,"",false,0,960.0,Room 119,"" +SMP-2025041539513186,2025-04-15,Hacienda San Angel,Simple Booking,,David Parsons,Parsons,dparsons@zelinkaparsons.com,+15204442286,,,,,,,"",2025-12-28,2026-01-02,5,,"","RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT APR152025 // +CREDIT CARD INFORMATION OK // +RATE $ 508.40 USD + TAXES // +STAY DEC282025-JAN022026 // +SUITE CELESTIAL // +SUBMITED APR152025NGR//",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,2542.0,3177.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3177.5,1588.75,2,0,0,1,,,0,1588.75,false,"",false,0,635.5,Room 103,"" +SMP-2025042739763085,2025-04-27,Hacienda San Angel,Simple Booking,,Barry,Ferg,barryferg@gmail.com,+17788963374,,,,,,Canada,"",2025-12-28,2026-01-03,6,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 492 USD + TAXES // +STAY DEC282025-JAN032026 // +SUITE ANGEL DOME // +SUBMITED APR272025NGR//",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,2952.0,3690.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3690.0,1845.0,2,0,0,1,,,0,1845.0,false,"",false,0,738.0,Room 113,"" +SMP-2025052540457165,2025-05-25,Hacienda San Angel,Simple Booking,,Margaret,Walker,margsinlb@gmail.com,+13128068958,,,,,,,"",2025-12-28,2025-12-30,2,,"","SIMPLEBOOKING.COM +SERFÍN SUITE & CROWN VIEW +DEC28-302025 +CC CVV PENDIENT +$1,230 + TAX +MAY252025NGR",,Confirmed,"","Serafin - Junior Suite,Crown View - Junior Suite","Serafin - Standard Rate,Crown View - Standard Rate",2460.0,3075.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3075.0,1537.5,4,0,0,2,,,0,1537.5,false,"",false,0,615.0,"Room 110, Room 112","" +SMP-2025070341518524,2025-07-03,Hacienda San Angel,Simple Booking,,Victoria,Yi,Yivictoria03@gmail.com,+14054160414,,,,,,,"",2025-12-28,2026-01-02,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $713.40+ TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JULY03/2025 +OK MARIANA JULY03/2025",,Cancelled,2025-07-17 22:00:59, San Miguel - Presidential Suite,San Miguel - Standard Rate,3595.52,4494.4,0.0,0.0,0.0,0.0,0,0.0,0.0,4494.4,0,2,0,0,1,,,0,4494.4,false,"",false,0,898.88,Room 107,"" +SMP-2025032639047148,2025-03-26,Hacienda San Angel,Simple Booking,,Adrian,Bourne,abourne@unitechsystems.com,+14036194915,,,,,,Canada,"",2025-12-29,2026-01-07,9,,"","RESERVATION FROM SIMPLE BOOKING +RATE $424.58 + TAXES +SECRET RATE// HOLIDAY SEASON +CREDIT CARD CVV AMEX PENDING +CONFIRMATION SENT MARCH26/2025 +OK MARIANA MARCH26/2025",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,3821.2,4776.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,4776.5,2388.25,2,0,0,1,,,0,2388.25,false,"",false,0,955.3,Room 109,"" +SMP-2025041439466802,2025-04-13,Hacienda San Angel,Simple Booking,,Ann & Alex,Robertson,aaarober@shaw.ca,+1250-650-0157,,,,,,Canada,"",2025-12-29,2026-01-03,5,,"",,,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,2700.0,3375.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3375.0,1687.5,2,0,0,1,,,0,1687.5,false,"",false,0,675.0,Room 118,"" +SMP-2025080642452278,2025-08-06,Hacienda San Angel,Simple Booking,,Alexis,Server,AlexisServer@gmail.com,+17703120654,,,,,,,"",2025-12-29,2025-12-31,2,,"We are VERY excited to stay at such a beautiful place. We are celebrating my wife, Holly's birthday. I made a dinner reservation at the on-site restaurant on Holly's birthday (December 30, 2025). We would love a premium table view, if possible. Thank you!","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT AGO 06 // +RATE $ 713.40 USD + TAX // +CREDIT CARD INFORMATION VISA CVV PENDING // +NO PROMO // +SECRET RATE // +SUITE SAN MIGUEL // +STAY DIC 29- 31 2025 // +AGO062025GV",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1426.8,1783.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1783.5,891.75,2,0,0,1,,,891.75,891.75,false,"",false,0,356.7,Room 107,"" +LH25092851206109,2025-09-28,Hacienda San Angel,Extranet,,Timothy,Ricker,tim@timrickerinteriors.com,+16126700700,,,,,,United States of America,"",2025-12-29,2025-12-30,1,,"","RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT SEP282025 // +CREDIT CARD INFORMATION OK // +RATE $ 750 USD + TAXES // +STAY DEC29-302025 // +SUITE ANGEL VIEW // +SUBMITED SEP282025NGR // +THIS EXTENSION COMES FROM THE ROOM OF SAN MIGUEL",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,750.0,937.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,937.5,468.75,2,0,0,1,,,0,468.75,false,"",false,0,187.5,Room 106,"" +MMS-OB25060400404300-2865970,2025-06-03,Hacienda San Angel,Mr and Mrs Smith,,Karen,Schultz,kschultzsf@gmail.com,+14155172452,,3148 Steiner St,,San Francisco,,United States,94123,2025-12-30,2026-01-02,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMMS // +RATE $600 USD + TAXES // +NO PROMO // +SUITE SERAFIN // +STAY DIC 30 2025- ENR 02 2026 // +CHARGE GUEST 5% // +VIRTUAL CARD FOR CHARGE // +JUN022025GV",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,1728.0,1890.0,0.0,0.0,0.0,-270.0,0,0.0,0.0,1890.0,0,2,0,0,1,,,0,1890.0,false,"",false,0,432.0,Room 110,"" +LH25070349180525,2025-07-03,Hacienda San Angel,Extranet,,Alex,Niedbalski,niedbalskia@hotmail.com,+16026846464,,,,,,,,2025-12-30,2026-01-02,3,,"","VS para los padres +Milagros para la abuela y dos adolescentes +colocar cama adicional. +El cargo de 300 dolares YA esta aplicado en la tarifa +DEPOSITO COBRADO DEL 50% +CONFIRMATION SENT JULY03/2025",,Confirmed,""," Vista de Santos - Master Suite, Milagros - Junior Suite","Vista de Santos - Standard Rate,Manual",4380.0,5475.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,5475.0,2737.5,4,0,0,2,,,0,2737.5,false,"",false,0,1095.0,"Room 121, Room 102","" +MMS-OBH25070622264706-2898538,2025-07-06,Hacienda San Angel,Mr and Mrs Smith,,Jessica,Obrien,JESSICAOBRIEN08@GMAIL.COM,,,,,,,,,2025-12-30,2026-01-03,4,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS / / +RATE $ 491.40 USD + TAXE // +NO PROMO // +SUITE CROWN VIEW // +STAY DIC 30 2025- ENE 03 2026 // +VIRTUAL CARD FOR CHARGE // +JUL062025GV",,Cancelled,2025-08-09 10:45:47,Crown View - Junior Suite,Crown View - Standard Rate,1886.98,2457.0,0.0,0.0,0.0,98.27,0,0.0,0.0,2457.0,0,2,0,0,1,,,0,2457.0,false,"",false,0,471.745,Room 112,"" +BDC-5573264251,2025-07-19,Hacienda San Angel,Booking.com,,Luke,Sheehy,lsheeh.851283@guest.booking.com,+61 408 510 508,,,,.,,Australia,"",2025-12-30,2026-01-06,7,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $569.31 + TAXES +HOLIDAY (SE COBRAR NORMAL POR POLITICAS DE BOOKING) +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JULY19/2025 +OK MARIANA JULY19/2025",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,3985.2,4981.5,0.0,0.0,0.0,0.0,0,0.0,0.0,4981.5,0,2,0,0,1,,,0,4981.5,false,"",false,0,996.3,Room 106,"" +BDC-5792071932,2025-09-01,Hacienda San Angel,Booking.com,,Jeannie,Agrios,agrios@telus.net,+1 469 675 9003,,3010 Lyndon B Johnson Fwy,,Dallas,,United States,75234-7770,2025-12-30,2026-01-02,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2025-12-28., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT SEP012025 // +CREDIT CARD INFORMATION OK // +RATE $ 630 USD + TAXES // +STAY DEC302025-JAN022026 // +SUITE CROWN VIEW // +SUBMITED SEP012025NGR //",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,1890.0,2362.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2362.5,0,2,0,0,1,,,0,2362.5,false,"",false,0,472.5,Room 112,"" +EXP-2219658857,2025-06-12,Hacienda San Angel,Expedia,,ALEJANDRO,MILITELLO,5ap2syrivp@m.expediapartnercentral.com,1 18662597766,,,,,,,,2025-12-31,2026-01-01,1,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 810.00, Expedia Virtual Card will be activated from the day of Check-in.","RESERVATION FROM EXPEDIA +RATE $675.00+ TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT JUNE12/25 +OK MARIANA JUNE12/25",,Cancelled,2025-06-13 06:57:05, Angels View - Master Suite,Angels View - Standard Rate,675.0,843.75,0.0,0.0,0.0,0.0,0,0.0,0.0,843.75,0,2,0,0,1,,,0,843.75,false,"",false,0,168.75,Room 106,"" +SMP-2025092143435120,2025-09-20,Hacienda San Angel,Simple Booking,,John,Crowell,johncrowell@gmail.com,+14169306942,,,,,,Canada,"",2026-01-01,2026-01-05,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $810.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD MC CVV PENDING +CONFIRMATION SENT SEP20/2025 +OK MARIANA SEP20/2025",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3265.92,4082.4,0.0,0.0,0.0,0.0,0,0.0,0.0,4082.4,0,2,0,0,1,,,0,4082.4,false,"",false,0,816.48,Room 107,"" +LH25011345435462,2025-01-13,Hacienda San Angel,Extranet,,France,Bilodeau,ines@haciendasanangel.com,"",,,,,,Canada,,2026-01-02,2026-02-04,33,,"","",,Cancelled,2025-01-15 12:23:48, Celestial - Royal Suite,Celestial - Standard Rate,24240.0,21210.0,0.0,0.0,0.0,0.0,0,0.0,0.0,21210.0,0,2,0,0,1,,,0,21210.0,false,"",false,0,4242.0,Room 103,"" +SMP-2025071541861738,2025-07-15,Hacienda San Angel,Simple Booking,,Alana,ABBOTT,alana.h.abbott@gmail.com,+15735447574,,,,,,,"",2026-01-02,2026-01-08,6,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT JUL 15 // +RATE $ 631.40 USD + TAX // +NO PROMO // +CREDIT CAR INFO VISA CVV PENDING // +SECRET RATE // +SUITE SAN MIGUEL // +STAR ENE02- 08 2025 // +JUL152025GV",,Cancelled,2025-09-01 08:41:08, San Miguel - Presidential Suite,San Miguel - Standard Rate,3818.7,4773.38,0.0,0.0,0.0,0.0,0,0.0,0.0,4773.38,0,2,0,0,1,,,0,4773.38,false,"",false,0,954.675,Room 107,"" +LH25011545476052,2025-01-15,Hacienda San Angel,Extranet,,France,Bilodeau,fbilodeau264@outlook.com,4185694124,,"","","","",Canada,"",2026-01-03,2026-02-05,33,,"","Loyal Customer they will have a flat rate of 550 per night +15% off F&B +Paula & Ines +ANGEL RATE +NO CARGAR A LA TARJETA. + + +RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT JAN252025// +CREDIT CARD INFORMATION // +STAY JAN02-FEB042026 // +SUITE CELESTIAL // +SUBMITED JAN252025INES//",,Confirmed,"", Celestial - Royal Suite,Manual,18150.0,18150.0,0.0,0.0,0.0,0.0,0,0.0,0.0,18150.0,0,2,0,0,1,,,0,18150.0,false,"",false,0,4537.5,Room 103,"" +EXP-2287436446,2025-09-10,Hacienda San Angel,Expedia,,Tammy,Tomczyk,fmswxm7mtx@m.expediapartnercentral.com,1 3039199832,,,,,,,,2026-01-03,2026-01-08,5,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT SEP102025 // +CREDIT CARD INFORMATION OK // +RATE $ 496.80 USD + TAXES // +STAY JAN03-082026 // +SUITE ANGEL DOME // +SUBMITED SEP102025NGR//",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,2484.0,3105.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3105.0,0,2,0,0,1,,,0,3105.0,false,"",false,0,621.0,Room 113,"" +SMP-2025090743167201,2025-09-07,Hacienda San Angel,Simple Booking,,Fredrick,Campbell,fred@trac.vc,+14152353123,,,,,,,"",2026-01-05,2026-01-07,2,,Please confirm that balcony is private to our room.,,,Confirmed,"", Rincon de Angeles - Royal Suite,Manual,1310.4,1638.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1638.0,0,2,0,0,1,,,0,1638.0,false,"",false,0,327.6,Room 119,"" +BDC-6997692458,2025-06-21,Hacienda San Angel,Booking.com,,SIMON,GRIEVE,sgriev.759021@guest.booking.com,+1 562 852 5144,,,,.,,United States,"",2026-01-08,2026-01-11,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-01-06., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFORMATION SENT JUN21 // +RATE $ 750 USD + TAXES // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +SUITE SAN MIGUEL // +STAY ENE 09- 11 2026 // +NO PROMO // +JUN212025GV",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2115.0,2670.75,0.0,0.0,0.0,27.0,0,0.0,0.0,2670.75,0,2,0,0,1,,,0,2670.75,false,"",false,0,528.75,Room 107,"" +EXP-2285153404,2025-09-08,Hacienda San Angel,Expedia,,TAMRAH,NEIL,b6askxka9u@m.expediapartnercentral.com,86 021 60781960,,,,,,,,2026-01-08,2026-01-10,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 2 Double Beds, Non-Smoking, Remittance amount: 1,263.24, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""2 人免费饮料(每人每次住宿一份)""","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT SEP052025// +CREDIT CARD INFORMATION OK // +RATE $ 520 USD + TAXES // +STAY JAN08-102026 // +SUITE SA GABRIEL // +SUBMITED SEP072025NGR //",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Standard Rate,1044.0,1305.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1305.0,0,2,0,0,1,,,0,1305.0,false,"",false,0,261.0,Room 118,"" +SMP-2025090743181451,2025-09-07,Hacienda San Angel,Simple Booking,,Linda,Mendelson,lhmendelson@comcast.net,+18479223481,,,,,,,"",2026-01-12,2026-01-14,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $640.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SEND SEP07/2025 +OK MARIANA SEP07/2025",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1290.24,1612.8,0.0,0.0,0.0,0.0,0,0.0,0.0,1612.8,0,2,0,0,1,,,0,1612.8,false,"",false,0,322.56,Room 106,"" +SMP-2025091643343651,2025-09-16,Hacienda San Angel,Simple Booking,,Tom,Holliman,tahollim@gmail.com,+13604211544,,,,,,,"",2026-01-15,2026-01-19,4,,"",,,Cancelled,2025-09-18 21:13:22, Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1901.09,2376.36,0.0,0.0,0.0,0.0,0,0.0,0.0,2376.36,0,2,0,0,1,,,0,2376.36,false,"",false,0,475.2725,Room 109,"" +SMP-2025091643343685,2025-09-16,Hacienda San Angel,Simple Booking,,Kristine,Akopyan,kris.akopyan@gmail.com,+12063030239,,,,,,,"",2026-01-15,2026-01-19,4,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT SEP192025 // +CREDIT CARD INFORMATION PENDIENT CVV // +RATE $ 475.27 USD + TAXES // +STAY ENE15-192025 // +SUITE CROWN VIEW // +SUBMITED SEP192025NGR //",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,1901.09,2376.36,0.0,0.0,0.0,0.0,0,0.0,0.0,2376.36,0,2,0,0,1,,,0,2376.36,false,"",false,0,475.2725,Room 112,"" +EXP-2293159048,2025-09-19,Hacienda San Angel,Expedia,,THOMAS,HOLLIMAN,0697d9dr4o@m.expediapartnercentral.com,1 18662597766,,,,,,,,2026-01-15,2026-01-19,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 2,831.40, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION FROM EXPEDIA +RATE $585.00 + TAXES +NO PROMO +VIRTUAL CREDIT CARD OK +CONFIRMATION SENT SEP18/2025 +OK MARIANA SEP18/2025",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,2340.0,2925.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2925.0,0,2,0,0,1,,,0,2925.0,false,"",false,0,585.0,Room 122,"" +EXP-2297263106,2025-09-25,Hacienda San Angel,Expedia,,Angela,Kawalski,dwgabw6mqq@m.expediapartnercentral.com,1 9896009482,,,,,,,,2026-01-15,2026-01-19,4,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,874.96, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: 1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT SEP242025// +CREDIT CARD INFORMATION OK // +RATE $ 594 USD + TAXES // +STAY JAN15-192026 // +SUITE RINCÓN OF ANGELS // +SUBMITED SEP242025NGR //",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2376.0,2970.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2970.0,0,2,0,0,1,,,0,2970.0,false,"",false,0,594.0,Room 119,"" +EXP-X-398972475,2025-01-19,Hacienda San Angel,Expedia,,David,Levine,2ggqc2ryk7@m.expediapartnercentral.com,1 847 7788227,,,,,,,,2026-01-16,2026-01-18,2,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT ENE19 // +CREDIT CARD INFORMATION // +RATE $ 510.40 USD + TAXES // +SILVER DISCOUNT 10% // +SUITE ANGEL VIEW // +STAY ENE 16- 18 2025 // +ENE192025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1020.8,1276.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1276.0,0,2,0,0,1,,,0,1276.0,false,"",false,0,255.2,Room 106,"" +SMP-2025072642158618,2025-07-26,Hacienda San Angel,Simple Booking,,John,Nachbar,jnachbar@hotmail.com,+13106210017,,,,,,,"",2026-01-16,2026-01-18,2,,"","RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT JULY262025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 619.92 USD + TAXES // +STAY JAN16-182025 // +SUITE SAN MIGUEL // +SUBMITED JULY262025NGR //",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1239.84,1549.8,0.0,0.0,0.0,0.0,0,0.0,0.0,1549.8,0,2,0,0,1,,,0,1549.8,false,"",false,0,309.96,Room 107,"" +SMP-2025092043421910,2025-09-20,Hacienda San Angel,Simple Booking,,Sean,Bartmasser,bartmasser@gmail.com,+15107252219,,,,,,,"",2026-01-16,2026-01-19,3,,Its our 10 year wedding anniversary :),"RESERVATION FROM SIMPLE BOOKING +RATE $442.80 + TAXES +SECRET RATE +VISA CREDIT CARD CVV PENDING +CONFIRMATION SENT SEP19/2025 +OK MARIANA SEP19/2025 + + + +THEY CELEBRATE 10 WEDDING ANNIVERSARY",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,1339.03,1673.79,0.0,0.0,0.0,0.0,0,0.0,0.0,1673.79,0,2,0,0,1,,,0,1673.79,false,"",false,0,334.7575,Room 113,"" +SMP-2025032038913871,2025-03-20,Hacienda San Angel,Simple Booking,,Michel,Lavoie,allard-lavoie@outlook.com,+15144974742,,,,,,Canada,"",2026-01-19,2026-01-23,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR20 // +RATE $ 625.25 USD + TAX // +CREDIT CARD INFORMATION AMEX CVV PENDING // +STAY JAN 19-23 2026 // +SUITE SAN MIGUEL // +NO PROMO // +SECRET RATE // +MAR202025GV",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2501.01,3126.26,0.0,0.0,0.0,0.0,0,0.0,0.0,3126.26,0,2,0,0,1,,,0,3126.26,false,"",false,0,625.2525,Room 107,"" +BDC-6525582671,2025-08-30,Hacienda San Angel,Booking.com,,Michael,Palucki,mpaluc.519134@guest.booking.com,+1 925 876 3469,,,,.,,United States,"",2026-01-20,2026-01-23,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-01-18., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT SEP012025 // +CREDIT CARD INFORMATION OK // +RATE $ 518.40 USD + TAXES // +STAY JAN20-232026 // +SUITE ANGEL VIEW // +SUBMITED SEP012025NGR //",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1555.2,1944.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1944.0,0,2,0,0,1,,,0,1944.0,false,"",false,0,388.8,Room 106,"" +LH25100151283129,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Package Rate,2970.0,3712.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3712.5,1856.25,2,0,0,1,,,0,1856.25,false,"",false,0,742.5,Room 119,"" +LH25100151283135,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"", San Jose - Master Suite,San Jose - Package Rate,2925.0,3656.25,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3656.25,1828.12,2,0,0,1,,,0,1828.13,false,"",false,0,731.25,Room 122,"" +LH25100151283162,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Package Rate,2790.0,3487.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3487.5,1743.75,2,0,0,1,,,0,1743.75,false,"",false,0,697.5,Room 121,"" +LH25100151283170,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"", San Gabriel - Junior Suite,San Gabriel - Package Rate,2610.0,3262.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3262.5,1631.25,2,0,0,1,,,0,1631.25,false,"",false,0,652.5,Room 118,"" +LH25100151283173,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"", Milagros - Junior Suite,Milagros - Package Rate,2587.5,3234.38,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3234.38,1617.19,2,0,0,1,,,0,1617.19,false,"",false,0,646.875,Room 102,"" +LH25100151283206,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"",Crown View - Junior Suite,Crown View - Package Rate,2587.5,3234.38,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3234.38,1617.19,2,0,0,1,,,0,1617.19,false,"",false,0,646.875,Room 112,"" +LH25100151283222,2025-10-01,Hacienda San Angel,Extranet,,MYLES,OSTHEIMER,myles@bridge-data.com,20618.5678,,,,,,,,2026-01-22,2026-01-27,5,,"","Group reservation in 7 rooms total. + +This group are all guests of our neighbor on the corner who has stayed here in the past and has purchased a home at the end of the street next to the stairs.- Paula + +Mr. Myles Ostheimer will pay for all the rooms balance, please make a normal check in with their own credit card information for hold. NGR",,Confirmed,"",Serafin - Junior Suite,Serafin - Package Rate,2245.5,2806.88,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2806.88,1403.44,2,0,0,1,,,0,1403.44,false,"",false,0,561.375,Room 110,"" +LH25090150612706,2025-09-01,Hacienda San Angel,Extranet,,ANN,XANDERS,xandersann@gmail.com,513 604 8169,,,,,,,,2026-01-23,2026-02-04,12,,"","RESERVATION THRU DIRECT .COM // +CONFIRMATION SENT SEP012025 // +CREDIT CARD INFORMATION OK // +RATE $ 640 USD + TAXES // +STAY JAN23-FEB042026 // +SUITE ANGEL VIEW // +SUBMITED SEP012025NGR //",,Cancelled,2025-09-02 13:45:15, Angels View - Master Suite,Angels View - Standard Rate,7680.0,9600.0,0.0,0.0,0.0,0.0,0,0.0,0.0,9600.0,0,2,0,0,1,,,0,9600.0,false,"",false,0,1920.0,Room 106,"" +MMS-OBH25042718315508-2824615,2025-04-27,Hacienda San Angel,Mr and Mrs Smith,,Victor,Jarvis,VICJARVISTEAM@GMAIL.COM,,,,,,,,,2026-01-24,2026-01-26,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS.COM // +CONFIRMATION SENT APR272025 // +CREDIT CARD INFORMATION OK // +RATE $425.06 USD + TAXES // +STAY JAN24-262026 // +SUITE ANGEL DOME // +SUBMITED APR272025NGR//",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,850.13,929.83,0.0,0.0,0.0,-132.83,0,0.0,0.0,929.83,0,2,0,0,1,,,0,929.83,false,"",false,0,212.5325,Room 113,"" +SMP-2025072442083572,2025-07-23,Hacienda San Angel,Simple Booking,,mary ann,landry,malandry@rogers.com,+1416-505-4850,,,,,,Canada,"",2026-01-24,2026-01-29,5,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT JULY232025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 475.27 USD + TAXES // +STAY JAN24-292026 // +SUITE GARDEN OF ANGELS // +SUBMITED JULY232025NGR //",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,2376.36,2970.45,0.0,0.0,0.0,0.0,0,0.0,0.0,2970.45,0,2,0,0,1,,,0,2970.45,false,"",false,0,594.09,Room 109,"" +MMS-OBH25080203265302-2925240,2025-08-02,Hacienda San Angel,Mr and Mrs Smith,,Victor,Jarvis,VICJARVISTEAM@GMAIL.COM,,,,,,,,,2026-01-24,2026-01-27,3,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,,,Cancelled,2025-08-01 20:30:51,Serafin - Junior Suite,Serafin - Standard Rate,1277.33,1596.66,0.0,0.0,0.0,0.0,0,0.0,0.0,1596.66,0,2,0,0,1,,,0,1596.66,false,"",false,0,319.3325,"","" +SMP-2025090743180573,2025-09-07,Hacienda San Angel,Simple Booking,,scott,cherkasky,confuciusayah@mac.com,+13109807360,,,,,,,"",2026-01-26,2026-01-31,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $750.00 + TAXES +BEST AVAILABLE RATE +CREDIT CARD INFO MC CVV PENDING +CONFIRMATION SEND SEP07/2025 +OK MARIANA SEP07/2025",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3780.0,4725.0,0.0,0.0,0.0,0.0,0,0.0,0.0,4725.0,0,2,0,0,1,,,0,4725.0,false,"",false,0,945.0,Room 107,"" +BDC-4485339427,2025-02-17,Hacienda San Angel,Booking.com,,Gus,Platas,gplata.571996@guest.booking.com,+1 585 738 7773,,,,.,,United States,"",2026-01-27,2026-02-04,8,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-01-25., booker_is_genius +smoking preference: Non-Smoking","RESERVATION FROM BOOKING +RATE $416.14 +TAXES + NO PROMO +CREDIT CARD INFO +CINFIRMATION SENT FEB16/2025 +OK MARIANA FEB16/2025",,Cancelled,2025-02-19 23:28:46,Crown View - Junior Suite,Crown View - Standard Rate,3329.1,4161.38,0.0,0.0,0.0,0.0,0,0.0,0.0,4161.38,0,2,0,0,1,,,0,4161.38,false,"",false,0,832.275,Room 112,"" +BDC-6870718423,2025-06-28,Hacienda San Angel,Booking.com,,Elinor,Bryant,ebryan.168208@guest.booking.com,+1 778 839 4229,,,,.,,Canada,"",2026-01-27,2026-01-30,3,,"booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JUN28 // +CREDIT CARD INFORMATION OK VISA // +GENIUS DISCOUNT 10% // +SUITE SERAFIN // +STAY ENE 27- 30 2026 // +JUN282025GV",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,1215.0,1540.62,0.0,0.0,0.0,21.87,0,0.0,0.0,1540.62,0,2,0,0,1,,,0,1540.62,false,"",false,0,303.75,Room 110,"" +LH25030746590598,2025-03-07,Hacienda San Angel,Extranet,,Lynne,Frank,lyfrank@rogers.com,"",,,,,,,,2026-01-29,2026-02-08,10,,"","RESERVATION DIRECTLY +RATE $518.85 + TAXES +NO PROMO +CREIT CARD INFO MC OK +CONFIRMATION SENT MARCH07/2025 +OK MARIANA MARCH07/2025 + + +THIS RESERVATION WAS TAKE BY PAULA, CHECK EMAIL",,Cancelled,2025-04-27 15:20:03, Angels View - Master Suite,Angels View - Package Rate,5188.5,6485.63,0.0,0.0,0.0,0.0,0,0.0,0.0,6485.63,0,2,0,0,1,,,0,6485.63,false,"",false,0,1297.125,Room 106,"" +SMP-2025032038914054,2025-03-20,Hacienda San Angel,Simple Booking,,Michel,Lavoie,allard-lavoie@outlook.com,+15144974742,,,,,,Canada,"",2026-01-31,2026-02-02,2,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT MAR20 // +RATE $ 619.10 USD + TAX // +CREDIT CARD INFORMATION AMEX CVV PENDING // +STAY JAN 31- 02 FRB 2026 // +SUITE SAN MIGUEL // +NO PROMO // +SECRET RATE // +MAR202025GV",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1238.2,1547.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1547.75,0,2,0,0,1,,,0,1547.75,false,"",false,0,309.55,Room 107,"" +BDC-5930787943,2025-07-14,Hacienda San Angel,Booking.com,,Heather,Weaver,hweave.457249@guest.booking.com,+61 466 819 754,,,,,,Australia,"",2026-02-02,2026-02-06,4,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-01-31., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT JUL14 // +RATE $ 650 USD + TAX // +CREDIT VARD INFORMATION K VIRTUAL CARD FOR CHARGE // +NO PROMO // +SUITE SAN JOSE // +STAY FEB 02- 06 2026 // +JUL142025GV",,Cancelled,2025-07-19 18:44:32, San Jose - Master Suite,San Jose - Standard Rate,2600.0,3250.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3250.0,0,2,0,0,1,,,0,3250.0,false,"",false,0,650.0,Room 122,"" +SMP-2025020237854316,2025-02-02,Hacienda San Angel,Simple Booking,,Derek,Bang,derekbang@gmail.com,+13174965431,,,,,,,"",2026-02-04,2026-02-13,9,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT FEB022025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 697 USD + TAXES // +STAY FEB4-132026 // +SUITE SAN MIGUEL// +SUBMITED FAB022025NGR//",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,6273.0,7841.25,0.0,0.0,0.0,0.0,0,0.0,0.0,7841.25,0,2,0,0,1,,,0,7841.25,false,"",false,0,1568.25,Room 107,"" +SMP-2025051540220451,2025-05-15,Hacienda San Angel,Simple Booking,,Jim,Rod,jrod54r@gmail.com,+19084333684,,,,,,,"",2026-02-04,2026-02-08,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $471.50 + TAXES +SECRET RATE +CREDIT CARD VISA OK +CONFIRMATION SENT MAY15/2025 +OK MARIANA MAY15/25",,Confirmed,"",Crown View - Junior Suite,Crown View - Standard Rate,1886.02,2357.53,0.0,0.0,0.0,0.0,0,0.0,0.0,2357.53,0,2,0,0,1,,,0,2357.53,false,"",false,0,471.505,Room 112,"" +SMP-2025061140910719,2025-06-11,Hacienda San Angel,Simple Booking,,Mike,Jones,jones.mike126@gmail.com,+16083321103,,,,,,,"",2026-02-04,2026-02-08,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT JUN11 // +SECRET RATE // +RATE $ 512.5 USD +TAX // +NO PROMO // +CREDIT CARD INFORMATION MC CVV PENDING // +EXP VIP // +SUITE ANGEL VIEW // +STAY FEB 4- 2026 // +JUN112025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,2050.02,2562.53,0.0,0.0,0.0,0.0,0,0.0,0.0,2562.53,0,2,0,0,1,,,0,2562.53,false,"",false,0,512.505,Room 106,"" +SMP-2025080842512539,2025-08-08,Hacienda San Angel,Simple Booking,,Shane,Manning,shanemanning@mac.com,+17135645644,,,,,,,"",2026-02-12,2026-02-16,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT AGO08 // +CREDIT CARD INFO MASTERCARD, PENDING CVV // +RATE $ 553.50 USD + TAX // +NO PROMO // +SECRET RATE // +SUITE CELESTIAL // +STAY FEB 12- 16 2026 // +AGO082025GV",,Cancelled,2025-08-28 18:42:58, Celestial - Royal Suite,Celestial - Standard Rate,2231.71,2231.71,0.0,0.0,0.0,0.0,0,0.0,0.0,2231.71,0,2,0,0,1,,,0,2231.71,false,"",false,0,557.9275,Room 103,"" +EXP-X-417020841,2025-02-20,Hacienda San Angel,Expedia,,Mathew,van Vooght,mecvplqp69@m.expediapartnercentral.com,1 604 8179873,,,,,,,,2026-02-13,2026-02-16,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,325.75, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay",,,Cancelled,2025-02-28 03:17:01, San Miguel - Presidential Suite,San Miguel - Standard Rate,1922.1,2402.63,0.0,0.0,0.0,0.0,0,0.0,0.0,2402.63,0,2,0,0,1,,,0,2402.63,false,"",false,0,480.525,Room 107,"" +BDC-4525175876,2025-02-22,Hacienda San Angel,Booking.com,,Deb,Evans,devans.800981@guest.booking.com,+1 406 868 7723,,,,,,United States,"",2026-02-13,2026-02-16,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-02-11. +Approximate time of arrival: between 15:00 and 16:00, booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT FEB222025 // +CREDIT CARD INFORMATION OK // +RATE $522 USD + TAXES // +STAY FEB13-162026// +SUITE ANGEL VIEW// +SUBMITED FEB222025NGR//",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1566.0,1957.5,0.0,0.0,0.0,0.0,0,0.0,0.0,1957.5,0,2,0,0,1,,,0,1957.5,false,"",false,0,391.5,Room 106,"" +EXP-X-423606404,2025-03-01,Hacienda San Angel,Expedia,,Mathew,van Vooght,w3tq3tivne@m.expediapartnercentral.com,1 604 8179873,,,,,,,,2026-02-13,2026-02-16,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 2,273.72, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXP // +CONFIRMATION SENT MAR 02 2025 // +RATE $ 626.36 USD + TAXES // +NO PROMO // +CREDIT CARD INFORMATION OK VIRTUAL CARD FOR CHARGE // +GOLD DISCOUNT EXP 10% // +SUITE SAN MIGUEL // +STAY FEB 13- 16 2026 // +MAR022025GV",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1879.1,2348.88,0.0,0.0,0.0,0.0,0,0.0,0.0,2348.88,0,2,0,0,1,,,0,2348.88,false,"",false,0,469.775,Room 107,"" +EXP-2297545185,2025-09-25,Hacienda San Angel,Expedia,,Jeff,Swinoga,8queo1pofj@m.expediapartnercentral.com,1 4168160424,,,,,,,,2026-02-13,2026-02-15,2,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, Remittance amount: 1,437.48, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD 85 food and beverage credit per room, per stay,1 Free beverage per person for 2 (once per stay)","RESERVATION THRU EXP // +CONFIRMATION SENT SEP25 // +RATE $594 USD + TAX // +SUITE CELESTIAL // +STAY FEB 13- 15 2026 // +PROMOTION SILVER 10% // +SEP252025GV",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,1188.0,1485.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1485.0,0,2,0,0,1,,,0,1485.0,false,"",false,0,297.0,Room 103,"" +SMP-2025032739074162,2025-03-27,Hacienda San Angel,Simple Booking,,Adam,Connerton,aconny23@gmail.com,+13607974742,,,,,,,"",2026-02-16,2026-02-21,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $622.38 + TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT MARCH27/2025 +OK MARIANA MARCH27/2025",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3111.92,3889.9,0.0,0.0,0.0,0.0,0,0.0,0.0,3889.9,0,2,0,0,1,,,0,3889.9,false,"",false,0,777.98,Room 107,"" +SMP-2025030538548313,2025-03-05,Hacienda San Angel,Simple Booking,,Ann,McAndrew,Annmmcandrew@gmail.com,+14349601730,,,,,,,"",2026-02-17,2026-02-22,5,,"","RESERVATION FROM SIMPLE BOOKING +RATE $475.60 + TAXES +NO PROMO +VISA CREDIT CARD OK +CONFRIMATION SNET MARCH05/2025 +OK MARIANA MARCH05/2025",,Cancelled,2025-08-24 13:03:57, Angels View - Master Suite,Angels View - Standard Rate,2378.0,2972.5,0.0,0.0,0.0,0.0,0,0.0,0.0,2972.5,0,2,0,0,1,,,0,2972.5,false,"",false,0,594.5,Room 106,"" +SMP-2025090343082184,2025-09-03,Hacienda San Angel,Simple Booking,,Shannon,Roberson,smroberson84@yahoo.com,+13173190817,,,,,,,"",2026-02-18,2026-02-22,4,,"","RESERVATION FROM SIMPLE BOOKING +RATE $553.50 + TAXES +SECRET RATE +VISA CREIT CARD CVV PENDING +CONFIRMATION SENT SEPT02/2025 +OK MARIANA SEPT02/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,2231.71,2789.64,0.0,0.0,0.0,0.0,0,0.0,0.0,2789.64,0,2,0,0,1,,,0,2789.64,false,"",false,0,557.9275,Room 103,"" +SMP-2025090743177572,2025-09-07,Hacienda San Angel,Simple Booking,,Susan,Shrack,susan@shrack.net,+17199638699,,,,,,,"",2026-02-24,2026-02-27,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $524.80 + TAXES +SECRET RATE +VISA CREDIT CARD CVV PENDING +CONFIRMATION SENT SEPT09/2025 +OK MARIANA SEPT09/2025",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1587.0,1983.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1983.75,0,2,0,0,1,,,0,1983.75,false,"",false,0,396.75,Room 106,"" +SMP-2025092843568061,2025-09-28,Hacienda San Angel,Simple Booking,,Katie,Bilich,kmbilich@gmail.com,+19063706223,,,,,,,"",2026-02-24,2026-02-25,1,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT SEP282025 // +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 637.56 USD + TAXES // +STAY FEB24-252026 // +SUITE SAN MIGUEL & SAN JOSÉ // +SUBMITED SEP282025NGR//",,Confirmed,""," San Miguel - Presidential Suite, San Jose - Master Suite","San Miguel - Standard Rate,San Jose - Standard Rate",1275.12,1593.9,0.0,0.0,0.0,0.0,0,0.0,0.0,1593.9,0,4,0,0,2,,,0,1593.9,false,"",false,0,318.78,"Room 107, Room 122","" +SMP-2025093043602078,2025-09-30,Hacienda San Angel,Simple Booking,,Richard,Lawrence,nlaw767@gmail.com,+15017655188,,,,,,,"",2026-02-24,2026-02-28,4,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT SEP30 // +RATE $ 553.50 USD + TAX // +CREDIT CARD INFO VISA CVV PENDING // +SUITE CELESTIAL // +STAY FEV 24- 28 2026 // +NO PROMO // +SECRET RATE // +SEP302025GV",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,2231.71,2789.64,0.0,0.0,0.0,0.0,0,0.0,0.0,2789.64,0,2,0,0,1,,,0,2789.64,false,"",false,0,557.9275,Room 103,"" +BDC-6712817491,2025-08-30,Hacienda San Angel,Booking.com,,Daniel,Cameron,dcamer.235554@guest.booking.com,+1 612 799 1816,,,,.,,United States,"",2026-02-25,2026-02-28,3,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-02-23., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING .COM // +CONFIRMATION SENT AUG292025 // +CREDIT CARD INFORMATION OK // +RATE $ 675 USD + TAXES // +STAY FEB25-282026// +SUITE SAN MIGUEL // +SUBMITED AUG292025NGR//",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2025.0,2531.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2531.25,0,2,0,0,1,,,0,2531.25,false,"",false,0,506.25,Room 107,"" +BDC-5743188797,2025-08-06,Hacienda San Angel,Booking.com,,Andrea,Clark,aclark.833180@guest.booking.com,+1 703 850 3631,,,,.,,United States,"",2026-02-27,2026-03-05,6,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-02-25., booker_is_genius +smoking preference: Non-Smoking","RESERVATION TRHU BOOKING.COM // +CONFIRMATION SENT AGO 06 // +RATE $ 450 USD + TAX // +VIRTUAL CARD FOR CHARGE // +SUITE SERAFIN // +STAY FEB 27- MAR 05 2026 // +MOBIL APP DISCOUNT 10% // +AGO062025GV",,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,2700.0,3375.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3375.0,0,2,0,0,1,,,0,3375.0,false,"",false,0,675.0,Room 110,"" +EXP-X-429614605,2025-03-16,Hacienda San Angel,Expedia,,Robert,Vanbesien,9mmxb00pbv@m.expediapartnercentral.com,1 646 6515372,,,,,,,,2026-02-28,2026-03-07,7,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION FROM EXPEDIA VIP PREMIUM +RATE $516.00 + TAXES +$85.00 CREDIT ON FOOD & BEVERAGE // BOTTLE OR UPGRADE +CREDIT CARD AMEX OK +CONFIRMATION SENT MARCH16/2025 +OK MARIANA MARCH16/2025",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,3612.0,4515.0,0.0,0.0,0.0,0.0,0,0.0,0.0,4515.0,0,2,0,0,1,,,0,4515.0,false,"",false,0,903.0,Room 122,"" +EXP-2175324462,2025-04-12,Hacienda San Angel,Expedia,,Stuart,Emmrich,nuokep0bwb@m.expediapartnercentral.com,1 646 2834760,,,,,,,,2026-02-28,2026-03-04,4,,"Hotel Collect Booking, Hotel Collect Booking Collect Payment From Guest., Value Add Promotion: USD 85 food and beverage credit per room, per stay","RESERVATION THRU EXPEDIAPREMIUMVIP.COM // +CONFIRMATION SENT APR122025 // +CREDIT CARD INFORMATION OK // +RATE $ 516 USD + TAXES // +STAY FEB28-MAR042026 // +SUITE VISTA DE SANTOS // +SUBMITED APR122025NGR //",,Confirmed,"", Vista de Santos - Master Suite,Vista de Santos - Standard Rate,2064.0,2580.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2580.0,0,1,0,0,1,,,0,2580.0,false,"",false,0,516.0,Room 121,"" +SMP-2025060540727268,2025-06-04,Hacienda San Angel,Simple Booking,,Steve,Higgins,michael.p.ray@outlook.com,+13617391263,,,,,,Canada,"",2026-03-01,2026-03-07,6,,"","RESERVATION FROM SIMPLE BOOKING +RATE $725.00 + TAXES +NO PROMO +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JUNE 06/25 +OK MARIANA JUNE06/25",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,4350.0,5437.5,0.0,0.0,0.0,0.0,0,0.0,0.0,5437.5,0,2,0,0,1,,,0,5437.5,false,"",false,0,1087.5,Room 107,"" +MMS-OBH25082423315802-2948908,2025-08-24,Hacienda San Angel,Mr and Mrs Smith,,Jane,Teel,JANELTEEL@GMAIL.COM,,,,,,,,,2026-03-01,2026-03-03,2,,PriceInformation : Tax is included at 20%. Please note the hotel charges an additional service charge of 5% per room per night on check-out,"RESERVATION THRU MMS // +RATE $ 480.60USD + TAX // +VIRTUAL CARD FOR CHARGE // +NO PROMO // +SUITE ANGEL DOME // +STAY MAR 01- 03 2026 // +AGO242025GV",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,922.75,1009.26,0.0,0.0,0.0,-144.18,0,0.0,0.0,1009.26,0,2,0,0,1,,,0,1009.26,false,"",false,0,230.6875,Room 113,"" +SMP-2025091443319312,2025-09-14,Hacienda San Angel,Simple Booking,,Joseph,Chiarmonte,jchiarmonte@outlook.com,+17165100960,,,,,,,"",2026-03-03,2026-03-09,6,,"","RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT SEP 14 // +RATE $ 524.80 USD + TAX // +SECRET RATE // +SUITE ANGEL VIEW // +STAY MAR 03- 09 2026 // +CREDIT CARD AMEX PENDING CVV +SEP142025GV",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,3174.0,3967.5,0.0,0.0,0.0,0.0,0,0.0,0.0,3967.5,0,2,0,0,1,,,0,3967.5,false,"",false,0,793.5,Room 106,"" +SMP-2025100243627267,2025-10-01,Hacienda San Angel,Simple Booking,,Patricia,Seib,p.seib@comcast.net,+13602802525,,,,,,,"",2026-03-03,2026-03-11,8,,"","RESERVATION FROM SIMPLE BOOOKING +RATE $578.97 + TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT OCTOBER 1ST/2025 +OK MARIANA OCTOBER 1ST/2025",,Confirmed,"", Milagros - Junior Suite,Milagros - Standard Rate,4631.76,5789.7,0.0,0.0,0.0,0.0,0,0.0,0.0,5789.7,0,2,0,0,1,,,0,5789.7,false,"",false,0,1157.94,Room 102,"" +LH25031346711843,2025-03-13,Hacienda San Angel,Extranet,,GREG,KONECNY,gjkonecny@att.net,5208584925,,,,,,,,2026-03-07,2026-03-12,5,,"","RESERVATION MADE DIRECTLY +RATE $753.00 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT MARCH13/2025 +OK MARIANA MARCH13/2025",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3765.0,4706.25,0.0,0.0,0.0,0.0,0,0.0,0.0,4706.25,0,2,0,0,1,,,0,4706.25,false,"",false,0,941.25,Room 107,"" +LH25031346711881,2025-03-13,Hacienda San Angel,Extranet,,KENNEDY MARIE,WEZA,jkrain@wavecable.com,2533774555,,,,,,,,2026-03-07,2026-03-12,5,,"","RESERVATION MADE DIRECTLY +RATE $620.00 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT MARCH13/2025 +OK MARIANA MARCH13/2025",,Confirmed,"", Celestial - Royal Suite,Celestial - Standard Rate,3100.0,3875.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3875.0,0,2,0,0,1,,,0,3875.0,false,"",false,0,775.0,Room 103,"" +SMP-2025061040889744,2025-06-10,Hacienda San Angel,Simple Booking,,Steve,Higgins,michael.p.ray@outlook.com,+13617391263,,,,,,Canada,"",2026-03-07,2026-03-11,4,,"","SIMPLEBOOKING +JUN102025 +CVV PENDIENT +$700 USD + TAX +RINCON OF ANGELS +JUN102025NGR",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2800.0,3500.0,0.0,0.0,0.0,0.0,0,0.0,0.0,3500.0,0,2,0,0,1,,,0,3500.0,false,"",false,0,700.0,Room 119,"" +BDC-4990821803,2025-05-11,Hacienda San Angel,Booking.com,,NICOLAS,CHLEBUSCH,nchleb.204898@guest.booking.com,+49 203 5640799,,"30 08 Prudential Tower, 19 Cecil St",,bangkok,,Germany,N/A,2026-03-19,2026-03-24,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-03-17. +smoking preference: Non-Smoking","BOOKING.COM +MAY112025 +$721 USD + TAX +MAR19-242026 +CREDIT CARD OK +MAY112025NGR",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3605.0,4506.25,0.0,0.0,0.0,0.0,0,0.0,0.0,4506.25,0,2,0,0,1,,,0,4506.25,false,"",false,0,901.25,Room 107,"" +LH25091650944359,2025-09-16,Hacienda San Angel,Extranet,,Jennifer,Smith,jensmith@jcsmithenterprises.com,"",,,,,,,,2026-03-21,2026-03-22,1,,"Group Reservation for 11 rooms- deposit $3,979 usd paid to date",Details to follow in time- Paula,,Confirmed,"", Celestial - Royal Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 103,"" +SMP-2025093043608602,2025-09-30,Hacienda San Angel,Simple Booking,,Marah,Graham,marahgraham@shaw.ca,+14035102594,,,,,,Canada,"",2026-03-22,2026-03-25,3,,"","RESERVATION FROM SIMPLE BOOKING +RATE $529.00 USD +SECRET RATE +CREDIT CARD AMEX CVV PENDING +CONFIRMATION SENT SEP30/2025 +OK MARIANA SEP30/2025",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,1587.0,1983.75,0.0,0.0,0.0,0.0,0,0.0,0.0,1983.75,0,2,0,0,1,,,0,1983.75,false,"",false,0,396.75,Room 106,"" +LH25042747689074,2025-04-27,Hacienda San Angel,Extranet,,Lynne,Frank,lyfrank@rogers.com,"",,,,,,,,2026-03-25,2026-03-29,4,,,,,Cancelled,2025-04-28 14:25:58, San Miguel - Presidential Suite,San Miguel - Standard Rate,2890.0,3612.5,0.0,0.0,0.0,0.0,0,0.0,0.0,3612.5,0,2,0,0,1,,,0,3612.5,false,"",false,0,722.5,Room 107,"" +LH25042847709564,2025-04-28,Hacienda San Angel,Extranet,,Lynne,Frank,lyfrank@rogers.com,"",,,,,,,,2026-03-25,2026-03-29,4,,,,,Cancelled,2025-04-28 14:36:01, Angels View - Master Suite,Angels View - Standard Rate,2490.0,2801.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2801.25,0,2,0,0,1,,,0,2801.25,false,"",false,0,560.25,Room 106,"" +LH25042847709780,2025-04-28,Hacienda San Angel,Extranet,,Lynne,Frank,lyfrank@rogers.com,"",,,,,,,,2026-03-25,2026-03-29,4,,"","RESERVATION MADE DIRECTLY +RATE $ 518.25.00 + TAXES +NO PROMO +CREDIT CARD INFO PENDING +CONFIRMATION SENT APRIL28/25 +OK MARIANA APRIL 28/25",,Confirmed,"", Angels View - Master Suite,Manual,2073.0,2591.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2591.25,0,2,0,0,1,,,0,2591.25,false,"",false,0,518.25,Room 106,"" +LH25090950795635,2025-09-09,Hacienda San Angel,Extranet,,Hadrien,Derveaux,reservations@verana.com,33 6 10 71 29 30,,,,,,,,2026-03-27,2026-03-28,1,,"","CXC VERANA + + + +CONFIRMATION SENT SEP09/2025 +OK MARIANA SEP09/2025",,Confirmed,"", Milagros - Junior Suite,Manual,320.0,400.0,0.0,0.0,0.0,0.0,0,0.0,0.0,400.0,0,2,0,0,1,,,0,400.0,false,"",false,0,80.0,Room 102,"" +LH25013045802467,2025-01-30,Hacienda San Angel,Extranet,,France,Bilodeau,fbilodeau264@outlook.com,4185694124,,"","","","",Canada,"",2026-03-28,2026-04-25,28,,"","Loyal Customer they will have a flat rate of 550 per night +15% off F&B +Paula & Ines +ANGEL RATE +NO CARGAR A LA TARJETA. + + +RESERVATION THRU DIRECT.COM // +CONFIRMATION SENT JAN302025// +CREDIT CARD INFORMATION // +RATE $568 USD + TAXES // +SUITE CELESTIAL // +SUBMITED JAN302025INES//",,Confirmed,"", Celestial - Royal Suite,Manual,15400.0,15400.0,0.0,0.0,0.0,0.0,0,0.0,0.0,15400.0,0,2,0,0,1,,,0,15400.0,false,"",false,0,3850.0,Room 103,"" +SMP-2025061741065474,2025-06-17,Hacienda San Angel,Simple Booking,,Lindsey,Harris,lindsey.harris@kirkland.com,+16083479417,,,,,,,"",2026-03-31,2026-04-03,3,,"","REERVATION FROM SIMPLE BOOKING +RATE $590.40+ TAXES +SECRET RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT JUNE17/25 +OK MARIANA JUNE17/25",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1771.21,2214.01,0.0,0.0,0.0,0.0,0,0.0,0.0,2214.01,0,2,0,0,1,,,0,2214.01,false,"",false,0,442.8025,Room 107,"" +EXP-2297242275,2025-09-25,Hacienda San Angel,Expedia,,LUKE,PENNIG,gxxp35p81b@m.expediapartnercentral.com,1 18662597766,,,,,,,,2026-03-31,2026-04-03,3,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, Remittance amount: 1,824.09, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT SEP242025 // +CREDIT CARD INFORMATION OK // +RATE $ 502.50 USD + TAXES // +STAY MAR31-ABR032025 // +SUITE GARDEN OF ANGELS // +SUBMITED SEP242025NGR //",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1507.5,1884.38,0.0,0.0,0.0,0.0,0,0.0,0.0,1884.38,0,2,0,0,1,,,0,1884.38,false,"",false,0,376.875,Room 109,"" +SMP-2025072942235040,2025-07-29,Hacienda San Angel,Simple Booking,,Ruth,Haney,ruthhaney@gmail.com,+12069998086,,,,,,,"",2026-04-04,2026-04-11,7,,"","RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT JULY2920265// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 592.17 USD + TAXES // +STAY APR04-112026 // +SUITE SAN MIGUEL // +SUBMITED JULY292025NGR //",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,4145.2,5181.5,0.0,0.0,0.0,0.0,0,0.0,0.0,5181.5,0,2,0,0,1,,,0,5181.5,false,"",false,0,1036.3,Room 107,"" +SMP-2025040639285028,2025-04-06,Hacienda San Angel,Simple Booking,,Bradd,Chisholm,Bschisholm@charter.net,+19895256020,,,,,,,"",2026-04-11,2026-04-13,2,,will be a 70th Birthday celebration. Will make additional arrangements after 1/1/2026,"RESERVATION THRU SIMPLEBOOKING .COM // +CONFIRMATION SENT APR052025 // +CREDIT CARD INFORMATION PENDIENT // +RATE $ 850 USD + TAXES // +STAY APR11-132026 // +SUITE SAN MIGUEL// +SUBMITED APR052025NGR//",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,1700.0,2125.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2125.0,0,2,0,0,1,,,0,2125.0,false,"",false,0,425.0,Room 107,"" +SMP-2025093043590691,2025-09-30,Hacienda San Angel,Simple Booking,,Junko,Chessen,junkochessen@gmail.com,+14156998853,,,,,,,"",2026-04-12,2026-04-14,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $856.80 + TAXES +SERENITY PACKAGE +VISA CREDIT CARD CVV PENDING +CONFIRMATION SENT SEP29/2025 +OK MARIANA SEP29/2025 + + +TWO 60 MIN MASSAGE +1MANICURE, 1 PEDICURE +$50.000 CREDIT IN THE RESTAURANT.",,Cancelled,2025-09-30 20:35:37, San Jose - Master Suite,San Jose - Standard Rate,1713.6,2142.0,0.0,0.0,0.0,0.0,0,0.0,0.0,2142.0,0,2,0,0,1,,,0,2142.0,false,"",false,0,428.4,Room 122,"" +SMP-2025100143609547,2025-10-01,Hacienda San Angel,Simple Booking,,Junko,Chessen,junkochessen@gmail.com,+14156998853,,,,,,,"",2026-04-12,2026-04-14,2,,"","RESERVATION FROM SIMPLE BOOKING +RATE $594.72 + TAXES +BEST AVAILABLE RATE +CREDIT CARD VISA CVV PENDING +CONFIRMATION SENT SEP30/2025 +OK MARIANA SEP30/2025",,Confirmed,"", San Jose - Master Suite,San Jose - Standard Rate,1189.44,1486.8,0.0,0.0,0.0,0.0,0,0.0,0.0,1486.8,0,2,0,0,1,,,0,1486.8,false,"",false,0,297.36,Room 122,"" +LH25081050098678,2025-08-10,Hacienda San Angel,Extranet,,Atwell,Goins,coxranch@yahoo.com,9032291714,,,,,,United States of America,75110,2026-04-21,2026-04-25,4,,"","RESERVATION DIRECTLY +RATE $586.25 + TAXES +NO PROMO + CREDIT CARD VISA CVV OK +CONFIRMATION SENT AUG10/2025 +OK MARIANA AUG10/2025",,Confirmed,"", Rincon de Angeles - Royal Suite,Rincon de Angeles - Standard Rate,2345.0,2931.25,0.0,0.0,0.0,0.0,0,0.0,0.0,2931.25,0,2,0,0,1,,,0,2931.25,false,"",false,0,586.25,Room 119,"" +LH25042847710019,2025-04-28,Hacienda San Angel,Extranet,,CHRISTIAN,LUDWIG,info@haciendasanangel.com,12397912914,,,,United States of America,,United States of America,"",2026-04-25,2026-04-28,3,,"",PAID RESERVATION FOR NO SHOW ON APRIL 27 TO MAY 04 2025,,Cancelled,2025-05-03 11:01:18, San Miguel - Presidential Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,"" +LH25051948172014,2025-05-19,Hacienda San Angel,Extranet,,CHRISTIAN,LUDWIG,chris-ludwig@att.net,2397912914,,,,,,,,2026-04-25,2026-05-02,7,,"","RESERVATION DIRECTLY +THIS IS A CREDIT FOR CANCELLATION LH25042847710019 OK PAULA +ORIGINAL RESERVATION WAS $6157.47 VS THIS ONE $5,987.50 THE CREDIT COVER THE ENTIRE STAY +ONLY WILL PAY EXTRAS +OK MARIANA MAY19/2025",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,4790.0,0.0,0.0,0.0,0.0,-5987.5,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,"" +SMP-2025082642908098,2025-08-26,Hacienda San Angel,Simple Booking,,Brian,Carbonneau,bscarbaec@gmail.com,+14045692581,,,,,,,"",2026-05-02,2026-05-09,7,,"","RESERVATION FROM SIMPLE BOOKING +RATE $358.46+ TAXES +SECRET RATE +CREDIT CARD MS CVV PENDING +CONFIRMATION SENT AUG25/2025 +OK MARIANA AUG25/2025",,Confirmed,"",Angels Dome - Junior Suite,Angels Dome - Standard Rate,2529.28,3161.6,0.0,0.0,0.0,0.0,0,0.0,0.0,3161.6,0,2,0,0,1,,,0,3161.6,false,"",false,0,632.32,Room 113,"" +EXP-2299703088,2025-09-28,Hacienda San Angel,Expedia,,Nathan,Holstrom,"",1 5157778996,,,,,,,,2026-05-03,2026-05-08,5,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 King Bed, Non-Smoking, My Girlfriend and I will be celebrating recently being engaged. Any special accommodations would be greatly appreciated!, Remittance amount: 3,297.25, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: ""1 Free beverage per person for 2 (once per stay)""","RESERVATION THRU EXPEDIA.COM // +CONFIRMATION SENT SEP282025 // +CREDIT CARD INFORMATION OK // +RATE $ 545 USD + TAXES // +STAY MAY03-082026 // +SUITE ANGEL VIEW // +SUBMITED SEP282025NGR //",,Confirmed,"", Angels View - Master Suite,Angels View - Standard Rate,2725.0,3406.25,0.0,0.0,0.0,0.0,0,0.0,0.0,3406.25,0,2,0,0,1,,,0,3406.25,false,"",false,0,681.25,Room 106,"" +SMP-2025092343469476,2025-09-22,Hacienda San Angel,Simple Booking,,SALLY,YEATES,sally@yeates.net.au,+61411501896,,,,,,Australia,"",2026-05-31,2026-06-06,6,,"","RESERVATION THRU SIMPLEBOOKING.COM // +CONFIRMATION SENT SEP222025// +CREDIT CARD INFORMATION CVV PENDIENT // +RATE $ 530.04 USD + TAXES // +STAY MAY31-JUN062026 // +SUITE SAN MIGUEL // +SUBMITED SEP22202NGR //",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,3180.24,3975.3,0.0,0.0,0.0,0.0,0,0.0,0.0,3975.3,0,2,0,0,1,,,0,3975.3,false,"",false,0,795.06,Room 107,"" +LH25092951238738,2025-09-29,Hacienda San Angel,Extranet,,ELLEN,TOSCANO,ellentoscano@gmail.com,(415) 314-7844,,,,,,,,2026-06-08,2026-06-11,3,,"","RESERVATION USING GIFT CERTIFICATE +VOUCHER HSA07112024-NGR (MENTIS) +INCLUDES A COUPLE'S MASSAGE AND DINNER FOR 2 +CONFIRMATION SENT SEP29/2025 +OK MARIANA SEP29/2025",,Confirmed,"", San Miguel - Presidential Suite,Manual,0.0,0.0,0.0,0.0,0.0,0.0,0,0.0,0.0,0.0,0,2,0,0,1,,,0,0.0,false,"",false,0,0,Room 107,"" +LH25092951238762,2025-09-29,Hacienda San Angel,Extranet,,ELLEN,TOSCANO,ellentoscano@gmail.com,(415) 314-7844,,,,,,,,2026-06-11,2026-06-12,1,,"","RESERVATION DIRECTLY +RATE $500.00 + TAXES +NO PROMO +CREDIT CARD VISA OK +CONFIRMATION SENT SEP29/2025 +OK MARIANA SEP29/2025 + +ANNIVERSARY",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,500.0,625.0,0.0,0.0,0.0,0.0,0,0.0,0.0,625.0,0,2,0,0,1,,,0,625.0,false,"",false,0,125.0,Room 107,"" +SMP-2025080342363570,2025-08-03,Hacienda San Angel,Simple Booking,,Danielle,Olson,Danielleolson97@gmail.com,+17022870939,,,,,,,"",2026-07-19,2026-07-25,6,,We will be celebrating our honeymoon! :),"RESERVATION FROM SIMPLEBOOKING // +CONFIRMATION SENT AGO 03 // +CREDIT CARD INFORMATION MASTERCARD CVV PENDING // +RATE 4 470.82 USD + TAX // +NO PORMO // +SECRET RATE // +SUITE SAN MIGUEL // +STAY JUL 19- 25 2026 // +AGO032025GV",,Confirmed,"", San Miguel - Presidential Suite,San Miguel - Standard Rate,2847.5,3559.38,0.0,0.0,0.0,0.0,0,0.0,0.0,3559.38,0,2,0,0,1,,,0,3559.38,false,"",false,0,711.875,Room 107,"" +EXP-2304213506,2025-10-05,Hacienda San Angel,Expedia,,CAROLINE,POON,qi3s3we97m@m.expediapartnercentral.com,0 0 61412285028,,,,,,,,2026-08-06,2026-08-12,6,,"Payment Method: VirtualCard, Remittance Model: Gross, Expedia Collect Booking, 1 Queen Bed, Non-Smoking, Remittance amount: 2,164.59, Expedia Virtual Card will be activated from the day of Check-in., Value Add Promotion: USD85 food and beverage credit per room, per stay|1 Free beverage per person for 2 (once per stay)",,,Confirmed,"",Serafin - Junior Suite,Serafin - Standard Rate,1788.9,2236.13,0.0,0.0,0.0,0.0,0,0.0,0.0,2236.13,0,2,0,0,1,,,0,2236.13,false,"",false,0,447.225,Room 110,"" +BDC-5361730657,2025-10-04,Hacienda San Angel,Booking.com,,David,Keif,dkeif.800466@guest.booking.com,+1 310 397 5882,,,,.,,United States,"",2026-08-24,2026-08-29,5,,"You've received a virtual credit card for this reservation.You can charge it as of 2026-08-22., booker_is_genius +smoking preference: Non-Smoking","RESERVATION THRU BOOKING.COM // +CONFIRMATION SENT OCT42025 // +CREDIT CARD INFORMATION OK // +RATE $ 259.20 USD + TAXES // +STAY AUG24-292025 // +SUITE GARDEN OF ANGELS // +SUBMITED OCT042025NGR //",,Confirmed,"", Garden of Angels - Junior Suite,Garden of Angels - Standard Rate,1296.0,1620.0,0.0,0.0,0.0,0.0,0,0.0,0.0,1620.0,0,2,0,0,1,,,0,1620.0,false,"",false,0,324.0,Room 109,"" +LH25042447624579,2025-04-24,Hacienda San Angel,Extranet,,France,Bilodeau,fbilodeau264@outlook.com,4185694124,,"","","","",Canada,"",2027-01-02,2027-01-30,28,,"","",,Confirmed,"", Celestial - Royal Suite,Manual,15400.0,15400.0,0.0,0.0,0.0,0.0,0,0.0,0.0,15400.0,0,2,0,0,1,,,0,15400.0,false,"",false,0,3850.0,Room 103,"" diff --git a/backend/hotel_hacienda/src/routes/auth.routes.js b/backend/hotel_hacienda/src/routes/auth.routes.js new file mode 100644 index 0000000..757ffda --- /dev/null +++ b/backend/hotel_hacienda/src/routes/auth.routes.js @@ -0,0 +1,11 @@ +const express = require('express'); +const router = express.Router(); +const authController = require('../controllers/auth.controller'); +const { loginValidator } = require('../middlewares/validators'); +const handleValidation = require('../middlewares/handleValidation'); + +router.post('/login',loginValidator, handleValidation, authController.login); +router.post('/createuser',authController.createuser); +router.post('/recoverpass',authController.passRecover); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/contract.routes.js b/backend/hotel_hacienda/src/routes/contract.routes.js new file mode 100644 index 0000000..ee9254c --- /dev/null +++ b/backend/hotel_hacienda/src/routes/contract.routes.js @@ -0,0 +1,16 @@ +const express = require('express'); +const router = express.Router(); +const contractController = require('../controllers/contract.controller'); + +router.get('/', contractController.getContracts); +router.get('/getinfocontract/:id', contractController.getContract); +router.get('/neartoend', contractController.neartoend); +router.get('/positions', contractController.getpositions); +router.get('/areas', contractController.getareas); +router.get('/bosses', contractController.getbosses); +router.get('/reportempcontract', contractController.reportEmployeeContract); +router.get('/disabledcontract', contractController.disabledcontracts); + +router.post('/newcontract',contractController.newContract); +router.put('/updatecontract/:id', contractController.updateContract); +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/employee.routes.js b/backend/hotel_hacienda/src/routes/employee.routes.js new file mode 100644 index 0000000..37ac5a3 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/employee.routes.js @@ -0,0 +1,14 @@ +const express = require('express'); +const router = express.Router(); +const employeeController = require('../controllers/employee.controller'); + +router.get('/', employeeController.getEmployees); +router.get('/activeEmployees',employeeController.getTotalActiveEmployees); +router.get('/getattendance',employeeController.getattendance); +router.get('/gradeofstudy',employeeController.getGradeOfStudy); +router.get('/relationship',employeeController.getRelationshipEmployee); +router.post('/employee',employeeController.getEmployee); +router.post('/newemployee',employeeController.newEmployee); +router.post('/updateemployee',employeeController.updateEmployee); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/exchange.routes.js b/backend/hotel_hacienda/src/routes/exchange.routes.js new file mode 100644 index 0000000..c14eaa8 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/exchange.routes.js @@ -0,0 +1,8 @@ +const express = require('express'); +const router = express.Router(); +const exchangeRouter = require('../controllers/exchange.controller'); + +router.post('/consultexchange',exchangeRouter.consultExchange ); +router.get('/getexchanges',exchangeRouter.getExchange ); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/expense.routes.js b/backend/hotel_hacienda/src/routes/expense.routes.js new file mode 100644 index 0000000..bdbca74 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/expense.routes.js @@ -0,0 +1,20 @@ +const express = require('express'); +const router = express.Router(); +const expenseController = require('../controllers/expense.controller'); + + +router.get('/pendingapproval', expenseController.getPendingAppExpenses); +router.get('/approvedexpenses', expenseController.getApprovedAppExpenses); +router.get('/rejectedexpenses', expenseController.getRejectedappExpenses); +router.get('/mainsupplier',expenseController.mainSupplier); +router.put('/getexpense/:id',expenseController.getExpense); +router.get('/getinfo', expenseController.getInfoExpense); +router.get('/reportexpenses', expenseController.getReportExpenses); +router.post('/countpending',expenseController.countpending); +router.get('/reportpayments',expenseController.getReportPayments); +router.get('/monthlypayments',expenseController.getmonthlypayments); +router.post('/newexpense',expenseController.newExpense); +router.post('/totalapproved', expenseController.getTotalApproved); +router.put('/updateexpense/:id',expenseController.updateExpense); +router.get('/gettaxes',expenseController.getTaxes); +module.exports = router; diff --git a/backend/hotel_hacienda/src/routes/hotelpl.routes.js b/backend/hotel_hacienda/src/routes/hotelpl.routes.js new file mode 100644 index 0000000..daaca29 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/hotelpl.routes.js @@ -0,0 +1,14 @@ +const express = require('express'); +const router = express.Router(); +const hotelControllers = require('../controllers/hotelp.controller'); + +router.post('/cogs', hotelControllers.cogs); +router.post('/ebitda', hotelControllers.ebitda); +router.post('/employeeshare', hotelControllers.employeeshare); +router.post('/grossprofit', hotelControllers.grossprofit); +router.post('/tips', hotelControllers.tips); +router.post('/totalrevenue', hotelControllers.totalrevenue); +router.post('/weightedCategoriesCost', hotelControllers.weightedCategoriesCost); + + +module.exports = router; diff --git a/backend/hotel_hacienda/src/routes/incomehrx.routes.js b/backend/hotel_hacienda/src/routes/incomehrx.routes.js new file mode 100644 index 0000000..e2162e8 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/incomehrx.routes.js @@ -0,0 +1,25 @@ +const express = require('express'); +const router = express.Router(); +const incomeController = require('../controllers/incomehrx.controller'); + +router.get('/accountincome', incomeController.getAccountIncome); +router.get('/categoryincome', incomeController.getCategoryIncome); +router.get('/invoiceIncome', incomeController.getInvoiceIncome); +router.get('/totalIncome', incomeController.getTotalIncome); +router.get('/incomehorux', incomeController.getIncomeHorux); +router.get('/oneincomehorux/:id', incomeController.getOneIncome); +router.get('/stripedata/', incomeController.getstripeservice); +router.post('/stripedatademo/', incomeController.addDemostripeData); +router.post('/insertinvoice', incomeController.addfacturas); +router.post('/newincome', incomeController.newIncome); +router.put('/updateincome/:id', incomeController.updateIncome); + + + + + + + + + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/incomes.routes.js b/backend/hotel_hacienda/src/routes/incomes.routes.js new file mode 100644 index 0000000..8cff3d5 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/incomes.routes.js @@ -0,0 +1,34 @@ +const express = require('express'); +const router = express.Router(); +const incomeController = require('../controllers/incomes.controller'); + + +router.post('/getincomes',incomeController.getincomes); +router.post('/totalincomes',incomeController.totalincomes); +router.post('/channelscards',incomeController.channelscards); +router.post('/loadincomes',incomeController.loadincomes); +router.post('/loadproductsales',incomeController.loadsoftrestaurant); +router.post('/loadchequesdetalle',incomeController.loadChequesDetalle); +router.post('/reportincomes',incomeController.reportIncomes); +router.post('/countticket',incomeController.countFolios); +router.post('/efectivo',incomeController.sumaEfectivo); +router.post('/otros',incomeController.sumaOtros); +router.post('/propinas',incomeController.sumaPropinas); +router.post('/tarjeta',incomeController.sumaTarjeta); +router.post('/vales',incomeController.sumaVales); +router.post('/sumatotal',incomeController.sumasTotales); +router.post('/ticketpromedio',incomeController.ticketPromedio); + + + + + + + + + + +router.get('/getproductsales',incomeController.getSoftRestaurant); +router.get('/getdetallecheque',incomeController.getdetallecheques); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/mail.routes.js b/backend/hotel_hacienda/src/routes/mail.routes.js new file mode 100644 index 0000000..659c804 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/mail.routes.js @@ -0,0 +1,12 @@ +const express = require('express'); +const router = express.Router(); +const emailController = require('../controllers/mail.controller'); + +router.post('/nearexpiring', emailController.contractsNearToEnd); +router.post('/paymentdelay', emailController.paymentDeadLine); +router.post('/expensesneartodeadline', emailController.expensesNearToDeadline); +router.post('/expensesspecial',emailController.expensesspecial); +router.post('/birthdays',emailController.emailbirthday); +router.post('/contractexpired',emailController.expiredcontracts); +router.post('/expiredcontractsmonth',emailController.expiredContractsMonth); +module.exports = router; diff --git a/backend/hotel_hacienda/src/routes/payment.routes.js b/backend/hotel_hacienda/src/routes/payment.routes.js new file mode 100644 index 0000000..3a22aac --- /dev/null +++ b/backend/hotel_hacienda/src/routes/payment.routes.js @@ -0,0 +1,11 @@ +const express = require('express'); +const router = express.Router(); +const paymentController = require('../controllers/payment.controller'); + +router.post('/newexpmonthly', paymentController.newMonthlyExpense); +router.get('/refreshmonthly',paymentController.refreshMonthlyExpenses); +router.put('/paymentstatusmonthly/:id', paymentController.setPaymentStatusMonthly); +router.put('/updateexpmonthly/:id',paymentController.updateMonthlyExpense); +router.get('/onemothlyexpense/:id', paymentController.getOneMonthly); +router.put('/needtorefresh/:id', paymentController.needtorefresh); +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/product.routes.js b/backend/hotel_hacienda/src/routes/product.routes.js new file mode 100644 index 0000000..a5f406d --- /dev/null +++ b/backend/hotel_hacienda/src/routes/product.routes.js @@ -0,0 +1,27 @@ +const express = require('express'); +const router = express.Router(); +const productController = require('../controllers/product.controller'); +const { route } = require('./contract.routes'); + +router.get('/', productController.getproductsdisplay); +router.get('/productcategory', productController.getcategoryproducts); +router.get('/producttype', productController.gettypeproduct); +router.get('/suppliers',productController.getsuppliers); +router.get('/gdiscardproducts',productController.getdiscardproduct); +router.get('/reportinventory',productController.reportInventory); +router.get('/stockadjusment',productController.getstockadjusments); +router.get('/gethousekeeper',productController.getHouseKeeper); +router.get('/getproducts',productController.getproducts); +router.get('/getconsumptionstockreport',productController.getConsumptionStockReport); + +router.post('/newsupplier',productController.newsupplier); +router.post('/newproduct',productController.newproduct); +router.post('/stockadjusmentset',productController.setstockadjusments); +router.post('/newconsumptionstock',productController.newConsumptionStock); +router.post('/disableSupplier',productController.disabledSupplier); + +router.put('/update_product/:id',productController.updateproduct); +router.put('/discardproduct/:id',productController.discardProduct); +router.put('/product/:id',productController.getproduct); +router.put('updatesupplier/:id',productController.updateSupplier); +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/purchase.routes.js b/backend/hotel_hacienda/src/routes/purchase.routes.js new file mode 100644 index 0000000..35a0375 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/purchase.routes.js @@ -0,0 +1,10 @@ +const express = require('express'); +const router = express.Router(); +const purchaseController = require('../controllers/purchase.controller'); + + + +router.get('/getpurchases',purchaseController.getpurchases); +router.put('/entry/:id',purchaseController.purchaseid); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/reportcontract.routes.js b/backend/hotel_hacienda/src/routes/reportcontract.routes.js new file mode 100644 index 0000000..80d6a00 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/reportcontract.routes.js @@ -0,0 +1,7 @@ +const express = require('express'); +const router = express.Router(); +const reportContractController = require('../controllers/reportcontract.controller'); + +router.get('/', reportContractController.getReportContracts); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/restaurantpl.routes.js b/backend/hotel_hacienda/src/routes/restaurantpl.routes.js new file mode 100644 index 0000000..658825e --- /dev/null +++ b/backend/hotel_hacienda/src/routes/restaurantpl.routes.js @@ -0,0 +1,12 @@ +const express = require('express'); +const router = express.Router(); +const restaurantControllers = require('../controllers/restaurantpl.controller'); + +router.post('/cogs', restaurantControllers.cogs); +router.post('/ebitda', restaurantControllers.ebitda); +router.post('/grossprofit', restaurantControllers.grossprofit); +router.post('/totalrevenue', restaurantControllers.totalrevenue); +router.post('/weightedCategoriesCost', restaurantControllers.weightedCategoriesCost); + + +module.exports = router; diff --git a/backend/hotel_hacienda/src/routes/settings.routes.js b/backend/hotel_hacienda/src/routes/settings.routes.js new file mode 100644 index 0000000..fc05187 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/settings.routes.js @@ -0,0 +1,16 @@ +const express = require('express'); +const router = express.Router(); +const settingsController = require('../controllers/settings.controller'); + + +router.post('/newroom', settingsController.addNewRoom); +router.post('/newproperty', settingsController.addNewProperty); +router.get('/reportrooms', settingsController.reportRoom); +router.get('/reportproperties', settingsController.reportProperties); +router.get('/approveby', settingsController.getapproveby); +router.get('/requestby', settingsController.getrequestby); +router.get('/categoryexpense', settingsController.getcategoryexpense); +router.get('/currency', settingsController.getcurrency); +router.get('/units', settingsController.getunits); +router.get('/recurrence', settingsController.getrecurrence); +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/routes/status.routes.js b/backend/hotel_hacienda/src/routes/status.routes.js new file mode 100644 index 0000000..cd74aa7 --- /dev/null +++ b/backend/hotel_hacienda/src/routes/status.routes.js @@ -0,0 +1,12 @@ +const express = require('express'); +const router = express.Router(); +const statusController = require('../controllers/status.controller'); + + +router.put('/approveupdate/:id',statusController.setapprovalstatus); +router.put('/paymentupdate/:id',statusController.setpaymentstatus); +router.get('/penapppayments',statusController.pendingAppPayments); +router.get('/countdelaypay',statusController.countDelayPayments); +router.get('/totalspent',statusController.totalSpent); + +module.exports = router; \ No newline at end of file diff --git a/backend/hotel_hacienda/src/server.js b/backend/hotel_hacienda/src/server.js new file mode 100644 index 0000000..1693f8f --- /dev/null +++ b/backend/hotel_hacienda/src/server.js @@ -0,0 +1,7 @@ +require('dotenv').config(); +const app = require('./app.js'); // Importamos la app +const PORT = process.env.PORT || 3000; + +app.listen(PORT, () => { + console.log(`Servidor corriendo en http://localhost:${PORT}`); +}); \ No newline at end of file diff --git a/backend/hotel_hacienda/src/services/mailService.js b/backend/hotel_hacienda/src/services/mailService.js new file mode 100644 index 0000000..3c2fc51 --- /dev/null +++ b/backend/hotel_hacienda/src/services/mailService.js @@ -0,0 +1,13 @@ +const nodemailer = require('nodemailer'); + +const transporter = nodemailer.createTransport({ + host: process.env.EMAIL_HOST, + port: process.env.EMAIL_PORT, + secure: false, + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS, + }, +}); + +module.exports = transporter; \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7045d73 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,57 @@ +version: "3.9" + +services: + postgres: + image: postgres:15 + container_name: postgres_db + restart: always + ports: + - "5432:5432" + environment: + POSTGRES_USER: oposgres + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: haciendasanangel + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U oposgres"] + interval: 10s + timeout: 5s + retries: 5 + + backend: + build: ./backend + container_name: backend_app + restart: always + ports: + - "4000:4000" + environment: + PORT: 4000 + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: oposgres + DB_PASSWORD: ${POSTGRES_PASSWORD} + DB_NAME: haciendasanangel + EMAIL_HOST: smtp-relay.brevo.com + EMAIL_PORT: 587 + EMAIL_USER: ${EMAIL_USER} + EMAIL_PASS: ${EMAIL_PASS} + URL_CORS: https://hotel.consultoria-as.com + BANXICO_TOKEN: ${BANXICO_TOKEN} + depends_on: + postgres: + condition: service_healthy + + frontend: + build: ./frontend + container_name: frontend_app + restart: always + ports: + - "5172:5172" + environment: + VITE_API_BASE_URL: http://backend:4000/api + depends_on: + - backend + +volumes: + postgres_data: diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..14a2f34 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,35 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copiar archivos de dependencias +COPY Frontend-Hotel/package*.json ./ + +# Instalar dependencias +RUN npm ci + +# Copiar codigo fuente +COPY Frontend-Hotel/ ./ + +# Construir la aplicacion +RUN npm run build + +# Etapa de produccion +FROM node:20-alpine + +WORKDIR /app + +# Copiar archivos de dependencias +COPY Frontend-Hotel/package*.json ./ + +# Instalar dependencias +RUN npm ci + +# Copiar codigo fuente +COPY Frontend-Hotel/ ./ + +# Exponer puerto +EXPOSE 5172 + +# Comando de inicio (modo desarrollo para hot reload) +CMD ["npm", "run", "dev"] diff --git a/frontend/Frontend-Hotel/.env.example b/frontend/Frontend-Hotel/.env.example new file mode 100644 index 0000000..eac0e25 --- /dev/null +++ b/frontend/Frontend-Hotel/.env.example @@ -0,0 +1 @@ +VITE_API_BASE_URL=http://localhost:4000/api diff --git a/frontend/Frontend-Hotel/.github/copilot-instructions.md b/frontend/Frontend-Hotel/.github/copilot-instructions.md new file mode 100644 index 0000000..8607d51 --- /dev/null +++ b/frontend/Frontend-Hotel/.github/copilot-instructions.md @@ -0,0 +1,44 @@ +# Copilot Instructions for AI Coding Agents + +## Project Overview +- This is a React (Vite) frontend for a hotel management system. +- Main app entry: `src/main.jsx`, root component: `src/App.jsx`. +- Pages are in `src/pages/` (e.g., `Dashboard.jsx`, `LoginPage.jsx`, `Employees.jsx`). +- Reusable UI components are in `src/components/` (e.g., `Navbar/`, `Sidebar.jsx`, `Modals/`, `Table/`). +- Service modules for API calls are in `src/services/` (e.g., `api.js`, `employeeService.js`). +- Styles are in `src/styles/` and component subfolders. + +## Architecture & Patterns +- **Routing**: Managed in `src/routes/ProtectedRoute.jsx` and page components. +- **State**: Local state via React hooks; no global state manager detected. +- **API**: All backend communication is abstracted in `src/services/`. +- **Component Structure**: Prefer functional components and hooks. Group related files (JSX, CSS) in subfolders. +- **UI**: Uses Tailwind CSS (see `tailwind.config.cjs`), with custom styles in `src/styles/` and per-component CSS files. + +## Developer Workflows +- **Start dev server**: `npm run dev` (Vite) +- **Build for production**: `npm run build` +- **Preview production build**: `npm run preview` +- **Install dependencies**: `npm install` +- **Lint**: `npm run lint` (uses `eslint.config.js`) +- **No test scripts or test files detected** + +## Conventions & Tips +- **Component Naming**: PascalCase for components, camelCase for files/variables. +- **Pages vs Components**: Pages in `src/pages/`, reusable elements in `src/components/`. +- **Service Layer**: All API logic should go in `src/services/`, not in components. +- **Assets**: Place images/icons in `public/` or `src/assets/`. +- **Modals, Tables, Filters**: Use the subfolders in `src/components/` as templates for new UI patterns. +- **Protected Routes**: Use `src/routes/ProtectedRoute.jsx` for auth-guarded navigation. + +## Integration Points +- **API Base URL**: Likely configured via `.env` (not shown here). +- **External Libraries**: React, Vite, Tailwind CSS, ESLint. + +## Examples +- To add a new page: create a file in `src/pages/`, add a route, and (if needed) update navigation in `Sidebar.jsx` or `Navbar.jsx`. +- To add a new API call: add a function in the relevant `src/services/*.js` file and import it in your component/page. + +--- + +For questions about unclear patterns or missing documentation, ask the user for clarification or examples from their workflow. \ No newline at end of file diff --git a/frontend/Frontend-Hotel/.gitignore b/frontend/Frontend-Hotel/.gitignore new file mode 100644 index 0000000..da6e18a --- /dev/null +++ b/frontend/Frontend-Hotel/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.env +.env.git diff --git a/frontend/Frontend-Hotel/eslint.config.js b/frontend/Frontend-Hotel/eslint.config.js new file mode 100644 index 0000000..cee1e2c --- /dev/null +++ b/frontend/Frontend-Hotel/eslint.config.js @@ -0,0 +1,29 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{js,jsx}'], + extends: [ + js.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], + }, + }, +]) diff --git a/frontend/Frontend-Hotel/index.html b/frontend/Frontend-Hotel/index.html new file mode 100644 index 0000000..0c1c9c8 --- /dev/null +++ b/frontend/Frontend-Hotel/index.html @@ -0,0 +1,14 @@ + + + + + + + + Hacienda San Angel + + +
    + + + diff --git a/frontend/Frontend-Hotel/package-lock.json b/frontend/Frontend-Hotel/package-lock.json new file mode 100644 index 0000000..b0ee15d --- /dev/null +++ b/frontend/Frontend-Hotel/package-lock.json @@ -0,0 +1,5994 @@ +{ + "name": "frontend-hotel-js", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend-hotel-js", + "version": "0.0.0", + "dependencies": { + "@hookform/resolvers": "^5.2.2", + "axios": "^1.11.0", + "bootstrap": "^5.3.8", + "multer": "^2.0.2", + "prop-types": "^15.8.1", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-hook-form": "^7.66.1", + "react-icons": "^5.5.0", + "react-router-dom": "^7.8.2", + "xlsx": "^0.18.5", + "yup": "^1.7.1" + }, + "devDependencies": { + "@eslint/js": "^9.33.0", + "@types/react": "^19.1.10", + "@types/react-dom": "^19.1.7", + "@vitejs/plugin-react-swc": "^4.0.0", + "autoprefixer": "^10.4.21", + "eslint": "^9.34.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "postcss": "^8.5.6", + "prettier": "^3.6.2", + "tailwindcss": "^4.1.13", + "vite": "^7.1.2", + "vite-plugin-svgr": "^4.5.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@hookform/resolvers": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", + "integrity": "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==", + "license": "MIT", + "dependencies": { + "@standard-schema/utils": "^0.3.0" + }, + "peerDependencies": { + "react-hook-form": "^7.55.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz", + "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@swc/core": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.3.tgz", + "integrity": "sha512-Qd8eBPkUFL4eAONgGjycZXj1jFCBW8Fd+xF0PzdTlBCWQIV1xnUT7B93wUANtW3KGjl3TRcOyxwSx/u/jyKw/Q==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.25" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.15.3", + "@swc/core-darwin-x64": "1.15.3", + "@swc/core-linux-arm-gnueabihf": "1.15.3", + "@swc/core-linux-arm64-gnu": "1.15.3", + "@swc/core-linux-arm64-musl": "1.15.3", + "@swc/core-linux-x64-gnu": "1.15.3", + "@swc/core-linux-x64-musl": "1.15.3", + "@swc/core-win32-arm64-msvc": "1.15.3", + "@swc/core-win32-ia32-msvc": "1.15.3", + "@swc/core-win32-x64-msvc": "1.15.3" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.3.tgz", + "integrity": "sha512-AXfeQn0CvcQ4cndlIshETx6jrAM45oeUrK8YeEY6oUZU/qzz0Id0CyvlEywxkWVC81Ajpd8TQQ1fW5yx6zQWkQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.3.tgz", + "integrity": "sha512-p68OeCz1ui+MZYG4wmfJGvcsAcFYb6Sl25H9TxWl+GkBgmNimIiRdnypK9nBGlqMZAcxngNPtnG3kEMNnvoJ2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.3.tgz", + "integrity": "sha512-Nuj5iF4JteFgwrai97mUX+xUOl+rQRHqTvnvHMATL/l9xE6/TJfPBpd3hk/PVpClMXG3Uvk1MxUFOEzM1JrMYg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.3.tgz", + "integrity": "sha512-2Nc/s8jE6mW2EjXWxO/lyQuLKShcmTrym2LRf5Ayp3ICEMX6HwFqB1EzDhwoMa2DcUgmnZIalesq2lG3krrUNw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.3.tgz", + "integrity": "sha512-j4SJniZ/qaZ5g8op+p1G9K1z22s/EYGg1UXIb3+Cg4nsxEpF5uSIGEE4mHUfA70L0BR9wKT2QF/zv3vkhfpX4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.3.tgz", + "integrity": "sha512-aKttAZnz8YB1VJwPQZtyU8Uk0BfMP63iDMkvjhJzRZVgySmqt/apWSdnoIcZlUoGheBrcqbMC17GGUmur7OT5A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.3.tgz", + "integrity": "sha512-oe8FctPu1gnUsdtGJRO2rvOUIkkIIaHqsO9xxN0bTR7dFTlPTGi2Fhk1tnvXeyAvCPxLIcwD8phzKg6wLv9yug==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.3.tgz", + "integrity": "sha512-L9AjzP2ZQ/Xh58e0lTRMLvEDrcJpR7GwZqAtIeNLcTK7JVE+QineSyHp0kLkO1rttCHyCy0U74kDTj0dRz6raA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.3.tgz", + "integrity": "sha512-B8UtogMzErUPDWUoKONSVBdsgKYd58rRyv2sHJWKOIMCHfZ22FVXICR4O/VwIYtlnZ7ahERcjayBHDlBZpR0aw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.3.tgz", + "integrity": "sha512-SpZKMR9QBTecHeqpzJdYEfgw30Oo8b/Xl6rjSzBt1g0ZsXyy60KLXrp6IagQyfTYqNYE/caDvwtF2FPn7pomog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", + "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", + "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react-swc": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.2.2.tgz", + "integrity": "sha512-x+rE6tsxq/gxrEJN3Nv3dIV60lFflPj94c90b+NNo6n1QV1QQUTLoL0MpaOVasUZ0zqVBn7ead1B5ecx1JAGfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.47", + "@swc/core": "^1.13.5" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4 || ^5 || ^6 || ^7" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", + "integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bootstrap": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz", + "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz", + "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.3" + } + }, + "node_modules/react-hook-form": { + "version": "7.68.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.68.0.tgz", + "integrity": "sha512-oNN3fjrZ/Xo40SWlHf1yCjlMK417JxoSJVUXQjGdvdRCU07NTFei1i1f8ApUAts+IVh14e4EdakeLEA+BEAs/Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-router": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.10.1.tgz", + "integrity": "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.10.1.tgz", + "integrity": "sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw==", + "license": "MIT", + "dependencies": { + "react-router": "7.10.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tailwindcss": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-svgr": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", + "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.2.0", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": ">=2.6.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", + "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + } + } +} diff --git a/frontend/Frontend-Hotel/package.json b/frontend/Frontend-Hotel/package.json new file mode 100644 index 0000000..63fb9b7 --- /dev/null +++ b/frontend/Frontend-Hotel/package.json @@ -0,0 +1,44 @@ +{ + "name": "frontend-hotel-js", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@hookform/resolvers": "^5.2.2", + "axios": "^1.11.0", + "bootstrap": "^5.3.8", + "multer": "^2.0.2", + "prop-types": "^15.8.1", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-hook-form": "^7.66.1", + "react-icons": "^5.5.0", + "react-router-dom": "^7.8.2", + "xlsx": "^0.18.5", + "yup": "^1.7.1" + }, + "devDependencies": { + "@eslint/js": "^9.33.0", + "@types/react": "^19.1.10", + "@types/react-dom": "^19.1.7", + "@vitejs/plugin-react-swc": "^4.0.0", + "autoprefixer": "^10.4.21", + "eslint": "^9.34.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "postcss": "^8.5.6", + "prettier": "^3.6.2", + "tailwindcss": "^4.1.13", + "vite": "^7.1.2", + "vite-plugin-svgr": "^4.5.0" + } +} diff --git a/frontend/Frontend-Hotel/pnpm-lock.yaml b/frontend/Frontend-Hotel/pnpm-lock.yaml new file mode 100644 index 0000000..3e72697 --- /dev/null +++ b/frontend/Frontend-Hotel/pnpm-lock.yaml @@ -0,0 +1,3751 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@hookform/resolvers': + specifier: ^5.2.2 + version: 5.2.2(react-hook-form@7.66.1(react@19.2.0)) + axios: + specifier: ^1.11.0 + version: 1.13.2 + bootstrap: + specifier: ^5.3.8 + version: 5.3.8(@popperjs/core@2.11.8) + multer: + specifier: ^2.0.2 + version: 2.0.2 + prop-types: + specifier: ^15.8.1 + version: 15.8.1 + react: + specifier: ^19.1.1 + version: 19.2.0 + react-dom: + specifier: ^19.1.1 + version: 19.2.0(react@19.2.0) + react-hook-form: + specifier: ^7.66.1 + version: 7.66.1(react@19.2.0) + react-icons: + specifier: ^5.5.0 + version: 5.5.0(react@19.2.0) + react-router-dom: + specifier: ^7.8.2 + version: 7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + xlsx: + specifier: ^0.18.5 + version: 0.18.5 + yup: + specifier: ^1.7.1 + version: 1.7.1 + devDependencies: + '@eslint/js': + specifier: ^9.33.0 + version: 9.39.1 + '@types/react': + specifier: ^19.1.10 + version: 19.2.6 + '@types/react-dom': + specifier: ^19.1.7 + version: 19.2.3(@types/react@19.2.6) + '@vitejs/plugin-react-swc': + specifier: ^4.0.0 + version: 4.2.2(vite@7.2.4) + autoprefixer: + specifier: ^10.4.21 + version: 10.4.22(postcss@8.5.6) + eslint: + specifier: ^9.34.0 + version: 9.39.1 + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@9.39.1) + eslint-plugin-react: + specifier: ^7.37.5 + version: 7.37.5(eslint@9.39.1) + eslint-plugin-react-hooks: + specifier: ^5.2.0 + version: 5.2.0(eslint@9.39.1) + eslint-plugin-react-refresh: + specifier: ^0.4.20 + version: 0.4.24(eslint@9.39.1) + globals: + specifier: ^16.3.0 + version: 16.5.0 + postcss: + specifier: ^8.5.6 + version: 8.5.6 + prettier: + specifier: ^3.6.2 + version: 3.6.2 + tailwindcss: + specifier: ^4.1.13 + version: 4.1.17 + vite: + specifier: ^7.1.2 + version: 7.2.4 + vite-plugin-svgr: + specifier: ^4.5.0 + version: 4.5.0(rollup@4.53.3)(vite@7.2.4) + +packages: + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@hookform/resolvers@5.2.2': + resolution: {integrity: sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==} + peerDependencies: + react-hook-form: ^7.55.0 + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + '@rolldown/pluginutils@1.0.0-beta.47': + resolution: {integrity: sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==} + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.53.3': + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.53.3': + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.53.3': + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.53.3': + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.53.3': + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.53.3': + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.53.3': + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.53.3': + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.53.3': + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.53.3': + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.53.3': + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.53.3': + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.53.3': + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openharmony-arm64@4.53.3': + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.53.3': + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.53.3': + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.53.3': + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.53.3': + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + cpu: [x64] + os: [win32] + + '@standard-schema/utils@0.3.0': + resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} + + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': + resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0': + resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0': + resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0': + resolution: {integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-svg-dynamic-title@8.0.0': + resolution: {integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-svg-em-dimensions@8.0.0': + resolution: {integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-transform-react-native-svg@8.1.0': + resolution: {integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-transform-svg-component@8.0.0': + resolution: {integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==} + engines: {node: '>=12'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-preset@8.1.0': + resolution: {integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/core@8.1.0': + resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==} + engines: {node: '>=14'} + + '@svgr/hast-util-to-babel-ast@8.0.0': + resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==} + engines: {node: '>=14'} + + '@svgr/plugin-jsx@8.1.0': + resolution: {integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==} + engines: {node: '>=14'} + peerDependencies: + '@svgr/core': '*' + + '@swc/core-darwin-arm64@1.15.3': + resolution: {integrity: sha512-AXfeQn0CvcQ4cndlIshETx6jrAM45oeUrK8YeEY6oUZU/qzz0Id0CyvlEywxkWVC81Ajpd8TQQ1fW5yx6zQWkQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.15.3': + resolution: {integrity: sha512-p68OeCz1ui+MZYG4wmfJGvcsAcFYb6Sl25H9TxWl+GkBgmNimIiRdnypK9nBGlqMZAcxngNPtnG3kEMNnvoJ2A==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.15.3': + resolution: {integrity: sha512-Nuj5iF4JteFgwrai97mUX+xUOl+rQRHqTvnvHMATL/l9xE6/TJfPBpd3hk/PVpClMXG3Uvk1MxUFOEzM1JrMYg==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.15.3': + resolution: {integrity: sha512-2Nc/s8jE6mW2EjXWxO/lyQuLKShcmTrym2LRf5Ayp3ICEMX6HwFqB1EzDhwoMa2DcUgmnZIalesq2lG3krrUNw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.15.3': + resolution: {integrity: sha512-j4SJniZ/qaZ5g8op+p1G9K1z22s/EYGg1UXIb3+Cg4nsxEpF5uSIGEE4mHUfA70L0BR9wKT2QF/zv3vkhfpX4g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-x64-gnu@1.15.3': + resolution: {integrity: sha512-aKttAZnz8YB1VJwPQZtyU8Uk0BfMP63iDMkvjhJzRZVgySmqt/apWSdnoIcZlUoGheBrcqbMC17GGUmur7OT5A==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.15.3': + resolution: {integrity: sha512-oe8FctPu1gnUsdtGJRO2rvOUIkkIIaHqsO9xxN0bTR7dFTlPTGi2Fhk1tnvXeyAvCPxLIcwD8phzKg6wLv9yug==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.15.3': + resolution: {integrity: sha512-L9AjzP2ZQ/Xh58e0lTRMLvEDrcJpR7GwZqAtIeNLcTK7JVE+QineSyHp0kLkO1rttCHyCy0U74kDTj0dRz6raA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.15.3': + resolution: {integrity: sha512-B8UtogMzErUPDWUoKONSVBdsgKYd58rRyv2sHJWKOIMCHfZ22FVXICR4O/VwIYtlnZ7ahERcjayBHDlBZpR0aw==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.15.3': + resolution: {integrity: sha512-SpZKMR9QBTecHeqpzJdYEfgw30Oo8b/Xl6rjSzBt1g0ZsXyy60KLXrp6IagQyfTYqNYE/caDvwtF2FPn7pomog==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.15.3': + resolution: {integrity: sha512-Qd8eBPkUFL4eAONgGjycZXj1jFCBW8Fd+xF0PzdTlBCWQIV1xnUT7B93wUANtW3KGjl3TRcOyxwSx/u/jyKw/Q==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/types@0.1.25': + resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.6': + resolution: {integrity: sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==} + + '@vitejs/plugin-react-swc@4.2.2': + resolution: {integrity: sha512-x+rE6tsxq/gxrEJN3Nv3dIV60lFflPj94c90b+NNo6n1QV1QQUTLoL0MpaOVasUZ0zqVBn7ead1B5ecx1JAGfA==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4 || ^5 || ^6 || ^7 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + append-field@1.0.0: + resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + autoprefixer@10.4.22: + resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + baseline-browser-mapping@2.8.30: + resolution: {integrity: sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==} + hasBin: true + + bootstrap@5.3.8: + resolution: {integrity: sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==} + peerDependencies: + '@popperjs/core': ^2.11.8 + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + browserslist@4.28.0: + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001756: + resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} + + cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.259: + resolution: {integrity: sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-refresh@0.4.24: + resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==} + peerDependencies: + eslint: '>=8.40' + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multer@2.0.2: + resolution: {integrity: sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==} + engines: {node: '>= 10.16.0'} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} + peerDependencies: + react: ^19.2.0 + + react-hook-form@7.66.1: + resolution: {integrity: sha512-2KnjpgG2Rhbi+CIiIBQQ9Df6sMGH5ExNyFl4Hw9qO7pIqMBR8Bvu9RQyjl3JM4vehzCh9soiNUM/xYMswb2EiA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + + react-icons@5.5.0: + resolution: {integrity: sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==} + peerDependencies: + react: '*' + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-router-dom@7.9.6: + resolution: {integrity: sha512-2MkC2XSXq6HjGcihnx1s0DBWQETI4mlis4Ux7YTLvP67xnGxCvq+BcCQSO81qQHVUTM1V53tl4iVVaY5sReCOA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.9.6: + resolution: {integrity: sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + rollup@4.53.3: + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-parser@2.0.4: + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + + tailwindcss@4.1.17: + resolution: {integrity: sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==} + + tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-plugin-svgr@4.5.0: + resolution: {integrity: sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==} + peerDependencies: + vite: '>=2.6.0' + + vite@7.2.4: + resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + word@0.3.0: + resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} + engines: {node: '>=0.8'} + + xlsx@0.18.5: + resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} + engines: {node: '>=0.8'} + hasBin: true + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yup@1.7.1: + resolution: {integrity: sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==} + +snapshots: + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.5': {} + + '@babel/core@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.0 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + + '@babel/traverse@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + dependencies: + eslint: 9.39.1 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.1': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@hookform/resolvers@5.2.2(react-hook-form@7.66.1(react@19.2.0))': + dependencies: + '@standard-schema/utils': 0.3.0 + react-hook-form: 7.66.1(react@19.2.0) + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@popperjs/core@2.11.8': {} + + '@rolldown/pluginutils@1.0.0-beta.47': {} + + '@rollup/pluginutils@5.3.0(rollup@4.53.3)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.53.3 + + '@rollup/rollup-android-arm-eabi@4.53.3': + optional: true + + '@rollup/rollup-android-arm64@4.53.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.53.3': + optional: true + + '@rollup/rollup-darwin-x64@4.53.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.53.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.53.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.53.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.53.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.53.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.53.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.53.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.53.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.53.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.53.3': + optional: true + + '@standard-schema/utils@0.3.0': {} + + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + + '@svgr/babel-preset@8.1.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.28.5) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.28.5) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.28.5) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.28.5) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.28.5) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.28.5) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.28.5) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.28.5) + + '@svgr/core@8.1.0': + dependencies: + '@babel/core': 7.28.5 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.5) + camelcase: 6.3.0 + cosmiconfig: 8.3.6 + snake-case: 3.0.4 + transitivePeerDependencies: + - supports-color + - typescript + + '@svgr/hast-util-to-babel-ast@8.0.0': + dependencies: + '@babel/types': 7.28.5 + entities: 4.5.0 + + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0)': + dependencies: + '@babel/core': 7.28.5 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.5) + '@svgr/core': 8.1.0 + '@svgr/hast-util-to-babel-ast': 8.0.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + + '@swc/core-darwin-arm64@1.15.3': + optional: true + + '@swc/core-darwin-x64@1.15.3': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.15.3': + optional: true + + '@swc/core-linux-arm64-gnu@1.15.3': + optional: true + + '@swc/core-linux-arm64-musl@1.15.3': + optional: true + + '@swc/core-linux-x64-gnu@1.15.3': + optional: true + + '@swc/core-linux-x64-musl@1.15.3': + optional: true + + '@swc/core-win32-arm64-msvc@1.15.3': + optional: true + + '@swc/core-win32-ia32-msvc@1.15.3': + optional: true + + '@swc/core-win32-x64-msvc@1.15.3': + optional: true + + '@swc/core@1.15.3': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.25 + optionalDependencies: + '@swc/core-darwin-arm64': 1.15.3 + '@swc/core-darwin-x64': 1.15.3 + '@swc/core-linux-arm-gnueabihf': 1.15.3 + '@swc/core-linux-arm64-gnu': 1.15.3 + '@swc/core-linux-arm64-musl': 1.15.3 + '@swc/core-linux-x64-gnu': 1.15.3 + '@swc/core-linux-x64-musl': 1.15.3 + '@swc/core-win32-arm64-msvc': 1.15.3 + '@swc/core-win32-ia32-msvc': 1.15.3 + '@swc/core-win32-x64-msvc': 1.15.3 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.25': + dependencies: + '@swc/counter': 0.1.3 + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/react-dom@19.2.3(@types/react@19.2.6)': + dependencies: + '@types/react': 19.2.6 + + '@types/react@19.2.6': + dependencies: + csstype: 3.2.3 + + '@vitejs/plugin-react-swc@4.2.2(vite@7.2.4)': + dependencies: + '@rolldown/pluginutils': 1.0.0-beta.47 + '@swc/core': 1.15.3 + vite: 7.2.4 + transitivePeerDependencies: + - '@swc/helpers' + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + adler-32@1.3.1: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + append-field@1.0.0: {} + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + async-function@1.0.0: {} + + asynckit@0.4.0: {} + + autoprefixer@10.4.22(postcss@8.5.6): + dependencies: + browserslist: 4.28.0 + caniuse-lite: 1.0.30001756 + fraction.js: 5.3.4 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + baseline-browser-mapping@2.8.30: {} + + bootstrap@5.3.8(@popperjs/core@2.11.8): + dependencies: + '@popperjs/core': 2.11.8 + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + browserslist@4.28.0: + dependencies: + baseline-browser-mapping: 2.8.30 + caniuse-lite: 1.0.30001756 + electron-to-chromium: 1.5.259 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.28.0) + + buffer-from@1.1.2: {} + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001756: {} + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + codepage@1.15.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + concat-map@0.0.1: {} + + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + typedarray: 0.0.6 + + convert-source-map@2.0.0: {} + + cookie@1.0.2: {} + + cosmiconfig@8.3.6: + dependencies: + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + path-type: 4.0.0 + + crc-32@1.2.2: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delayed-stream@1.0.0: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.259: {} + + entities@4.5.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.24.0: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@10.1.8(eslint@9.39.1): + dependencies: + eslint: 9.39.1 + + eslint-plugin-react-hooks@5.2.0(eslint@9.39.1): + dependencies: + eslint: 9.39.1 + + eslint-plugin-react-refresh@0.4.24(eslint@9.39.1): + dependencies: + eslint: 9.39.1 + + eslint-plugin-react@7.37.5(eslint@9.39.1): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.39.1 + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.39.1: + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.39.1 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + follow-redirects@1.15.11: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + frac@1.1.2: {} + + fraction.js@5.3.4: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@16.5.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + gopd@1.2.0: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + ignore@5.3.2: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lines-and-columns@1.2.4: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimist@1.2.8: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + ms@2.1.3: {} + + multer@2.0.2: + dependencies: + append-field: 1.0.0 + busboy: 1.6.0 + concat-stream: 2.0.0 + mkdirp: 0.5.6 + object-assign: 4.1.1 + type-is: 1.6.18 + xtend: 4.0.2 + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-releases@2.0.27: {} + + normalize-range@0.1.2: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-type@4.0.0: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + possible-typed-array-names@1.1.0: {} + + postcss-value-parser@4.2.0: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@3.6.2: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + property-expr@2.0.6: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + react-dom@19.2.0(react@19.2.0): + dependencies: + react: 19.2.0 + scheduler: 0.27.0 + + react-hook-form@7.66.1(react@19.2.0): + dependencies: + react: 19.2.0 + + react-icons@5.5.0(react@19.2.0): + dependencies: + react: 19.2.0 + + react-is@16.13.1: {} + + react-router-dom@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-router: 7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + + react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + cookie: 1.0.2 + react: 19.2.0 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.2.0(react@19.2.0) + + react@19.2.0: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + resolve-from@4.0.0: {} + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rollup@4.53.3: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.53.3 + '@rollup/rollup-android-arm64': 4.53.3 + '@rollup/rollup-darwin-arm64': 4.53.3 + '@rollup/rollup-darwin-x64': 4.53.3 + '@rollup/rollup-freebsd-arm64': 4.53.3 + '@rollup/rollup-freebsd-x64': 4.53.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 + '@rollup/rollup-linux-arm-musleabihf': 4.53.3 + '@rollup/rollup-linux-arm64-gnu': 4.53.3 + '@rollup/rollup-linux-arm64-musl': 4.53.3 + '@rollup/rollup-linux-loong64-gnu': 4.53.3 + '@rollup/rollup-linux-ppc64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-musl': 4.53.3 + '@rollup/rollup-linux-s390x-gnu': 4.53.3 + '@rollup/rollup-linux-x64-gnu': 4.53.3 + '@rollup/rollup-linux-x64-musl': 4.53.3 + '@rollup/rollup-openharmony-arm64': 4.53.3 + '@rollup/rollup-win32-arm64-msvc': 4.53.3 + '@rollup/rollup-win32-ia32-msvc': 4.53.3 + '@rollup/rollup-win32-x64-gnu': 4.53.3 + '@rollup/rollup-win32-x64-msvc': 4.53.3 + fsevents: 2.3.3 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + set-cookie-parser@2.7.2: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + snake-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + source-map-js@1.2.1: {} + + ssf@0.11.2: + dependencies: + frac: 1.1.2 + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + streamsearch@1.1.0: {} + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-parser@2.0.4: {} + + tailwindcss@4.1.17: {} + + tiny-case@1.0.3: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + toposort@2.0.2: {} + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@2.19.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray@0.0.6: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + update-browserslist-db@1.1.4(browserslist@4.28.0): + dependencies: + browserslist: 4.28.0 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + vite-plugin-svgr@4.5.0(rollup@4.53.3)(vite@7.2.4): + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.53.3) + '@svgr/core': 8.1.0 + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0) + vite: 7.2.4 + transitivePeerDependencies: + - rollup + - supports-color + - typescript + + vite@7.2.4: + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.53.3 + tinyglobby: 0.2.15 + optionalDependencies: + fsevents: 2.3.3 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wmf@1.0.2: {} + + word-wrap@1.2.5: {} + + word@0.3.0: {} + + xlsx@0.18.5: + dependencies: + adler-32: 1.3.1 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + + xtend@4.0.2: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + yup@1.7.1: + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 diff --git a/frontend/Frontend-Hotel/postcss-config.js b/frontend/Frontend-Hotel/postcss-config.js new file mode 100644 index 0000000..8567b4c --- /dev/null +++ b/frontend/Frontend-Hotel/postcss-config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; \ No newline at end of file diff --git a/frontend/Frontend-Hotel/public/IconoHotel.svg b/frontend/Frontend-Hotel/public/IconoHotel.svg new file mode 100644 index 0000000..8a2086d --- /dev/null +++ b/frontend/Frontend-Hotel/public/IconoHotel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/Frontend-Hotel/public/icono-svg.svg b/frontend/Frontend-Hotel/public/icono-svg.svg new file mode 100644 index 0000000..ea21c7a --- /dev/null +++ b/frontend/Frontend-Hotel/public/icono-svg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/Frontend-Hotel/public/logoHotel.png b/frontend/Frontend-Hotel/public/logoHotel.png new file mode 100644 index 0000000..4209bfb Binary files /dev/null and b/frontend/Frontend-Hotel/public/logoHotel.png differ diff --git a/frontend/Frontend-Hotel/public/logoHotel2.png b/frontend/Frontend-Hotel/public/logoHotel2.png new file mode 100644 index 0000000..4209bfb Binary files /dev/null and b/frontend/Frontend-Hotel/public/logoHotel2.png differ diff --git a/frontend/Frontend-Hotel/public/vite.svg b/frontend/Frontend-Hotel/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/frontend/Frontend-Hotel/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/App.css b/frontend/Frontend-Hotel/src/App.css new file mode 100644 index 0000000..b9d355d --- /dev/null +++ b/frontend/Frontend-Hotel/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/frontend/Frontend-Hotel/src/App.jsx b/frontend/Frontend-Hotel/src/App.jsx new file mode 100644 index 0000000..0587c53 --- /dev/null +++ b/frontend/Frontend-Hotel/src/App.jsx @@ -0,0 +1,142 @@ +import React from "react"; +import { BrowserRouter as Router,Routes, Route } from "react-router-dom"; +import Layout from "./components/Layout2.jsx"; +import Login from "./pages/Login.jsx"; +import LoginAssets from "./assets/pages/login.jsx"; +import BasePositiva from "./pages/BasePositiva.jsx"; +import Sifen from "./pages/Sifen.jsx"; +import NotFound from "./pages/NotFound.jsx"; +import RoomManagement from "./pages/Settings/RoomsManagement.jsx"; +//Submenú de Dashboard +import Income from "./pages/Dashboard/Income.jsx"; +import Employees from "./pages/Employees.jsx"; +import Contracts from "./pages/Contracts.jsx"; +import HotelPL from "./pages/Dashboard/HotelPL.jsx"; +import RestaurantPL from "./pages/Dashboard/RestaurantPL.jsx"; +import RestaurantAnalysis from "./pages/Dashboard/RestaurantAnalysis.jsx"; +import Budget from "./pages/Dashboard/Budget.jsx"; +import CostPerRoom from "./pages/Dashboard/CostPerRoom.jsx"; +import Expenses from "./pages/Dashboard/Expenses.jsx"; +import RoomAnalysis from "./pages/Dashboard/RoomAnalysis.jsx"; +//Submenú de Expenses to be approved +import PendingApproval from "./pages/PendingApproval.jsx"; +import Approved from "./pages/ExpensesToBeApproval/Approved.jsx"; +import Rejected from "./pages/ExpensesToBeApproval/Rejected.jsx"; +//Submenú de Expenses +import ReportExpense from "./pages/Expenses/ReportExpense.jsx"; +import Payments from "./pages/Expenses/Payments.jsx"; +import MonthlyPayments from "./pages/Expenses/MonthlyPayments.jsx"; +import MonthlyReport from "./pages/Expenses/MonthlyReport.jsx"; +import ExpenseDetail from "./pages/Expenses/ExpenseDetail.jsx"; +import EditExpense from "./pages/Expenses/EditExpense.jsx"; +import NewExpense from "./pages/Expenses/NewExpense.jsx"; +import PurchaseEntries from "./pages/Expenses/PurchaseEntries.jsx"; +import NewSuppliers from "./pages/Expenses/NewSuppliers.jsx"; +//Submenú de Inventory +import Products from "./pages/Inventory/Products.jsx"; +import NewProduct from "./pages/Inventory/NewProduct.jsx"; +import InventoryReport from "./pages/Inventory/InventoryReport.jsx"; +import NewMonthlyPayment from "./pages/Expenses/NewMonthlyPayment.jsx"; +import Outcomes from "./pages/Inventory/Outcomes.jsx"; +import HousekeeperOutcomes from "./pages/Inventory/HousekeeperOutcomes.jsx"; + +import "./styles/global.css"; +//Submenú de Hotel +import Properties from "./pages/Hotel/Properties.jsx"; +import PropertyDetailPage from "./pages/Hotel/PropertiesId.jsx"; + +//Submenú de Payroll +import Payroll from "./pages/Payroll/Payroll.jsx"; +import Settings from "./pages/Settings/Settings.jsx"; +import SettingsId from "./pages/Settings/SettingsId.jsx"; +import Plantillapayroll from "./pages/Payroll/Plantillapayroll.jsx"; +import ContractsDetail from "./pages/Payroll/ContractsDetail.jsx"; +import PayrollContract from "./pages/Payroll/PayrollContract.jsx"; +import EditPayroll from "./pages/Payroll/EditPayroll.jsx"; + +//Submenú de Inventory + +import Adjustments from "./pages/Inventory/Adjustments.jsx"; +import AlterProduct from "./pages/Inventory/AlterProduct.jsx"; +import PayrollAttendance from "./pages/Payroll/PayrollAttendance.jsx"; +import PayrollEmployees from "./pages/Payroll/PayrollEmployees.jsx"; +import PayrollNewEmployee from "./pages/Payroll/NewEmployee.jsx"; + +import NewIncome from "./pages/Income/NewIncome.jsx"; +import IncomeReport from "./pages/Income/IncomeReport.jsx"; +import DiscardProduct from "./pages/Inventory/DiscardProduct.jsx"; + +export default function App() { + // const location = useLocation(); + // const isLogin = location.pathname === "/"; + return ( + <> + {/* */} + {/**{!isLogin && } */} + + } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + ); +} + +/* } /> +} /> +*/ diff --git a/frontend/Frontend-Hotel/src/assets/pages/login.jsx b/frontend/Frontend-Hotel/src/assets/pages/login.jsx new file mode 100644 index 0000000..af24afd --- /dev/null +++ b/frontend/Frontend-Hotel/src/assets/pages/login.jsx @@ -0,0 +1,63 @@ +import { useState } from "react"; +import "../../components/Buttons/Button"; +function LoginAssets() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + + const handleSubmit = (e) => { + e.preventDefault(); + alert(`Email: ${email}, Password: ${password}`); + }; + + return ( +
    +
    + {/* Logo */} +
    + Logo +
    + + {/* Formulario */} +
    +
    + + setPassword(e.target.value)} + /> +
    + + +
    +
    +
    +
    +
    + ); +} + +export default LoginAssets; diff --git a/frontend/Frontend-Hotel/src/assets/react.svg b/frontend/Frontend-Hotel/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/frontend/Frontend-Hotel/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/components/Buttons/Button.css b/frontend/Frontend-Hotel/src/components/Buttons/Button.css new file mode 100644 index 0000000..37d24a8 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Buttons/Button.css @@ -0,0 +1,89 @@ +.btn { + border: none; + padding: 10px 20px; + font-size: 1rem; + font-weight: bold; + border-radius: 999px; /* Súper redondo */ + background-color: #521414; + font-family: 'Roboto', sans-serif; + cursor: pointer; + color: #ffffff; + transition: all 0.3s ease; + box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.2); + width: 100%; + max-width: 400px; + text-align: center; + transition: all 0.3s ease; +} + +.btn.primary { + background-color: #4a0d0d; + color: white; +} + +.btn.primary:hover { + transform: translateY(-2px); + box-shadow: 0px 12px 20px rgba(0, 0, 0, 0.3); +} + +.btn.secundary { + border: none; + padding: 20px 40px; + font-size: 1.8rem; + font-weight: bold; + border-radius: 999px; + background-color: #eeeeee; + cursor: pointer; + color: #555555; + box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.15); + width: 100%; + max-width: 400px; + text-align: center; + transition: all 0.3s ease; +} + +.btn.secundary:hover { + transform: translateY(-2px); + box-shadow: 0px 12px 20px rgba(0, 0, 0, 0.2); +} + +.button-group { + display: flex; + flex-direction: column; + gap: 20px; + margin-top: 30px; + align-items: center; +} + + + + +/* +.button-group { + display: flex; + flex-direction: column; + gap: 20px; + margin-top: 30px; + align-items: center; +} + +.input-field { + background-color: #eeeeee; + color: #555; + font-size: 1.8rem; + font-weight: bold; + border-radius: 999px; + padding: 20px 40px; + box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.15); + border: none; + width: 100%; + max-width: 400px; + text-align: center; + outline: none; +} + +.btn.gray { + background-color: #ccc; + color: #333; +} + */ diff --git a/frontend/Frontend-Hotel/src/components/Buttons/Button.jsx b/frontend/Frontend-Hotel/src/components/Buttons/Button.jsx new file mode 100644 index 0000000..1de68b0 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Buttons/Button.jsx @@ -0,0 +1,18 @@ +// src/components/Button.jsx +import React from "react"; +import "./Button.css"; // estilos separados + +function Button({ label, onClick, variant = "primary" | "secundary"}) { +return ( +
    +

    Login

    + + +
    + ); +} +export default Button; diff --git a/frontend/Frontend-Hotel/src/components/ExcelExportButton.jsx b/frontend/Frontend-Hotel/src/components/ExcelExportButton.jsx new file mode 100644 index 0000000..d23c8e6 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/ExcelExportButton.jsx @@ -0,0 +1,118 @@ +import React, { useContext } from "react"; +import PropTypes from "prop-types"; +import * as XLSX from "xlsx"; +import { FiDownload } from "react-icons/fi"; +import { langContext } from "../context/LenguageContext"; + +export default function ExcelExportButton({ + data, + columns, + filenamePrefix, + sheetName, + dataTransform = null, + className = "", + style = {}, +}) { + const { lang } = useContext(langContext); + + const handleExportToExcel = () => { + if (!data || data.length === 0) { + alert(lang === "es" ? "No hay datos para exportar" : "No data to export"); + return; + } + + let dataToExport = dataTransform ? dataTransform(data) : data; + + const excelData = dataToExport.map((row) => { + const excelRow = {}; + columns.forEach((column) => { + if (column.key) { + let value = row[column.key]; + + // Handle render functions (extract text value) + if (column.render && typeof column.render === "function") { + // Try to get the raw value if render is used + value = row[column.key]; + } + + if (value instanceof Date) { + value = isNaN(value.getTime()) + ? "" + : value.toLocaleDateString(lang === "es" ? "es-MX" : "en-US"); + } + + const header = + typeof column.header === "string" + ? column.header + : (lang === "es" ? column.header?.es : column.header?.en) || + column.key; + + excelRow[header] = value || ""; + } + }); + return excelRow; + }); + + const worksheet = XLSX.utils.json_to_sheet(excelData); + const workbook = XLSX.utils.book_new(); + + const finalSheetName = + typeof sheetName === "string" + ? sheetName + : (lang === "es" ? sheetName?.es : sheetName?.en) || "Sheet1"; + + XLSX.utils.book_append_sheet(workbook, worksheet, finalSheetName); + + const today = new Date(); + const dateStr = today.toISOString().split("T")[0]; + const filename = `${filenamePrefix}-${dateStr}.xlsx`; + + XLSX.writeFile(workbook, filename); + }; + + const defaultStyle = { + backgroundColor: "#ffcb05", + color: "#fff", + padding: "10px 20px", + fontWeight: "bold", + border: "none", + borderRadius: "8px", + cursor: "pointer", + display: "flex", + alignItems: "center", + gap: "8px", + fontSize: "14px", + transition: "background-color 0.3s ease", + ...style, + }; + + return ( + + ); +} + +ExcelExportButton.propTypes = { + data: PropTypes.arrayOf(PropTypes.object).isRequired, + columns: PropTypes.arrayOf( + PropTypes.shape({ + header: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + key: PropTypes.string.isRequired, + render: PropTypes.func, + }) + ).isRequired, + filenamePrefix: PropTypes.string.isRequired, + sheetName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) + .isRequired, + dataTransform: PropTypes.func, + className: PropTypes.string, + style: PropTypes.object, +}; diff --git a/frontend/Frontend-Hotel/src/components/Filters/DateRangeFilter.css b/frontend/Frontend-Hotel/src/components/Filters/DateRangeFilter.css new file mode 100644 index 0000000..39b304a --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Filters/DateRangeFilter.css @@ -0,0 +1,64 @@ +.date-range-filter { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 15px; + margin-bottom: 20px; +} + +.date-input-group { + display: flex; + align-items: center; + gap: 8px; +} + +.date-label { + font-size: 14px; + font-weight: 600; + color: #333; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + white-space: nowrap; +} + +.date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 150px; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +@media (max-width: 768px) { + .date-range-filter { + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .date-input-group { + width: 100%; + } + + .date-input { + flex: 1; + } +} + diff --git a/frontend/Frontend-Hotel/src/components/Filters/DateRangeFilter.jsx b/frontend/Frontend-Hotel/src/components/Filters/DateRangeFilter.jsx new file mode 100644 index 0000000..efb2c77 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Filters/DateRangeFilter.jsx @@ -0,0 +1,45 @@ +import React from 'react'; +import './DateRangeFilter.css'; + +const DateRangeFilter = ({ + dateRange, + onDateChange, + labels = { from: 'From:', to: 'To:' }, + lang = 'en' +}) => { + const fromLabel = lang === 'en' ? labels.from : 'Desde:'; + const toLabel = lang === 'en' ? labels.to : 'Hasta:'; + + return ( +
    +
    + + onDateChange({ ...dateRange, from: e.target.value })} + /> +
    + +
    + + onDateChange({ ...dateRange, to: e.target.value })} + /> +
    +
    + ); +}; + +export default DateRangeFilter; + diff --git a/frontend/Frontend-Hotel/src/components/Filters/Filters.css b/frontend/Frontend-Hotel/src/components/Filters/Filters.css new file mode 100644 index 0000000..e8c89d9 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Filters/Filters.css @@ -0,0 +1,265 @@ +/* src/styles/Filters.css */ + +.page-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.new-payment-btn { + background-color: #FFD700; + color: #800000; + font-weight: bold; + padding: 10px 20px; + border-radius: 20px; + border: none; + cursor: pointer; + font-size: 14px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.new-payment-btn:hover { + background-color: #fcd200; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.new-payment-btn:active { + transform: translateY(0); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.report-page { + padding: 0; + max-width: 100%; +} + +.table-section { + margin-top: 20px; +} + +select, +input[type="date"] { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + max-width: 250px; + min-width: 150px; + width: auto; + flex: 0 1 auto; + /* appearance: none; + -webkit-appearance: none; + -moz-appearance: none; */ + /* background-image: url("data:image/svg+xml,%3Csvg fill='gold' viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 2px center; + background-size: 18px 18px; */ + font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-weight: bold; + cursor: pointer; + box-sizing: border-box; + /* display: flex; + justify-content: flex-end; + gap: 10px; + margin-bottom: 15px; */ + +} + +select:focus, +input[type="date"]:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filters { + display: flex; + gap: 15px; + margin: 20px 0; +} + +.filter-container { + display: flex; + gap: 1rem; + margin-bottom: 1rem; +} + +.filter-select, .filter-date { + background-color: white; + border: none; + border-radius: 2rem; + padding: 0.5rem 1rem; + font-size: 1rem; + color: #333; + box-shadow: 0 0 3px rgba(0,0,0,0.1); + appearance: none; + background-image: url('data:image/svg+xml;utf8,...'); /* usa ícono amarillo aquí */ + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 1rem; +} + +.filter-select:focus, .filter-date:focus { + outline: none; + box-shadow: 0 0 0 2px #FFD700; +} + + .status-button { + border: 2px solid; + padding: 4px 10px; + border-radius: 6px; + font-weight: bold; + text-transform: uppercase; + font-size: 12px; + min-width: 80px; +} + +.status-button.approve { + color: #28a745; + border-color: #28a745; + background-color: #e6fff0; +} + +.status-button.approved { + color: #28a745; + border-color: #28a745; + background-color: #e6fff0; +} + +.status-button.reject { + color: #dc3545; + border-color: #dc3545; + background-color: #ffe6e6; +} +.status-button.rejected { + color: #dc3545; + border-color: #dc3545; + background-color: #ffe6e6; +} + +.status-button.pending { + color: #f0ad4e; + border-color: #f0ad4e; + background-color: #fff7e6; +} + +.status-button.paid { + color: #28a745; + border-color: #28a745; + background-color: #e6fff0; +} + + +.income-card { + background-color: white; + border-radius: 15px; + padding: 15px 20px; + min-width: 140px; + text-align: center; + box-shadow: 0 1px 4px rgba(0,0,0,0.1); + align-items: center; +} + +.summary-container { + display: flex; + gap: 80px; + margin-bottom: 20px; +} + +/* .summary-card { + background: #ffffff; + border-radius: 10px; + padding: 10px 20px; + box-shadow: 0 0 10px rgba(0,0,0,0.1); + font-size: 1rem; + min-width: 160px; +} */ + + +.summary-card { + background-color: white; + border-radius: 12px; + padding: 15px 25px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + min-width: 140px; + text-align: center; + color: #333; + align-items: center; + display: block; +} + +/*Date*/ +.date-filter { + display: flex; + justify-content: flex-end; + align-items: center; + margin-bottom: 20px; + font-size: 14px; + color: #333; + font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-weight: bold; +} + +.date-filter-button { + background: none; + border: none; + cursor: pointer; + padding-left: 8px; + display: flex; + align-items: center; +} +/* +.status-button.approve { + background-color: #8bed92; + border: 1.5px solid #33a544; + color: #33a544; + border-radius: 20px; + padding: 5px 15px; + font-weight: bold; + pointer-events: none; +} */ + + +.page-filters { + display: flex; + justify-content: flex-end; + gap: 10px; + margin-bottom: 15px; +} + +.approved-page h2 { + margin-bottom: 10px; +} + + +/* +.status-button { + border: 2px solid #28a745; + color: #28a745; + padding: 4px 10px; + border-radius: 6px; + font-weight: bold; + background-color: #e6fff0; +} + +.status-button.inactive { + border-color: #dc3545; + color: #dc3545; + background-color: #ffe6e6; +} + */ \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/components/Filters/Filters.jsx b/frontend/Frontend-Hotel/src/components/Filters/Filters.jsx new file mode 100644 index 0000000..f0cbe4d --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Filters/Filters.jsx @@ -0,0 +1,99 @@ +// src/components/Filters/Filters.jsx +import React from 'react'; +import './Filters.css'; + +const Filters = ({ + areaOptions = [], + statusOptions = [], + selectedArea, + selectedStatus, + onAreaChange, + onStatusChange, + startDate, + endDate, + onStartDateChange, + onEndDateChange, +}) => { + return ( +
    + {areaOptions.length > 0 && ( +
    + +
    + )} + + {statusOptions.length > 0 && ( +
    + +
    + )} + + {onStartDateChange && ( + + )} + + {onEndDateChange && ( + + )} +
    + ); +}; + +export default Filters; + + + +// src/components/Filters.jsx +// import React from 'react'; +// import '../styles/Filters.css'; + +// export default function Filters({ area, status, startDate, endDate, onChange }) { +// return ( +//
    +// + +// + +// onChange('startDate', e.target.value)} +// /> +// onChange('endDate', e.target.value)} +// /> +//
    +// ); +// } diff --git a/frontend/Frontend-Hotel/src/components/FormInput.jsx b/frontend/Frontend-Hotel/src/components/FormInput.jsx new file mode 100644 index 0000000..629929f --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/FormInput.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +// export default function FormInput({ label, name, value, onChange, ...rest }) { +// return ( +//
    +// {label && } +// +//
    +// ); +// } + + + +export default function FormInput({ label, name, value, onChange, placeholder, type = "text", ...props }) { + return ( +
    + + +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/components/FormSelect.jsx b/frontend/Frontend-Hotel/src/components/FormSelect.jsx new file mode 100644 index 0000000..5e2a7d1 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/FormSelect.jsx @@ -0,0 +1,13 @@ +export default function FormSelect({ label, name, value, onChange, options }) { + return ( +
    + + +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/components/Inputs/Input.css b/frontend/Frontend-Hotel/src/components/Inputs/Input.css new file mode 100644 index 0000000..7233b76 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Inputs/Input.css @@ -0,0 +1,8 @@ +.input { + width: 100%; + padding: 12px; + margin: 8px 0; + border-radius: 12px; + border: 1px solid #ccc; + font-size: 1rem; +} diff --git a/frontend/Frontend-Hotel/src/components/Inputs/Input.jsx b/frontend/Frontend-Hotel/src/components/Inputs/Input.jsx new file mode 100644 index 0000000..88ae05f --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Inputs/Input.jsx @@ -0,0 +1,17 @@ +// src/components/Input.jsx +import React from "react"; +import "./Input.css"; + +function Input({ type = "text", placeholder, value, onChange }) { + return ( + + ); +} + +export default Input; diff --git a/frontend/Frontend-Hotel/src/components/Layout.jsx b/frontend/Frontend-Hotel/src/components/Layout.jsx new file mode 100644 index 0000000..eb28c91 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Layout.jsx @@ -0,0 +1,357 @@ +// Layout.jsx +// import React, { useState } from "react"; +// import { Outlet, NavLink, useLocation } from "react-router-dom"; +// import { useNavigate } from 'react-router-dom'; +// import { FaBell, FaCog } from "react-icons/fa"; +// import "../styles/Dashboard.css"; + +// const menuConfig = [ +// { +// label: "Dashboards", +// basePath: "/app/income", +// submenu: [ +// { label: "Income", route: "/app/income" }, +// { label: "Expenses", route: "/app/expenses" }, +// { label: "Cost per room", route: "/app/cost-per-room" }, +// { label: "Budget", route: "/app/budget" }, +// ], +// }, +// { +// label: "Expenses to be approved", +// basePath: "/app/pending-approval", +// submenu: [ +// { label: "Pending approval", route: "/app/pending-approval" }, +// { label: "Approved", route: "/app/approved" }, +// { label: "Rejected", route: "/app/rejected" }, +// ], +// }, +// { +// label: "Expenses", +// basePath: "/app/report", +// submenu: [ +// { label: "Report", route: "/app/report" }, +// { label: "New Expense", route: "/app/new-expense" }, +// { label: "Payments", route: "/app/payments" }, +// { label: "Monthly Payments", route: "/app/monthly-payments" }, +// { label: "Id", route: "/app/expense-id" }, +// ], +// }, +// { +// label: "Inventory", +// basePath: "/app/products", +// submenu: [ +// { label: "Products", route: "/app/products" }, +// { label: "New Product", route: "/app/new-product" }, +// { label: "Report", route: "/app/inventory-report" }, + +// ], +// }, +// { +// label: "Payroll", +// basePath: "/app/payroll", +// submenu: [ +// { label: "Report", route: "/app/payroll" }, +// ], +// }, +// { +// label: "Hotel", +// basePath: "/app/properties", +// submenu: [ +// { label: "Properties", route: "/app/properties" }, +// // { label: "New Property", route: "/app/properties/:id"}, +// ], +// }, + +// ]; + +// export default function Layout() { +// const navigate = useNavigate(); +// const location = useLocation(); +// const [isSidebarOpen, setSidebarOpen] = useState(true); +// const toggleSidebar = () => setSidebarOpen(!isSidebarOpen); +// const isDetailPage = /^\/app\/properties\/\d+$/.test(location.pathname); +// const isSettingsPage = location.pathname === "/app/settings"; +// // Detectar qué menú está activo según la ruta actual +// // const activeSection = menuConfig.find(section => +// // location.pathname.startsWith(section.basePath) +// // ); + +// // const activeSection = menuConfig.find(section => +// // section.submenu.some(item => location.pathname.startsWith(item.route)) +// // ); + +// // Encuentra la sección activa o ignórala si es una ruta especial como "/app/properties/:id" +// const activeSection = menuConfig.find(section => +// section.submenu.some(item => location.pathname.startsWith(item.route)) +// ); + +// // Si no hay sección activa, es una página sin menú (como detalles) +// const activeSubmenu = activeSection?.submenu || []; + +// return ( +//
    +// {/* Sidebar */} +// {isSidebarOpen && ( +// +// )} + +// {/* Main content */} +//
    +// {/* Topbar */} +//
    +//
    +// {/* Oculta título si estamos en /app/settings */} +// {!isSettingsPage && ( +//
    {activeSection?.label}
    +// )} + +//
    +// +// navigate("/app/settings")} +// /> +//
    +//
    + +// {/*Oculta submenú si es página de detalles o settings */} +// {!isDetailPage && !isSettingsPage && ( +//
    +// {activeSubmenu.map((item, index) => ( +// +// isActive ? "submenu-link active" : "submenu-link" +// } +// > +// {item.label} +// +// ))} +//
    +// )} +//
    + +// {/* Página actual */} +//
    +// +//
    +//
    +//
    +// ); + + // return ( + //
    + // {/* Sidebar */} + // {isSidebarOpen && ( + // + // )} + + // {/* Contenido principal */} + //
    + // {/* ÚNICO Topbar */} + //
    + // {/* Línea superior: título + iconos */} + //
    + //
    {activeSection?.label}
    + //
    + // + // navigate("/app/settings")} /> + //
    + //
    + + // {/* Línea inferior: submenú dinámico */} + + // {/* Línea inferior: submenú dinámico */} + // {!isDetailPage && ( + //
    + // {activeSubmenu.map((item, index) => ( + // + // isActive ? "submenu-link active" : "submenu-link" + // } + // > + // {item.label} + // + // ))} + //
    + // )} + + // {/*
    + // {activeSubmenu.map((item, index) => ( + // + // isActive ? "submenu-link active" : "submenu-link" + // } + // > + // {item.label} + // + // ))} + //
    */} + //
    + + // {/* Aquí va el contenido de la página */} + //
    + // + //
    + //
    + //
    + // ); + //} + + + +//{ label: "Property", route: "/app/properties/:id" }, + +// import React from "react"; +// import { Outlet, useLocation, NavLink } from "react-router-dom"; +// import { menuConfig } from "../constants/menuConfig"; +// import { FaBell, FaCog } from "react-icons/fa"; +// import "../styles/Dashboard.css"; + +// export default function Layout() { +// const location = useLocation(); +// const pathname = location.pathname; + +// // Encuentra la sección activa +// const activeSectionKey = Object.keys(menuConfig).find((key) => +// pathname.startsWith(menuConfig[key].baseRoute) +// ); +// const activeSection = menuConfig[activeSectionKey]; +// const activeSubmenu = activeSection?.submenu || []; + +// return ( +//
    +// {/* SIDEBAR */} +// + +// {/* CONTENIDO PRINCIPAL */} +//
    +// {/* TOPBAR */} +//
    +//
    +//
    {activeSection?.label}
    +//
    +// +// +//
    +//
    + +//
    +// {activeSubmenu.map((item, index) => ( +// +// isActive ? "submenu-link active" : "submenu-link" +// } +// > +// {item.label} +// +// ))} +//
    +//
    + + +// {/* CONTENIDO */} +//
    +// +//
    +//
    +//
    +// ); +// } + + + +// // src/components/Layout.jsx +// import React, { useState } from "react"; +// import { Outlet, NavLink } from "react-router-dom"; +// import "../styles/Dashboard.css"; + +// export default function Layout() { +// const [isSidebarOpen, setSidebarOpen] = useState(true); + +// const toggleSidebar = () => { +// setSidebarOpen(!isSidebarOpen); +// }; + +// return ( +//
    + +// {/* Sidebar */} +// {isSidebarOpen && ( +// +// )} + +// {/* Contenedor principal */} +//
    +// {/* Topbar */} +//
    +// +// Dashboard {/* Cambia esto dinámicamente si deseas */} +//
    + +// {/* Contenido de cada página */} +//
    +// +//
    +//
    +//
    +// ); +// } + +// Users \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/components/Layout2.jsx b/frontend/Frontend-Hotel/src/components/Layout2.jsx new file mode 100644 index 0000000..1c95a04 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Layout2.jsx @@ -0,0 +1,426 @@ +// Layout.jsx +import React, { useContext, useState } from "react"; +import { Outlet, NavLink, useLocation } from "react-router-dom"; +import { useNavigate } from 'react-router-dom'; +import "../styles/Dashboard.css"; +import { AuthContext } from "../context/AuthContext"; +import { langContext } from "../context/LenguageContext"; +import { FaSignOutAlt } from "react-icons/fa"; +import { menuConfig } from "../constants/menuconfig"; + +export default function Layout() { + const { toggleLang, lang } = useContext(langContext); + const { user, logout } = useContext(AuthContext); + console.log('user', user); + const handleLogout = () => { + logout(); + navigate("/"); + }; + const menuConfigWithPermissions = Object.values(menuConfig).map(section => ({ + ...section, + hidden: + section.label === "Dashboards" ? (user >= 1 && user <= 2 ? false : true) : + section.label === "Expenses to be approved" ? (user === 1 || user === 2 ? false : true) : + section.label === "Expenses" ? (user >= 1 && user <= 5 ? false : true) : + section.label === "Inventory" ? (user >= 1 && user <= 5 ? false : true) : + section.label === "Payroll" ? (user >= 1 && user <= 4 ? false : true) : + section.label === "Hotel" ? (user === 1 ? false : true) : + section.label === "Income" ? (user >= 1 && user <= 4 ? false : true) : + section.label === "Housekeeper" ? (user === 6 ? false : true) : + false, + submenu: section.submenu?.map(item => ({ + ...item, + hidden: item.hidden || + (section.label === "Expenses" && user === 2 && item.label !== "Report" && item.label !== "Monthly Report" ? true : false) || + (section.label === "Payroll" && user === 2 && !["Report", "Attendance", "Employees", "Contracts"].includes(item.label) ? true : false) || + (section.label === "Expenses" && user === 5 && !["New Expense", "Purchase Entries", "New Suppliers"].includes(item.label) ? true : false) + })) + })); + + const navigate = useNavigate(); + const location = useLocation(); + const [isSidebarOpen, setSidebarOpen] = useState(true); + const toggleSidebar = () => setSidebarOpen(!isSidebarOpen); + // const isDetailPage = /^\/app\/properties\/\d+$/.test(location.pathname); + // Detectar páginas de detalle (para ocultar el submenú) + const isDetailPage = + /^\/app\/properties\/\d+$/.test(location.pathname) || // Propiedades (ya existente) + /^\/app\/payroll\/contracts-detail(\/.*)?$/.test(location.pathname) || // Contract Detail + /^\/app\/expenses\/detail(\/.*)?$/.test(location.pathname); // Otros detalles si los tienes + + + const activeSection = menuConfigWithPermissions.find(section => { + if (section.hidden) return false; + + const matchesSubmenu = section.submenu.some(item => location.pathname.startsWith(item.route)); + const matchesBasePath = location.pathname.startsWith(section.basePath); + + if (matchesSubmenu || matchesBasePath) { + return true; + } + + if (section.label === "Income" && location.pathname.startsWith("/app/edit-income-form")) { + return true; + } + + if (section.label === "Expenses" && (location.pathname.startsWith("/app/expenses/edit/") || location.pathname.startsWith("/app/expenses/") || location.pathname === "/app/new-monthly")) { + return true; + } + + if (section.label === "Inventory" && location.pathname.startsWith("/app/alter-product/")) { + return true; + } + + if (section.label === "Payroll" && (location.pathname.startsWith("/app/payroll/employee/") || location.pathname.startsWith("/app/payroll/contract/") || location.pathname.startsWith("/app/payroll/edit/") || location.pathname.startsWith("/app/payroll/contracts-detail/"))) { + return true; + } + + if (section.label === "Hotel" && location.pathname.startsWith("/app/properties/")) { + return true; + } + + return false; + }); + + const activeSubmenu = activeSection?.label === "Housekeeper" + ? [{ label: "Outcomes", spanish_label: "Salidas", route: "/app/housekeeper/outcomes" }] + : activeSection?.submenu || []; + + const isLandingPage = location.pathname === '/app' || !activeSection; + + + return ( +
    + {/* Sidebar */} + {isSidebarOpen && ( + + )} + + {/* Main content */} +
    + {/* Topbar */} +
    +
    + + {/* Botón + Título (alineados a la izquierda) */} +
    + + +
    + {lang === "en" ? activeSection?.label : activeSection?.spanish_label} +
    +
    + + + {/* Iconos a la derecha */} +
    + + +
    +
    + + {/* Submenú (solo si no es página de detalle) */} + {!isDetailPage && ( +
    + {activeSubmenu.filter(section => !section.hidden).map((item, index) => ( + + isActive ? "submenu-link active" : "submenu-link" + } + > + {lang === "en" ? item.label : item.spanish_label} + + ))} +
    + )} +
    + {/* Página actual */} +
    + {isLandingPage ? ( +
    + Hotel Logo +

    + {lang === "en" + ? "To get started, select an option from the menu on the left." + : "Para comenzar, selecciona una opción del menú de la izquierda."} +

    +
    + ) : ( + + )} +
    +
    +
    + ); +} + +// // Layout.jsx +// import React, { use, useContext, useState } from "react"; +// import { Outlet, NavLink, useLocation } from "react-router-dom"; +// import { useNavigate } from 'react-router-dom'; +// import { FaBell, FaCog } from "react-icons/fa"; +// import "../styles/Dashboard.css"; +// import { AuthContext } from "../context/AuthContext"; +// import { langContext } from "../context/LenguageContext"; +// import { FaSignOutAlt } from "react-icons/fa"; + +// export default function Layout() { +// const { toggleLang } = useContext(langContext); +// const { user, logout } = useContext(AuthContext); +// const handleLogout = () => { +// logout(); +// navigate("/"); +// }; +// // const {lang, setLang} = useContext(AuthContext); +// // console.log(lang); +// const menuConfig = [ +// { +// label: "Dashboards", +// basePath: "/app/income", +// submenu: [ +// { label: "Income", route: "/app/income" }, +// // { label: "Expenses", route: "/app/expenses" }, +// // { label: "Cost per room", route: "/app/cost-per-room" }, +// // { label: "Budget", route: "/app/budget" }, +// ], +// hidden: user === 1 ? false : true //Solo admin puede ver dashboards, +// }, +// { +// label: "Expenses to be approved", +// basePath: "/app/pending-approval", +// submenu: [ +// { label: "Pending approval", route: "/app/pending-approval" }, +// { label: "Approved", route: "/app/approved" }, +// { label: "Rejected", route: "/app/rejected" }, +// ], +// hidden: user === 1 ? false : true +// }, +// { +// label: "Expenses", +// basePath: "/app/report-expense", +// submenu: [ +// { label: "Report", route: "/app/report-expense" }, +// { label: "New Expense", route: "/app/new-expense" }, +// { label: "Payments", route: "/app/payments" }, +// { label: "Monthly Payments", route: "/app/monthly-payments" }, +// { label: "New Monthly Payments", route: "/app/new-monthly" }, +// { label: "Purchase Entries", route: "/app/purchase-entries" }, +// ], +// hidden: user >= 1 && user <= 3 ? false : true +// }, +// { +// label: "Inventory", +// basePath: "/app/products", +// submenu: [ +// { label: "Products", route: "/app/products", hidden: user === 5 ? true : false }, +// { label: "New Product", route: "/app/new-product", hidden: user === 5 ? true : false }, +// { label: "Report", route: "/app/inventory-report", hidden: user === 5 ? true : false }, +// { label: "Discard Product", route: "/app/discard-product", hidden: user === 5 ? true : false }, +// { label: "Adjustments", route: "/app/product-adjustments", hidden: user === 5 ? true : false } +// ], +// hidden: user >= 1 && user <= 4 ? false : true +// }, +// { +// label: "Payroll", +// basePath: "/app/payroll", +// submenu: [ +// { label: "Report", route: "/app/payroll" }, +// { label: "New Contract", route: "/app/payroll/NewPayRoll"}, +// { label: "Attendance", route: "/app/payroll/attendance" }, +// { label: "Employees", route: "/app/payroll/employees" }, +// { label: "New Employee", route: "/app/payroll/newemployee" }, +// ], +// hidden: user >= 1 && user <= 3 ? false : true +// }, +// { +// label: "Hotel", +// basePath: "/app/properties", +// submenu: [ +// { label: "Properties", route: "/app/properties" }, +// ], +// hidden: user === 1 ? false : true +// }, +// //SECCIÓN "OCULTA" PARA SETTINGS +// { +// label: "Settings", +// basePath: "/app/settings", +// submenu: [ +// { label: "General", route: "/app/settings" }, +// { label: "Users", route: "/app/settings/users" }, +// { label: "Units", route: "/app/settings/roles" }, +// { label: "Room management", route: "/app/settings/room-management" }, +// ], +// hidden: true, //etiqueta para ignorar en sidebar +// }, +// ]; + +// const navigate = useNavigate(); +// const location = useLocation(); +// const [isSidebarOpen, setSidebarOpen] = useState(true); +// const toggleSidebar = () => setSidebarOpen(!isSidebarOpen); +// const isDetailPage = /^\/app\/properties\/\d+$/.test(location.pathname); + +// //Identificar la sección activa, incluyendo settings +// const activeSection = menuConfig.find(section => +// section.submenu.some(item => location.pathname.startsWith(item.route)) +// ); + +// const activeSubmenu = activeSection?.submenu || []; + + +// return ( +//
    +// {/* Sidebar */} +// {isSidebarOpen && ( +// +// )} + +// {/* Main content */} +//
    +// {/* Topbar */} +//
    +//
    + +// {/* Botón + Título (alineados a la izquierda) */} +//
    +// + +//
    {activeSection?.label}
    +//
    + + +// {/* Iconos a la derecha */} +//
    +// +// navigate("/app/settings")} +// /> +// +// + + + +//
    +//
    + +// {/* Submenú (solo si no es página de detalle) */} +// {!isDetailPage && ( +//
    +// {activeSubmenu.filter(section => !section.hidden).map((item, index) => ( +// +// isActive ? "submenu-link active" : "submenu-link" +// } +// > +// {item.label} +// +// ))} +//
    +// )} +//
    + + +// {/* Página actual */} +//
    +// +//
    +//
    +//
    +// ); +// } diff --git a/frontend/Frontend-Hotel/src/components/Modals/ConfirmationModal.css b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationModal.css new file mode 100644 index 0000000..9435d40 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationModal.css @@ -0,0 +1,74 @@ +/* components/Modals/ConfirmationModal.css */ + +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(122, 0, 41, 0.6); + display: flex; + align-items: center; + justify-content: center; + z-index: 999; +} + +.modal { + background: white; + padding: 30px; + border-radius: 6px; + width: 450px; + max-width: 95%; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.4); + border: 5px solid #7a0029; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + color: white; + background-color: #7a0029; + padding: 15px 20px; + border-radius: 5px 5px 0 0; +} + +.modal-body { + padding: 20px; + font-size: 16px; + text-align: center; +} + +.modal-buttons { + margin-top: 20px; + display: flex; + justify-content: center; + gap: 20px; +} + +.modal-button { + padding: 10px 25px; + font-size: 18px; + border-radius: 30px; + border: 2px solid #7a0029; + cursor: pointer; + min-width: 100px; +} + +.modal-button.yes { + color: green; + background-color: white; +} + +.modal-button.no { + color: #7a0029; + background-color: white; +} + +.close-button { + font-size: 24px; + color: white; + background: none; + border: none; + cursor: pointer; +} diff --git a/frontend/Frontend-Hotel/src/components/Modals/ConfirmationModal.jsx b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationModal.jsx new file mode 100644 index 0000000..d06f3a0 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationModal.jsx @@ -0,0 +1,28 @@ +// components/Modals/ConfirmationModal.jsx +import React from 'react'; +import './ConfirmationModal.css'; // Estilos separados +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function ConfirmationModal({ isOpen, statusType, onConfirm, onCancel }) { + const { lang } = useContext(langContext); + if (!isOpen) return null; + + return ( +
    +
    +
    +

    {lang === "en" ? "Confirm the status change" : "Confirmar el cambio de estado"}

    + +
    +
    +

    {lang === "en" ? "Are you sure you received" : "¿Estás seguro de que recibiste"} "{statusType}"?

    +
    + + +
    +
    +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/components/Modals/ConfirmationMontlyPay.jsx b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationMontlyPay.jsx new file mode 100644 index 0000000..7454c7b --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationMontlyPay.jsx @@ -0,0 +1,70 @@ +// components/Modals/ConfirmationModal.jsx +import React, { useState, useEffect } from 'react'; +import './ConfirmationModal.css'; // Estilos separados +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + + +export default function ConfirmationOutcome({ isOpen, onConfirm, onCancel, description, taxes, initialAmount, initialTaxId, isFixedPayment }) { + /*const [formHousekepeer, setFormHousekepeer] = useState(null)/*/ + const { lang } = useContext(langContext); + const [form, setForm] = useState({ + tax: '', + amount: '' + }); + + useEffect(() => { + if (isOpen) { + setForm({ + tax: initialTaxId || '', + amount: initialAmount || '' + }); + } + }, [isOpen, initialAmount, initialTaxId]); + + if (!isOpen) return null; + const handleChange = (e) => { + const { name, value } = e.target; + //console.log(name, value); + setForm((prev) => ({ ...prev, [name]: value })); + }; + + const handleConfirmClick = () => { + // Envía los valores al padre (Outcomes.jsx) + onConfirm(form.tax, form.amount); + }; + return ( +
    +
    +
    +
    +

    {lang === "en" ? "Confirm the status change" : "Confirmar el cambio de estado"}

    + +
    +
    +
    +

    {lang === "en" ? "Payment" : "Pago"}

    + +
    +
    +

    {lang === "en" ? "Amount" : "Subtotal"}

    + +
    +
    +

    {lang === "en" ? "Tax" : "Impuesto"}

    + +
    +
    + +
    +
    +
    +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/components/Modals/ConfirmationOutcome.jsx b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationOutcome.jsx new file mode 100644 index 0000000..89dfecd --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/ConfirmationOutcome.jsx @@ -0,0 +1,122 @@ +// components/Modals/ConfirmationModal.jsx +import React, { useState, useEffect } from 'react'; +import './ConfirmationModal.css'; // Estilos separados +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + + +export default function ConfirmationOutcome({ isOpen, onConfirm, onCancel, formHousekepeer, idproduct, nameProduct, productStock }) { + /*const [formHousekepeer, setFormHousekepeer] = useState(null)/*/ + const { lang } = useContext(langContext); + if (!isOpen) return null; + const [PCO, setProduct] = useState(idproduct); + const [UCO, setUnits] = useState(null); + const [HCO, setHousekeeper] = useState(null); + const [form, setForm] = useState({ + PCO: idproduct || '', + UCO: '', + HCO: '' + }); + + const handleChange = (e) => { + const { name, value } = e.target; + + if (name === 'UCO') { + const numericValue = Number(value); + const maxStock = Number(productStock) || 0; + if (value === '') { + setForm((prev) => ({ ...prev, [name]: '' })); + } else if (!isNaN(numericValue) && numericValue >= 0) { + const cappedValue = numericValue > maxStock ? maxStock : numericValue; + setForm((prev) => ({ ...prev, [name]: cappedValue.toString() })); + } + } else { + setForm((prev) => ({ ...prev, [name]: value })); + } + }; + + const handleConfirmClick = () => { + // Envía los valores al padre (Outcomes.jsx) + onConfirm(form.PCO, form.UCO, form.HCO); + }; + return ( +
    +
    +
    +

    {lang === "en" ? "Confirm the status change" : "Confirmar el cambio de estado"}

    + +
    +
    +
    +

    {lang === "en" ? "Product" : "Producto"}

    + +
    +
    +

    {lang === "en" ? "Units" : "Unidades"}

    + { + if (e.key === '-' || e.key === 'e' || e.key === 'E' || e.key === '+') { + e.preventDefault(); + } + }} + onChange={handleChange} + style={{ + color: '#000', + width: '100%', + padding: '8px', + backgroundColor: (!productStock || Number(productStock) <= 0) ? '#f0f0f0' : 'white', + cursor: (!productStock || Number(productStock) <= 0) ? 'not-allowed' : 'text', + opacity: (!productStock || Number(productStock) <= 0) ? 0.6 : 1 + }} + /> + {(!productStock || Number(productStock) <= 0) && ( +

    + {lang === "es" ? "No hay stock disponible" : "There is no stock"} +

    + )} +
    +
    +

    {lang === "en" ? "Housekeeper" : "Camarista"}

    + +
    +
    + +
    +
    +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/components/Modals/DiscardConfirmModal.css b/frontend/Frontend-Hotel/src/components/Modals/DiscardConfirmModal.css new file mode 100644 index 0000000..439e4a6 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/DiscardConfirmModal.css @@ -0,0 +1,111 @@ +.discard-modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + animation: fadeIn 0.2s ease-in-out; +} + +.discard-modal-box { + background: white; + padding: 0; + border-radius: 12px; + width: 450px; + max-width: 90%; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + animation: slideUp 0.3s ease-out; + overflow: hidden; +} + +.discard-modal-header { + background-color: #7a0029; + color: white; + padding: 20px; + text-align: center; +} + +.discard-modal-header h3 { + margin: 0; + font-size: 1.25rem; + font-weight: 600; +} + +.discard-modal-body { + padding: 24px; + text-align: center; + color: #213547; + font-size: 1rem; + line-height: 1.5; +} + +.discard-modal-body p { + margin: 0; +} + +.discard-modal-actions { + display: flex; + gap: 12px; + padding: 20px 24px; + border-top: 1px solid #e2e8f0; + justify-content: flex-end; +} + +.discard-modal-button { + padding: 10px 24px; + border-radius: 8px; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + border: none; + transition: all 0.2s ease; + min-width: 100px; +} + +.discard-modal-button-cancel { + background-color: #e2e8f0; + color: #4a5568; +} + +.discard-modal-button-cancel:hover { + background-color: #cbd5e0; +} + +.discard-modal-button-confirm { + background-color: #7a0029; + color: white; +} + +.discard-modal-button-confirm:hover { + background-color: #5a001f; +} + +.discard-modal-button:active { + transform: translateY(1px); +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + diff --git a/frontend/Frontend-Hotel/src/components/Modals/DiscardConfirmModal.jsx b/frontend/Frontend-Hotel/src/components/Modals/DiscardConfirmModal.jsx new file mode 100644 index 0000000..d836255 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/DiscardConfirmModal.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +import './DiscardConfirmModal.css'; + +export default function DiscardConfirmModal({ isOpen, message, onConfirm, onCancel }) { + const { lang } = useContext(langContext); + + if (!isOpen) return null; + + return ( +
    +
    e.stopPropagation()}> +
    +

    {lang === "es" ? "Confirmar descarte" : "Confirm Discard"}

    +
    +
    +

    {message}

    +
    +
    + + +
    +
    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/components/Modals/Modal.css b/frontend/Frontend-Hotel/src/components/Modals/Modal.css new file mode 100644 index 0000000..bfc06cb --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/Modal.css @@ -0,0 +1,57 @@ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.55); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; +} + +.modal-box { + background: white; + padding: 30px; + border-radius: 10px; + width: 350px; + max-width: 90%; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); +} + +.modal-box h3 { + margin-top: 0; + margin-bottom: 15px; + color: #111; + text-align: center; +} + +.modal-input { + width: 100%; + padding: 12px; + margin-bottom: 15px; + border: none; + border-radius: 12px; + background: #f1f1f1; + font-size: 14px; +} + +.btn { + width: 100%; + padding: 12px; + border: none; + border-radius: 6px; + font-weight: 600; + margin-bottom: 10px; + cursor: pointer; +} + +.btn--primary { + background-color: #8b0000; + color: white; +} + +.btn--primary:hover { + background-color: #a00000; +} diff --git a/frontend/Frontend-Hotel/src/components/Modals/Modal.jsx b/frontend/Frontend-Hotel/src/components/Modals/Modal.jsx new file mode 100644 index 0000000..36666c5 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Modals/Modal.jsx @@ -0,0 +1,22 @@ +import React, { useState } from 'react'; +import './Modal.css'; // Asegúrate de tener el estilo del modal + +export default function Modal({ isOpen, closeModal }) { + return ( + isOpen && ( +
    +
    +

    Enter your email address and we'll send a new password to your email.

    + + +
    +
    + ) + ); +} diff --git a/frontend/Frontend-Hotel/src/components/Navbar/Navbar.css b/frontend/Frontend-Hotel/src/components/Navbar/Navbar.css new file mode 100644 index 0000000..2747eda --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Navbar/Navbar.css @@ -0,0 +1,53 @@ +z/* src/styles/Navbar.css */ + +.navbar { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #4a0d0d; /* Marrón oscuro */ + padding: 12px 20px; + color: white; +} + +.navbar__brand { + font-size: 1.2rem; + font-weight: bold; +} + +.navbar__nav { + display: flex; + gap: 15px; +} + +.nav__link { + color: white; + text-decoration: none; + font-size: 0.95rem; +} + +.nav__link.active { + border-bottom: 2px solid #f8d47b; /* Amarillo suave */ +} + +.navbar__actions { + display: flex; + gap: 10px; +} + +.btn { + padding: 6px 12px; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 0.9rem; +} + +.btn--primary { + background-color: #f8d47b; /* Amarillo */ + color: #4a0d0d; +} + +.btn--secondary { + background-color: #ddd; + color: #333; +} diff --git a/frontend/Frontend-Hotel/src/components/Navbar/Navbar.jsx b/frontend/Frontend-Hotel/src/components/Navbar/Navbar.jsx new file mode 100644 index 0000000..3dfe527 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Navbar/Navbar.jsx @@ -0,0 +1,33 @@ +// src/components/Navbar.jsx +import { NavLink, useNavigate } from "react-router-dom"; +import { useAuth } from "../../context/AuthContext.jsx"; +import "./Navbar.css"; // estilos separados + +export default function Navbar() { + const { isAuthenticated, logout } = useAuth(); + const navigate = useNavigate(); + + const handleLogout = () => { + logout(); + navigate("/"); // 👈 al cerrar sesión vuelve al Login + }; + + return ( +
    +
    + +
    + {isAuthenticated ? ( + + ) : ( + + Login + + )} +
    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/components/Sidebar.jsx b/frontend/Frontend-Hotel/src/components/Sidebar.jsx new file mode 100644 index 0000000..7aa9474 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Sidebar.jsx @@ -0,0 +1,53 @@ +// Sidebar.jsx +import { useNavigate } from "react-router-dom"; +import { menuConfig } from "../constants/menuConfig"; + +const Sidebar = () => { + const navigate = useNavigate(); + + return ( + + ); +}; + +export default Sidebar; + +// import React, { useState } from "react"; +// import { NavLink } from "react-router-dom"; +// import "./..styles/Sidebar.css"; + +// export default function Sidebar() { +// const [collapsed, setCollapsed] = useState(false); + +// return ( +//
    +//
    +// +// {!collapsed && Dashboard} +//
    + +// +//
    +// ); +// } diff --git a/frontend/Frontend-Hotel/src/components/SummaryCard.css b/frontend/Frontend-Hotel/src/components/SummaryCard.css new file mode 100644 index 0000000..d6e8a54 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/SummaryCard.css @@ -0,0 +1,100 @@ +.summary-card-enhanced { + background: linear-gradient(145deg, #ffffff, #f8f9fa); + border-radius: 16px; + padding: 20px 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-width: 180px; + flex: 1; + transition: all 0.3s ease; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.summary-card-enhanced:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); +} + +.summary-card-enhanced.primary { + background: linear-gradient(145deg, #ffffff, #f8f9fa); + color: #333; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.card-header { + display: flex; + align-items: center; + margin-bottom: 12px; +} + +.card-title { + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + margin: 0; + color: #666; +} + +.card-amount { + font-size: 28px; + font-weight: 700; + color: #333; + margin: 8px 0; + line-height: 1.2; +} + +.card-percentage { + font-size: 16px; + font-weight: 600; + color: #28a745; + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.card-loading { + display: flex; + justify-content: center; + align-items: center; + min-height: 100px; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 4px solid rgba(0, 0, 0, 0.1); + border-top-color: #fcd200; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +@media (max-width: 1200px) { + .summary-card-enhanced { + min-width: 150px; + } + + .card-amount { + font-size: 24px; + } +} + +@media (max-width: 768px) { + .summary-card-enhanced { + min-width: 100%; + } + + .card-amount { + font-size: 22px; + } + + .card-title { + font-size: 12px; + } +} + diff --git a/frontend/Frontend-Hotel/src/components/SummaryCard.jsx b/frontend/Frontend-Hotel/src/components/SummaryCard.jsx new file mode 100644 index 0000000..e509b8b --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/SummaryCard.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import './SummaryCard.css'; + +const SummaryCard = ({ + title, + amount, + isLoading = false, + isPrimary = false +}) => { + if (isLoading) { + return ( +
    +
    +
    +
    +
    + ); + } + + return ( +
    +
    +

    {title}

    +
    +
    ${amount || 0}
    +
    + ); +}; + +export default SummaryCard; + diff --git a/frontend/Frontend-Hotel/src/components/Switch.jsx b/frontend/Frontend-Hotel/src/components/Switch.jsx new file mode 100644 index 0000000..7bb8e90 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Switch.jsx @@ -0,0 +1,28 @@ +import React from 'react'; + +const Switch = ({ checked, onChange, disabled = false }) => { + return ( + + ); +}; + +export default Switch; diff --git a/frontend/Frontend-Hotel/src/components/Table/HotelTable copy.jsx b/frontend/Frontend-Hotel/src/components/Table/HotelTable copy.jsx new file mode 100644 index 0000000..209a2f9 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Table/HotelTable copy.jsx @@ -0,0 +1,152 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { FaExternalLinkAlt } from 'react-icons/fa'; +import './Table.css'; + +export default function Table({ columns, data }) { + return ( + + + + {columns.map((col) => ( + + ))} + + + + {data.map((row, rowIndex) => ( + + {columns.map((col, colIndex) => ( + + ))} + + ))} + +
    {col.header}
    + {col.render + ? col.render(row[col.key], row, rowIndex) + : col.key === 'propertyId' + ? ( + + {row[col.key]} + + + ) + : row[col.key]} +
    + ); +} + +// import React from 'react'; +// import { Link } from 'react-router-dom'; +// import { FaArrowRight } from 'react-icons/fa'; +// import './Table.css'; + +// export default function Table({ columns, data }) { +// return ( +// +// +// +// {columns.map((col) => ( +// +// ))} +// +// +// +// {data.map((row, rowIndex) => ( +// +// {columns.map((col, colIndex) => ( +// +// ))} +// +// ))} +// +//
    {col.header}
    +// {col.render +// ? col.render(row[col.key], row) +// : col.key === 'propertyId' +// ? ( +// +// {row[col.key]} +// +// +// ) +// : row[col.key]} +//
    +// ); +// } + +// import React from 'react'; +// import { Link } from 'react-router-dom'; +// import './Table.css'; + +// export default function Table({ columns, data }) { +// return ( +// +// +// +// {columns.map((col) => ( +// +// ))} +// +// +// +// {data.map((row, rowIndex) => ( +// +// {columns.map((col, colIndex) => ( +// +// ))} +// +// ))} +// +//
    {col.header}
    +// {col.render +// ? col.render(row[col.key], row) // usar render si está definido +// : col.key === 'propertyId' +// ? {row[col.key]} +// : row[col.key]} +//
    +// ); +// } + + +// import React from 'react'; +// import './Table.css'; + +// export default function Table({ columns, data }) { +// return ( +// +// +// +// {columns.map((col) => ( +// +// ))} +// +// +// +// {data.map((row, rowIndex) => ( +// +// {columns.map((col, colIndex) => ( +// +// ))} +// +// ))} +// + +//
    {col.header}
    +// {col.render +// ? col.render(row[col.key], row) // usar render si está definido +// : row[col.key]} +//
    +// ); +// } diff --git a/frontend/Frontend-Hotel/src/components/Table/HotelTable.jsx b/frontend/Frontend-Hotel/src/components/Table/HotelTable.jsx new file mode 100644 index 0000000..9e6990f --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Table/HotelTable.jsx @@ -0,0 +1,152 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { FaExternalLinkAlt } from 'react-icons/fa'; +import './Table.css'; + +export default function Table({ columns, data }) { + return ( + + + + {columns.map((col) => ( + + ))} + + + + {data.map((row, rowIndex) => ( + + {columns.map((col, colIndex) => ( + + ))} + + ))} + +
    {col.header}
    + {col.render + ? col.render(row[col.key], row) + : col.key === 'propertyId' + ? ( + + {row[col.key]} + + + ) + : row[col.key]} +
    + ); +} + +// import React from 'react'; +// import { Link } from 'react-router-dom'; +// import { FaArrowRight } from 'react-icons/fa'; +// import './Table.css'; + +// export default function Table({ columns, data }) { +// return ( +// +// +// +// {columns.map((col) => ( +// +// ))} +// +// +// +// {data.map((row, rowIndex) => ( +// +// {columns.map((col, colIndex) => ( +// +// ))} +// +// ))} +// +//
    {col.header}
    +// {col.render +// ? col.render(row[col.key], row) +// : col.key === 'propertyId' +// ? ( +// +// {row[col.key]} +// +// +// ) +// : row[col.key]} +//
    +// ); +// } + +// import React from 'react'; +// import { Link } from 'react-router-dom'; +// import './Table.css'; + +// export default function Table({ columns, data }) { +// return ( +// +// +// +// {columns.map((col) => ( +// +// ))} +// +// +// +// {data.map((row, rowIndex) => ( +// +// {columns.map((col, colIndex) => ( +// +// ))} +// +// ))} +// +//
    {col.header}
    +// {col.render +// ? col.render(row[col.key], row) // usar render si está definido +// : col.key === 'propertyId' +// ? {row[col.key]} +// : row[col.key]} +//
    +// ); +// } + + +// import React from 'react'; +// import './Table.css'; + +// export default function Table({ columns, data }) { +// return ( +// +// +// +// {columns.map((col) => ( +// +// ))} +// +// +// +// {data.map((row, rowIndex) => ( +// +// {columns.map((col, colIndex) => ( +// +// ))} +// +// ))} +// + +//
    {col.header}
    +// {col.render +// ? col.render(row[col.key], row) // usar render si está definido +// : row[col.key]} +//
    +// ); +// } diff --git a/frontend/Frontend-Hotel/src/components/Table/Table.css b/frontend/Frontend-Hotel/src/components/Table/Table.css new file mode 100644 index 0000000..3179f67 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/Table/Table.css @@ -0,0 +1,184 @@ +/* .custom-table { + width: 100%; + border-collapse: collapse; + font-family:'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; +} + +.custom-table thead tr { + background-color: #7b001a; + color: white; +} + +.custom-table th, +.custom-table td { + padding: 10px 15px; + border: 2px solid #ffcc00; + text-align: left; +} + +.custom-table tbody tr { + background-color: #ffffff; + color: black; +} + +.status-badge { + padding: 5px 10px; + border-radius: 14px; + font-weight: bold; + display: inline-block; + text-align: center; +} + +.status-badge.active { + color: green; + border: 1px solid green; + background-color: rgba(0, 128, 0, 0.192); +} + +.status-badge.reject { + color: red; + border: 1px solid rgb(190, 4, 4); + background-color: rgba(255, 0, 0, 0.171); +} + +.status-badge.pending { + color: rgb(128, 83, 0); + border: 1px solid rgb(235, 158, 15); + background-color: rgba(248, 176, 42, 0.76); +} + +.status-button.approve { + background-color: #009e2db0; + color: white; + border: none; + padding: 4px 12px; + border-radius: 2px; + font-weight: bold; +} + +.status-button.reject { + background-color: #d80404b0; + color: white; + border: none; + padding: 4px 12px; + border-radius: 2px; + font-weight: bold; +} */ + +.custom-table { + width: 100%; + border-collapse: collapse; + /* font-family:'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; */ + font-family: 'Franklin Gothic', 'Arial Narrow', Monserrat, sans-serif +} + +.custom-table thead tr { + background-color: #7b001a; + color: white; +} + +/*Bordes de línea*/ +.custom-table th, +.custom-table td { + padding: 10px 15px; + border: 2px solid #ffcc00; + text-align: left; +} + +.custom-table tbody tr { + font-family: montserrat; + background-color: #ffffff; + color: #515151; +} + +.status-badge { + padding: 5px 10px; + border-radius: 14px; + font-weight: bold; + display: inline-block; + text-align: center; +} + +.status-badge.active { + color: green; + border: 1px solid green; + background-color: rgba(0, 128, 0, 0.192); +} + +.status-badge.reject { + color: red; + border: 1px solid rgb(190, 4, 4); + background-color: rgba(255, 0, 0, 0.171); +} + +.status-badge.pending { + color: rgb(128, 83, 0); + border: 1px solid rgb(235, 158, 15); + background-color: rgba(248, 176, 42, 0.76); +} + +.status-badge.paid { + color: green; + border: 1px solid green; + background-color: rgba(0, 128, 0, 0.192); +} + +.status-button.approve { + background-color: #009e2db0; + color: white; + border: none; + padding: 4px 12px; + border-radius: 2px; + font-weight: bold; +} + +.status-button.reject { + background-color: #d80404b0; + color: white; + border: none; + padding: 4px 12px; + border-radius: 2px; + font-weight: bold; +} + +.status-button.pending { + background-color: #e2c000; + color: white; + border: none; + padding: 4px 12px; + border-radius: 2px; + font-weight: bold; +} + +.status-button.paid { + background-color: #009e2db0; + color: white; + border: none; + padding: 4px 12px; + border-radius: 2px; + font-weight: bold; +} + +.add-button { + background-color: transparent; + color: #7b001a; + font-weight: bold; + border: none; + cursor: pointer; + font-size: 14px; +} + +.add-button:hover { + text-decoration: underline; +} + +/*Icono de flecha*/ + +.custom-table a:hover { + color: #0055aa; +} + +.custom-table a:hover svg { + transform: translateX(2px); + transition: transform 0.2s ease; +} diff --git a/frontend/Frontend-Hotel/src/components/topbar/Topbar.css b/frontend/Frontend-Hotel/src/components/topbar/Topbar.css new file mode 100644 index 0000000..4bd4f06 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/topbar/Topbar.css @@ -0,0 +1,8 @@ +/* .topbar { + background-color: #e0b200; + padding: 1rem; + color: #0f0d75; + font-weight: bold; + font-size: 20px; + box-shadow: 0 2px 5px rgba(0,0,0,0.1); +} */ diff --git a/frontend/Frontend-Hotel/src/components/topbar/Topbar.jsx b/frontend/Frontend-Hotel/src/components/topbar/Topbar.jsx new file mode 100644 index 0000000..37d32c0 --- /dev/null +++ b/frontend/Frontend-Hotel/src/components/topbar/Topbar.jsx @@ -0,0 +1,13 @@ +// src/components/Topbar.jsx +import React from "react"; +import "./Topbar.css"; + +const Topbar = () => { + return ( +
    +

    Hacienda San Ángel

    +
    + ); +}; + +export default Topbar; diff --git a/frontend/Frontend-Hotel/src/components/users/userHacienda.jsx b/frontend/Frontend-Hotel/src/components/users/userHacienda.jsx new file mode 100644 index 0000000..e69de29 diff --git a/frontend/Frontend-Hotel/src/constants/menuConfig.js b/frontend/Frontend-Hotel/src/constants/menuConfig.js new file mode 100644 index 0000000..3495e64 --- /dev/null +++ b/frontend/Frontend-Hotel/src/constants/menuConfig.js @@ -0,0 +1,66 @@ +// src/constants/menuConfig.js + +export const menuConfig = { + dashboards: { + label: "Dashboards", + basePath: "/app/income", + submenu: [ + { label: "Income", route: "/app/income" }, + { label: "Hotel P&L", route: "/app/hotelpl" }, + { label: "P&L Restaurant", route: "/app/restaurantpl" }, + { label: "Room Analysis", route: "/app/cost-per-room" }, + { label: "Budget", route: "/app/budget" }, + { label: "Expenses", route: "/app/expenses" }, + ], + }, + income: { + label: "Income", + basePath: "/app/new-income-report", + submenu: [ + { label: "Report", route: "/app/new-income-report" }, + { label: "New Income", route: "/app/new-income-form" }, + ], + }, + expensesToApprove: { + label: "Expenses to be approved", + basePath: "/app/pending-approval", + submenu: [ + { label: "Pending approval", route: "/app/pending-approval" }, + { label: "Approved", route: "/app/approved" }, + { label: "Rejected", route: "/app/rejected" }, + ], + }, + expenses: { + label: "Expenses", + basePath: "/app/report-expense", + submenu: [], + }, + inventory: { + label: "Inventory", + basePath: "/app/products", + submenu: [ + { label: "Products", route: "/app/products" }, + { label: "New Product", route: "/app/new-product" }, + { label: "Report", route: "/app/inventory-report" }, + { label: "Discard Product", route: "/app/discard-product" }, + { label: "Adjustments", route: "/app/product-adjustments" }, + { label: "Outcomes", route: "/app/inventory/outcomes" } + ], + }, + payroll: { + label: "Payroll", + basePath: "/app/payroll", + submenu: [ + { label: "Report", route: "/app/payroll" }, + { label: "Attendance", route: "/app/payroll/attendance" }, + { label: "Employees", route: "/app/payroll/employees" }, + { label: "New Employee", route: "/app/payroll/newemployee" }, + { label: "Contracts", route: "/app/payroll/contract" } + ], + }, + hotel: { + label: "Hotel", + basePath: "/app/hotel", + submenu: [], + }, +}; diff --git a/frontend/Frontend-Hotel/src/constants/menuconfig.js b/frontend/Frontend-Hotel/src/constants/menuconfig.js new file mode 100644 index 0000000..5a15565 --- /dev/null +++ b/frontend/Frontend-Hotel/src/constants/menuconfig.js @@ -0,0 +1,90 @@ +// src/constants/menuConfig.js + +export const menuConfig = { + dashboards: { + label: "Dashboards", + spanish_label: "Tableros", + basePath: "/app/income", + submenu: [ + { label: "Little Hotelier", spanish_label: "Little Hotelier", route: "/app/income" }, + { label: "Hotel P&L", spanish_label: "P&L Hotel", route: "/app/hotelpl" }, + { label: "Room Analysis", spanish_label: "Análisis de Habitaciones", route: "/app/room-analysis" }, + { label: "P&L Restaurant", spanish_label: "P&L Restaurante", route: "/app/restaurantpl" }, + { label: "Restaurant Analysis", spanish_label: "Análisis de Restaurante", route: "/app/restaurant-analysis" }, + // { label: "Budget", spanish_label: "Presupuesto", route: "/app/budget" }, + // { label: "Expenses", spanish_label: "Gastos", route: "/app/expenses" }, + ], + }, + housekeeper: { + label: "Housekeeper", + spanish_label: "Cuidador de Habitaciones", + basePath: "/app/housekeeper/outcomes", + submenu: [], + }, + income: { + label: "Income", + spanish_label: "Ingresos", + basePath: "/app/new-income-report", + submenu: [ + { label: "Report", spanish_label: "Reporte", route: "/app/new-income-report" }, + { label: "New Income", spanish_label: "Nuevo Ingreso", route: "/app/new-income-form" }, + ], + }, + expensesToApprove: { + label: "Expenses to be approved", + spanish_label: "Gastos por aprobar", + basePath: "/app/pending-approval", + submenu: [ + { label: "Pending approval", spanish_label: "Pendientes de aprobación", route: "/app/pending-approval" }, + { label: "Approved", spanish_label: "Aprobados", route: "/app/approved" }, + { label: "Rejected", spanish_label: "Rechazados", route: "/app/rejected" }, + ], + }, + expenses: { + label: "Expenses", + spanish_label: "Gastos", + basePath: "/app/report-expense", + submenu: [ + { label: "Report", spanish_label: "Reporte", route: "/app/report-expense" }, + { label: "New Expense", spanish_label: "Nuevo Gasto", route: "/app/new-expense" }, + { label: "Payments", spanish_label: "Pagos", route: "/app/payments" }, + { label: "Monthly Report", spanish_label: "Reporte Mensual", route: "/app/monthly-report" }, + { label: "Monthly Payments", spanish_label: "Pagos Mensuales", route: "/app/monthly-payments" }, + { label: "New Monthly Payments", spanish_label: "Nuevos Pagos Mensuales", route: "/app/new-monthly", hidden: true }, + { label: "Purchase Entries", spanish_label: "Entradas de Compra", route: "/app/purchase-entries" }, + { label: "New Suppliers", spanish_label: "Nuevos Proveedores", route: "/app/new-suppliers" }, + ], + }, + inventory: { + label: "Inventory", + spanish_label: "Inventario", + basePath: "/app/products", + submenu: [ + { label: "Products", spanish_label: "Productos", route: "/app/products" }, + { label: "New Product", spanish_label: "Nuevo Producto", route: "/app/new-product" }, + { label: "Report", spanish_label: "Reporte", route: "/app/inventory-report" }, + { label: "Discard Product", spanish_label: "Descartar Producto", route: "/app/discard-product" }, + { label: "Adjustments", spanish_label: "Ajustes", route: "/app/product-adjustments" }, + { label: "Outcomes", spanish_label: "Salidas", route: "/app/inventory/outcomes" } + ], + }, + payroll: { + label: "Payroll", + spanish_label: "Nómina", + basePath: "/app/payroll", + submenu: [ + { label: "Report", spanish_label: "Reporte", route: "/app/payroll" }, + { label: "New Contract", spanish_label: "Nuevo Contrato", route: "/app/payroll/newcontract" }, + { label: "Attendance", spanish_label: "Asistencia", route: "/app/payroll/attendance" }, + { label: "Employees", spanish_label: "Empleados", route: "/app/payroll/employees" }, + { label: "New Employee", spanish_label: "Nuevo Empleado", route: "/app/payroll/newemployee" }, + { label: "Contracts", spanish_label: "Contratos", route: "/app/payroll/contract" } + ], + }, + // hotel: { + // label: "Hotel", + // spanish_label: "Hotel", + // basePath: "/app/hotel", + // submenu: [], + // }, +}; diff --git a/frontend/Frontend-Hotel/src/context/AuthContext.jsx b/frontend/Frontend-Hotel/src/context/AuthContext.jsx new file mode 100644 index 0000000..115a608 --- /dev/null +++ b/frontend/Frontend-Hotel/src/context/AuthContext.jsx @@ -0,0 +1,85 @@ +// context/AuthContext.jsx +import { createContext, useState, useEffect } from "react"; + +export const AuthContext = createContext(); + +function AuthProvider({ children }) { + const [user, setUser] = useState(null); // { id, name, role } + const [userData, setUserData] = useState(null); + + // Recuperar user de localStorage al iniciar + useEffect(() => { + const savedUser = localStorage.getItem("rol"); + if (savedUser) { + try { + setUser(JSON.parse(savedUser)); + } catch (error) { + console.error("Error parsing user data:", error); + localStorage.removeItem("rol"); + } + } + }, []); + + const login = (userData, data) => { + setUserData(data); + setUser(userData); + localStorage.setItem("rol", JSON.stringify(userData)); + }; + + const logout = () => { + setUser(null); + localStorage.removeItem("rol"); + }; + + return ( + + {children} + + ); +} + +export { AuthProvider }; + +// // context/AuthContext.jsx +// import { createContext, useState, useEffect } from "react"; + +// export const AuthContext = createContext(); + +// export const AuthProvider = ({ children }) => { +// const [user, setUser] = useState(null); // { id, name, role } +// const [lang, setLang] = useState("es");//true = español + +// // useEffect(() => { +// // const savedUser = localStorage.getItem("rol"); +// // if (savedUser && savedUser !== "undefined") { +// // try { +// // setUser(JSON.parse(savedUser)); +// // } catch (error) { +// // console.error("Error al parsear el usuario:", error); +// // localStorage.removeItem("rol"); // limpia el valor corrupto +// // } +// // } +// // }, []); + +// // Recuperar user de localStorage al iniciar +// useEffect(() => { +// const savedUser = localStorage.getItem("rol"); +// if (savedUser) setUser(JSON.parse(savedUser)); +// }, []); + +// const login = (userData) => { +// setUser(userData); +// localStorage.setItem("rol", JSON.stringify(userData)); +// }; + +// const logout = () => { +// setUser(null); +// localStorage.removeItem("rol"); +// }; + +// return ( +// +// {children} +// +// ); +// }; \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/context/LenguageContext.jsx b/frontend/Frontend-Hotel/src/context/LenguageContext.jsx new file mode 100644 index 0000000..dcb5cd0 --- /dev/null +++ b/frontend/Frontend-Hotel/src/context/LenguageContext.jsx @@ -0,0 +1,24 @@ +import { createContext, useState, useEffect, useContext } from "react"; + +export const langContext = createContext(); + +export const LangProvider = ({ children }) => { + const [lang, setLang] = useState("en"); // Estado para el idioma + + // Ahora 'event' es el objeto de evento de React + const toggleLang = (event) => { + // Extraemos el valor de la opción seleccionada (ej: "es" o "en") + const newLang = event.target.value; + console.log("Nuevo idioma seleccionado:", newLang); + // Establecemos el estado 'lang' con el valor seleccionado + setLang(newLang); + } + + return ( + + {children} + + ); +}; + +export const useLang = () => useContext(langContext); diff --git a/frontend/Frontend-Hotel/src/index.css b/frontend/Frontend-Hotel/src/index.css new file mode 100644 index 0000000..11a1f18 --- /dev/null +++ b/frontend/Frontend-Hotel/src/index.css @@ -0,0 +1,97 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); + +@tailwind base; +@tailwind components; +@tailwind utilities; + + +:root { + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #cc0404de; + text-decoration: inherit; +} + +a:hover { + color: #ff8513; +} + +/* +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; + margin: 0; + padding: 0; + overflow: hidden; + height: 100vh; +} + */ + +body { + margin: 0; + padding: 0; + min-width: 320px; + min-height: 100vh; + height: auto; + overflow-x: hidden; + background-color: #f5f5f5; + display: block; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} + +button:hover { + border-color: #791002; +} + +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + + a:hover { + color: #640f04; + } + + button { + background-color: #f9f9f9; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/main.jsx b/frontend/Frontend-Hotel/src/main.jsx new file mode 100644 index 0000000..29e5407 --- /dev/null +++ b/frontend/Frontend-Hotel/src/main.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import App from "./App.jsx"; +//import { AuthProvider } from "./context/AuthContext.jsx"; +import "./styles/global.css"; +import './index.css'; // o './styles/tailwind.css' +import { AuthProvider } from "./context/AuthContext.jsx"; +import { LangProvider } from "./context/LenguageContext.jsx"; + + +ReactDOM.createRoot(document.getElementById("root")).render( + + + + + + + + +); \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/BasePositiva.jsx b/frontend/Frontend-Hotel/src/pages/BasePositiva.jsx new file mode 100644 index 0000000..b3a74a5 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/BasePositiva.jsx @@ -0,0 +1,40 @@ +import { useState } from "react"; + +export default function BasePositiva() { + const [file, setFile] = useState(null); + const [tipoOp, setTipoOp] = useState("14"); // 14=Alta, 15=Actualización + + const handleSubmit = (e) => { + e.preventDefault(); + if (!file) { + alert("Seleccione un archivo ZIP válido"); + return; + } + // Simulación: aquí luego conectamos al WSUploadFiles + alert(`Archivo ${file.name} enviado como operación ${tipoOp}`); + }; + + return ( +
    +

    Carga de Archivos - Base Positiva

    +
    + + + +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Contracts.jsx b/frontend/Frontend-Hotel/src/pages/Contracts.jsx new file mode 100644 index 0000000..307acde --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Contracts.jsx @@ -0,0 +1,159 @@ +import React, { useEffect, useState } from 'react'; +import Table from '../components/Table/HotelTable'; +import '../components/Filters/Filters.css'; + +// Fake data para probar la tabla con filtros +const fakeContracts = [ + { + id: '0000001', + name: 'María Fernanda López', + position: 'Concierge', + area: 'Hotel', + startDate: '2024-01-17', + endDate: '2025-01-17', + status: 'ACTIVE', + }, + { + id: '0000002', + name: 'José Ángel Ramírez', + position: 'Chef', + area: 'Restaurant', + startDate: '2024-01-15', + endDate: '2025-01-15', + status: 'ACTIVE', + }, + { + id: '0000003', + name: 'Ana Sofía Torres', + position: 'Chef', + area: 'Restaurant', + startDate: '2024-01-23', + endDate: '2025-01-23', + status: 'ACTIVE', + }, + { + id: '0000004', + name: 'Luis Eduardo Mendoza', + position: 'Hostess', + area: 'Restaurant', + startDate: '2024-01-28', + endDate: '2025-04-28', + status: 'INACTIVE', + }, +]; + +export default function Contracts() { + const [contracts, setContracts] = useState([]); + const [filteredContracts, setFilteredContracts] = useState([]); + const [areaFilter, setAreaFilter] = useState(''); + const [statusFilter, setStatusFilter] = useState(''); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + + useEffect(() => { + // Simular fetch de datos + setContracts(fakeContracts); + setFilteredContracts(fakeContracts); + }, []); + + // 🔍 Función para filtrar + useEffect(() => { + let filtered = [...contracts]; + + if (areaFilter) { + filtered = filtered.filter((c) => c.area === areaFilter); + } + + if (statusFilter) { + filtered = filtered.filter((c) => c.status === statusFilter); + } + + if (dateRange.from && dateRange.to) { + filtered = filtered.filter( + (c) => c.endDate >= dateRange.from && c.endDate <= dateRange.to + ); + } + + setFilteredContracts(filtered); + }, [areaFilter, statusFilter, dateRange, contracts]); + + const columns = [ + { header: 'CONTRACT ID', key: 'id' }, + { header: 'NAME', key: 'name' }, + { header: 'POSITION', key: 'position' }, + { header: 'AREA', key: 'area' }, + { header: 'START OF CONTRACT', key: 'startDate' }, + { header: 'END OF CONTRACT', key: 'endDate' }, + { header: 'STATUS', key: 'status' }, + ]; + + return ( +
    +

    Contracts

    + + {/* Filtros */} +
    + + + + + setDateRange({ ...dateRange, from: e.target.value })} + /> + setDateRange({ ...dateRange, to: e.target.value })} + /> +
    + + + + ); +} + + + + +// import React, { useEffect, useState } from 'react'; +// import { getContracts } from '../services/contractService'; +// import Table from '../components/Table/HotelTable'; + +// export default function Contracts() { +// const [contracts, setContracts] = useState([]); + +// useEffect(() => { +// async function fetchData() { +// const data = await getContracts(); +// setContracts(data); +// } + +// fetchData(); +// }, []); + +// const columns = [ +// { header: 'CONTRACT ID', key: 'id' }, +// { header: 'NAME', key: 'name' }, +// { header: 'POSITION', key: 'position' }, +// { header: 'AREA', key: 'area' }, +// { header: 'START OF CONTRACT', key: 'startDate' }, +// { header: 'END OF CONTRACT', key: 'endDate' }, +// { header: 'STATUS', key: 'status' }, +// ]; + +// return ( +//
    +//

    Contracts

    +//
    +// +// ); +// } diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard.jsx new file mode 100644 index 0000000..a41a144 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard.jsx @@ -0,0 +1,43 @@ +import { useEffect, useState } from "react"; +import api from "../services/api.js"; + +export default function Dashboard() { + const [users, setUsers] = useState([]); + const [loading, setLoading] = useState(true); + const [err, setErr] = useState(""); + + useEffect(() => { + let mounted = true; + (async () => { + try { + // Demo: trae usuarios desde la API configurada + const { data } = await api.get("/users"); + if (mounted) setUsers(data); + } catch (e) { + setErr("No se pudo cargar el Dashboard"); + } finally { + if (mounted) setLoading(false); + } + })(); + return () => { mounted = false; }; + }, []); + + if (loading) return

    Cargando...

    ; + if (err) return

    {err}

    ; + + return ( +
    +

    Dashboard

    +

    Usuarios demo desde la API:

    +
    + {users.map((u) => ( +
    +

    {u.name}

    +

    {u.email}

    + {u.username} +
    + ))} +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/Budget.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/Budget.jsx new file mode 100644 index 0000000..fd6efd6 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/Budget.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +export default function Budget() { + return ( +
    +

    Budget

    +

    Budget dashboard coming soon...

    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/CostPerRoom.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/CostPerRoom.jsx new file mode 100644 index 0000000..94e5ded --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/CostPerRoom.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +export default function CostPerRoom() { + return ( +
    +

    Cost Per Room

    +

    Cost per room analysis coming soon...

    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/Expenses.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/Expenses.jsx new file mode 100644 index 0000000..f26c6b3 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/Expenses.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +export default function Expenses() { + return ( +
    +

    Expenses

    +

    Expenses dashboard coming soon...

    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/HotelPL.css b/frontend/Frontend-Hotel/src/pages/Dashboard/HotelPL.css new file mode 100644 index 0000000..402ca53 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/HotelPL.css @@ -0,0 +1,350 @@ +.report-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.loading-container { + display: flex; + justify-content: center; + align-items: center; + padding: 60px 20px; + color: #666; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 4px solid #f3f3f3; + border-top: 4px solid #5D1A2A; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +.loading-text { + margin-left: 15px; + font-size: 16px; +} + +.pl-form-container { + display: flex; + flex-direction: column; + gap: 24px; + margin-top: 24px; +} + +.pl-section { + background-color: white; + border-radius: 8px; + padding: 24px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + border: 1px solid #e5e7eb; +} + +.section-title { + margin: 0 0 20px 0; + font-size: 22px; + font-weight: 600; + color: #374151; + border-bottom: 2px solid #5D1A2A; + padding-bottom: 10px; +} + +.section-header-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + align-items: center; + margin: 0 0 20px 0; + border-bottom: 2px solid #5D1A2A; + padding-bottom: 10px; +} + +.section-header-row .section-title { + margin: 0; + border-bottom: none; + padding-bottom: 0; +} + +.section-header-percentage { + font-size: 16px; + font-weight: 700; + color: #5D1A2A; + text-align: left; + padding-left: 212px; +} + +.form-row { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 16px; + gap: 16px; +} + +.form-row-split { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + margin-bottom: 16px; +} + +.form-col { + display: flex; + flex-direction: row; + align-items: center; + gap: 12px; +} + +.form-label { + font-weight: 600; + font-size: 16px; + color: #374151; + min-width: 200px; + flex-shrink: 0; +} + +.form-label.label-bold { + font-weight: 900; + color: #000; + font-size: 18px; +} + + +.form-input { + width: 100%; + padding: 10px 12px; + border: 1px solid #d1d5db; + border-radius: 6px; + font-size: 16px; + background-color: #f9fafb; + color: #111827; + font-weight: 500; + box-sizing: border-box; +} + +.form-input:focus { + outline: none; + border-color: #5D1A2A; +} + +.form-input.highlight { + background-color: #fef3c7; + border-color: #fbbf24; + font-weight: 700; + font-size: 15px; +} + +.no-data-message { + text-align: center; + padding: 40px 20px; + color: #9ca3af; + font-size: 14px; +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } +} + +@media (max-width: 768px) { + .report-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .form-row { + flex-direction: column; + align-items: flex-start; + gap: 6px; + } + + .form-row-split { + grid-template-columns: 1fr; + gap: 12px; + } + + .form-col { + flex-direction: column; + align-items: flex-start; + gap: 6px; + } + + .form-label { + min-width: auto; + } + + .section-header-row { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + + .section-header-percentage { + display: none; + } + + .pl-section { + padding: 16px; + } + + .section-title { + font-size: 16px; + } +} + +/* Metrics Grid Styles */ +.metrics-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 20px; + margin-top: 24px; +} + +.metric-card { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + transition: all 0.2s ease; +} + +.metric-card:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + transform: translateY(-2px); +} + +.metric-card h3 { + color: #1a1a1a; + font-size: 16px; + font-weight: 600; + margin: 0 0 16px 0; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + text-transform: uppercase; + letter-spacing: 0.5px; + opacity: 0.8; +} + +.metric-value { + display: flex; + align-items: center; + min-height: 48px; +} + +.count-value { + font-size: 32px; + font-weight: 700; + color: #1a1a1a; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +.currency-value { + font-size: 28px; + font-weight: 700; + color: #1a1a1a; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +.total-value { + color: #5D1A2A; + font-size: 32px; +} + +.loading-skeleton { + width: 120px; + height: 40px; + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: loading 1.5s infinite; + border-radius: 4px; +} + +@keyframes loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +@media (max-width: 768px) { + .metrics-grid { + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 16px; + } + + .metric-card { + padding: 20px; + } + + .count-value { + font-size: 28px; + } + + .currency-value { + font-size: 24px; + } + + .total-value { + font-size: 28px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .form-input { + font-size: 13px; + padding: 8px 10px; + } + + .form-label { + font-size: 13px; + } + + .metrics-grid { + grid-template-columns: 1fr; + gap: 12px; + } + + .metric-card { + padding: 16px; + } + + .metric-card h3 { + font-size: 14px; + margin-bottom: 12px; + } + + .count-value { + font-size: 24px; + } + + .currency-value { + font-size: 20px; + } + + .total-value { + font-size: 24px; + } +} diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/HotelPL.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/HotelPL.jsx new file mode 100644 index 0000000..24dfbd7 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/HotelPL.jsx @@ -0,0 +1,438 @@ +import React, { useEffect, useState } from 'react'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import './HotelPL.css'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function HotelPL() { + const { lang } = useContext(langContext); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [revenue, setRevenue] = useState(0); + const [cogs, setCogs] = useState(0); + const [employeeShare, setEmployeeShare] = useState(0); + const [tips, setTips] = useState(0); + const [grossProfit, setGrossProfit] = useState(0); + const [weightedCategoriesCost, setWeightedCategoriesCost] = useState([]); + const [totalExpenses, setTotalExpenses] = useState(0); + const [ebitda, setEbitda] = useState(0); + const [loading, setLoading] = useState(false); + + const formatDate = (dateStr) => { + return dateStr; + }; + + const formatCurrency = (value) => { + const num = parseFloat(value || 0); + return num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + }; + + const calculatePercentage = (value, total) => { + if (!total || total === 0) return '0.00'; + return ((parseFloat(value) / parseFloat(total)) * 100).toFixed(2); + }; + + const formatPercentageForDisplay = (percentageValue) => { + const numValue = parseFloat(percentageValue); + return (numValue * 100).toFixed(2); + }; + + const loadRevenue = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/totalrevenue`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setRevenue(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading revenue:', err); + setRevenue(0); + } + }; + + const loadCogs = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/cogs`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setCogs(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading COGS:', err); + setCogs(0); + } + }; + + const loadEmployeeShare = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/employeeshare`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setEmployeeShare(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading employee share:', err); + setEmployeeShare(0); + } + }; + + const loadTips = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/tips`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setTips(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading tips:', err); + setTips(0); + } + }; + + const loadGrossProfit = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/grossprofit`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setGrossProfit(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading gross profit:', err); + setGrossProfit(0); + } + }; + + const loadWeightedCategoriesCost = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/weightedcategoriescost`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + + const mapped = json.data.map(item => ({ + id: item.id_expense_cat, + category: item.category_name, + es_category: item.spanish_name, + total: item.total, + participation: parseFloat(item.participation).toFixed(2) + '%' + })); + + setWeightedCategoriesCost(mapped); + + } catch (err) { + console.error('Error loading weigted categories:', err); + } + }; + + const loadEbidta = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/hotelpl/ebitda`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + + const data = json.data[0]; + setTotalExpenses(parseFloat(data.expenses_total || 0)); + setEbitda(parseFloat(data.ebitda || 0)); + + } catch (err) { + console.error('Error loading ebitda:', err); + setTotalExpenses(0); + setEbitda(0); + } + }; + + + useEffect(() => { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const pad = (n) => n.toString().padStart(2, '0'); + const from = `${year}-${pad(month + 1)}-${pad(firstDay.getDate())}`; + const to = `${year}-${pad(month + 1)}-${pad(lastDay.getDate())}`; + setDateRange({ from, to }); + }, []); + + useEffect(() => { + if (!dateRange.from || !dateRange.to) return; + + setLoading(true); + setRevenue(0); + setCogs(0); + setEmployeeShare(0); + setGrossProfit(0); + setWeightedCategoriesCost([]); + setTotalExpenses(0); + setEbitda(0); + + Promise.all([ + loadRevenue(), + loadCogs(), + loadEmployeeShare(), + loadTips(), + loadGrossProfit(), + loadWeightedCategoriesCost(), + loadEbidta() + ]).finally(() => { + setLoading(false); + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dateRange]); + + const totalNetRevenue = revenue; + + return ( +
    +
    +

    + {lang === "en" ? "Hotel P&L" : "P&L del Hotel"} +

    +
    + + + + {loading ? ( +
    +
    + + + {lang === "en" ? "Loading financial data..." : "Cargando datos financieros..."} + +
    + ) : ( +
    + +
    +
    +

    + {lang === "en" ? "Income" : "Ingresos"} +

    + + % {lang === "en" ? "Total Net Revenue" : "Ingreso Neto Total"} + +
    + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    +
    +
    + +
    +
    +

    + {lang === "en" ? "Expenses" : "Gastos"} +

    + + % {lang === "en" ? "Total Net Revenue" : "Ingreso Neto Total"} + +
    + + {weightedCategoriesCost.length > 0 ? ( + <> + {weightedCategoriesCost.map((expense, index) => ( +
    +
    + + +
    +
    + +
    +
    + ))} + + ) : ( +
    + {lang === "en" ? "No expense data available" : "No hay datos de gastos disponibles"} +
    + )} +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    + )} +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/Income.css b/frontend/Frontend-Hotel/src/pages/Dashboard/Income.css new file mode 100644 index 0000000..4d102cb --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/Income.css @@ -0,0 +1,144 @@ +.income-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.summary-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 20px; + padding: 24px; + margin-bottom: 32px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.summary-cards-wrapper { + display: flex; + gap: 20px; + flex-wrap: wrap; +} + +.table-section { + background: white; + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-height: 400px; +} + +.table-loading { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 400px; + gap: 16px; +} + +.loading-spinner-large { + width: 60px; + height: 60px; + border: 5px solid rgba(0, 0, 0, 0.1); + border-top-color: #fcd200; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +.table-loading p { + color: #666; + font-size: 16px; + font-weight: 500; + margin: 0; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +@media (max-width: 1400px) { + .summary-cards-wrapper { + gap: 16px; + } +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } + + .summary-section { + padding: 20px; + } + + .summary-cards-wrapper { + gap: 12px; + } + + .table-section { + padding: 20px; + } +} + +@media (max-width: 768px) { + .income-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .summary-section { + padding: 16px; + border-radius: 16px; + } + + .summary-cards-wrapper { + flex-direction: column; + gap: 12px; + } + + .table-section { + padding: 16px; + border-radius: 12px; + } + + .table-loading { + min-height: 300px; + } + + .loading-spinner-large { + width: 50px; + height: 50px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .summary-section { + padding: 12px; + } + + .table-section { + padding: 12px; + } +} + diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/Income.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/Income.jsx new file mode 100644 index 0000000..e48ada1 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/Income.jsx @@ -0,0 +1,365 @@ +import React, { useEffect, useState } from 'react'; +import Table from '../../components/Table/HotelTable'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import SummaryCard from '../../components/SummaryCard'; +import ExcelExportButton from '../../components/ExcelExportButton'; +import '../../components/Filters/Filters.css'; +import './Income.css'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + + +// Ya no se usan datos estáticos para canales + + +export default function Income() { + const {lang} = useContext(langContext); + // Card: Total income (dinámico) + const [totalIncome, setTotalIncome] = useState(0); + // Cards: canales (Booking, Expedia, Mr and Mrs Smith) + const [channels, setChannels] = useState({ booking: 0, expedia: 0, mrsmith: 0 }); + // Tabla usa datos del endpoint + const [filteredRooms, setFilteredRooms] = useState([]); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [loadingChannels, setLoadingChannels] = useState(false); + const [loadingTotalIncome, setLoadingTotalIncome] = useState(false); + const [loadingTable, setLoadingTable] = useState(false); + // Consumir el endpoint para las tarjetas de canales + useEffect(() => { + async function fetchChannels() { + if (dateRange.from && dateRange.to) { + setLoadingChannels(true); + // Formatear fechas a dd-mm-yyyy + const formatDate = (dateStr) => { + const [year, month, day] = dateStr.split('-'); + return `${year}-${month}-${day}`; + }; + const checkin_initial = formatDate(dateRange.from); + const checkin_final = formatDate(dateRange.to); + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/incomes/channelscards', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ checkin_initial, checkin_final }) + }); + const data = await response.json(); + console.log(data.data); + setChannels({ + booking: data.data[3].total_channel || 0, + expedia: data.data[1].total_channel || 0, + mrsmith: data.data[4].total_channel || 0, + }); + } catch { + setChannels({ booking: 0, expedia: 0, mrsmith: 0 }); + } finally { + setLoadingChannels(false); + } + } else { + setChannels({ booking: 0, expedia: 0, mrsmith: 0 }); + setLoadingChannels(false); + } + } + fetchChannels(); + }, [dateRange]); + // Consumir el endpoint para la tarjeta Total income + useEffect(() => { + async function fetchTotalIncome() { + if (dateRange.from && dateRange.to) { + setLoadingTotalIncome(true); + // Formatear fechas a dd-mm-yyyy + const formatDate = (dateStr) => { + const [year, month, day] = dateStr.split('-'); + return `${year}-${month}-${day}`; + }; + const checkin_initial = formatDate(dateRange.from); + const checkin_final = formatDate(dateRange.to); + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/incomes/totalincomes', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ checkin_initial, checkin_final }) + }); + const data = await response.json(); + setTotalIncome(data.data || 0); + } catch { + setTotalIncome(0); + } finally { + setLoadingTotalIncome(false); + } + } else { + setTotalIncome(0); + setLoadingTotalIncome(false); + } + } + fetchTotalIncome(); + }, [dateRange]); + + // Al cargar la página, seleccionar el rango de fechas de un mes + useEffect(() => { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + // Primer día del mes + const firstDay = new Date(year, month, 1); + // Último día del mes + const lastDay = new Date(year, month + 1, 0); + // Formato yyyy-mm-dd + const pad = (n) => n.toString().padStart(2, '0'); + const from = `${year}-${pad(month + 1)}-${pad(firstDay.getDate())}`; + const to = `${year}-${pad(month + 1)}-${pad(lastDay.getDate())}`; + setDateRange({ from, to }); + }, []); + + // Consumir el endpoint solo para la tabla + useEffect(() => { + async function fetchIncome() { + if (dateRange.from && dateRange.to) { + setLoadingTable(true); + // Formatear fechas a dd-mm-yyyy + const formatDate = (dateStr) => { + const [year, month, day] = dateStr.split('-'); + return `${year}-${month}-${day}`; + }; + try { + const checkin_initial = formatDate(dateRange.from); + const checkin_final = formatDate(dateRange.to); + // GET pero solo para la tabla + const url = import.meta.env.VITE_API_BASE_URL + `/incomes/getincomes`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ checkin_initial, checkin_final }) + }); + const data = await response.json(); + setFilteredRooms( data.data || []); + } catch { + setFilteredRooms([]); + } finally { + setLoadingTable(false); + } + } else { + setFilteredRooms([]); + setLoadingTable(false); + } + } + fetchIncome(); + }, [dateRange]); + + const columns = [ + { header: 'ROOM', key: 'room' }, + { header: 'OCCUPATION', key: 'occupation' }, + { + header: 'AVG. INCOME PER NIGHT', + key: 'income_per_night', + render: (value) => value ? `$${parseFloat(value).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '' + }, + { + header: 'TOTAL INCOME', + key: 'total_income', + render: (value) => value ? `$${parseFloat(value).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '' + }, + ]; + + const exportColumns = [ + { header: lang === "es" ? "HABITACIÓN" : "ROOM", key: "room" }, + { header: lang === "es" ? "OCUPACIÓN" : "OCCUPATION", key: "occupation" }, + { header: lang === "es" ? "INGRESO PROMEDIO POR NOCHE" : "AVG. INCOME PER NIGHT", key: "income_per_night" }, + { header: lang === "es" ? "INGRESO TOTAL" : "TOTAL INCOME", key: "total_income" }, + ]; + + const dataTransform = (data) => { + return data.map((row) => ({ + ...row, + income_per_night: row.income_per_night ? `$${parseFloat(row.income_per_night).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '', + total_income: row.total_income ? `$${parseFloat(row.total_income).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '', + })); + }; + + // Cards usan datos dinámicos de canales y totalIncome + const bookingPercentage = totalIncome + ? Math.round((channels.booking / totalIncome) * 100) + : 0; + const expediaPercentage = totalIncome + ? Math.round((channels.expedia / totalIncome) * 100) + : 0; + const mrsmithPercentage = totalIncome + ? Math.round((channels.mrsmith / totalIncome) * 100) + : 0; + + return ( +
    +
    +

    + {lang === "en" ? "Little Hotelier" : "Little Hotelier"} +

    +
    + + + +
    +
    + + + + +
    +
    + +
    + +
    + +
    + {loadingTable ? ( +
    +
    +

    {lang === "en" ? "Loading data..." : "Cargando datos..."}

    +
    + ) : ( +
    + )} + + + ); +} + +// const fakeIncome = { +// totalIncome: 15950, +// booking: 7975, +// expedia: 4785, +// rooms: [ +// { +// name: 'San Miguel Presidential', +// occupation: '10 nights', +// avgIncomePerNight: '$300', +// totalIncome: '$3,000', +// }, +// { +// name: 'Angels View', +// occupation: '15 nights', +// avgIncomePerNight: '$300', +// totalIncome: '$4,500', +// }, +// { +// name: 'Angels Dome', +// occupation: '17 nights', +// avgIncomePerNight: '$250', +// totalIncome: '$4,250', +// }, +// { +// name: 'Celestial', +// occupation: '21 nights', +// avgIncomePerNight: '$200', +// totalIncome: '$4,200', +// }, +// ], +// }; + +// export default function Income() { +// const [income, setIncome] = useState({}); +// const [filteredRooms, setFilteredRooms] = useState([]); +// const [dateRange, setDateRange] = useState({ from: '', to: '' }); + +// useEffect(() => { +// // Simular carga de datos +// setIncome(fakeIncome); +// setFilteredRooms(fakeIncome.rooms); +// }, []); + +// // Si en el futuro deseas aplicar filtros por fecha real: +// useEffect(() => { +// if (dateRange.from && dateRange.to) { +// // Lógica de filtrado por fecha (si tuvieras fechas en los datos de cada habitación) +// // Aquí se deja como estático porque los datos no tienen campo de fecha +// setFilteredRooms(fakeIncome.rooms); // Simulando que no cambia +// } +// }, [dateRange]); + +// const columns = [ +// { header: 'ROOM', key: 'name' }, +// { header: 'OCCUPATION', key: 'occupation' }, +// { header: 'AVG. INCOME PER NIGHT', key: 'avgIncomePerNight' }, +// { header: 'TOTAL INCOME', key: 'totalIncome' }, +// ]; + +// const bookingPercentage = income.totalIncome +// ? Math.round((income.booking / income.totalIncome) * 100) +// : 0; +// const expediaPercentage = income.totalIncome +// ? Math.round((income.expedia / income.totalIncome) * 100) +// : 0; + +// return ( +//
    +//

    INCOME

    + +// {/* Date Filters */} +//
    +// setDateRange({ ...dateRange, from: e.target.value })} +// /> +// setDateRange({ ...dateRange, to: e.target.value })} +// /> +//
    + +// {/* Summary Cards */} +//
    +//
    +// Total income +//
    ${income.totalIncome?.toLocaleString() || 0}
    +//
    +//
    +// Booking +//
    ${income.booking?.toLocaleString() || 0}
    +//
    {bookingPercentage}%
    +//
    +//
    +// Expedia +//
    ${income.expedia?.toLocaleString() || 0}
    +//
    {expediaPercentage}%
    +//
    +//
    + +// {/* Income Table */} +//
    +// +// ); +// } + + +//style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px', marginBottom: '15px' }} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/RestaurantAnalysis.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/RestaurantAnalysis.jsx new file mode 100644 index 0000000..1e09ca6 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/RestaurantAnalysis.jsx @@ -0,0 +1,348 @@ +import React, { useEffect, useState, useCallback } from 'react'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import './HotelPL.css'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function RestaurantAnalysis() { + const { lang } = useContext(langContext); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [countticket, setCountticket] = useState(0); + const [efectivo, setEfectivo] = useState(0); + const [otros, setOtros] = useState(0); + const [propinas, setPropinas] = useState(0); + const [tarjeta, setTarjeta] = useState(0); + const [vales, setVales] = useState(0); + const [sumatotal, setSumatotal] = useState(0); + const [ticketpromedio, setTicketpromedio] = useState(0); + const [loading, setLoading] = useState(false); + + // Set default dates to current month + useEffect(() => { + const now = new Date(); + const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); + const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); + + const formatDateForInput = (date) => { + return date.toISOString().split('T')[0]; + }; + + setDateRange({ + from: formatDateForInput(startOfMonth), + to: formatDateForInput(endOfMonth) + }); + }, []); + + const formatDate = (dateStr) => { + if (!dateStr) return ''; + const date = new Date(dateStr); + return date.toISOString().split('T')[0]; + }; + + const formatCurrency = (value) => { + const num = parseFloat(value || 0); + return num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + }; + + const loadCountticket = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/countticket`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setCountticket(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading countticket:', err); + setCountticket(0); + } + }, [dateRange]); + + const loadEfectivo = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/efectivo`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setEfectivo(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading efectivo:', err); + setEfectivo(0); + } + }, [dateRange]); + + const loadOtros = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/otros`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setOtros(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading otros:', err); + setOtros(0); + } + }, [dateRange]); + + const loadPropinas = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/propinas`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setPropinas(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading propinas:', err); + setPropinas(0); + } + }, [dateRange]); + + const loadTarjeta = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/tarjeta`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setTarjeta(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading tarjeta:', err); + setTarjeta(0); + } + }, [dateRange]); + + const loadVales = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/vales`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setVales(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading vales:', err); + setVales(0); + } + }, [dateRange]); + + const loadSumatotal = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/sumatotal`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setSumatotal(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading sumatotal:', err); + setSumatotal(0); + } + }, [dateRange]); + + const loadTicketpromedio = useCallback(async () => { + if (!dateRange.from || !dateRange.to) return; + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomes/ticketpromedio`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + initial_date: formatDate(dateRange.from), + final_date: formatDate(dateRange.to) + }) + }); + const json = await res.json(); + setTicketpromedio(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading ticketpromedio:', err); + setTicketpromedio(0); + } + }, [dateRange]); + + useEffect(() => { + const loadAllData = async () => { + if (!dateRange.from || !dateRange.to) return; + + setLoading(true); + try { + await Promise.all([ + loadCountticket(), + loadEfectivo(), + loadOtros(), + loadPropinas(), + loadTarjeta(), + loadVales(), + loadSumatotal(), + loadTicketpromedio() + ]); + } catch (err) { + console.error('Error loading data:', err); + } finally { + setLoading(false); + } + }; + + loadAllData(); + }, [dateRange, loadCountticket, loadEfectivo, loadOtros, loadPropinas, loadTarjeta, loadVales, loadSumatotal, loadTicketpromedio]); + + return ( +
    +
    +

    + {lang === "en" ? "Restaurant Analysis" : "Análisis de Restaurante"} +

    +
    + +
    + +
    + +
    + {/* Count Tickets Card */} +
    +

    {lang === "en" ? "Count Tickets" : "Cantidad de Tickets"}

    +
    + {loading ? ( +
    + ) : ( + {countticket.toLocaleString()} + )} +
    +
    + + {/* Efectivo Card */} +
    +

    {lang === "en" ? "Cash" : "Efectivo"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(efectivo)} + )} +
    +
    + + {/* Otros Card */} +
    +

    {lang === "en" ? "Others" : "Otros"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(otros)} + )} +
    +
    + + {/* Propinas Card */} +
    +

    {lang === "en" ? "Tips" : "Propinas"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(propinas)} + )} +
    +
    + + {/* Tarjeta Card */} +
    +

    {lang === "en" ? "Card" : "Tarjeta"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(tarjeta)} + )} +
    +
    + + {/* Vales Card */} +
    +

    {lang === "en" ? "Vouchers" : "Vales"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(vales)} + )} +
    +
    + + {/* Suma Total Card */} +
    +

    {lang === "en" ? "Total Sum" : "Suma Total"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(sumatotal)} + )} +
    +
    + + {/* Ticket Promedio Card */} +
    +

    {lang === "en" ? "Average Ticket" : "Ticket Promedio"}

    +
    + {loading ? ( +
    + ) : ( + ${formatCurrency(ticketpromedio)} + )} +
    +
    +
    +
    + ); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/RestaurantPL.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/RestaurantPL.jsx new file mode 100644 index 0000000..b845267 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/RestaurantPL.jsx @@ -0,0 +1,349 @@ +import React, { useEffect, useState } from 'react'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import './HotelPL.css'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function RestaurantPL() { + const { lang } = useContext(langContext); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [revenue, setRevenue] = useState(0); + const [cogs, setCogs] = useState(0); + const [grossProfit, setGrossProfit] = useState(0); + const [weightedCategoriesCost, setWeightedCategoriesCost] = useState([]); + const [totalExpenses, setTotalExpenses] = useState(0); + const [ebitda, setEbitda] = useState(0); + const [loading, setLoading] = useState(false); + + const formatDate = (dateStr) => { + return dateStr; + }; + + const formatCurrency = (value) => { + const num = parseFloat(value || 0); + return num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + }; + + const calculatePercentage = (value, total) => { + if (!total || total === 0) return '0.00'; + return ((parseFloat(value) / parseFloat(total)) * 100).toFixed(2); + }; + + const formatPercentageForDisplay = (percentageValue) => { + const numValue = parseFloat(percentageValue); + return (numValue * 100).toFixed(2); + }; + + const loadRevenue = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/restaurantpl/totalrevenue`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setRevenue(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading revenue:', err); + setRevenue(0); + } + }; + + const loadCogs = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/restaurantpl/cogs`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setCogs(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading COGS:', err); + setCogs(0); + } + }; + + const loadGrossProfit = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/restaurantpl/grossprofit`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + setGrossProfit(parseFloat(json.data || 0)); + } catch (err) { + console.error('Error loading gross profit:', err); + setGrossProfit(0); + } + }; + + const loadWeightedCategoriesCost = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/restaurantpl/weightedcategoriescost`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + + const mapped = json.data.map(item => ({ + id: item.id_expense_cat, + category: item.category_name, + es_category: item.spanish_name, + total: item.total, + participation: parseFloat(item.participation).toFixed(2) + '%' + })); + + setWeightedCategoriesCost(mapped); + + } catch (err) { + console.error('Error loading weigted categories:', err); + } + }; + + const loadEbidta = async () => { + const start_date = formatDate(dateRange.from); + const end_date = formatDate(dateRange.to); + + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/restaurantpl/ebitda`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ start_date, end_date }) + }); + const json = await res.json(); + + const data = json.data[0]; + setTotalExpenses(parseFloat(data.expenses_total || 0)); + setEbitda(parseFloat(data.ebitda || 0)); + + } catch (err) { + console.error('Error loading ebitda:', err); + setTotalExpenses(0); + setEbitda(0); + } + }; + + + useEffect(() => { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const pad = (n) => n.toString().padStart(2, '0'); + const from = `${year}-${pad(month + 1)}-${pad(firstDay.getDate())}`; + const to = `${year}-${pad(month + 1)}-${pad(lastDay.getDate())}`; + setDateRange({ from, to }); + }, []); + + useEffect(() => { + if (!dateRange.from || !dateRange.to) return; + + setLoading(true); + setRevenue(0); + setCogs(0); + setGrossProfit(0); + setWeightedCategoriesCost([]); + setTotalExpenses(0); + setEbitda(0); + + Promise.all([ + loadRevenue(), + loadCogs(), + loadGrossProfit(), + loadWeightedCategoriesCost(), + loadEbidta() + ]).finally(() => { + setLoading(false); + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dateRange]); + + const totalNetRevenue = revenue; + + return ( +
    +
    +

    + {lang === "en" ? "Restaurant P&L" : "P&L del Restaurante"} +

    +
    + + + + {loading ? ( +
    +
    + + + {lang === "en" ? "Loading financial data..." : "Cargando datos financieros..."} + +
    + ) : ( +
    + +
    +
    +

    + {lang === "en" ? "Income" : "Ingresos"} +

    + + % {lang === "en" ? "Total Net Revenue" : "Ingreso Neto Total"} + +
    + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + +
    +
    + + +
    +
    + +
    +
    +
    + +
    +
    +

    + {lang === "en" ? "Expenses" : "Gastos"} +

    + + % {lang === "en" ? "Total Net Revenue" : "Ingreso Neto Total"} + +
    + + {weightedCategoriesCost.length > 0 ? ( + <> + {weightedCategoriesCost.map((expense, index) => ( +
    +
    + + +
    +
    + +
    +
    + ))} + + ) : ( +
    + {lang === "en" ? "No expense data available" : "No hay datos de gastos disponibles"} +
    + )} +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    + )} +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Dashboard/RoomAnalysis.jsx b/frontend/Frontend-Hotel/src/pages/Dashboard/RoomAnalysis.jsx new file mode 100644 index 0000000..ffa6c9e --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Dashboard/RoomAnalysis.jsx @@ -0,0 +1,234 @@ +import React, { useEffect, useState, useContext } from 'react'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import SummaryCard from '../../components/SummaryCard'; +import Table from '../../components/Table/HotelTable'; +import ExcelExportButton from '../../components/ExcelExportButton'; +import { langContext } from '../../context/LenguageContext'; +import '../../components/Filters/Filters.css'; +import './Income.css'; + +export default function RoomAnalysis() { + const { lang } = useContext(langContext); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [reportData, setReportData] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const formatCurrency = (value) => { + const num = parseFloat(value || 0); + return num.toLocaleString('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }); + }; + + const fetchReportData = async () => { + if (!dateRange.from || !dateRange.to) return; + + setLoading(true); + setError(null); + + try { + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/incomes/reportincomes`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + initial_date: dateRange.from, + final_date: dateRange.to, + }), + } + ); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (Array.isArray(data)) { + setReportData(data); + } else if (data.data && Array.isArray(data.data)) { + setReportData(data.data); + } else if (data.result && Array.isArray(data.result)) { + setReportData(data.result); + } else { + setReportData([]); + } + } catch (err) { + console.error('Error fetching report data:', err); + setError(err.message); + setReportData([]); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + + const pad = (n) => n.toString().padStart(2, '0'); + const from = `${year}-${pad(month + 1)}-${pad(firstDay.getDate())}`; + const to = `${year}-${pad(month + 1)}-${pad(lastDay.getDate())}`; + + setDateRange({ from, to }); + }, []); + + useEffect(() => { + if (dateRange.from && dateRange.to) { + fetchReportData(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dateRange]); + + const calculateSummary = () => { + if (!reportData.length) return { revpar: 0, fixedCost: 0 }; + + const totalIncome = reportData.reduce((sum, item) => { + return sum + parseFloat(item.total_income || 0); + }, 0); + + const totalUses = reportData.reduce((sum, item) => { + return sum + parseInt(item.total_uses || 0, 10); + }, 0); + + const revpar = totalUses > 0 ? totalIncome / totalUses : 0; + const fixedCost = totalIncome; + + return { revpar, fixedCost }; + }; + + const summary = calculateSummary(); + + const columns = [ + { + header: 'ROOM', + key: 'room_type', + render: (value) => value || '-' + }, + { + header: 'ADR', + key: 'ADR', + render: (value) => `$${formatCurrency(value || 0)}` + }, + { + header: 'CPOR', + key: 'CPOR', + render: (value) => `$${formatCurrency(value || 0)}` + }, + { + header: 'CPAR', + key: 'CPAR', + render: (value) => `$${formatCurrency(value || 0)}` + }, + { + header: 'PPOR', + key: 'PPOR', + render: (value) => `$${formatCurrency(value || 0)}` + }, + { + header: 'BREAK EVEN POINT', + key: 'break_event_point', + render: (value) => parseFloat(value || 0).toFixed(2) + }, + { + header: 'GIFT ROOM', + key: 'gift_room', + render: (value) => `$${formatCurrency(value || 0)}` + }, + ]; + + const exportColumns = [ + { header: lang === "es" ? "HABITACIÓN" : "ROOM", key: "room_type" }, + { header: lang === "es" ? "ADR" : "ADR", key: "ADR" }, + { header: lang === "es" ? "CPOR" : "CPOR", key: "CPOR" }, + { header: lang === "es" ? "CPAR" : "CPAR", key: "CPAR" }, + { header: lang === "es" ? "PPOR" : "PPOR", key: "PPOR" }, + { header: lang === "es" ? "PUNTO DE EQUILIBRIO" : "BREAK EVEN POINT", key: "break_event_point" }, + { header: lang === "es" ? "HABITACIÓN DE REGALO" : "GIFT ROOM", key: "gift_room" }, + ]; + + const dataTransform = (data) => { + return data.map((row) => ({ + ...row, + ADR: row.ADR ? `$${formatCurrency(row.ADR)}` : '', + CPOR: row.CPOR ? `$${formatCurrency(row.CPOR)}` : '', + CPAR: row.CPAR ? `$${formatCurrency(row.CPAR)}` : '', + PPOR: row.PPOR ? `$${formatCurrency(row.PPOR)}` : '', + break_event_point: row.break_event_point ? parseFloat(row.break_event_point || 0).toFixed(2) : '', + gift_room: row.gift_room ? `$${formatCurrency(row.gift_room)}` : '', + })); + }; + + return ( +
    +
    +

    + {lang === 'en' ? 'Room Analysis' : 'Análisis de Habitaciones'} +

    +
    + + + +
    +
    + + +
    +
    + +
    + +
    + +
    + {loading ? ( +
    +
    +

    {lang === 'en' ? 'Loading room analysis data...' : 'Cargando datos de análisis de habitaciones...'}

    +
    + ) : error ? ( +
    +

    {lang === 'en' ? `Error loading data: ${error}` : `Error al cargar datos: ${error}`}

    +
    + ) : ( +
    + )} + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Employees.jsx b/frontend/Frontend-Hotel/src/pages/Employees.jsx new file mode 100644 index 0000000..79b96b0 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Employees.jsx @@ -0,0 +1,241 @@ +import React, { useEffect, useState } from 'react'; +import Table from '../components/Table/HotelTable'; +import '../components/Filters/Filters.css'; + +// Fake data para probar la tabla con filtros +const fakeEmployees = [ + { + id: '0001', + name: 'María Fernanda López', + nss: '00111111', + position: 'Concierge', + area: 'Hotel', + phone: '33-33-33-33-33', + endDate: '2025-01-17', + status: 'ACTIVE', + }, + { + id: '0002', + name: 'José Ángel Ramírez', + nss: '00111111', + position: 'Chef', + area: 'Restaurant', + phone: '33-33-33-33-33', + endDate: '2025-01-15', + status: 'ACTIVE', + }, + { + id: '0003', + name: 'Ana Sofía Torres', + nss: '00111111', + position: 'Chef', + area: 'Restaurant', + phone: '33-33-33-33-33', + endDate: '2025-01-23', + status: 'ACTIVE', + }, + { + id: '0004', + name: 'Luis Eduardo Mendoza', + nss: '00111111', + position: 'Hostess', + area: 'Restaurant', + phone: '33-33-33-33-33', + endDate: '2025-04-28', + status: 'INACTIVE', + }, +]; + +export default function Employees() { + const [employees, setEmployees] = useState([]); + const [filteredEmployees, setFilteredEmployees] = useState([]); + + const [areaFilter, setAreaFilter] = useState(''); + const [statusFilter, setStatusFilter] = useState(''); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + + useEffect(() => { + setEmployees(fakeEmployees); + setFilteredEmployees(fakeEmployees); + }, []); + + useEffect(() => { + let filtered = [...employees]; + + if (areaFilter) { + filtered = filtered.filter((e) => e.area === areaFilter); + } + + if (statusFilter) { + filtered = filtered.filter((e) => e.status === statusFilter); + } + + if (dateRange.from && dateRange.to) { + filtered = filtered.filter( + (e) => e.endDate >= dateRange.from && e.endDate <= dateRange.to + ); + } + + setFilteredEmployees(filtered); + }, [areaFilter, statusFilter, dateRange, employees]); + + const columns = [ + { header: 'NAME', key: 'name' }, + { header: 'NSS', key: 'nss' }, + { header: 'POSITION', key: 'position' }, + { header: 'AREA', key: 'area' }, + { header: 'PHONE', key: 'phone' }, + { header: 'END OF CONTRACT', key: 'endDate' }, + { + header: 'STATUS', + key: 'status', + render: (status) => ( + + ), + }, + ]; + + return ( +
    +

    Employees

    + + {/* Filtros */} +
    + + + + + setDateRange({ ...dateRange, from: e.target.value })} + /> + setDateRange({ ...dateRange, to: e.target.value })} + /> +
    + +
    + + ); +} + +// import React, { useEffect, useState } from 'react'; +// import Table from '../components/Table/HotelTable'; +// import '../components/Filters/Filters.css'; +// import Filters from '../components/Filters/Filters'; + +// export default function Employees() { +// const [employees, setEmployees] = useState([]); + +// // Filtros +// const [selectedArea, setSelectedArea] = useState('Hotel, Restaurant'); +// const [selectedStatus, setSelectedStatus] = useState('Active'); + +// useEffect(() => { +// // Datos de prueba +// const fakeData = [ +// { +// name: 'Maria Fernanda López', +// nss: '00111111', +// position: 'Concierge', +// area: 'Hotel', +// phone: '33-33-33-33-33', +// endDate: '17/01/2025', +// status: 'ACTIVE', +// }, +// { +// name: 'José Ángel Ramírez', +// nss: '00111111', +// position: 'Chef', +// area: 'Restaurant', +// phone: '33-33-33-33-33', +// endDate: '15/01/2025', +// status: 'ACTIVE', +// }, +// ]; +// setEmployees(fakeData); +// }, []); + +// const columns = [ +// { header: 'NAME', key: 'name' }, +// { header: 'NSS', key: 'nss' }, +// { header: 'POSITION', key: 'position' }, +// { header: 'AREA', key: 'area' }, +// { header: 'PHONE', key: 'phone' }, +// { header: 'END OF CONTRACT', key: 'endDate' }, +// { header: 'STATUS', key: 'status' }, +// ]; + +// return ( +//
    +//

    Employees

    + +// {/* Filtros */} +// setSelectedArea(e.target.value)} +// onStatusChange={(e) => setSelectedStatus(e.target.value)} +// /> + +// {/* Tabla */} +//
    +// +// ); +// } + +/**Reemplazar fakeData por */ +// const data = await getEmployees(); +// setEmployees(data); + + + +/**Sin los datos de Prueba */ +// import React, { useEffect, useState } from 'react'; +// import { getEmployees } from '../services/employeeService'; +// import Table from '../components/Table/HotelTable'; + +// export default function Employees() { +// const [employees, setEmployees] = useState([]); + +// useEffect(() => { +// async function fetchData() { +// const data = await getEmployees(); +// setEmployees(data); +// } + +// fetchData(); +// }, []); + +// const columns = [ +// { header: 'NAME', key: 'name' }, +// { header: 'NSS', key: 'nss' }, +// { header: 'POSITION', key: 'position' }, +// { header: 'AREA', key: 'area' }, +// { header: 'PHONE', key: 'phone' }, +// { header: 'END OF CONTRACT', key: 'endDate' }, +// { header: 'STATUS', key: 'status' }, +// ]; + +// return ( +//
    +//

    Employees

    +//
    +// +// ); +// } diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/EditExpense.css b/frontend/Frontend-Hotel/src/pages/Expenses/EditExpense.css new file mode 100644 index 0000000..aa81ec0 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/EditExpense.css @@ -0,0 +1,182 @@ +.new-expense-container { + color: #333; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.form-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.form-id { + font-weight: bold; + font-size: 18px; +} + +.back-button { + background-color: #6c757d; + color: #fff; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + gap: 5px; + font-size: 14px; + transition: background-color 0.2s; +} + +.back-button:hover { + background-color: #5a6268; +} + +.back-button:active { + background-color: #545b62; +} + +.form-grid { + display: grid; + /* grid-template-columns: repeat(3, 1fr); */ + grid-template-columns: 1fr 1fr; + gap: 15px; + margin-bottom: 30px; +} + +.form-grid label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #333; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 6px 4px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 20px; +} + +.save-button { + background-color: #ffcb05; + color: #fff; + padding: 10px 30px; + font-weight: bold; + border: none; + border-radius: 25px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.save-button:hover { + background-color: #f4b400; +} + +.product-table-section { + margin-top: 25px; +} + + +/*Actualización de New Expense con tabla*/ + +/* src/pages/Expenses/NewExpense.css */ + +.new-expense-container { + padding: 20px; +} + +.form-card { + background-color: #fff; + border-radius: 8px; + padding: 24px; + box-shadow: 0 0 10px rgba(0,0,0,0.1); +} + +.form-id { + font-weight: bold; + margin-bottom: 10px; +} + +/* .form-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 20px; +} */ + +.save-button-wrapper { + margin-top: 20px; + display: flex; + justify-content: flex-end; +} + +.save-button { + background-color: #ffc107; /* amarillo/dorado */ + color: #000; /* ajustar según contraste */ + border: none; + padding: 10px 24px; + border-radius: 20px; + font-weight: bold; + cursor: pointer; +} + +.product-table-section { + margin-top: 20px; + overflow-x: auto; +} + +.product-table { + width: 100%; + border-collapse: collapse; +} + +.product-table th, .product-table td { + border: 1px solid #d4af37; /* dorado */ + padding: 8px; + text-align: center; +} + +.product-table th { + background-color: #800020; /* bordo/morado oscuro, según tus imágenes */ + color: white; + font-weight: bold; +} + +.add-product-row { + cursor: pointer; + color: #d4af37; /* dorado */ + text-align: center; + padding: 10px; + font-style: italic; +} + +.tax-pill { + background-color: white; + border: 1px solid #d4af37; + border-radius: 12px; + padding: 2px 6px; + color: #800020; +} + +.product-table tfoot td { + border-top: 2px solid #d4af37; + padding: 8px; +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/EditExpense.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/EditExpense.jsx new file mode 100644 index 0000000..939ca4e --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/EditExpense.jsx @@ -0,0 +1,774 @@ +import React, { useEffect, useState } from 'react'; +import './EditExpense.css'; +import { useParams, useNavigate } from 'react-router-dom'; +import Table from '../../components/Table/HotelTable'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function EditExpense() { + const { id } = useParams(); + const { lang } = useContext(langContext); + const navigate = useNavigate(); + + const [form, setForm] = useState({ + up_description: '', + up_id_suppliers: '', + up_request_date: '', + up_payment_deadline: '', + request_by: '', + area: '', + expense_cat: '', + currency_id: '', + needtoapprove: true, + totalAmount: 0, + subtotal: 0, //------ + products: [] + }); + + const [loading, setLoading] = useState(true); // Start with loading: true + const [success, setSuccess] = useState(false); + const [error, setError] = useState(''); + // eslint-disable-next-line no-unused-vars + const [savedExpense, setSavedExpense] = useState(null); + + // estados para datos de selects + const [suppliers, setSuppliers] = useState([]); + const [users, setUsers] = useState([]); + const [areas, setAreas] = useState([]); + const [categories, setCategories] = useState([]); + const [currencies, setCurrencies] = useState([]); + const [taxes, setTaxes] = useState([]); + const [listproducts, setListProducts] = useState([]); + + const formatDate = (isoDate) => { + if (!isoDate) return ''; + const d = new Date(isoDate); + return d.toISOString().slice(0, 10); + }; + + useEffect(() => { + async function fetchSelectData() { + try { + const res = await fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/getinfo', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) throw new Error(`Error fetching info: ${res.status}`); + const data = await res.json(); + // Supongo que data tiene algo como: + // { suppliers: [...], users: [...], areas: [...], categories: [...], currencies: [...] } + setSuppliers(data.suppliers || []); + setUsers(data.users || []); + setAreas(data.areas || []); + setCategories(data.categories || []); + setCurrencies(data.currencies || []); + setTaxes(data.tax || []); + } catch (err) { + console.error('Error cargando metadata (getinfo):', err); + setError('No se pudo cargar opciones de formulario.'); + } + } + // Helper para cargar opciones de selects + const fetchOptions = (url, setter, mapFn) => { + fetch(import.meta.env.VITE_API_BASE_URL + url) + .then(res => res.json()) + .then(data => { + const items = data.data || data.currency || data.categoryex || data.approve || data.request; + if (items) { + setter(items.map(mapFn)); + } + }) + .catch(err => console.error(`Error fetching ${url}`, err)); + }; + + const fetchExpense = async () => { + try { + const res = await fetch(import.meta.env.VITE_API_BASE_URL + `/expenses/getexpense/${id}`, { + method: 'PUT', + }); + + if (!res.ok) { + const textResponse = await res.text(); + throw new Error(`HTTP ${res.status}: ${textResponse}`); + } + + const data = await res.json(); + + if (!data.data || data.data.length === 0) { + setError('Expense not found'); + return; + } + + const base = data.data[0]; + + let tax_id = null; + + if (base.iva > 0) { + const tax_rate = parseFloat((base.iva / base.subtotal).toFixed(2)); + const taxMap = { + 0.16: 1, + 0.08: 2, + 0.00: 3 + }; + tax_id = taxMap[tax_rate] || null; + } + + + setForm({ + up_description: base.description_exp || '', + up_id_suppliers: base.suppliers_id || '', + up_request_date: formatDate(base.request_date), + up_payment_deadline: formatDate(base.payment_deadline), + request_by: base.request_by, + area: base.id_area, + expense_cat: base.category_exp, + currency_id: base.currency, + needtoapprove: base.needtoapprove !== undefined ? base.needtoapprove : true, + subtotal: base.subtotal, + up_tax: tax_id, + iva: base.iva, + ieps: base.ieps, + total: base.total, + products: base.products + }); + + setLoading(false); + } catch (err) { + console.error('Error fetching expense:', err); + setError('Failed to load expense data'); + setLoading(false); + } + }; + /**/ + fetchExpense(); + fetchOptions('/products', setListProducts, c => ({ id: c.id_product, name: c.name_product })); + fetchSelectData(); + }, [id]); + + const handleChange = (e) => { + const { name, type, checked, value } = e.target; + + // Crear una copia del formulario + const updatedForm = { ...form, [name]: type === 'checkbox' ? checked : value }; + + // Inicializar valores por si están vacíos + const subtotal = parseFloat(updatedForm.subtotal) || 0; + const ieps = parseFloat(updatedForm.ieps) || 0; + + let ivaAmount = 0; + + // Si hay productos, recalcular desde ellos + if (updatedForm.products.length > 0) { + updatedForm.subtotal = updatedForm.products.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + ivaAmount = updatedForm.products.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + } else { + // Si no hay productos, calcular IVA a partir del subtotal y tasa + const taxRate = parseFloat( + taxes.find(t => t.id === parseInt(updatedForm.up_tax))?.number || 0 + ); + ivaAmount = subtotal * taxRate; + } + + updatedForm.iva = ivaAmount; + + // Calcular total final (subtotal + IVA + IEPS) + updatedForm.total = subtotal + ivaAmount + ieps; + + // Actualizar estado + setForm({ + ...updatedForm, + iva: updatedForm.iva.toFixed(2), + total: updatedForm.total.toFixed(2), + }); + }; + + + const handleCategoryChange = (e) => { + const { name, value } = e.target; + const categoryValue = Number(value) || 0; // si el value es numérico + setForm(prev => { // Clonamos el form actual + const updatedForm = { ...prev, [name]: categoryValue }; + + // Find the selected category to check its name + const selectedCategory = categories.find(c => c.id === categoryValue); + const isSuppliesCategory = selectedCategory && ( + selectedCategory.name === "Supplies" || + selectedCategory.name === "Laundry Supplies" || + selectedCategory.id === 1 + ); + + if (isSuppliesCategory) { + updatedForm.products = [ + { + id_product: null, + quantity: 1, + unit_cost: 0, + id_tax: null, + total: 0 + } + ]; + updatedForm.up_tax = ""; + } else { // Si cambia a otra categoría, vaciamos los productos + updatedForm.products = []; + } return updatedForm; + }); + }; + + const handleProductChange = (index, field, value) => { + const updatedProducts = [...form.products]; // Convertir a entero si es un campo numérico esperado + const ieps = parseFloat(form.ieps) || 0; + const processedValue = ['unit_cost'].includes(field) ? parseFloat(value) : ['quantity', 'id_tax', 'id_product'].includes(field) ? parseInt(value) : value; + updatedProducts[index][field] = processedValue; + + if (field === 'quantity' || field === 'unit_cost' || field === 'id_tax') { + const qty = parseFloat(updatedProducts[index].quantity) || 0; + const cost = parseFloat(updatedProducts[index].unit_cost) || 0; + const taxValue = parseFloat(taxes.find(t => t.id === parseInt(updatedProducts[index].id_tax))?.number || 0); + updatedProducts[index].subtotal = qty * cost; + updatedProducts[index].iva = qty * cost * taxValue; + } + + // Recalcular el amount (suma de todos los productos) + const subtotalAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + // Recalcular el amount (suma de todos los productos) + const ivaAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + + setError(null); + setSuccess(false); + + setForm(prev => ({ + ...prev, + products: updatedProducts, + subtotal: subtotalAmount.toFixed(2), // redondeado a 2 decimales + iva: ivaAmount.toFixed(2), // redondeado a 2 decimales + total: (subtotalAmount + ivaAmount + ieps).toFixed(2) // Calcular total final (subtotal + IVA + IEPS) + })); + }; + + const handleAddProduct = () => { + const ieps = parseFloat(form.ieps) || 0; + + // Primero, agregamos el nuevo producto + const updatedProducts = [ + ...form.products, + { + id_product: null, + quantity: 1, + unit_cost: 0, + id_tax: '', + subtotal: 0, + iva: 0 + } + ]; + + // Ahora sí, recalculamos después de agregarlo + const subtotalAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + const ivaAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + + setForm(prev => ({ + ...prev, + products: updatedProducts, + subtotal: subtotalAmount.toFixed(2), + iva: ivaAmount.toFixed(2), + total: (subtotalAmount + ivaAmount + ieps).toFixed(2) + })); + }; + + const handleRemoveProduct = (index) => { + setForm(prev => { + const updated = [...prev.products]; + updated.splice(index, 1); + + // Recalcular el amount (suma de todos los productos) + const subtotalAmount = updated.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + // Recalcular el amount (suma de todos los productos) + const ivaAmount = updated.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + + const ieps = parseFloat(prev.ieps) || 0; + + return { + ...prev, + products: updated, + subtotal: subtotalAmount.toFixed(2), // redondeado a 2 decimales + iva: ivaAmount.toFixed(2), // redondeado a 2 decimales + total: (subtotalAmount + ivaAmount + ieps).toFixed(2) // Calcular total final (subtotal + IVA + IEPS) + }; + }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setSuccess(false); + setError(''); + + try { + const payload = { + up_description: form.up_description,// + suppliers_id: Number(form.up_id_suppliers), // + up_req_date: form.up_request_date,// + up_deadline: form.up_payment_deadline,// + up_currency: Number(form.currency_id), // + up_request_by: Number(form.request_by),// + up_area: Number(form.area), // + up_category: Number(form.expense_cat), // + needtoapprove: form.needtoapprove, + up_subtotal: Number(form.subtotal), //------ + up_iva: Number(form.iva), //------ + up_ieps: Number(form.ieps), //------ + up_total: Number(form.total), // + products: form.products // + }; + + const res = await fetch(import.meta.env.VITE_API_BASE_URL + `/expenses/updateexpense/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + + const text = await res.text(); + let data; + try { data = JSON.parse(text); } catch { data = text; } + + if (!res.ok) { + console.error('Error response:', res.status, data); + throw new Error(`Server error ${res.status}: ${JSON.stringify(data)}`); + } + + setSuccess(true); + setSavedExpense(payload); + + } catch (err) { + console.error('handleSubmit error:', err); + setError(err.message || 'Unexpected error'); + } finally { + setLoading(false); + } + }; + + if (loading) { + return ( +
    +
    {lang === "en" ? "Loading expense data..." : "Cargando datos del gasto..."}
    +
    + ); + } + + return ( +
    +
    +
    +
    + {lang === "en" ? "Edit expense (" : "Editar gasto ("}{id}) +
    + +
    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + { + const selectedCategory = categories.find(c => c.id === Number(form.expense_cat)); + return selectedCategory && ( + selectedCategory.name === "Supplies" || + selectedCategory.name === "Laundry Supplies" || + selectedCategory.id === 1 + ); + })()} + /> +
    + + {(() => { + const selectedCategory = categories.find(c => c.id === Number(form.expense_cat)); + const isSuppliesCategory = selectedCategory && ( + selectedCategory.name === "Supplies" || + selectedCategory.name === "Laundry Supplies" || + selectedCategory.id === 1 + ); + return !isSuppliesCategory; + })() && ( +
    + + +
    + )} + +
    + + { + const selectedCategory = categories.find(c => c.id === Number(form.expense_cat)); + return selectedCategory && ( + selectedCategory.name === "Supplies" || + selectedCategory.name === "Laundry Supplies" || + selectedCategory.id === 1 + ); + })()} + /> +
    + +
    + + +
    + +
    + + { + const selectedCategory = categories.find(c => c.id === Number(form.expense_cat)); + return selectedCategory && ( + selectedCategory.name === "Supplies" || + selectedCategory.name === "Laundry Supplies" || + selectedCategory.id === 1 + ); + })()} + /> +
    + + {/* Need to Approve (Campo solicitado en la estructura) */} +
    + + +
    +
    + + {/* Sección de Productos */} + {(() => { + const selectedCategory = categories.find(c => c.id === Number(form.expense_cat)); + const isSuppliesCategory = selectedCategory && ( + selectedCategory.name === "Supplies" || + selectedCategory.name === "Laundry Supplies" || + selectedCategory.id === 1 + ); + return isSuppliesCategory; + })() && ( +
    +

    + {lang === "en" ? "Products" : "Productos"} +

    + +
    + {form.products.map((product, index) => ( +
    +
    + + +
    +
    + + handleProductChange(index, 'quantity', e.target.value)} + placeholder={lang === "en" ? "Quantity" : "Cantidad"} + /> +
    +
    + + handleProductChange(index, 'unit_cost', e.target.value)} + placeholder={lang === "en" ? "Unit Cost" : "Precio Unitario"} + /> +
    +
    + + +
    + +
    + + {index === form.products.length - 1 && ( + + )} +
    +
    + ))} +
    +
    + )} + + {/* Botón de Actualización que dispara la petición PUT */} +
    + +
    + + {success && ( + + {lang === "en" ? "Expense saved successfully!" : "¡Gasto guardado con éxito!"} + + )} + {error && {error}} + +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/ExpenseDetail.css b/frontend/Frontend-Hotel/src/pages/Expenses/ExpenseDetail.css new file mode 100644 index 0000000..d10e9e8 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/ExpenseDetail.css @@ -0,0 +1,201 @@ + +.expense-detail { + background-color: #fff; + padding: 2rem; + font-family: 'Montserrat'; + max-width: 1000px; + margin: 2rem auto; + border-radius: 16px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06); + border: 1px solid #e0e0e0; +} + +.expense-detail h2 { + color: #000; + margin-bottom: 1.5rem; + font-weight: 700; + font-size: 1.8rem; +} + +.expense-detail h3 { + color: #000; +} + +.expense-detail-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 20px; + margin-bottom: 2rem; +} + +.expense-detail label { + font-weight: 600; + color: #000; + margin-bottom: 0.4rem; + display: block; +} + +.expense-detail p { + color: #000; +} + +.expense-detail input[type="text"], +.expense-detail input[type="number"], +.expense-detail input[type="date"] { + width: 90%; + max-width: 280px; + padding: 10px 14px; + border: 1px solid #ccc; + border-radius: 10px; + font-size: 14px; + font-family: 'Montserrat'; + background-color: #f9f9f9; + transition: border-color 0.3s ease; +} + +.expense-detail input:focus { + outline: none; + border-color: #f1c40f; + background-color: #fff; + box-shadow: 0 0 0 2px rgba(241, 196, 15, 0.2); +} + +.expense-detail button { + margin-top: 2rem; + padding: 12px 24px; + background-color: #f1c40f; + border: none; + color: #000; + font-weight: 700; + font-size: 16px; + border-radius: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.expense-detail button:hover { + background-color: #d4ac0d; +} + +.products-section { + margin-top: 2rem; +} + +.products-section h3 { + margin-bottom: 1rem; + font-weight: 700; + color: #333; +} + +.product-table { + width: 100%; + border-collapse: collapse; + font-size: 14px; + border: 1px solid #f1c40f; +} + +.product-table th, +.product-table td { + border: 1px solid #f1c40f; + padding: 12px; + text-align: center; +} + +.product-table th { + background-color: #800020; + color: #fff; + font-weight: 700; +} + +.product-table td { + background-color: #fff; +} + +.product-table input[type="number"] { + width: 80px; + padding: 6px; + text-align: center; + border-radius: 8px; + border: 1px solid #ccc; +} + +.success-message { + color: green; + margin-top: 1rem; + font-weight: 600; +} + +.loading, +.error { + text-align: center; + font-family: 'Montserrat', sans-serif; + font-weight: 600; +} + +.error { + color: red; +} + + +/* .expense-detail-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; + margin-bottom: 2rem; +} */ + +/* .expense-detail-container { +>>>>>>> Stashed changes + padding: 2rem; + max-width: 900px; + margin: auto; + background: white; + border-radius: 12px; +} + +.expense-form { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; +} + +.form-group { + flex: 1 1 45%; + display: flex; + flex-direction: column; +} + +label { + margin-bottom: 0.3rem; + font-weight: 600; +} + +input, select { + padding: 0.5rem; + border-radius: 6px; + border: 1px solid #ccc; +} + +.save-button { + margin-top: 1rem; + padding: 0.75rem 2rem; + background-color: #f4b400; + color: white; + border: none; + border-radius: 8px; + cursor: not-allowed; +} + +.amount-warning-banner { + background-color: #fff3cd; + color: #856404; + border: 1px solid #ffeeba; + padding: 1rem; + border-radius: 8px; + margin-bottom: 1rem; + font-weight: 500; +} +.amount-warning-banner::before { + content: "⚠️"; + margin-right: 0.5rem; +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/ExpenseDetail.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/ExpenseDetail.jsx new file mode 100644 index 0000000..746d56a --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/ExpenseDetail.jsx @@ -0,0 +1,217 @@ + +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +import './ExpenseDetail.css'; + +export default function ExpenseDetail() { + const { id } = useParams(); + const { lang } = useContext(langContext); + + const [form, setForm] = useState({ + up_description: '', + up_id_suppliers: '', + up_request_by: '', + up_area: '', + up_category: '', + up_req_date: '', + up_deadline: '', + up_currency: '', + up_approbal_by:'', + needtoapprove: true, + amount: '', + products: [] + }); + + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const [suppliers, setSuppliers] = useState([]); + const [users, setUsers] = useState([]); + const [areas, setAreas] = useState([]); + const [categories, setCategories] = useState([]); + const [currencies, setCurrencies] = useState([]); + const [taxes, setTaxes] = useState([]); + + const formatDate = (isoDate) => { + if (!isoDate) return ''; + const d = new Date(isoDate); + return d.toISOString().slice(0, 10); + }; + + // Cargar listas de referencia (suppliers, users, areas, etc.) + useEffect(() => { + async function fetchSelectData() { + try { + const res = await fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/getinfo', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) throw new Error(`Error fetching info: ${res.status}`); + const data = await res.json(); + + setSuppliers(data.suppliers || []); + setUsers(data.users || []); + setAreas(data.areas || []); + setCategories(data.categories || []); + setCurrencies(data.currencies || []); + setTaxes(data.tax || []); + } catch (err) { + console.error('Error cargando metadata (getinfo):', err); + setError('No se pudo cargar opciones de formulario.'); + } + } + + fetchSelectData(); + }, []); + + // Cargar datos del gasto + useEffect(() => { + async function fetchExpense() { + try { + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/expenses/getexpense/${id}`, { + method: 'PUT', + }); + const data = await res.json(); + + if (!data.data || data.data.length === 0) { + setError('No se encontraron datos del gasto.'); + setLoading(false); + return; + } + + const base = data.data[0]; + setForm({ + up_description: base.description_exp || '', + up_id_suppliers: base.suppliers_id || '', + up_request_by: base.request_by || '', + up_area: base.id_area || '', + up_category: base.category_exp || '', + up_req_date: formatDate(base.request_date), + up_deadline: formatDate(base.payment_deadline), + up_currency: base.currency || '', + up_approbal_by: base.approval_by || '', + needtoapprove: base.needtoapprove !== undefined ? base.needtoapprove : true, + amount: base.amount || '', + products: base.products || [] + }); + setLoading(false); + } catch (err) { + console.error('Error cargando gasto:', err); + setError('No se pudo cargar el gasto.'); + setLoading(false); + } + } + + fetchExpense(); + }, [id]); + + if (loading) return
    Loading...
    ; + if (error) return
    {error}
    ; + + return ( +
    +

    {lang === "en" ? "Detail" : "Información"} (ID: {id})

    + +
    + {/* Description */} +
    + +

    {form.up_description}

    +
    + + {/* Supplier */} +
    + +

    {suppliers.find(s => String(s.id) === String(form.up_id_suppliers))?.name || form.up_id_suppliers}

    +
    + + {/* Request By */} +
    + +

    {users.find(u => String(u.id) === String(form.up_request_by))?.name || form.up_request_by}

    +
    + + {/* Area */} +
    + +

    {areas.find(a => String(a.id) === String(form.up_area))?.name || form.up_area}

    +
    + + {/* Category */} +
    + +

    {categories.find(c => String(c.id) === String(form.up_category))?.name || form.up_category}

    +
    + + {/* Request Date */} +
    + +

    {form.up_req_date}

    +
    + + {/* Payment Deadline */} +
    + +

    {form.up_deadline}

    +
    + + {/* Currency */} +
    + +

    {currencies.find(c => String(c.id) === String(form.up_currency))?.name || form.up_currency}

    +
    + + {/* Amount */} +
    + +

    {form.amount}

    +
    + + {/* Needs Approval */} +
    + +

    {form.needtoapprove ? (lang === "en" ? 'Yes' : 'Sí') : (lang === "en" ? 'No' : 'No')}

    +
    +
    + +
    + + {/* Products */} +

    {lang === "en" ? "Products" : "Productos"}

    +
    + {form.products.length > 0 ? ( + form.products.map((product, index) => ( +
    +
    + +

    {product.name || product.id_product}

    +
    +
    + +

    {product.quantity}

    +
    +
    + +

    {taxes.find(t => String(t.id) === String(product.id_tax))?.name || product.id_tax}

    +
    +
    + )) + ) : ( +

    {lang === "en" ? "No products loaded." : "No hay productos cargados."}

    + )} +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyPayments.css b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyPayments.css new file mode 100644 index 0000000..2fbc92d --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyPayments.css @@ -0,0 +1,75 @@ +.monthly-payments-page .page-filters { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + gap: 12px; + align-items: stretch; +} + +.monthly-payments-page .filters-row { + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.monthly-payments-page .filters-row.second-row { + justify-content: flex-end; + align-items: flex-start; +} + +.monthly-payments-page .filters-row.second-row .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +.monthly-payments-page .filters-row.second-row .clear-filters-btn { + flex-shrink: 0; + margin-left: 8px; +} + +.monthly-payments-page .filters-row .filter-search { + flex: 1; + max-width: 280px; + min-width: 180px; +} + +@media (max-width: 768px) { + .monthly-payments-page .page-filters { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .monthly-payments-page .filters-row { + flex-direction: column; + gap: 10px; + } + + .monthly-payments-page .filters-row.second-row { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .monthly-payments-page .filter-search { + min-width: 100%; + max-width: 100%; + order: -1; + } + + .monthly-payments-page .filter-select { + min-width: 100%; + } + + .monthly-payments-page .clear-filters-btn { + width: 100%; + align-self: stretch; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyPayments.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyPayments.jsx new file mode 100644 index 0000000..ef6e0b3 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyPayments.jsx @@ -0,0 +1,436 @@ +import React, { useEffect, useState, useContext } from 'react'; +import Table from '../../components/Table/HotelTable'; +import Switch from '../../components/Switch'; +import { useNavigate } from 'react-router-dom'; +import { langContext } from '../../context/LenguageContext'; +import ConfirmationModal from '../../components/Modals/ConfirmationMontlyPay'; +import '../../components/Filters/Filters.css'; +import './MonthlyPayments.css'; + +export default function MonthlyPayments() { + const [payments, setPayments] = useState([]); + const [switchStates, setSwitchStates] = useState({}); + const [descriptionSearch, setDescriptionSearch] = useState(''); + const [areaFilter, setAreaFilter] = useState(''); + const [statusFilter, setStatusFilter] = useState(''); + const [paymentStatusFilter, setPaymentStatusFilter] = useState(''); + const [supplierFilter, setSupplierFilter] = useState(''); + const navigate = useNavigate(); + const { lang } = useContext(langContext); + const [modalOpen, setModalOpen] = useState(false); + const [selectedId, setSelectedId] = useState(null); + const [taxes, setTaxes] = useState([]); + const [selectedDescription, setselectedDescription] = useState([]); + const [initialAmount, setInitialAmount] = useState(null); + const [initialTaxId, setInitialTaxId] = useState(null); + const [isFixedPayment, setIsFixedPayment] = useState(false); + + const refreshMonthlyData = async () => { + try { + await fetch(`${import.meta.env.VITE_API_BASE_URL}/payment/refreshmonthly`, { + method: 'GET' + }); + } catch (error) { + console.error('Error refreshing monthly data:', error); + } + }; + + const filteredData = payments.filter((item) => { + const matchesDescription = item.description.toLowerCase().includes(descriptionSearch.toLowerCase()); + const matchesArea = !areaFilter || item.area === areaFilter; + const matchesStatus = !statusFilter || item.status === statusFilter; + const matchesPaymentStatus = !paymentStatusFilter || item.paymentStatus === paymentStatusFilter; + const matchesSupplier = !supplierFilter || item.supplier === supplierFilter; + const isPending = item.paymentStatus === "PENDING"; + + return matchesDescription && matchesArea && matchesStatus && matchesPaymentStatus && matchesSupplier && isPending; + }); + + const uniqueAreas = [...new Set(payments.map(item => item.area).filter(Boolean))].sort(); + const uniqueStatuses = [...new Set(payments.map(item => item.status).filter(Boolean))].sort(); + const uniquePaymentStatuses = [...new Set(payments.map(item => item.paymentStatus).filter(Boolean))].sort(); + const uniqueSuppliers = [...new Set(payments.map(item => item.supplier).filter(Boolean))].sort(); + + const clearFilters = () => { + setDescriptionSearch(''); + setAreaFilter(''); + setStatusFilter(''); + setPaymentStatusFilter(''); + setSupplierFilter(''); + }; + + const handleSwitchToggle = async (expenseId) => { + const newState = !switchStates[expenseId]; + + try { + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/payment/needtorefresh/${expenseId}`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + notrefresh: newState + }), + } + ); + + if (!response.ok) { + throw new Error("Error updating refresh status"); + } + + const newStates = { + ...switchStates, + [expenseId]: newState + }; + setSwitchStates(newStates); + + localStorage.setItem('recurrenceSwitchStates', JSON.stringify(newStates)); + + await refreshTableData(); + + } catch (error) { + console.error("Error updating refresh status:", error); + } + }; + + const refreshTableData = async () => { + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/monthlypayments'); + const data = await response.json(); + + const groupedDataObj = data.data.reduce((acc, item) => { + const key = `${item.expense_description}-${item.area}`; + const itemDate = new Date(item.payment_deadline); + + if (!acc[key] || itemDate > new Date(acc[key].payment_deadline)) { + acc[key] = item; + } + + return acc; + }, {}); + + const adaptedData = Object.values(groupedDataObj).map((item) => ({ + id: item.id_expense, + description: item.expense_description, + date: new Date(item.payment_deadline).toISOString().split('T')[0], + area: item.area.toUpperCase(), + recurrence: item.recurrence_name, + supplier: item.supplier, + status: capitalizeFirstLetter(item.status), + amount: `$${parseFloat(item.total || 0).toLocaleString()}`, + paymentStatus: item.status_payment.toUpperCase(), + more: { id: item.id_expense, description: item.expense_description, status: item.status_payment } + })); + + const groupedData = adaptedData.sort((a, b) => { + if (a.paymentStatus === "PENDING" && b.paymentStatus !== "PENDING") return -1; + if (a.paymentStatus !== "PENDING" && b.paymentStatus === "PENDING") return 1; + + const descCompare = a.description.localeCompare(b.description); + if (descCompare !== 0) return descCompare; + + const areaCompare = a.area.localeCompare(b.area); + if (areaCompare !== 0) return areaCompare; + + return 0; + }); + + setPayments(groupedData); + } catch (error) { + console.error('Error refreshing table data:', error); + } + }; + + const handleOpenModal = async (more) => { + const {id, description} = more; + const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/payment/onemothlyexpense/${id}`); + const data = await response.json(); + setSelectedId(id); + setselectedDescription(description); + + if (data.data && data.data[0] && data.data[0].payment_type === 1) { + setInitialAmount(data.data[0].new_subtotal); + setInitialTaxId(data.data[0].tax_id); + setIsFixedPayment(true); + } else { + setInitialAmount(null); + setInitialTaxId(null); + setIsFixedPayment(false); + } + + setModalOpen(true); + }; + const handleConfirm = async (taxid, amount) => { + console.log(taxid, amount, selectedId); + + try { + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/payment/paymentstatusmonthly/${selectedId}`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + status_payment: 1, + tax_id: taxid, + subtotal: amount, + }), + } + ); + + if (!response.ok) { + throw new Error("Error al aplicar el cambio"); + } + + const data = await response.json(); + console.log("✅ Respuesta del servidor:", data); + + await refreshMonthlyData(); + + await refreshTableData(); + + } catch (err) { + console.error("❌ Error en handleConfirm:", err); + } + }; + + const handleCancel = () => { + setModalOpen(false); + }; + + + useEffect(() => { + const loadData = async () => { + await refreshMonthlyData(); + + async function MP() { + await fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/monthlypayments') + .then((response) => response.json()) + .then((data) => { + const groupedDataObj = data.data.reduce((acc, item) => { + const key = `${item.expense_description}-${item.area}`; + const itemDate = new Date(item.payment_deadline); + + if (!acc[key] || itemDate > new Date(acc[key].payment_deadline)) { + acc[key] = item; + } + + return acc; + }, {}); + + const adaptedData = Object.values(groupedDataObj).map((item) => ({ + id: item.id_expense, + description: item.expense_description, + date: new Date(item.payment_deadline).toISOString().split('T')[0], + area: item.area.toUpperCase(), + recurrence: item.recurrence_name, + supplier: item.supplier, + status: capitalizeFirstLetter(item.status), + amount: `$${parseFloat(item.total || 0).toLocaleString()}`, + paymentStatus: item.status_payment.toUpperCase(), + more: { id: item.id_expense, description: item.expense_description, status: item.status_payment } + })); + + const groupedData = adaptedData.sort((a, b) => { + if (a.paymentStatus === "PENDING" && b.paymentStatus !== "PENDING") return -1; + if (a.paymentStatus !== "PENDING" && b.paymentStatus === "PENDING") return 1; + + const descCompare = a.description.localeCompare(b.description); + if (descCompare !== 0) return descCompare; + + const areaCompare = a.area.localeCompare(b.area); + if (areaCompare !== 0) return areaCompare; + + return 0; + }); + + setPayments(groupedData); + + const savedStates = JSON.parse(localStorage.getItem('recurrenceSwitchStates') || '{}'); + const initialStates = {}; + groupedData.forEach(expense => { + initialStates[expense.id] = savedStates[expense.id] !== undefined ? savedStates[expense.id] : true; + }); + setSwitchStates(initialStates); + }) + .catch((error) => { + console.error('Error fetching monthly payments:', error); + }); + } + async function Impuestos() { + await fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/getinfo') + .then(res => res.json()) + .then(data => { + setTaxes(data.tax); + }) + .catch(err => console.error('Error fetching suppliers', err)); + } + + MP(); + Impuestos(); + }; + + loadData(); + }, []); + + const columns = [ + { + header: lang === "en" ? "ACTIVE" : "ACTIVO", + key: 'active', + render: (value, row) => ( + handleSwitchToggle(row.id)} + /> + ), + }, + { header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", key: 'description' }, + { + header: lang === "en" ? "PAYMENT DEADLINE" : "FECHA LÍMITE DE PAGO", + key: 'date', + render: (date, row) => ( + + {date} + + ) + }, + { header: lang === "en" ? "AREA" : "ÁREA", key: 'area' }, + { header: lang === "en" ? "RECURRENCE" : "RECURRENCIA", key: 'recurrence' }, + { header: lang === "en" ? "SUPPLIER" : "PROVEEDOR", key: 'supplier' }, + { header: lang === "en" ? "STATUS" : "ESTADO", key: 'status' }, + { header: lang === "en" ? "AMOUNT" : "IMPORTE", key: 'amount' }, + { + header: lang === "en" ? "PAYMENT STATUS" : "ESTADO DE PAGO", + key: 'paymentStatus', + headerStyle: { textAlign: 'center' }, + render: (status) => ( +
    + +
    + ), + }, + { + header: lang === "en" ? "PAID" : "PAGAR", + key: 'more', + headerStyle: { textAlign: 'center' }, + render: (more) => ( +
    + + +
    + ), + }, + + ]; + + function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); + } + + return ( +
    +
    +

    + {lang === "en" ? "Monthly payments" : "Pagos mensuales"} +

    + +
    + +
    +
    + setDescriptionSearch(e.target.value)} + placeholder={lang === "en" ? "Search by description..." : "Buscar por descripción..."} + className="filter-search" + /> + + + + +
    + +
    + + + + + +
    +
    + +
    +
    + + + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyReport.css b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyReport.css new file mode 100644 index 0000000..df7e485 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyReport.css @@ -0,0 +1,221 @@ +.monthly-report-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + gap: 12px; + align-items: stretch; +} + +.monthly-report-page .filters-row { + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.monthly-report-page .filters-row.second-row { + justify-content: flex-end; + align-items: center; +} + +.monthly-report-page .filters-row.second-row .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +.monthly-report-page .filters-row.second-row .clear-filters-btn { + flex-shrink: 0; + margin-left: 12px; + align-self: center; + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.monthly-report-page .filters-row.second-row .clear-filters-btn:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.monthly-report-page .filters-row.second-row .clear-filters-btn:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.monthly-report-page .filters-row .filter-search { + flex: 0 1 280px; + max-width: 280px; + min-width: 180px; + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + margin-top: 26px; +} + +.monthly-report-page .filters-row .filter-search:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.monthly-report-page .filters-row .filter-search:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.monthly-report-page .date-input-group { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 140px; +} + +.monthly-report-page .date-label { + font-size: 11px; + font-weight: 700; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; +} + +.monthly-report-page .date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.monthly-report-page .date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.monthly-report-page .date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +@media (max-width: 768px) { + .monthly-report-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .monthly-report-page .filters-row { + flex-direction: column; + gap: 10px; + } + + .monthly-report-page .filters-row.second-row { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .monthly-report-page .filter-search { + flex: 1; + min-width: 200px; + max-width: 100%; + order: -1; + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + margin-top: 26px; + } + + .monthly-report-page .filter-search:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; + } + + .monthly-report-page .filter-search:hover { + box-shadow: 0 0 0 2px #e6e6e6; + } + + + .monthly-report-page .filter-select { + min-width: 100%; + } + + .monthly-report-page .date-input-group { + min-width: auto; + width: 100%; + } + + .monthly-report-page .date-inputs { + flex-direction: column; + } + + .monthly-report-page .date-input { + min-width: 100%; + } + + .monthly-report-page .clear-filters-btn { + width: 100%; + align-self: center; + margin-top: 12px; + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + } + + .monthly-report-page .clear-filters-btn:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; + } + + .monthly-report-page .clear-filters-btn:hover { + box-shadow: 0 0 0 2px #e6e6e6; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyReport.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyReport.jsx new file mode 100644 index 0000000..9d6bfa7 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/MonthlyReport.jsx @@ -0,0 +1,311 @@ +import React, { useEffect, useState, useContext } from "react"; +import Table from "../../components/Table/HotelTable"; +import { langContext } from "../../context/LenguageContext"; +import "../../components/Filters/Filters.css"; +import "./MonthlyReport.css"; + +export default function MonthlyReport() { + const { lang } = useContext(langContext); + + const getCurrentMonthRange = () => { + const now = new Date(); + const firstDay = new Date(now.getFullYear(), now.getMonth(), 1); + const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0); + return { + start: firstDay.toISOString().split("T")[0], + end: lastDay.toISOString().split("T")[0], + }; + }; + + const currentMonth = getCurrentMonthRange(); + + const [payments, setPayments] = useState([]); + const [descriptionSearch, setDescriptionSearch] = useState(""); + const [areaFilter, setAreaFilter] = useState(""); + const [statusFilter, setStatusFilter] = useState(""); + const [paymentStatusFilter, setPaymentStatusFilter] = useState(""); + const [supplierFilter, setSupplierFilter] = useState(""); + const [dateRange, setDateRange] = useState({ + from: currentMonth.start, + to: currentMonth.end, + }); + + const filteredData = payments.filter((item) => { + const matchesDescription = item.description + .toLowerCase() + .includes(descriptionSearch.toLowerCase()); + const matchesArea = !areaFilter || item.area === areaFilter; + const matchesStatus = !statusFilter || item.status === statusFilter; + const matchesPaymentStatus = + !paymentStatusFilter || item.paymentStatus === paymentStatusFilter; + const matchesSupplier = !supplierFilter || item.supplier === supplierFilter; + + let matchesDateRange = true; + if (dateRange.from || dateRange.to) { + if (!item.date) { + matchesDateRange = false; + } else { + const itemDate = new Date(item.date); + if (dateRange.from) { + const fromDate = new Date(dateRange.from); + if (itemDate < fromDate) matchesDateRange = false; + } + if (dateRange.to) { + const toDate = new Date(dateRange.to); + if (itemDate > toDate) matchesDateRange = false; + } + } + } + + return ( + matchesDescription && + matchesArea && + matchesStatus && + matchesPaymentStatus && + matchesSupplier && + matchesDateRange + ); + }); + + const uniqueAreas = [ + ...new Set(payments.map((item) => item.area).filter(Boolean)), + ].sort(); + const uniqueStatuses = [ + ...new Set(payments.map((item) => item.status).filter(Boolean)), + ].sort(); + const uniquePaymentStatuses = [ + ...new Set(payments.map((item) => item.paymentStatus).filter(Boolean)), + ].sort(); + const uniqueSuppliers = [ + ...new Set(payments.map((item) => item.supplier).filter(Boolean)), + ].sort(); + + const clearFilters = () => { + setDescriptionSearch(""); + setAreaFilter(""); + setStatusFilter(""); + setPaymentStatusFilter(""); + setSupplierFilter(""); + const currentMonth = getCurrentMonthRange(); + setDateRange({ from: currentMonth.start, to: currentMonth.end }); + }; + + const refreshMonthlyData = async () => { + try { + await fetch( + `${import.meta.env.VITE_API_BASE_URL}/payment/refreshmonthly`, + { + method: "GET", + } + ); + } catch (error) { + console.error("Error refreshing monthly data:", error); + } + }; + + useEffect(() => { + const loadData = async () => { + await refreshMonthlyData(); + + async function fetchMonthlyPaymentsData() { + await fetch( + import.meta.env.VITE_API_BASE_URL + "/expenses/monthlypayments" + ) + .then((response) => response.json()) + .then((data) => { + const adaptedData = data.data.map((item) => ({ + id: item.id_expense, + description: item.expense_description, + date: new Date(item.payment_deadline).toISOString().split("T")[0], + area: item.area.toUpperCase(), + recurrence: item.recurrence_name, + supplier: item.supplier, + status: capitalizeFirstLetter(item.status), + amount: `$${parseFloat(item.total || 0).toLocaleString()}`, + paymentStatus: item.status_payment.toUpperCase(), + more: { + id: item.id_expense, + description: item.expense_description, + status: item.status_payment, + }, + })); + + const groupedData = adaptedData.sort((a, b) => { + const descCompare = a.description.localeCompare(b.description); + if (descCompare !== 0) return descCompare; + + const areaCompare = a.area.localeCompare(b.area); + if (areaCompare !== 0) return areaCompare; + + return 0; + }); + + setPayments(groupedData); + }) + .catch((error) => { + console.error("Error fetching latest expenses:", error); + }); + } + + fetchMonthlyPaymentsData(); + }; + + loadData(); + }, []); + + const columns = [ + { + header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", + key: "description", + }, + { + header: lang === "en" ? "PAYMENT DEADLINE" : "FECHA LÍMITE DE PAGO", + key: "date", + }, + { header: lang === "en" ? "AREA" : "ÁREA", key: "area" }, + { header: lang === "en" ? "RECURRENCE" : "RECURRENCIA", key: "recurrence" }, + { header: lang === "en" ? "SUPPLIER" : "PROVEEDOR", key: "supplier" }, + { header: lang === "en" ? "STATUS" : "ESTADO", key: "status" }, + { header: lang === "en" ? "AMOUNT" : "IMPORTE", key: "amount" }, + { + header: lang === "en" ? "PAYMENT STATUS" : "ESTADO DE PAGO", + key: "paymentStatus", + headerStyle: { textAlign: "center" }, + render: (status) => ( +
    + +
    + ), + }, + ]; + + function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); + } + + return ( +
    +
    +

    + {lang === "en" ? "Monthly Report" : "Reporte Mensual"} +

    +
    + +
    +
    + setDescriptionSearch(e.target.value)} + placeholder={ + lang === "en" + ? "Search by description..." + : "Buscar por descripción..." + } + className="filter-search" + /> + +
    + + + setDateRange({ ...dateRange, from: e.target.value }) + } + className="date-input" + /> +
    + +
    + + setDateRange({ ...dateRange, to: e.target.value })} + className="date-input" + /> +
    +
    + +
    + + + + + + + + + +
    +
    + +
    +
    + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/NewExpense.css b/frontend/Frontend-Hotel/src/pages/Expenses/NewExpense.css new file mode 100644 index 0000000..2297537 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/NewExpense.css @@ -0,0 +1,254 @@ +* { + box-sizing: border-box; +} + +.new-expense-container { + color: #333; + padding: 20px; +} + +.new-expense-container * { + box-sizing: border-box; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.form-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.form-id { + font-weight: bold; + font-size: 18px; +} + +.back-button { + background-color: #6c757d; + color: #fff; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + gap: 5px; + font-size: 14px; + transition: background-color 0.2s; +} + +.back-button:hover { + background-color: #5a6268; +} + +.back-button:active { + background-color: #545b62; +} + +.form-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 15px; + margin-bottom: 30px; +} + +.form-grid > div { + display: flex; + flex-direction: column; + width: 100%; +} + +.form-grid label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #333; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 8px 10px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; + transition: border-color 0.2s, background-color 0.2s; + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.form-grid input:focus, +.form-grid select:focus { + outline: none; + border-color: #5D1A2A; + background-color: #fff; +} + +.form-grid input:disabled, +.form-grid select:disabled { + background-color: #e9ecef; + cursor: not-allowed; + opacity: 0.7; +} + +.form-grid input[type="text"], +.form-grid input[type="number"], +.form-grid input[type="date"] { + width: 100%; + box-sizing: border-box; + -webkit-appearance: none; + -moz-appearance: textfield; + appearance: none; +} + +.form-grid input[type="number"]::-webkit-outer-spin-button, +.form-grid input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.checkbox-field { + display: flex; + flex-direction: row !important; + align-items: center; + justify-content: flex-start; + gap: 8px; + width: 100%; + box-sizing: border-box; + padding: 4px 0; +} + +.checkbox-field label { + margin-bottom: 0 !important; + font-weight: bold; + font-size: 14px; + color: #333; + line-height: 1; +} + +.checkbox-field input[type="checkbox"] { + width: 14px !important; + height: 14px !important; + min-width: 14px; + min-height: 14px; + cursor: pointer; + accent-color: #5D1A2A; + flex-shrink: 0; + margin: 0; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 30px; +} + +.save-button { + background-color: #ffc107; + color: #000; + padding: 10px 30px; + font-weight: bold; + border: none; + border-radius: 20px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.1s ease; +} + +.save-button:hover { + background-color: #f4b400; + transform: translateY(-1px); +} + +.save-button:active { + transform: translateY(0); +} + +.save-button:disabled { + background-color: #e0e0e0; + color: #999; + cursor: not-allowed; + transform: none; +} + +.product-table-section { + margin-top: 25px; + overflow-x: auto; +} + +.product-table { + width: 100%; + border-collapse: collapse; +} + +.product-table th, .product-table td { + border: 1px solid #d4af37; + padding: 8px; + text-align: center; +} + +.product-table th { + background-color: #800020; + color: white; + font-weight: bold; +} + +.add-product-row { + cursor: pointer; + color: #d4af37; + text-align: center; + padding: 10px; + font-style: italic; +} + +.tax-pill { + background-color: white; + border: 1px solid #d4af37; + border-radius: 12px; + padding: 2px 6px; + color: #800020; +} + +.product-table tfoot td { + border-top: 2px solid #d4af37; + padding: 8px; +} + +.add-products { + width: 100%; + margin-top: 30px; + padding-top: 20px; + border-top: 2px solid #e0e0e0; +} + +.add-products h3 { + color: #333; + font-size: 18px; + font-weight: bold; + margin-bottom: 15px; +} + +@media (max-width: 768px) { + .form-grid { + grid-template-columns: 1fr; + gap: 12px; + } + + .form-card { + padding: 16px; + } + + .checkbox-field { + padding: 10px 0; + } +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/NewExpense.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/NewExpense.jsx new file mode 100644 index 0000000..ac30edf --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/NewExpense.jsx @@ -0,0 +1,798 @@ +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import "./NewExpense.css"; +import { useContext } from "react"; +import { langContext } from "../../context/LenguageContext"; +import { AuthContext } from "../../context/AuthContext"; + +export default function NewExpense() { + const { lang } = useContext(langContext); + const { userData } = useContext(AuthContext); + const navigate = useNavigate(); + + const isEditMode = false; + + const categoryRequiresProducts = (categoryId) => { + return categoryId === 1 || categoryId === 10; + }; + const [form, setForm] = useState({ + new_description: "", + suppliers_id: "", + new_request_date: "", + new_payment_deadline: "", + area: "", + expense_cat: "", + currency_id: "", + new_tax: 1, + subtotal: 0, + iva: 0, + ieps: 0, + total: 0, + needtoapprove: false, + products: [], + }); + + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(""); + + // estados para datos de selects + const [suppliers, setSuppliers] = useState([]); + const [areas, setAreas] = useState([]); + const [categories, setCategories] = useState([]); + const [currencies, setCurrencies] = useState([]); + const [taxes, setTaxes] = useState([]); + const [listproducts, setListProducts] = useState([]); + + useEffect(() => { + async function fetchSelectData() { + try { + const res = await fetch( + import.meta.env.VITE_API_BASE_URL + "/expenses/getinfo", + { + method: "GET", + headers: { "Content-Type": "application/json" }, + } + ); + if (!res.ok) throw new Error(`Error fetching info: ${res.status}`); + const data = await res.json(); + // Supongo que data tiene algo como: + // { suppliers: [...], areas: [...], categories: [...], currencies: [...] } + setSuppliers(data.suppliers || []); + setAreas(data.areas || []); + setCategories(data.categories || []); + setCurrencies(data.currencies || []); + setTaxes(data.tax || []); + } catch (err) { + console.error("Error cargando metadata (getinfo):", err); + } + } + // Helper para cargar opciones de selects + const fetchOptions = (url, setter, mapFn) => { + fetch(import.meta.env.VITE_API_BASE_URL + url) + .then((res) => res.json()) + .then((data) => { + const items = + data.data || + data.currency || + data.categoryex || + data.approve || + data.request; + if (items) { + setter(items.map(mapFn)); + } + }) + .catch((err) => console.error(`Error fetching ${url}`, err)); + }; + fetchOptions("/products", (data) => { + const sortedProducts = data.map(c => ({ + id: c.id_product, + name: c.name_product, + })).sort((a, b) => a.name.localeCompare(b.name)); + setListProducts(sortedProducts); + }, (c) => c); + fetchSelectData(); + }, []); + + const handleChange = (e) => { + const { name, type, checked, value } = e.target; + + // Crear una copia del formulario + const updatedForm = { + ...form, + [name]: type === "checkbox" ? checked : value, + }; + // Inicializar valores por si están vacíos + const subtotal = parseFloat(updatedForm.subtotal) || 0; + const ieps = parseFloat(updatedForm.ieps) || 0; + + let ivaAmount = 0; + + if (name === "total" && !categoryRequiresProducts(Number(updatedForm.expense_cat))) { + const totalValue = parseFloat(value) || 0; + const iepsValue = parseFloat(updatedForm.ieps) || 0; + const taxRate = parseFloat( + taxes.find((t) => t.id === parseInt(updatedForm.new_tax))?.number || 0 + ); + + if (taxRate > 0) { + const subtotalBeforeIeps = totalValue - iepsValue; + const calculatedSubtotal = subtotalBeforeIeps / (1 + taxRate); + const calculatedIva = calculatedSubtotal * taxRate; + + updatedForm.subtotal = calculatedSubtotal; + updatedForm.iva = calculatedIva; + updatedForm.total = totalValue; + } else { + updatedForm.subtotal = totalValue - iepsValue; + updatedForm.iva = 0; + updatedForm.total = totalValue; + } + + setForm({ + ...updatedForm, + subtotal: updatedForm.subtotal.toFixed(2), + iva: updatedForm.iva.toFixed(2), + total: updatedForm.total, + }); + return; + } + + // Si hay productos, recalcular desde ellos + if (updatedForm.products.length > 0) { + updatedForm.subtotal = updatedForm.products.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + ivaAmount = updatedForm.products.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + console.log(ivaAmount); + } else { + const taxRate = parseFloat( + taxes.find((t) => t.id === parseInt(updatedForm.new_tax))?.number || 0 + ); + console.log(taxRate); + ivaAmount = subtotal * taxRate; + } + + updatedForm.iva = ivaAmount; + + // Calcular total final (subtotal + IVA + IEPS) + updatedForm.total = subtotal + ivaAmount + ieps; + + // Actualizar estado + setForm({ + ...updatedForm, + iva: updatedForm.iva.toFixed(2), + total: name === "total" ? updatedForm.total : updatedForm.total.toFixed(2), + }); + }; + + const handleCategoryChange = (e) => { + const { name, value } = e.target; + const categoryValue = Number(value) || 0; + setForm((prev) => { + const updatedForm = { ...prev, [name]: categoryValue }; + if (categoryRequiresProducts(categoryValue)) { + updatedForm.products = [ + { + id_product: null, + quantity: 1, + unit_cost: 0, + id_tax: 1, + subtotal: 0, + iva: 0, + }, + ]; + updatedForm.new_tax = ""; + } else { + // Si cambia a otra categoría, vaciamos los productos + updatedForm.products = []; + } + return updatedForm; + }); + }; + + const handleProductChange = (index, field, value) => { + const updatedProducts = [...form.products]; // Convertir a entero si es un campo numérico esperado + const ieps = parseFloat(form.ieps) || 0; + const processedValue = ["unit_cost"].includes(field) + ? parseFloat(value) + : ["quantity", "id_tax", "id_product"].includes(field) + ? parseInt(value) + : value; + updatedProducts[index][field] = processedValue; + + if (field === "quantity" || field === "unit_cost" || field === "id_tax") { + const qty = parseFloat(updatedProducts[index].quantity) || 0; + const cost = parseFloat(updatedProducts[index].unit_cost) || 0; + const taxValue = parseFloat( + taxes.find((t) => t.id === parseInt(updatedProducts[index].id_tax)) + ?.number || 0 + ); + updatedProducts[index].subtotal = qty * cost; + updatedProducts[index].iva = qty * cost * taxValue; + } + + // Recalcular el amount (suma de todos los productos) + const subtotalAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + // Recalcular el amount (suma de todos los productos) + const ivaAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + + setError(null); + setSuccess(false); + + setForm((prev) => ({ + ...prev, + products: updatedProducts, + subtotal: subtotalAmount.toFixed(2), // redondeado a 2 decimales + iva: ivaAmount.toFixed(2), // redondeado a 2 decimales + total: (subtotalAmount + ivaAmount + ieps).toFixed(2), // Calcular total final (subtotal + IVA + IEPS) + })); + }; + + const handleAddProduct = () => { + const ieps = parseFloat(form.ieps) || 0; + + // Primero, agregamos el nuevo producto + const updatedProducts = [ + ...form.products, + { + id_product: null, + quantity: 1, + unit_cost: 0, + id_tax: "", + subtotal: 0, + iva: 0, + }, + ]; + + // Ahora sí, recalculamos después de agregarlo + const subtotalAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + const ivaAmount = updatedProducts.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + + setForm((prev) => ({ + ...prev, + products: updatedProducts, + subtotal: subtotalAmount.toFixed(2), + iva: ivaAmount.toFixed(2), + total: (subtotalAmount + ivaAmount + ieps).toFixed(2), + })); + }; + + const handleRemoveProduct = (index) => { + setForm((prev) => { + const updated = [...prev.products]; + updated.splice(index, 1); + + // Recalcular el amount (suma de todos los productos) + const subtotalAmount = updated.reduce( + (acc, p) => acc + (parseFloat(p.subtotal) || 0), + 0 + ); + + // Recalcular el amount (suma de todos los productos) + const ivaAmount = updated.reduce( + (acc, p) => acc + (parseFloat(p.iva) || 0), + 0 + ); + + const ieps = parseFloat(prev.ieps) || 0; + + return { + ...prev, + products: updated, + subtotal: subtotalAmount.toFixed(2), // redondeado a 2 decimales + iva: ivaAmount.toFixed(2), // redondeado a 2 decimales + total: (subtotalAmount + ivaAmount + ieps).toFixed(2), // Calcular total final (subtotal + IVA + IEPS) + }; + }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setSuccess(false); + setError(""); + + // ✅ Validar campos obligatorios antes de enviar + if ( + !form.suppliers_id || + !form.area || + !form.expense_cat || + !form.currency_id || + !form.total + ) { + setError( + lang === "en" + ? "Please fill in all required fields (Supplier, Area, Category, Currency, total)." + : "Por favor llena todos los campos obligatorios (Proveedor, Área, Categoría, Moneda, Monto)." + ); + setLoading(false); + return; + } + + try { + const payload = { + new_description: form.new_description, + suppliers_id: Number(form.suppliers_id), + new_request_date: form.new_request_date, + new_payment_deadline: form.new_payment_deadline, + request_by: Number(userData.user_id), + area: Number(form.area), + expense_cat: Number(form.expense_cat), + currency_id: Number(form.currency_id), + needtoapprove: form.needtoapprove, + products: form.products, + new_subtotal: Number(form.subtotal), + new_iva: Number(form.iva), + new_ieps: Number(form.ieps), + new_total: Number(form.total), + }; + + // 🔍 LOGS para depurar el error 500 + console.group("🧾 Envío de nuevo gasto"); + console.log("Payload completo que se enviará al backend:", payload); + console.log("Tipo de cada campo:"); + Object.entries(payload).forEach(([k, v]) => + console.log(`${k}:`, v, typeof v) + ); + console.groupEnd(); + + // Enviar petición + console.log('payload', payload); + const res = await fetch( + import.meta.env.VITE_API_BASE_URL + "/expenses/newexpense", + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + } + ); + console.log('res', res); + + const text = await res.text(); + let data; + try { + data = JSON.parse(text); + } catch { + data = text; + } + + // 🧩 Nuevo: Log para inspeccionar respuesta cruda + console.group("📨 Respuesta del servidor"); + console.log("Status:", res.status); + console.log("Texto recibido:", text); + console.groupEnd(); + + if (!res.ok) { + console.error("Error response:", res.status, data); + throw new Error(`Server error ${res.status}: ${JSON.stringify(data)}`); + } + + setSuccess(true); + + // limpiar formulario + setForm({ + new_description: "", + suppliers_id: "", + new_request_date: "", + new_payment_deadline: "", + area: "", + expense_cat: "", + currency_id: "", + subtotal: 0, + needtoapprove: false, + iva: 0, + ieps: 0, + total: 0, + products: [], + }); + } catch (err) { + console.error("❌ handleSubmit error:", err); + setError(err.message || "Unexpected error"); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    +
    +
    {lang === "en" ? "New expense" : "Nuevo gasto"}
    + +
    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + + {!categoryRequiresProducts(Number(form.expense_cat)) && ( +
    + + +
    + )} + +
    + + +
    + +
    + + +
    + +
    + + +
    + + {/* Need to Approve (Campo solicitado en la estructura) */} +
    + + +
    +
    + + {/* Sección de Productos */} + {categoryRequiresProducts(Number(form.expense_cat)) && ( +
    +

    + {lang === "en" ? "Products" : "Productos"} +

    + +
    + {form.products.map((product, index) => ( +
    +
    + + +
    +
    + + + handleProductChange(index, "quantity", e.target.value) + } + placeholder={lang === "en" ? "Quantity" : "Cantidad"} + /> +
    +
    + + + handleProductChange( + index, + "unit_cost", + e.target.value + ) + } + placeholder={ + lang === "en" ? "Unit Cost" : "Precio Unitario" + } + /> +
    +
    + + +
    + +
    + + {index === form.products.length - 1 && ( + + )} +
    +
    + ))} +
    +
    + )} + +
    + +
    + + {success && ( + + {lang === "en" + ? "Expense saved successfully!" + : "¡Gasto guardado con éxito!"} + + )} + {error && {error}} + +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/NewMonthlyPayment.css b/frontend/Frontend-Hotel/src/pages/Expenses/NewMonthlyPayment.css new file mode 100644 index 0000000..67b13eb --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/NewMonthlyPayment.css @@ -0,0 +1,149 @@ + +.new-expense-container { + color: #333; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.form-id { + font-weight: bold; + margin-bottom: 20px; + font-size: 24px; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 15px; + margin-bottom: 30px; +} + +.form-grid label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #333; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 6px 4px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 20px; +} + +.save-button { + background-color: #ffcb05; + color: #fff; + padding: 10px 30px; + font-weight: bold; + border: none; + border-radius: 25px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.save-button:hover { + background-color: #f4b400; +} + +.product-table-section { + margin-top: 25px; +} + + +/*Actualización de New Expense con tabla*/ + +/* src/pages/Expenses/NewExpense.css */ + +.new-expense-container { + padding: 20px; +} + +.form-card { + background-color: #fff; + border-radius: 8px; + padding: 24px; + box-shadow: 0 0 10px rgba(0,0,0,0.1); +} + +.form-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 20px; +} + +.save-button-wrapper { + margin-top: 20px; + display: flex; + justify-content: flex-end; +} + +.save-button { + background-color: #ffc107; /* amarillo/dorado */ + color: #000; /* ajustar según contraste */ + border: none; + padding: 10px 24px; + border-radius: 20px; + font-weight: bold; + cursor: pointer; +} + +.product-table-section { + margin-top: 20px; + overflow-x: auto; +} + +.product-table { + width: 100%; + border-collapse: collapse; +} + +.product-table th, .product-table td { + border: 1px solid #d4af37; /* dorado */ + padding: 8px; + text-align: center; +} + +.product-table th { + background-color: #800020; /* bordo/morado oscuro, según tus imágenes */ + color: white; + font-weight: bold; +} + +.add-product-row { + cursor: pointer; + color: #d4af37; /* dorado */ + text-align: center; + padding: 10px; + font-style: italic; +} + +.tax-pill { + background-color: white; + border: 1px solid #d4af37; + border-radius: 12px; + padding: 2px 6px; + color: #800020; +} + +.product-table tfoot td { + border-top: 2px solid #d4af37; + padding: 8px; +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/NewMonthlyPayment.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/NewMonthlyPayment.jsx new file mode 100644 index 0000000..54281e5 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/NewMonthlyPayment.jsx @@ -0,0 +1,300 @@ +import React, { useEffect, useState } from 'react'; +import './NewMonthlyPayment.css'; +// import '../Inventory/NewProduct.css '; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + + +//**////** */ */ REVISAR POR QUE NO AGREGA UN NEWMONTLYEXPENSE +export default function NewMonthlyPayment() { + const { lang } = useContext(langContext); + const [suppliers, setSuppliers] = useState([]); + const [recurrences, setRecurrences] = useState([]); + const [currencies, setCurrencies] = useState([]); + const [categories, setCategories] = useState([]); + const [areas, setAreas] = useState([]); + const [taxes, setTaxes] = useState([]); + const [form, setForm] = useState({ + descriptionex: '', + recurrence_id: "", + payment_type: "", + currency_id: "", + suppliers_id: '', + area: '', + expense_category: '', + day_expense: '', + tax_id: '', + new_subtotal: '' + }); + + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(''); + + useEffect(() => { + if (form.payment_type === "2") { + setForm(prev => ({ + ...prev, + new_subtotal: '', + tax_id: '' + })); + } + }, [form.payment_type]); + + useEffect(() => { + fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/getinfo') + .then(res => res.json()) + .then(data => { + setSuppliers(data.suppliers); + setCurrencies(data.currencies); + setAreas(data.areas); + setCategories(data.categories); + setTaxes(data.tax); + }) + .catch(err => console.error('Error fetching suppliers', err)); + fetch(import.meta.env.VITE_API_BASE_URL + '/settings/recurrence') + .then(res => res.json()) + .then(data => setRecurrences(data.currency)); + + }, []); + + const handleChange = (e) => { + const { name, value } = e.target; + setForm(prev => ({ ...prev, [name]: value })); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setError(''); + setSuccess(false); + + try { + const isVariable = Number(form.payment_type) === 2; + + const payload = { + ...form, + recurrence_id: Number(form.recurrence_id), + payment_type: Number(form.payment_type), + currency_id: Number(form.currency_id), + area: Number(form.area), + expense_category: Number(form.expense_category), + day_expense: Number(form.day_expense), + tax_id: isVariable ? null : form.tax_id, + new_subtotal: isVariable ? null : form.new_subtotal + }; + + const res = await fetch(import.meta.env.VITE_API_BASE_URL + '/payment/newexpmonthly', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + if (!res.ok) throw new Error('Error al guardar el gasto mensual'); + + setSuccess(true); + setForm({ + descriptionex: '', + recurrence_id: '', + payment_type: '', + currency_id: '', + suppliers_id: '', + area: '', + expense_category: '', + day_expense: '', + amount_expense: '', + tax_id: '', + new_subtotal: '' + }); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    +
    + {lang === "en" ? "New monthly payment" : "Nuevo pago mensual"} +
    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + + {form.payment_type !== "2" && ( +
    + + +
    + )} + +
    + + +
    + +
    + + +
    + +
    + + +
    + + {form.payment_type !== "2" && ( +
    + + +
    + )} + +
    + + +
    + +
    + +
    + +
    + + {success && ( + + {lang === "en" + ? "Monthly payment saved!" + : "¡Pago mensual guardado!"} + + )} + + {error && {error}} + +
    +
    + + ); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/NewSuppliers.css b/frontend/Frontend-Hotel/src/pages/Expenses/NewSuppliers.css new file mode 100644 index 0000000..33feabc --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/NewSuppliers.css @@ -0,0 +1,63 @@ +.new-supplier-container { + padding: 20px; + color: #333; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.form-id { + font-weight: bold; + margin-bottom: 20px; + font-size: 18px; +} + +.form-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 15px; + margin-bottom: 30px; +} + +.form-grid label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #333; +} + +.form-grid input { + width: 100%; + padding: 6px 4px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 20px; +} + +.save-button { + background-color: #ffcb05; + color: #fff; + padding: 10px 30px; + font-weight: bold; + border: none; + border-radius: 25px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.save-button:hover { + background-color: #f4b400; +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/NewSuppliers.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/NewSuppliers.jsx new file mode 100644 index 0000000..e10ea12 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/NewSuppliers.jsx @@ -0,0 +1,212 @@ +import React, { useState, useContext } from 'react'; +import './NewSuppliers.css'; +import { langContext } from '../../context/LenguageContext'; +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +import * as Yup from 'yup'; + +export default function NewSuppliers() { + const { lang } = useContext(langContext); + const [suppliers, setSuppliers] = useState([]); + const [success, setSuccess] = useState(false); + + //Generador de IDs automáticos tipo SUP-0001 + const generateSupplierId = (index) => { + const num = (index + 1).toString().padStart(4, '0'); + return `SUP-${num}`; + }; + + //Esquema Yup (solo RFC y Name son obligatorios) + const supplierSchema = Yup.object({ + new_rfc_suppliers: Yup.string() + .required(lang === 'en' ? 'RFC is required' : 'El RFC es obligatorio') + .min(12, lang === 'en' ? 'Min 12 characters' : 'Mínimo 12 caracteres') + .max(13, lang === 'en' ? 'Max 13 characters' : 'Máximo 13 caracteres'), + + new_name_suppliers: Yup.string() + .required(lang === 'en' ? 'Name is required' : 'El nombre es obligatorio') + .min(10, lang === 'en' ? 'Min 10 characters' : 'Mínimo 10 caracteres') + .max(50, lang === 'en' ? 'Max 50 characters' : 'Máximo 50 caracteres'), + + new_email_suppliers: Yup.string() + .email(lang === 'en' ? 'Invalid email format' : 'Formato de correo no válido') + .nullable() + .transform((value, originalValue) => originalValue.trim() === '' ? null : value), + + new_phone_suppliers: Yup.string() + .max(15, lang === 'en' ? 'Max 15 digits' : 'Máximo 15 dígitos') + .matches(/^[0-9+\- ]*$/, lang === 'en' ? 'Only numbers and symbols (+, -)' : 'Solo números y símbolos (+, -)') + .nullable() + .transform((value, originalValue) => originalValue.trim() === '' ? null : value) + }); + + //Inicializar react-hook-form con Yup + const { + register, + handleSubmit, + reset, + formState: { errors, isSubmitting } + } = useForm({ + resolver: yupResolver(supplierSchema), + defaultValues: { + new_rfc_suppliers: '', + new_name_suppliers: '', + new_email_suppliers: '', + new_phone_suppliers: '' + } + }); + + const [errorMsg, setErrorMsg] = useState(''); + + const onSubmit = async (data) => { + setSuccess(false); + setErrorMsg(''); + + const body = { + new_name_supp: data.new_name_suppliers, + new_rfc_supp: data.new_rfc_suppliers, + new_mail_supp: data.new_email_suppliers, + new_phone_supp: data.new_phone_suppliers + }; + + try { + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/newsupplier`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + } + ); + + const result = await response.json(); + + //Si el backend indica conflicto o duplicado + if (!response.ok) { + if (response.status === 409 || result.message?.toLowerCase().includes('exists')) { + setErrorMsg( + lang === 'en' + ? 'This supplier is already registered.' + : 'Este proveedor ya está registrado.' + ); + } else { + setErrorMsg( + lang === 'en' + ? 'Error saving supplier.' + : 'Error al guardar el proveedor.' + ); + } + return; + } + + console.log('Supplier creado:', result); + setSuppliers(prev => [...prev, result]); + setSuccess(true); + reset(); + + } catch (error) { + console.error('Error al crear supplier:', error); + setErrorMsg( + lang === 'en' + ? 'Network error while saving supplier.' + : 'Error de red al guardar el proveedor.' + ); + } + }; + + // Actualizar estado de pago (PUT) + const updatePaymentStatus = async (supplierId) => { + try { + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/status/paymentupdate/${supplierId}`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ status: 1 }) + } + ); + + if (!response.ok) throw new Error('Error al actualizar status'); + + const result = await response.json(); + console.log('Payment status updated:', result); + } catch (error) { + console.error('Error actualizando el status de pago:', error); + } + }; + + + return ( +
    +
    +

    {lang === 'en' ? 'New Supplier' : 'Nuevo Proveedor'}

    +
    +
    + {/* RFC */} +
    + + + {errors.new_rfc_suppliers && ( +

    {errors.new_rfc_suppliers.message}

    + )} +
    + + {/* Name */} +
    + + + {errors.new_name_suppliers && ( +

    {errors.new_name_suppliers.message}

    + )} +
    + + {/* Email */} +
    + + + {errors.new_email_suppliers && ( +

    {errors.new_email_suppliers.message}

    + )} +
    + + {/* Phone */} +
    + + + {errors.new_phone_suppliers && ( +

    {errors.new_phone_suppliers.message}

    + )} +
    +
    + + {errorMsg && ( +

    + {errorMsg} +

    + )} + + + {success && ( +

    + {lang === 'en' + ? 'Supplier saved successfully!' + : '¡Proveedor guardado exitosamente!'} +

    + )} + +
    + +
    + +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/Payments.css b/frontend/Frontend-Hotel/src/pages/Expenses/Payments.css new file mode 100644 index 0000000..cb865ff --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/Payments.css @@ -0,0 +1,255 @@ +.report-page { + padding: 20px; +} + +.page-filters { + display: flex; + flex-direction: column; + gap: 12px; + margin: 20px 0; + padding: 15px; + background-color: #f8f9fa; + border-radius: 8px; + align-items: stretch; +} + +.filters-row { + width: 100%; + display: flex; + gap: 12px; + align-items: center; + flex-wrap: wrap; + justify-content: flex-end; +} + +.filters-row.second-row { + justify-content: flex-end; + align-items: flex-start; +} + +.filters-row.second-row .date-filter-group { + flex: 0 0 auto; + min-width: 180px; +} + +.filters-row.second-row .clear-filters-btn { + flex-shrink: 0; + margin-left: 8px; +} + +.filters-row .filter-search { + flex: 1; + max-width: 280px; + min-width: 180px; + height: 38px; + box-sizing: border-box; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + background-color: #fff; + margin: 0; +} + +.filters-row .filter-select { + min-width: 180px; + height: 38px; + box-sizing: border-box; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 30px; + font-size: 14px; + background-color: #fff; + margin: 0; + line-height: normal; +} + +.filter-group { + display: flex; + flex-direction: column; + min-width: 180px; +} + +.filter-group label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + color: #333; +} + +.filter-group select, +.filter-group input { + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + background-color: #fff; +} + +.filter-group select:focus, +.filter-group input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25); +} + +.clear-filters-btn { + background-color: #6c757d; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + align-self: end; + transition: background-color 0.2s; +} + +.clear-filters-btn:hover { + background-color: #5a6268; +} + +@media (max-width: 768px) { + .page-filters { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .filters-row { + flex-direction: column; + gap: 10px; + } + + .filters-row.second-row { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .filters-row .filter-search { + min-width: 100%; + max-width: 100%; + order: -1; + height: 38px; + box-sizing: border-box; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + background-color: #fff; + margin: 0; + } + + .filter-select { + min-width: 100%; + height: 38px; + box-sizing: border-box; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + background-color: #fff; + margin: 0; + line-height: normal; + } + + .date-filter-group { + flex: 1; + min-width: 200px; + } + + .date-inputs { + flex-direction: column; + } + + .date-input { + min-width: 100%; + } + + .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} + +.summary-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 15px; + margin: 20px 0; +} + +.summary-card { + background-color: #fff; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + text-align: center; +} + +.summary-card strong { + display: block; + font-size: 14px; + color: #666; + margin-bottom: 10px; +} + +.summary-card div { + font-size: 24px; + font-weight: bold; + color: #333; +} + +.status-badge { + padding: 6px 12px; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 12px; + font-weight: bold; + transition: all 0.2s; +} + +.status-badge.active { + background-color: #28a745; + color: white; +} + +.status-badge.active:hover { + background-color: #218838; +} + +.status-badge.reject { + background-color: #dc3545; + color: white; +} + +.status-badge.reject:hover { + background-color: #c82333; +} + +.status-button { + padding: 4px 8px; + border: none; + border-radius: 4px; + font-size: 12px; + font-weight: bold; + text-transform: uppercase; +} + +.status-button.approved { + background-color: #28a745; + color: white; +} + +.status-button.pending { + background-color: #ffc107; + color: black; +} + +.status-button.rejected { + background-color: #dc3545; + color: white; +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/Payments.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/Payments.jsx new file mode 100644 index 0000000..e440b53 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/Payments.jsx @@ -0,0 +1,333 @@ +import React, { useEffect, useState } from 'react'; +import Table from '../../components/Table/HotelTable'; +import SummaryCard from '../../components/SummaryCard'; +import '../../components/Filters/Filters.css'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +import ConfirmationModal from '../../components/Modals/ConfirmationModal'; +import axios from 'axios'; +import { Link } from 'react-router-dom'; +import ExcelExportButton from '../../components/ExcelExportButton'; +import './Payments.css'; + +export default function Payments() { + const { lang } = useContext(langContext); + const [data, setData] = useState([]); + const [modalOpen, setModalOpen] = useState(false); + const [selectedStatus, setSelectedStatus] = useState(''); + const [selectedStatusId, setSelectedStatusId] = useState(null); + const [selectedId, setSelectedId] = useState(null); + const [filters, setFilters] = useState({ + status: '', + requestedBy: '', + requestDateFrom: '', + requestDateTo: '', + approvedDateFrom: '', + approvedDateTo: '', + searchTerm: '' + }); + const loadExpenses = () => { + fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/reportexpenses') + .then(res => res.json()) + .then(resData => { + const mapped = resData.data.map(item => { + return { + id: item.id_expense, + description: item.expense_description, + requestDate: item.request_date?.split('T')[0], + approvedDate: item.approval_date?.split('T')[0], + requestedBy: item.requested_by, + totalpesos: Number(item.totalpesos), + status: item.status_approval, + paymentStatus: item.status_payment, + supplier: item.supplier || 'Unknown', + is_monthly : item.is_monthly + }; + }); + setData(mapped.filter(c => c.is_monthly !== true && c.status === "Approved" && c.paymentStatus === "PENDING")); + }) + .catch(() => {}); + }; + + useEffect(() => { + loadExpenses(); + }, []); + + const handleOpenModal = (id, statusType, statusId) => { + setSelectedId(id); + setSelectedStatus(statusType); + setSelectedStatusId(statusId); + setModalOpen(true); + }; + + + const handleConfirm = () => { + if (!selectedId || !selectedStatus || !selectedStatusId) return; + + const statusValue = selectedStatusId; + + axios.put(`${import.meta.env.VITE_API_BASE_URL}/status/paymentupdate/${selectedId}`, { + status: statusValue + }) + .then(() => { + loadExpenses(); + + setModalOpen(false); + setSelectedId(null); + setSelectedStatus(null); + }) + .catch(() => { + alert('❌ Error al actualizar el estado. Intenta nuevamente.'); + }); + }; + + const handleCancel = () => { + setModalOpen(false); + }; + + const filteredData = data.filter((item) => { + if (filters.searchTerm && (!item.description || !item.description.toLowerCase().includes(filters.searchTerm.toLowerCase()))) return false; + + if (filters.status && item.status !== filters.status) return false; + + if (filters.requestedBy && item.requestedBy !== filters.requestedBy) return false; + + if (filters.requestDateFrom || filters.requestDateTo) { + if (!item.requestDate) return false; + + const requestDate = new Date(item.requestDate); + if (filters.requestDateFrom) { + const from = new Date(filters.requestDateFrom); + if (requestDate < from) return false; + } + if (filters.requestDateTo) { + const to = new Date(filters.requestDateTo); + if (requestDate > to) return false; + } + } + + if (filters.approvedDateFrom || filters.approvedDateTo) { + if (!item.approvedDate) return false; + + const approvedDate = new Date(item.approvedDate); + if (filters.approvedDateFrom) { + const from = new Date(filters.approvedDateFrom); + if (approvedDate < from) return false; + } + if (filters.approvedDateTo) { + const to = new Date(filters.approvedDateTo); + if (approvedDate > to) return false; + } + } + + return true; + }); + + const totalAmount = filteredData + .reduce((acc, curr) => { + return curr.totalpesos + acc; + }, 0); + + const uniqueStatuses = [...new Set(data.map(item => item.status))].filter(Boolean); + const uniqueRequestedBy = [...new Set(data.map(item => item.requestedBy))].filter(Boolean); + + const columns = [ + { + header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", + key: 'description', + render: (text, row) => ( + + {text} + + ), + }, + { header: lang === "en" ? "REQUEST DATE" : "FECHA DE SOLICITUD", key: 'requestDate' }, + { header: lang === "en" ? "APPROVED DATE" : "FECHA DE APROBACIÓN", key: 'approvedDate' }, + { header: lang === "en" ? "REQUESTED BY" : "SOLICITADO POR", key: 'requestedBy' }, + { + header: lang === "en" ? "AMOUNT" : "IMPORTE", + key: 'totalpesos', + render: (value) => { + const num = parseFloat(value || 0); + return `$${num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + } + }, + { + header: lang === "en" ? "APPROVAL STATUS" : "ESTADO DE APROBACIÓN", + key: 'status', + headerStyle: { textAlign: 'center' }, + render: (status) => ( +
    + +
    + ), + }, + { + header: lang === "en" ? "PAYMENT STATUS" : "ESTADO DE PAGO", + key: 'id', + headerStyle: { textAlign: 'center' }, + render: (id) => { + return ( +
    + + +
    + ); + }, + }, +]; + + const exportColumns = columns.slice(0, -1); + + + return ( +
    +
    +

    + {lang === "en" ? "Payment" : "Pagos"} +

    +
    + +
    +
    + setFilters({ ...filters, searchTerm: e.target.value })} + className="filter-search" + /> + + + + +
    + +
    +
    + +
    + setFilters({ ...filters, requestDateFrom: e.target.value })} + className="date-input" + /> + setFilters({ ...filters, requestDateTo: e.target.value })} + className="date-input" + /> +
    +
    + +
    + +
    + setFilters({ ...filters, approvedDateFrom: e.target.value })} + className="date-input" + /> + setFilters({ ...filters, approvedDateTo: e.target.value })} + className="date-input" + /> +
    +
    + + +
    +
    + +
    +
    + +
    + +
    + +
    +
    + + + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/PurchaseEntries.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/PurchaseEntries.jsx new file mode 100644 index 0000000..9f8a4a3 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/PurchaseEntries.jsx @@ -0,0 +1,156 @@ +import React, { useEffect, useState } from 'react'; +import ConfirmationModal from '../../components/Modals/ConfirmationModal'; +import Table from '../../components/Table/HotelTable'; +import { Link } from 'react-router-dom'; +import axios from 'axios'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +//**////** */ */ REVISAR DELIVERED NULL +export default function PurchaseEntries() { + const { lang } = useContext(langContext); + const [purchases, setPurchases] = useState([]); + const [searchTerm, setSearchTerm] = useState(''); + const [modalOpen, setModalOpen] = useState(false); + const [checking, setChecking] = useState(null); + const [selectedId, setSelectedId] = useState(null); + + const loadPurchases = () => { + fetch(import.meta.env.VITE_API_BASE_URL + '/purchases/getpurchases') + .then(res => res.json()) + .then(resData => { + const mapped = resData.data.map(item => ({ + id: item.id_purchase_dt, + expense_id: item.id_expense, + name: item.product_name, + quantity: item.quantity, + delivered: item.delivered, + check: 0, + })); + setPurchases(mapped); + }) + .catch(err => console.error('Error loading expense report:', err)); + }; + + useEffect(() => { + loadPurchases(); + }, []); + + const filteredPurchases = purchases.filter(purchase => + purchase.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); + + const columns = [ + { header: lang === "en" ? "PURCHASE ID" : "ID DE COMPRA", key: 'id' }, + { header: lang === "en" ? "EXPENSE ID" : "ID DE GASTO", key: 'expense_id' }, + { header: lang === "en" ? "PRODUCT" : "PRODUCTO", key: 'name' }, + { header: lang === "en" ? "REQUESTED" : "SOLICITADOS", key: 'quantity' }, + { header: lang === "en" ? "DELIVERED" : "ENTREGADOS", key: 'delivered' }, + { + header: lang === "en" ? "CHECKING" : "RECIBIENDO", + key: 'check', + render: (check, row) => ( + handleCheckingChange(row.id, e.target.value)} + placeholder={lang === "en" ? "Checking" : "Recibiendo"} + /> + ), + }, + { + header: lang === "en" ? "CONFIRM RECEIVED" : "CONFIRMAR RECEPCIÓN", + key: 'id', + headerStyle: { textAlign: 'center' }, + render: (id, row) => ( +
    + +
    + ), + }, + ]; + + const handleCheckingChange = (id, value) => { + setPurchases(prev => + prev.map(p => + p.id === id ? { ...p, check: value } : p + ) + ); + }; + + + const handleOpenModal = (id, check) => { + setSelectedId(id); + setChecking(check); + setModalOpen(true); + }; + + const handleConfirm = () => { + if (!selectedId || !checking) return; + + axios.put(`${import.meta.env.VITE_API_BASE_URL}/purchases/entry/${selectedId}`, { + checking: parseInt(checking) + }) + .then((res) => { + console.log(res.data.message || 'Estado actualizado correctamente'); + + //Actualizar purchases + loadPurchases(); + + // Cerrar el modal y limpiar selección + setModalOpen(false); + setSelectedId(null); + setChecking(null); + }) + .catch((err) => { + console.error(`Error al actualizar el estado del gasto ${selectedId}:`, err); + alert('❌ Error al actualizar el estado. Intenta nuevamente.'); + }); + }; + + const handleCancel = () => { + setModalOpen(false); + }; + + return ( +
    +

    {lang === "en" ? "Purchase Entries" : "Entradas de compras"}

    + +
    + setSearchTerm(e.target.value)} + style={{ + padding: '10px 16px', + border: 'none', + borderRadius: '30px', + backgroundColor: 'white', + boxShadow: '0 0 0 2px #f4f4f4', + fontSize: '14px', + color: '#333', + fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", + fontWeight: 'bold', + minWidth: '250px', + width: '100%', + maxWidth: '400px' + }} + /> +
    + +
    + + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/ReportExpense.css b/frontend/Frontend-Hotel/src/pages/Expenses/ReportExpense.css new file mode 100644 index 0000000..2f0ba40 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/ReportExpense.css @@ -0,0 +1,362 @@ +.report-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.report-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + gap: 12px; + align-items: stretch; +} + +.report-page .filters-row { + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.report-page .filters-row.second-row { + justify-content: flex-end; + max-width: 100%; + align-items: flex-start; +} + +.report-page .filters-row.second-row .date-filter-group { + flex: 0 0 auto; + min-width: 180px; +} + +.report-page .filters-row.second-row .filter-search { + flex: 0 1 300px; + max-width: 300px; + min-width: 200px; + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.report-page .filters-row.second-row .clear-filters-btn { + flex-shrink: 0; + margin-left: 8px; +} + +@media (min-width: 1400px) { + .report-page .filters-row.second-row { + flex-wrap: nowrap; + } +} + +.filter-search { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + margin-top: 26px; +} + +.filter-search::placeholder { + color: #999; +} + +.filter-search:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-search:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.filter-select { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 180px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.filter-select:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-select:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.date-filter-group { + display: flex; + flex-direction: column; + gap: 8px; +} + +.date-filter-label { + font-size: 11px; + font-weight: 700; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; +} + +.date-inputs { + display: flex; + gap: 8px; +} + +.date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 145px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.clear-filters-btn { + padding: 10px 20px; + background-color: white; + border: 2px solid #e0e0e0; + border-radius: 30px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + color: #666; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.clear-filters-btn:hover { + background-color: #f5f5f5; + border-color: #ccc; + color: #333; +} + +.summary-actions-section { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; + gap: 20px; + flex-wrap: wrap; +} + +.summary-cards-wrapper { + display: flex; + gap: 20px; + flex-wrap: wrap; +} + +.info-card { + background: linear-gradient(145deg, #ffffff, #f8f9fa); + border-radius: 16px; + padding: 20px 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-width: 180px; + flex: 1; + transition: all 0.3s ease; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.info-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); +} + +.info-card .card-title { + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + margin: 0 0 12px 0; + color: #666; +} + +.info-card .card-value { + font-size: 28px; + font-weight: 700; + color: #333; + line-height: 1.2; +} + + +.table-section { + background: white; + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-height: 400px; +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } + + .table-section { + padding: 20px; + } +} + +@media (max-width: 768px) { + .report-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .report-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .report-page .filters-row { + flex-direction: column; + gap: 10px; + } + + .report-page .filters-row.second-row { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .report-page .filter-search { + flex: 1; + min-width: 200px; + max-width: 100%; + order: -1; + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + } + + .report-page .filter-select { + min-width: 100%; + } + + .report-page .date-filter-group { + flex: 1; + min-width: 200px; + } + + .report-page .date-inputs { + flex-direction: column; + } + + .report-page .date-input { + min-width: 100%; + } + + .report-page .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } + + .summary-actions-section { + flex-direction: column; + align-items: stretch; + } + + .summary-cards-wrapper { + flex-direction: column; + } + + .export-button { + align-self: stretch; + } + + .table-section { + padding: 16px; + border-radius: 12px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .table-section { + padding: 12px; + } +} + diff --git a/frontend/Frontend-Hotel/src/pages/Expenses/ReportExpense.jsx b/frontend/Frontend-Hotel/src/pages/Expenses/ReportExpense.jsx new file mode 100644 index 0000000..d2dced1 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Expenses/ReportExpense.jsx @@ -0,0 +1,404 @@ +import React, { useEffect, useState } from 'react'; +import Table from '../../components/Table/HotelTable'; +import SummaryCard from '../../components/SummaryCard'; +import './ReportExpense.css'; +import { Link } from 'react-router-dom'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +import ExcelExportButton from '../../components/ExcelExportButton'; + +export default function ReportExpense() { + const { lang } = useContext(langContext); + const [data, setData] = useState([]); + + const refreshMonthlyData = async () => { + try { + await fetch(`${import.meta.env.VITE_API_BASE_URL}/payment/refreshmonthly`, { + method: 'GET' + }); + } catch (error) { + console.error('Error refreshing monthly data from Expenses section:', error); + } + }; + const [approvedDateRange, setApprovedDateRange] = useState({ from: '', to: '' }); + const [requestDateRange, setRequestDateRange] = useState({ from: '', to: '' }); + const [statusFilter, setStatusFilter] = useState(''); + const [paymentStatusFilter, setPaymentStatusFilter] = useState(''); + const [requestedByFilter, setRequestedByFilter] = useState(''); + const [categoryFilter, setCategoryFilter] = useState(''); + const [areaFilter, setAreaFilter] = useState(''); + const [descriptionSearch, setDescriptionSearch] = useState(''); + + const clearFilters = () => { + setDescriptionSearch(''); + setStatusFilter(''); + setPaymentStatusFilter(''); + setRequestedByFilter(''); + setCategoryFilter(''); + setAreaFilter(''); + setRequestDateRange({ from: '', to: '' }); + setApprovedDateRange({ from: '', to: '' }); + }; + + useEffect(() => { + const loadData = async () => { + await refreshMonthlyData(); + + fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/reportexpenses') + .then(res => res.json()) + .then(resData => { + const mapped = resData.data.map(item => ({ + id: item.id_expense, + description: item.expense_description, + requestDate: item.request_date?.split('T')[0], + approvedDate: item.approval_date?.split('T')[0], + requestedBy: item.requested_by, + totalpesos: Number(item.totalpesos), + status: item.status_approval, + paymentStatus: item.status_payment, + supplier: item.supplier || 'Unknown', + category: item.category, + area: item.area, + is_monthly: item.is_monthly + })); + const filteredData = mapped.filter(c => c.is_monthly !== true); + setData(filteredData); + + }) + .catch(err => console.error('Error loading expense report:', err)); + }; + + loadData(); + }, []); + + const uniqueStatuses = [...new Set(data.map(item => item.status).filter(Boolean))].sort(); + const uniquePaymentStatuses = [...new Set(data.map(item => item.paymentStatus).filter(Boolean))].sort(); + const uniqueRequestedBy = [...new Set(data.map(item => item.requestedBy).filter(Boolean))].sort(); + const uniqueCategories = [...new Set(data.map(item => item.category).filter(Boolean))].sort(); + const uniqueAreas = [...new Set(data.map(item => item.area).filter(Boolean))].sort(); + + const filteredData = data.filter((item) => { + if (requestDateRange.from || requestDateRange.to) { + if (!item.requestDate) return false; + + const request = new Date(item.requestDate); + if (requestDateRange.from) { + const from = new Date(requestDateRange.from); + if (request < from) return false; + } + if (requestDateRange.to) { + const to = new Date(requestDateRange.to); + if (request > to) return false; + } + } + + if (approvedDateRange.from || approvedDateRange.to) { + if (!item.approvedDate) return false; + + const approved = new Date(item.approvedDate); + if (approvedDateRange.from) { + const from = new Date(approvedDateRange.from); + if (approved < from) return false; + } + if (approvedDateRange.to) { + const to = new Date(approvedDateRange.to); + if (approved > to) return false; + } + } + + if (statusFilter && item.status !== statusFilter) return false; + + if (paymentStatusFilter && item.paymentStatus !== paymentStatusFilter) return false; + + if (requestedByFilter && item.requestedBy !== requestedByFilter) return false; + + if (categoryFilter && item.category !== categoryFilter) return false; + + if (areaFilter && item.area !== areaFilter) return false; + + if (descriptionSearch && !item.description?.toLowerCase().includes(descriptionSearch.toLowerCase())) { + return false; + } + + return true; + }); + + const totalAmount = filteredData + .filter(item => item.status === "Approved" && item.paymentStatus === "PAID") + .reduce((acc, curr) => { + return curr.totalpesos + acc; + }, 0); + + const formatDate = (dateStr) => { + if (!dateStr) return ''; + const [year, month, day] = dateStr.split('-'); + return `${month}/${day}/${year}`; + }; + + const columns = [ + { + header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", + key: 'description', + render: (text, row) => { + const targetUrl = row.is_monthly ? `/app/expenses/${row.id}` : `/app/expenses/edit/${row.id}`; + return ( + + {text} + + ); + }, + }, + { + header: lang === "en" ? "REQUEST DATE" : "FECHA DE SOLICITUD", + key: 'requestDate', + render: (value) => formatDate(value) + }, + { + header: lang === "en" ? "APPROVED DATE" : "FECHA DE APROBACIÓN", + key: 'approvedDate', + render: (value) => formatDate(value) + }, + { header: lang === "en" ? "REQUESTED BY" : "SOLICITADO POR", key: 'requestedBy' }, + { header: lang === "en" ? "CATEGORY" : "CATEGORÍA", key: 'category' }, + { header: lang === "en" ? "AREA" : "ÁREA", key: 'area' }, + { + header: lang === "en" ? "AMOUNT MXN" : "IMPORTE", + key: 'totalpesos', + render: (value) => { + const num = parseFloat(value || 0); + return `$${num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + } + }, + { + header: lang === "en" ? "APPROVAL STATUS" : "ESTADO DE APROBACIÓN", + key: 'status', + headerStyle: { textAlign: 'center' }, + render: (status) => ( +
    + +
    + ), + }, + { + header: lang === "en" ? "PAYMENT STATUS" : "ESTADO DE PAGO", + key: 'paymentStatus', + headerStyle: { textAlign: 'center' }, + render: (status) => { + const statusClass = status.toLowerCase(); + return ( +
    + +
    + ); + }, + }, +]; + + const exportColumns = [ + { header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", key: 'description' }, + { header: lang === "en" ? "REQUEST DATE" : "FECHA DE SOLICITUD", key: 'requestDate' }, + { header: lang === "en" ? "APPROVED DATE" : "FECHA DE APROBACIÓN", key: 'approvedDate' }, + { header: lang === "en" ? "REQUESTED BY" : "SOLICITADO POR", key: 'requestedBy' }, + { header: lang === "en" ? "CATEGORY" : "CATEGORÍA", key: 'category' }, + { header: lang === "en" ? "AREA" : "ÁREA", key: 'area' }, + { header: lang === "en" ? "AMOUNT MXN" : "IMPORTE", key: 'totalpesos' }, + { header: lang === "en" ? "APPROVAL STATUS" : "ESTADO DE APROBACIÓN", key: 'status' }, + { header: lang === "en" ? "PAYMENT STATUS" : "ESTADO DE PAGO", key: 'paymentStatus' }, + ]; + + + const pendingPaymentsCount = filteredData.filter( + (item) => item.paymentStatus?.toLowerCase() === 'pending' + ).length; + + const rejectedExpensesCount = filteredData.filter( + (item) => item.status === "Rejected" && item.paymentStatus === "REJECTED" + ).length; + + return ( +
    +
    +

    + {lang === "en" ? "Report" : "Reporte"} +

    +
    + +
    +
    + + + + + + + + + +
    + +
    + setDescriptionSearch(e.target.value)} + className="filter-search" + /> + +
    + +
    + setRequestDateRange({ ...requestDateRange, from: e.target.value })} + className="date-input" + /> + setRequestDateRange({ ...requestDateRange, to: e.target.value })} + className="date-input" + /> +
    +
    + +
    + +
    + setApprovedDateRange({ ...approvedDateRange, from: e.target.value })} + className="date-input" + /> + setApprovedDateRange({ ...approvedDateRange, to: e.target.value })} + className="date-input" + /> +
    +
    + + +
    +
    + +
    +
    + +
    +

    + {lang === "en" ? "Pending Approved Payments" : "Pagos aprobados pendientes"} +

    +
    {pendingPaymentsCount}
    +
    +
    +

    + {lang === "en" ? "Rejected Expenses" : "Gastos rechazados"} +

    +
    {rejectedExpensesCount}
    +
    +
    + +
    + +
    +
    + + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Approved.css b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Approved.css new file mode 100644 index 0000000..fbe9461 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Approved.css @@ -0,0 +1,231 @@ +.approved-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 12px; + align-items: center; +} + +.filters-section .date-range-filter { + margin-bottom: 0; +} + +.filter-search { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 200px; + max-width: 300px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + flex-shrink: 0; + margin-bottom: 22px; +} + +.filter-search::placeholder { + color: #999; +} + +.filter-search:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-search:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.filter-select { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 180px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.filter-select:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-select:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.clear-filters-btn { + padding: 10px 20px; + background-color: white; + border: 2px solid #e0e0e0; + border-radius: 30px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + color: #666; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + margin-bottom: 24px; +} + +.clear-filters-btn:hover { + background-color: #f5f5f5; + border-color: #ccc; + color: #333; +} + +.summary-cards-wrapper { + display: flex; + gap: 20px; + margin-bottom: 24px; + flex-wrap: wrap; +} + +.info-card { + background: linear-gradient(145deg, #ffffff, #f8f9fa); + border-radius: 16px; + padding: 20px 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-width: 180px; + flex: 1; + transition: all 0.3s ease; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.info-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); +} + +.info-card .card-title { + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + margin: 0 0 12px 0; + color: #666; +} + +.info-card .card-value { + font-size: 28px; + font-weight: 700; + color: #333; + line-height: 1.2; +} + +.table-section { + background: white; + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-height: 400px; +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } + + .filters-section { + padding: 16px; + } + + .table-section { + padding: 20px; + } +} + +@media (max-width: 768px) { + .approved-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .filters-section { + padding: 12px; + border-radius: 12px; + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .filter-search { + min-width: 100%; + max-width: 100%; + } + + .filter-select { + min-width: 100%; + } + + .clear-filters-btn { + width: 100%; + } + + .summary-cards-wrapper { + flex-direction: column; + } + + .table-section { + padding: 16px; + border-radius: 12px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .filters-section { + padding: 10px; + } + + .table-section { + padding: 12px; + } +} + diff --git a/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Approved.jsx b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Approved.jsx new file mode 100644 index 0000000..11e7529 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Approved.jsx @@ -0,0 +1,217 @@ +import React, { useEffect, useState } from 'react'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import SummaryCard from '../../components/SummaryCard'; +import '../../components/Filters/Filters.css'; +import './Approved.css'; +import Table from '../../components/Table/HotelTable'; +import axios from 'axios'; +import { Link } from 'react-router-dom'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +//**////** */ */ +export default function Approved() { + const { lang } = useContext(langContext); + const [approvedExpenses, setApprovedExpenses] = useState([]); + const [filteredExpenses, setFilteredExpenses] = useState([]); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [totalApprovedFromAPI, setTotalApprovedFromAPI] = useState(0); + const [mainSupplier, setMainSupplier] = useState('N/A'); + const [descriptionFilter, setDescriptionFilter] = useState(''); + const [areaFilter, setAreaFilter] = useState(''); + + + + //Obtener lista de gastos aprobados + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/approvedexpenses') + .then((res) => { + const formatted = res.data.data.map((item, index) => ({ + id: index + 1, + description: item.expense_description, + requestDate: new Date(item.request_date).toISOString().split('T')[0], + approvedDate: new Date(item.approval_date).toISOString().split('T')[0], + area: item.area, + requestedBy: item.requested_by, + amount: parseFloat(item.amount), + })); + + setApprovedExpenses(formatted); + setFilteredExpenses(formatted); + }) + .catch((err) => { + if (err.response) { + console.error(`❌ Error ${err.response.status}: ${err.response.data.message}`); + } else { + console.error('❌ Error fetching approved expenses:', err.message); + } + }); + }, []); + + //Obtener total aprobado (GET con opción 1) + useEffect(() => { + axios.post(import.meta.env.VITE_API_BASE_URL + '/expenses/totalapproved', { option: 1 }) + .then((response) => { + // Aquí asumo que response.data tiene la forma { message, data } + // El valor está en response.data.data y es string, convertir a número: + const total = parseFloat(response.data.data); + setTotalApprovedFromAPI(isNaN(total) ? 0 : total); + }) + .catch((error) => { + console.error('Error fetching total approved:', error); + }); + }, []); + + + + + // Obtener proveedor principal + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/mainsupplier') + .then((res) => { + const supplier = res.data?.data?.[0]?.supplier || 'N/A'; + setMainSupplier(supplier); + }) + .catch((err) => { + if (err.response) { + console.error(`❌ Error ${err.response.status}: ${err.response.data.message}`); + } else { + console.error('❌ Error fetching main supplier:', err.message); + } + }); + }, []); + + useEffect(() => { + let filtered = [...approvedExpenses]; + + if (dateRange.from && dateRange.to) { + const from = new Date(dateRange.from); + const to = new Date(dateRange.to); + filtered = filtered.filter((item) => { + const itemDate = new Date(item.approvedDate); + return itemDate >= from && itemDate <= to; + }); + } + + if (descriptionFilter) { + filtered = filtered.filter((item) => + item.description?.toLowerCase().includes(descriptionFilter.toLowerCase()) + ); + } + + if (areaFilter) { + filtered = filtered.filter((item) => item.area === areaFilter); + } + + setFilteredExpenses(filtered); + }, [dateRange, approvedExpenses, descriptionFilter, areaFilter]); + + // Columnas para la tabla + const columns = [ + { + header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", + key: 'description', + render: (text, row) => ( + + {text} + + ), + } + , + { header: lang === "en" ? "REQUEST DATE" : "FECHA DE SOLICITUD", key: 'requestDate' }, + { header: lang === "en" ? "APPROVED DATE" : "FECHA DE APROBACIÓN", key: 'approvedDate' }, + { header: lang === "en" ? "AREA" : "ÁREA", key: 'area' }, + { header: lang === "en" ? "REQUESTED BY" : "SOLICITADO POR", key: 'requestedBy' }, + { + header: lang === "en" ? "AMOUNT" : "IMPORTE", + key: 'amount', + render: (amount) => `$${amount.toLocaleString()}` + }, + { + header: lang === "en" ? "STATUS" : "ESTADO", + key: 'id', + headerStyle: { textAlign: 'center' }, + render: () => ( +
    + +
    + ) + } + ]; + + const uniqueAreas = [...new Set(approvedExpenses.map(item => item.area).filter(Boolean))].sort(); + + const clearFilters = () => { + setDateRange({ from: '', to: '' }); + setDescriptionFilter(''); + setAreaFilter(''); + }; + + return ( +
    +
    +

    + {lang === "en" ? "Approved Expenses" : "Gastos Aprobados"} +

    +
    + +
    + setDescriptionFilter(e.target.value)} + className="filter-search" + /> + + + + + + +
    + +
    + +
    +

    {lang === "en" ? "Main Supplier" : "Proveedor Principal"}

    +
    {mainSupplier}
    +
    +
    + +
    +
    + + + ); +} + + + diff --git a/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Rejected.css b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Rejected.css new file mode 100644 index 0000000..f1cb20b --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Rejected.css @@ -0,0 +1,231 @@ +.rejected-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 12px; + align-items: center; +} + +.filters-section .date-range-filter { + margin-bottom: 0; +} + +.filter-search { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 200px; + max-width: 300px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + flex-shrink: 0; + margin-bottom: 22px; +} + +.filter-search::placeholder { + color: #999; +} + +.filter-search:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-search:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.filter-select { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 180px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.filter-select:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-select:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.clear-filters-btn { + padding: 10px 20px; + background-color: white; + border: 2px solid #e0e0e0; + border-radius: 30px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + color: #666; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + margin-bottom: 24px; +} + +.clear-filters-btn:hover { + background-color: #f5f5f5; + border-color: #ccc; + color: #333; +} + +.summary-cards-wrapper { + display: flex; + gap: 20px; + margin-bottom: 24px; + flex-wrap: wrap; +} + +.info-card { + background: linear-gradient(145deg, #ffffff, #f8f9fa); + border-radius: 16px; + padding: 20px 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-width: 180px; + flex: 1; + transition: all 0.3s ease; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.info-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); +} + +.info-card .card-title { + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + margin: 0 0 12px 0; + color: #666; +} + +.info-card .card-value { + font-size: 28px; + font-weight: 700; + color: #333; + line-height: 1.2; +} + +.table-section { + background: white; + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-height: 400px; +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } + + .filters-section { + padding: 16px; + } + + .table-section { + padding: 20px; + } +} + +@media (max-width: 768px) { + .rejected-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .filters-section { + padding: 12px; + border-radius: 12px; + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .filter-search { + min-width: 100%; + max-width: 100%; + } + + .filter-select { + min-width: 100%; + } + + .clear-filters-btn { + width: 100%; + } + + .summary-cards-wrapper { + flex-direction: column; + } + + .table-section { + padding: 16px; + border-radius: 12px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .filters-section { + padding: 10px; + } + + .table-section { + padding: 12px; + } +} + diff --git a/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Rejected.jsx b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Rejected.jsx new file mode 100644 index 0000000..2fd7f07 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/ExpensesToBeApproval/Rejected.jsx @@ -0,0 +1,464 @@ +import React, { useEffect, useState } from 'react'; +import DateRangeFilter from '../../components/Filters/DateRangeFilter'; +import SummaryCard from '../../components/SummaryCard'; +import '../../components/Filters/Filters.css'; +import './Rejected.css'; +import Table from '../../components/Table/HotelTable'; +import axios from 'axios'; +import { Link } from 'react-router-dom'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +//**////** */ */ APROBADOS Y RECHAZADOS +export default function Rejected() { + const { lang } = useContext(langContext); + const [rejectedExpenses, setRejectedExpenses] = useState([]); + const [filteredExpenses, setFilteredExpenses] = useState([]); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [totalRejected, setTotalRejected] = useState(0); + const [mainSupplier, setMainSupplier] = useState('N/A'); + const [descriptionFilter, setDescriptionFilter] = useState(''); + const [areaFilter, setAreaFilter] = useState(''); + + //Obtener lista de gastos rechazados + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/rejectedexpenses') + .then((res) => { + const formatted = res.data.data.map((item, index) => ({ + id: index + 1, + description: item.expense_description, + requestDate: new Date(item.request_date).toISOString().split('T')[0], + rejectedDate: new Date(item.reject_date).toISOString().split('T')[0], + area: item.area, + requestedBy: item.requested_by, + amount: parseFloat(item.amount), + supplier: 'N/A' + })); + setRejectedExpenses(formatted); + setFilteredExpenses(formatted); + }) + .catch((err) => { + console.error('❌ Error fetching rejected expenses:', err.message); + }); + }, []); + + //Obtener Total Rejected usando método GET correcto + useEffect(() => { + axios.post(import.meta.env.VITE_API_BASE_URL + '/expenses/totalapproved', { option: 2 }) + .then((res) => { + const total = parseFloat(res.data.data); + setTotalRejected(isNaN(total) ? 0 : total); + }) + .catch((err) => { + if (err.response) { + console.error(`❌ Error ${err.response.status}: ${err.response.data.message}`); + } else { + console.error('❌ Error fetching total rejected amount:', err.message); + } + }); + }, []); + + //Obtener proveedor principal + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/mainsupplier') + .then((res) => { + if (res.data.data.length > 0) { + setMainSupplier(res.data.data[0].supplier); + } + }) + .catch((err) => { + if (err.response) { + console.error(`❌ Error ${err.response.status}: ${err.response.data.message}`); + } else { + console.error('❌ Error fetching main supplier:', err.message); + } + }); + }, []); + + useEffect(() => { + let filtered = [...rejectedExpenses]; + + if (dateRange.from && dateRange.to) { + const from = new Date(dateRange.from); + const to = new Date(dateRange.to); + filtered = filtered.filter((item) => { + const itemDate = new Date(item.rejectedDate); + return itemDate >= from && itemDate <= to; + }); + } + + if (descriptionFilter) { + filtered = filtered.filter((item) => + item.description?.toLowerCase().includes(descriptionFilter.toLowerCase()) + ); + } + + if (areaFilter) { + filtered = filtered.filter((item) => item.area === areaFilter); + } + + setFilteredExpenses(filtered); + }, [dateRange, rejectedExpenses, descriptionFilter, areaFilter]); + + //Columnas de tabla + const columns = [ + { + header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", + key: 'description', + render: (text, row) => ( + + {text} + + ), + }, + { header: lang === "en" ? "REQUEST DATE" : "FECHA DE SOLICITUD", key: 'requestDate' }, + { header: lang === "en" ? "REJECTED DATE" : "FECHA DE RECHAZO", key: 'rejectedDate' }, + { header: lang === "en" ? "AREA" : "ÁREA", key: 'area' }, + { header: lang === "en" ? "REQUESTED BY" : "SOLICITADO POR", key: 'requestedBy' }, + { + header: lang === "en" ? "AMOUNT" : "IMPORTE", + key: 'amount', + render: (amount) => `$${amount.toLocaleString()}` + }, + { + header: lang === "en" ? "STATUS" : "ESTADO", + key: 'id', + headerStyle: { textAlign: 'center' }, + render: () => ( +
    + +
    + ), + }, + ]; + + const uniqueAreas = [...new Set(rejectedExpenses.map(item => item.area).filter(Boolean))].sort(); + + const clearFilters = () => { + setDateRange({ from: '', to: '' }); + setDescriptionFilter(''); + setAreaFilter(''); + }; + + return ( +
    +
    +

    + {lang === "en" ? "Rejected Expenses" : "Gastos Rechazados"} +

    +
    + +
    + setDescriptionFilter(e.target.value)} + className="filter-search" + /> + + + + + + +
    + +
    + +
    +

    {lang === "en" ? "Main Supplier" : "Proveedor Principal"}

    +
    {mainSupplier}
    +
    +
    + +
    +
    + + + ); +} + + +// import React, { useEffect, useState } from 'react'; +// import '../../components/Filters/Filters.css'; +// import Table from '../../components/Table/HotelTable'; +// import axios from 'axios'; + +// export default function Rejected() { +// const [rejectedExpenses, setRejectedExpenses] = useState([]); +// const [filteredExpenses, setFilteredExpenses] = useState([]); +// const [dateRange, setDateRange] = useState({ from: '', to: '' }); +// const [totalRejected, setTotalRejected] = useState(0); +// const [mainSupplier, setMainSupplier] = useState('N/A'); + +// // ✅ Cargar lista de gastos rechazados +// useEffect(() => { +// axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/rejectedexpenses') +// .then((res) => { +// const formatted = res.data.data.map((item, index) => ({ +// id: index + 1, +// description: item.expense_description, +// requestDate: new Date(item.request_date).toISOString().split('T')[0], +// rejectedDate: new Date(item.reject_date).toISOString().split('T')[0], +// area: item.area, +// requestedBy: item.requested_by, +// amount: parseFloat(item.amount), +// supplier: 'N/A' +// })); +// setRejectedExpenses(formatted); +// setFilteredExpenses(formatted); +// }) +// .catch((err) => { +// console.error('Error fetching rejected expenses:', err); +// }); +// }, []); + +// // ✅ CORREGIDO: Método GET con parámetro en URL +// useEffect(() => { +// axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/totalapproved/2') +// .then((res) => { +// setTotalRejected(parseFloat(res.data.data)); +// }) +// .catch((err) => { +// console.error('Error fetching total rejected amount:', err); +// }); +// }, []); + + +// // ✅ Obtener Main Supplier +// useEffect(() => { +// axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/mainsupplier') +// .then((res) => { +// if (res.data.data.length > 0) { +// setMainSupplier(res.data.data[0].supplier); // "Costco" +// } +// }) +// .catch((err) => { +// console.error('Error fetching main supplier:', err); +// }); +// }, []); + +// // ✅ Filtrar por fechas +// useEffect(() => { +// if (dateRange.from && dateRange.to) { +// const from = new Date(dateRange.from); +// const to = new Date(dateRange.to); +// const filtered = rejectedExpenses.filter((item) => { +// const itemDate = new Date(item.rejectedDate); +// return itemDate >= from && itemDate <= to; +// }); +// setFilteredExpenses(filtered); +// } else { +// setFilteredExpenses(rejectedExpenses); +// } +// }, [dateRange, rejectedExpenses]); + +// const columns = [ +// { +// header: 'EXPENSE DESCRIPTION', +// key: 'description', +// render: (text) => {text}, +// }, +// { header: 'REQUEST DATE', key: 'requestDate' }, +// { header: 'REJECTED DATE', key: 'rejectedDate' }, +// { header: 'AREA', key: 'area' }, +// { header: 'REQUESTED BY', key: 'requestedBy' }, +// { +// header: 'AMOUNT', +// key: 'amount', +// render: (amount) => `$${amount.toLocaleString()}` +// }, +// { +// header: 'STATUS', +// key: 'id', +// render: () => ( +// +// ), +// }, +// ]; + +// return ( +//
    +//

    REJECTED

    + +// {/* Filtros de fecha */} +//
    +// setDateRange({ ...dateRange, from: e.target.value })} +// /> +// setDateRange({ ...dateRange, to: e.target.value })} +// /> +//
    + +// {/* Summary Cards */} +//
    +//
    +// Total Rejected +//
    ${totalRejected.toLocaleString()}
    +//
    +//
    +// Main Supplier +//
    {mainSupplier}
    +//
    +//
    + +// {/* Tabla */} +//
    +// +// ); +// } + + +// import React, { useEffect, useState } from 'react'; +// import '../../components/Filters/Filters.css'; +// import Table from '../../components/Table/HotelTable'; +// import axios from 'axios'; + +// export default function Rejected() { +// const [rejectedExpenses, setRejectedExpenses] = useState([]); +// const [filteredExpenses, setFilteredExpenses] = useState([]); +// const [dateRange, setDateRange] = useState({ from: '', to: '' }); + +// //Obtener datos reales desde el backend +// useEffect(() => { +// axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/rejectedexpenses') +// .then((res) => { +// const formatted = res.data.data.map((item, index) => ({ +// id: index + 1, // temporal, ya que no viene `id_expense` +// description: item.expense_description, +// requestDate: new Date(item.request_date).toISOString().split('T')[0], +// rejectedDate: new Date(item.reject_date).toISOString().split('T')[0], +// area: item.area, +// requestedBy: item.requested_by, +// amount: parseFloat(item.amount), +// supplier: 'N/A' // ❗ backend no envía proveedor +// })); + +// setRejectedExpenses(formatted); +// setFilteredExpenses(formatted); +// }) +// .catch((err) => { +// console.error('Error fetching rejected expenses:', err); +// }); +// }, []); + +// //Filtrar por fechas +// useEffect(() => { +// if (dateRange.from && dateRange.to) { +// const from = new Date(dateRange.from); +// const to = new Date(dateRange.to); +// const filtered = rejectedExpenses.filter((item) => { +// const itemDate = new Date(item.rejectedDate); +// return itemDate >= from && itemDate <= to; +// }); +// setFilteredExpenses(filtered); +// } else { +// setFilteredExpenses(rejectedExpenses); +// } +// }, [dateRange, rejectedExpenses]); + +// //Columnas de la tabla +// const columns = [ +// { +// header: 'EXPENSE DESCRIPTION', +// key: 'description', +// render: (text) => {text}, // ❌ sin enlace por falta de ID +// }, +// { header: 'REQUEST DATE', key: 'requestDate' }, +// { header: 'REJECTED DATE', key: 'rejectedDate' }, +// { header: 'AREA', key: 'area' }, +// { header: 'REQUESTED BY', key: 'requestedBy' }, +// { +// header: 'AMOUNT', +// key: 'amount', +// render: (amount) => `$${amount.toLocaleString()}` +// }, +// { +// header: 'STATUS', +// key: 'id', +// render: () => ( +// +// ), +// }, +// ]; + +// //Cálculo de total rechazado +// const totalAmount = filteredExpenses.reduce((sum, item) => sum + item.amount, 0); + +// //Proveedor principal (no aplica) +// const mainSupplier = 'N/A'; + +// return ( +//
    +//

    REJECTED

    + +// {/* Filtros de fecha */} +//
    +// setDateRange({ ...dateRange, from: e.target.value })} +// /> +// setDateRange({ ...dateRange, to: e.target.value })} +// /> +//
    + +// {/* Summary Cards */} +//
    +//
    +// Total Rejected +//
    ${totalAmount.toLocaleString()}
    +//
    +//
    +// Main Supplier +//
    {mainSupplier}
    +//
    +//
    + +// {/* Tabla */} +//
    +// +// ); +// } + + diff --git a/frontend/Frontend-Hotel/src/pages/Hotel/Properties.jsx b/frontend/Frontend-Hotel/src/pages/Hotel/Properties.jsx new file mode 100644 index 0000000..fd2533c --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Hotel/Properties.jsx @@ -0,0 +1,130 @@ +import React, { useState } from 'react'; +import Table from '../../components/Table/HotelTable'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function PropertiesPage() { + const { lang } = useContext(langContext); + const [properties, setProperties] = useState([ + { + propertyId: '0000001', + name: 'Hacienda San Angel', + areas: 'Hotel, Restaurant', + }, + ]); + + //Función para añadir una propiedad falsa (puedes adaptarla luego) + const handleAddProperty = () => { + const newId = String(properties.length + 1).padStart(7, '0'); // e.g. "0000002" + const newProperty = { + propertyId: newId, + name: `New Property ${newId}`, + areas: 'TBD', + }; + setProperties([...properties, newProperty]); + }; + + const columns = [ + { + key: 'propertyId', + header: lang === "en" ? 'PROPERTY ID' : 'ID DE PROPIEDAD', + render: (value, row) => ( + {value} + ), + }, + { + key: 'name', + header: lang === "en" ? 'NAME' : 'NOMBRE', + }, + { + key: 'areas', + header: lang === "en" ? 'AREAS' : 'ÁREAS', + }, + ]; + + //Agregamos la fila del botón como última fila (solo visual) + const tableData = [...properties, { propertyId: 'add-row' }]; + + return ( +
    +

    {lang === "en" ? "Properties" : "Propiedades"}

    +
    ({ + ...col, + render: (value, row) => { + if (row.propertyId === 'add-row') { + if (col.key === 'propertyId') { + return ( + + ); + } + return null; + } + + //render personalizado + return col.render + ? col.render(row[col.key], row) + : row[col.key]; + }, + }))} + data={tableData} + /> + + ); +} + + + +// export default function Properties(){ +//

    Properties

    +// }; + +// import React from 'react'; +// import Table from '../../components/Table/HotelTable'; // tu componente reutilizable + +// export default function PropertiesPage() { +// const columns = [ +// { +// key: 'propertyId', +// header: 'PROPERTY ID', +// render: (value, row) => { +// if (value === 'add') { +// return + Add property…; +// } +// return {value}; +// }, +// }, +// { +// key: 'name', +// header: 'NAME', +// render: (value, row) => row.propertyId === 'add' ? null : value, +// }, +// { +// key: 'areas', +// header: 'AREAS', +// render: (value, row) => row.propertyId === 'add' ? null : value, +// }, +// ]; + +// const data = [ +// { +// propertyId: '0000001', +// name: 'Hacienda San Angel', +// areas: 'Hotel, Restaurant', +// }, +// { +// propertyId: 'add', +// name: '+ Add property…', +// areas: '', +// }, +// ]; + +// return ( +//
    +//

    Properties

    +//
    +// +// ); +// } diff --git a/frontend/Frontend-Hotel/src/pages/Hotel/PropertiesId.jsx b/frontend/Frontend-Hotel/src/pages/Hotel/PropertiesId.jsx new file mode 100644 index 0000000..c2daa07 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Hotel/PropertiesId.jsx @@ -0,0 +1,101 @@ +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import './PropertyDetailPage.css'; + +export default function PropertyDetailPage() { + const { id } = useParams(); + + // Simulación de datos por ID + const [property, setProperty] = useState(null); + + useEffect(() => { + // Aquí normalmente iría un fetch a backend con el id + // Simulamos los datos por ahora + const mockData = { + propertyId: id, + name: 'Hacienda San Angel', + rfc: 'XAXX010101000', + phone: '33-33-33-33-33', + address: 'Example 110, Puerto Vallarta, Jalisco', + areas: ['Hotel', 'Restaurant'], + mainArea: 'Hotel', + services: [ + { name: 'ELECTRICITY', percent: 80 }, + { name: 'WATER', percent: 90 }, + { name: 'GAS', percent: 60 }, + ], + }; + setProperty(mockData); + }, [id]); + + const handleAddService = () => { + const newService = { name: 'NEW SERVICE', percent: 50 }; + setProperty((prev) => ({ + ...prev, + services: [...prev.services, newService], + })); + }; + + if (!property) return

    Loading...

    ; + + return ( +
    +

    Property {property.propertyId}

    + +
    +
    +

    ID: #{property.propertyId}

    +

    {property.name}

    +

    RFC:

    +

    Areas: + +

    +

    Main area: + +

    +
    + +
    +

    Phone number:

    +

    Address: {property.address}

    + +
    +
    + +
    + + + + + + + + {property.services.map((service, idx) => ( + + + + + ))} + + + + + +
    SERVICE%
    {service.name}{service.percent}
    + +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Hotel/PropertyDetailPage.css b/frontend/Frontend-Hotel/src/pages/Hotel/PropertyDetailPage.css new file mode 100644 index 0000000..345122e --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Hotel/PropertyDetailPage.css @@ -0,0 +1,43 @@ +.property-detail-container { + padding: 20px; + font-family: 'Trebuchet MS', sans-serif; +} + +.property-info-box { + display: flex; + justify-content: space-between; + background-color: #f8f8f8; + padding: 20px; + border-radius: 10px; + margin-bottom: 30px; +} + +.property-info p, +.property-contact p { + margin-bottom: 10px; +} + +.property-contact { + text-align: right; +} + +input, select { + padding: 5px; + margin-left: 10px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.save-button { + background-color: #f2c300; + border: none; + padding: 10px 20px; + border-radius: 20px; + font-weight: bold; + color: white; + cursor: pointer; +} + +.save-button:hover { + opacity: 0.9; +} diff --git a/frontend/Frontend-Hotel/src/pages/Income/IncomeReport.css b/frontend/Frontend-Hotel/src/pages/Income/IncomeReport.css new file mode 100644 index 0000000..0a12fe1 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Income/IncomeReport.css @@ -0,0 +1,253 @@ +.income-report-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.error-message { + padding: 12px 16px; + background-color: #ffebee; + color: #c62828; + border-radius: 12px; + margin-bottom: 20px; + border: 1px solid #ef9a9a; + font-size: 14px; + font-weight: 500; +} + +.filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + justify-content: flex-end; + flex-wrap: wrap; + gap: 12px; + align-items: center; +} + +.filters-section .date-range-filter { + margin-bottom: 0; +} + +.filter-select { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + min-width: 180px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.filter-select:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.filter-select:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.clear-filters-btn { + padding: 10px 20px; + background-color: white; + border: 2px solid #e0e0e0; + border-radius: 30px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + color: #666; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; + margin-top: 20px; +} + +.clear-filters-btn:hover { + background-color: #f5f5f5; + border-color: #ccc; + color: #333; +} + +.summary-actions-section { + display: flex; + justify-content: space-between; + align-items: flex-end; + margin-bottom: 24px; + gap: 20px; + flex-wrap: wrap; +} + +.summary-card-wrapper { + flex: 0 0 auto; + min-width: 220px; +} + +.new-income-btn { + padding: 12px 24px; + background-color: #5d1a2a; + color: white; + text-decoration: none; + border-radius: 30px; + font-weight: 600; + font-size: 14px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(93, 26, 42, 0.3); + white-space: nowrap; +} + +.new-income-btn:hover { + background-color: #7a2236; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(93, 26, 42, 0.4); +} + +.table-section { + background: white; + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-height: 400px; +} + +.table-loading { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 400px; + gap: 16px; +} + +.loading-spinner-large { + width: 60px; + height: 60px; + border: 5px solid rgba(0, 0, 0, 0.1); + border-top-color: #5d1a2a; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +.table-loading p { + color: #666; + font-size: 16px; + font-weight: 500; + margin: 0; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } + + .filters-section { + padding: 16px; + } + + .additional-filters { + gap: 10px; + } + + .table-section { + padding: 20px; + } +} + +@media (max-width: 768px) { + .income-report-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .filters-section { + padding: 12px; + border-radius: 12px; + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .filter-select { + min-width: 100%; + } + + .clear-filters-btn { + width: 100%; + } + + .summary-actions-section { + flex-direction: column; + align-items: stretch; + } + + .summary-card-wrapper { + min-width: 100%; + } + + .new-income-btn { + width: 100%; + text-align: center; + } + + .table-section { + padding: 16px; + border-radius: 12px; + } + + .table-loading { + min-height: 300px; + } + + .loading-spinner-large { + width: 50px; + height: 50px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .filters-section { + padding: 10px; + } + + .table-section { + padding: 12px; + } +} diff --git a/frontend/Frontend-Hotel/src/pages/Income/IncomeReport.jsx b/frontend/Frontend-Hotel/src/pages/Income/IncomeReport.jsx new file mode 100644 index 0000000..9aee916 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Income/IncomeReport.jsx @@ -0,0 +1,393 @@ +import React, { useEffect, useState, useContext } from "react"; +import { Link, useNavigate } from "react-router-dom"; + +import { langContext } from "../../context/LenguageContext"; +import DateRangeFilter from "../../components/Filters/DateRangeFilter"; +import SummaryCard from "../../components/SummaryCard"; +import ExcelExportButton from "../../components/ExcelExportButton"; +import "../../components/Filters/Filters.css"; +import "./IncomeReport.css"; +import Table from "../../components/Table/HotelTable"; + +export default function IncomeReport() { + const navigate = useNavigate(); + const { lang } = useContext(langContext); + const [incomeData, setIncomeData] = useState([]); + const [filteredData, setFilteredData] = useState([]); + const [dateRange, setDateRange] = useState({ from: "", to: "" }); + const [accountFilter, setAccountFilter] = useState(""); + const [statusFilter, setStatusFilter] = useState(""); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(""); + const [accounts, setAccounts] = useState([]); + + useEffect(() => { + async function fetchAccounts() { + try { + await fetch( + `${import.meta.env.VITE_API_BASE_URL}/incomeshrx/stripedata` + ); + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/incomeshrx/accountincome` + ); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + const data = Array.isArray(result) ? result : result.data || []; + setAccounts(data); + } catch (err) { + console.error("Error fetching accounts:", err); + setAccounts([]); + } + } + + fetchAccounts(); + }, []); + + useEffect(() => { + async function fetchIncomeData() { + try { + setLoading(true); + setError(""); + + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/incomeshrx/incomehorux` + ); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + + const data = Array.isArray(result) ? result : result.data || []; + + const mappedData = data.map((item) => ({ + id_hrx_income: item.id_hrx_income, + date: item.date_in, + created_at: item.createddate || item.date_in, + account: item.account_name, + amount: item.account_name === "STRIPE" ? parseFloat(item.amountinvoice || 0).toFixed(2) : parseFloat(item.amount || 0).toFixed(2), + invoiceAmount: item.account_name === "STRIPE" ? parseFloat(item.amount || 0).toFixed(2) : parseFloat(item.amountinvoice || 0).toFixed(2), + invoices: item.invoice, + status: item.status_in ? "Distributed" : "Pending", + categories: item.categories || [], + })); + + setIncomeData(mappedData); + setFilteredData(mappedData); + } catch (err) { + console.error("Error fetching income data:", err); + setError( + lang === "es" + ? "Error al cargar los datos de ingresos. Por favor, intente de nuevo." + : "Failed to load income data. Please try again." + ); + setIncomeData([]); + setFilteredData([]); + } finally { + setLoading(false); + } + } + + fetchIncomeData(); + }, [lang]); + + useEffect(() => { + let filtered = [...incomeData]; + + if (dateRange.from && dateRange.to) { + filtered = filtered.filter((item) => { + const itemDate = item.created_at?.slice(0, 10); + + if (!itemDate) return false; + + return itemDate >= dateRange.from && itemDate <= dateRange.to; + }); + } + + if (accountFilter) { + filtered = filtered.filter((item) => item.account === accountFilter); + } + + if (statusFilter) { + filtered = filtered.filter((item) => item.status === statusFilter); + } + + setFilteredData(filtered); + }, [dateRange, accountFilter, statusFilter, incomeData]); + + const clearFilters = () => { + setDateRange({ from: "", to: "" }); + setAccountFilter(""); + setStatusFilter(""); + }; + + const formatDate = (dateStr) => { + if (!dateStr) return ""; + + const date = new Date(dateStr); + if (isNaN(date.getTime())) return ""; + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}/${month}/${year}`; + }; + + const handleStatusClick = (label, row) => { + if (label === "Pending") { + navigate(`/app/edit-income-form/${row.id}`, { + state: { + incomeData: { + id: row.id, + date: row.created_at, + account: row.account, + amount: row.amount, + invoiceAmount: row.invoiceAmount, + invoices: row.invoices, + status: row.status, + categories: row.categories + } + } + }); + } + }; + + const totalIncome = filteredData.reduce((sum, item) => { + return sum + parseFloat(item.amount || 0); + }, 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + + const statusOptions = ["Distributed", "Pending"]; + + const columns = [ + { header: lang === "es" ? "ID" : "ID", key: "id_hrx_income" }, + { + header: lang === "es" ? "FECHA" : "DATE", + key: "created_at", + render: (value) => formatDate(value), + }, + { + header: lang === "es" ? "CUENTA" : "ACCOUNT", + key: "account", + render: (value, row) => ( + navigate(`/app/edit-income-form/${row.id}`, { + state: { + incomeData: { + id: row.id, + date: row.created_at, + account: row.account, + amount: row.amount, + invoiceAmount: row.invoiceAmount, + invoices: row.invoices, + status: row.status, + categories: row.categories + } + } + })} + style={{ + color: "#5D1A2A", + textDecoration: "underline", + cursor: "pointer", + fontWeight: "500", + }} + > + {value} + + ), + }, + { + header: lang === "es" ? "MONTO" : "AMOUNT", + key: "amount", + render: (value) => { + const num = parseFloat(value); + return `$${num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + }, + }, + { + header: lang === "es" ? "MONTO FACTURA" : "INVOICE AMOUNT", + key: "invoiceAmount", + render: (value) => { + const num = parseFloat(value); + return `$${num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + }, + }, + { + header: lang === "es" ? "FACTURA" : "INVOICE", + key: "invoices", + }, + { + header: lang === "es" ? "CATEGORÍAS" : "CATEGORIES", + key: "categories", + render: (value, row) => { + if (!row.categories || row.categories.length === 0) { + return "-"; + } + + return row.categories.map((category, index) => { + const total = parseFloat(category.total || 0); + const formattedTotal = `$${total.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + return ( +
    + {category.category}: {formattedTotal} +
    + ); + }); + }, + }, + { + header: lang === "es" ? "ESTADO" : "STATUS", + key: "status", + headerStyle: { textAlign: "center" }, + render: (value, row) => ( +
    + +
    + ), + }, + ]; + + const exportColumns = [ + { header: lang === "es" ? "ID" : "ID", key: "id_hrx_income" }, + { header: lang === "es" ? "FECHA" : "DATE", key: "created_at" }, + { header: lang === "es" ? "CUENTA" : "ACCOUNT", key: "account" }, + { header: lang === "es" ? "MONTO" : "AMOUNT", key: "amount" }, + { header: lang === "es" ? "MONTO FACTURA" : "INVOICE AMOUNT", key: "invoiceAmount" }, + { header: lang === "es" ? "FACTURA" : "INVOICE", key: "invoices" }, + { header: lang === "es" ? "CATEGORÍAS" : "CATEGORIES", key: "categories" }, + { header: lang === "es" ? "ESTADO" : "STATUS", key: "status" }, + ]; + + const dataTransform = (data) => { + return data.map((row) => ({ + ...row, + created_at: formatDate(row.created_at), + amount: row.amount ? `$${parseFloat(row.amount).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '', + invoiceAmount: row.invoiceAmount ? `$${parseFloat(row.invoiceAmount).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '', + categories: row.categories && row.categories.length > 0 + ? row.categories.map(cat => { + const total = parseFloat(cat.total || 0); + const formattedTotal = `$${total.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + return `${cat.category}: ${formattedTotal}`; + }).join('; ') + : '', + status: lang === "es" + ? (row.status === "Distributed" ? "Distribuido" : "Pendiente") + : row.status, + })); + }; + + return ( +
    +
    +

    + {lang === "es" ? "Informe de Ingresos" : "Income Report"} +

    +
    + + {error &&
    {error}
    } + +
    +
    + +
    + + {lang === "es" ? "+ Nuevo Ingreso" : "+ New Income"} + +
    + +
    + + + + + + + +
    + +
    + +
    + +
    + {loading ? ( +
    +
    +

    {lang === "es" ? "Cargando..." : "Loading..."}

    +
    + ) : ( + + )} + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Income/NewIncome.css b/frontend/Frontend-Hotel/src/pages/Income/NewIncome.css new file mode 100644 index 0000000..9d7826f --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Income/NewIncome.css @@ -0,0 +1,281 @@ +.new-income-container { + color: #333; + width: 100%; + max-width: 100vw; + margin: 0 auto; + padding: 20px; + box-sizing: border-box; + overflow-x: hidden; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.form-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.form-header h1 { + font-size: 24px; + font-weight: bold; + color: #333; + margin: 0; +} + +.back-button { + background-color: #6c757d; + color: #fff; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + gap: 5px; + font-size: 14px; + transition: background-color 0.2s; +} + +.back-button:hover { + background-color: #5a6268; +} + +.back-button:active { + background-color: #545b62; +} + +.success-message { + background-color: #d4edda; + color: #155724; + padding: 12px; + border-radius: 6px; + margin-bottom: 20px; + border: 1px solid #c3e6cb; +} + +.error-message { + background-color: #f8d7da; + color: #721c24; + padding: 12px; + border-radius: 6px; + margin-bottom: 20px; + border: 1px solid #f5c6cb; +} + +.form-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 15px; + margin-bottom: 30px; +} + +.form-group { + display: flex; + flex-direction: column; +} + +.form-grid label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #333; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; + transition: border-color 0.2s ease; +} + +.form-grid input:focus, +.form-grid select:focus { + outline: none; + border-color: #ffcb05; + background-color: #fff; +} + +.form-grid input[type="number"] { + text-align: right; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 20px; +} + +.save-button { + background-color: #ffcb05; + color: #fff !important; + padding: 12px 30px; + font-weight: bold; + border: none; + border-radius: 25px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.save-button:hover:not(:disabled) { + background-color: #f4b400; +} + +.save-button:disabled { + background-color: #ccc; + cursor: not-allowed; +} + +.income-categories { + width: 100%; + box-sizing: border-box; +} + +.income-categories h3 { + margin-top: 20px; + margin-bottom: 10px; +} + +.income-categories > div { + border: 1px solid #ccc; + padding: 10px; + margin-top: 10px; + width: 100%; + box-sizing: border-box; +} + +.income-categories .category-item { + margin-bottom: 10px; + border-bottom: 1px dotted #eee; + padding-bottom: 5px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; + width: 100%; + box-sizing: border-box; +} + +.category-item > div { + width: 100%; + box-sizing: border-box; +} + +.category-item label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #333; +} + +.category-item select, +.category-item input { + width: 100%; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; + transition: border-color 0.2s ease; + box-sizing: border-box; +} + +.category-item input[readonly] { + background-color: #f5f5f5; + cursor: not-allowed; +} + +.category-item input:focus, +.category-item select:focus { + outline: none; + border-color: #ffcb05; + background-color: #fff; +} + +.taxes-container { + display: flex; + flex-wrap: wrap; + gap: 8px; + width: 100%; + box-sizing: border-box; +} + +.taxes-container label { + display: flex; + align-items: center; + gap: 3px; + margin: 0; + font-weight: normal; + font-size: 13px; +} + +.taxes-container input[type="checkbox"] { + width: 8px; + height: 8px; + margin: 0; + transform: scale(0.5); +} + +.total-income-summary { + margin-top: 20px; + padding: 10px; + border: 1px solid #ccc; + background-color: #f9f9f9; + width: 100%; + box-sizing: border-box; +} + +/* Responsive design */ +@media (max-width: 768px) { + .form-grid { + grid-template-columns: 1fr; + } + + .new-income-container { + padding: 10px; + max-width: 100vw; + overflow-x: hidden; + } + + .form-card { + padding: 15px; + } + + .category-item { + grid-template-columns: 1fr !important; + gap: 5px !important; + } + + .taxes-container { + flex-direction: column; + gap: 5px; + } + + .taxes-container label { + margin: 2px 0; + } +} + +.save-button.disabled-validation { + background-color: #808080 !important; + color: #fff !important; + cursor: not-allowed !important; + opacity: 0.6; +} + +.save-button.disabled-validation:hover { + background-color: #dc3545 !important; + transform: none !important; +} diff --git a/frontend/Frontend-Hotel/src/pages/Income/NewIncome.jsx b/frontend/Frontend-Hotel/src/pages/Income/NewIncome.jsx new file mode 100644 index 0000000..59b035a --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Income/NewIncome.jsx @@ -0,0 +1,899 @@ +import React, { useState, useEffect, useRef, useContext } from "react"; +import { useNavigate, useParams, useLocation } from "react-router-dom"; +import { langContext } from "../../context/LenguageContext"; +import "./NewIncome.css"; + +export default function NewIncome() { + const navigate = useNavigate(); + const { id } = useParams(); + const location = useLocation(); + const { lang } = useContext(langContext); + const isEditMode = Boolean(id); + + const [form, setForm] = useState({ + account_id: "", + date: "", + amount: "", + invoice: "", + categories: [], + }); + + const [loading, setLoading] = useState(false); + const [loadingData, setLoadingData] = useState(false); + const [error, setError] = useState(""); + const [success, setSuccess] = useState(false); + const [accounts, setAccounts] = useState([]); + const [categoryOptions, setCategoryOptions] = useState([]); + const [invoiceOptions, setInvoiceOptions] = useState([]); + const [invoiceSearchTerm, setInvoiceSearchTerm] = useState(""); + const [showInvoiceDropdown, setShowInvoiceDropdown] = useState(false); + const [filteredInvoices, setFilteredInvoices] = useState([]); + const [isAmountDisabled, setIsAmountDisabled] = useState(false); + + const invoiceInputRef = useRef(null); + const invoiceDropdownRef = useRef(null); + + const taxOptions = [ + { value: 0, label: "0%" }, + { value: 8, label: "8%" }, + { value: 16, label: "16%" }, + ]; + + useEffect(() => { + async function fetchAccounts() { + try { + const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomeshrx/accountincome`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + const data = Array.isArray(result) ? result : (result.data || []); + setAccounts(data); + } catch (err) { + console.error('Error fetching accounts:', err); + setAccounts([]); + } + } + fetchAccounts(); + }, []); + + useEffect(() => { + async function fetchCategories() { + try { + const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomeshrx/categoryincome`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + const data = Array.isArray(result) ? result : (result.data || []); + setCategoryOptions(data); + } catch (err) { + console.error('Error fetching categories:', err); + setCategoryOptions([]); + } + } + fetchCategories(); + }, []); + + useEffect(() => { + async function fetchInvoices() { + try { + const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/incomeshrx/invoiceIncome`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + const data = Array.isArray(result) ? result : (result.data || []); + setInvoiceOptions(data); + } catch (err) { + console.error('Error fetching invoices:', err); + setInvoiceOptions([]); + } + } + fetchInvoices(); + }, []); + + useEffect(() => { + if (invoiceSearchTerm.trim() === "") { + setFilteredInvoices(invoiceOptions); + } else { + const filtered = invoiceOptions.filter((invoice) => + invoice.name_inv_income.toLowerCase().includes(invoiceSearchTerm.toLowerCase()) + ); + setFilteredInvoices(filtered); + } + }, [invoiceSearchTerm, invoiceOptions]); + + useEffect(() => { + function handleClickOutside(event) { + if ( + invoiceInputRef.current && + !invoiceInputRef.current.contains(event.target) && + invoiceDropdownRef.current && + !invoiceDropdownRef.current.contains(event.target) + ) { + setShowInvoiceDropdown(false); + } + } + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, []); + + useEffect(() => { + if (!isEditMode) { + setForm({ + account_id: "", + date: "", + amount: "", + invoice: "", + categories: [{ + categoryType: "", + amount: "", + selectedTax: null, + total: "0.00", + }], + }); + setInvoiceSearchTerm(""); + setSuccess(false); + setError(""); + } + }, [isEditMode]); + + const calculateSelectedTax = (amount, tax) => { + if (!amount || amount === 0) return null; + + const taxPercentage = Math.round((tax / amount) * 100); + const availableTaxes = [16, 8, 0]; + + for (const taxValue of availableTaxes) { + if (taxPercentage === taxValue) { + return taxValue; + } + } + + return null; + }; + + useEffect(() => { + if (!isEditMode || !id) return; + + const navigationData = location.state?.incomeData; + + if (navigationData) { + try { + setLoadingData(true); + setError(""); + + + const formattedDate = navigationData.date + ? new Date(navigationData.date).toISOString().slice(0, 10) + : ""; + + const mappedCategories = navigationData.categories?.map((cat) => { + const catAmount = parseFloat(cat.amount) || 0; + const catTax = parseFloat(cat.tax) || 0; + const selectedTax = calculateSelectedTax(catAmount, catTax); + + return { + categoryType: String(cat.id_category || cat.id_cat_income || ""), + amount: String(cat.amount || ""), + selectedTax: selectedTax, + total: String(cat.total || "0.00"), + }; + }) || [{ + categoryType: "", + amount: "", + selectedTax: null, + total: "0.00", + }]; + + const invoiceString = navigationData.invoices; + let matchedInvoice = null; + let isAmountDisabled = false; + + if (invoiceString && invoiceOptions.length > 0) { + matchedInvoice = invoiceOptions.find( + (inv) => String(inv.id_inv_income) === invoiceString || + inv.name_inv_income === invoiceString + ); + + if (matchedInvoice) { + isAmountDisabled = true; + setInvoiceSearchTerm(matchedInvoice.name_inv_income); + } else { + isAmountDisabled = false; + setInvoiceSearchTerm(invoiceString); + } + } + + setIsAmountDisabled(isAmountDisabled); + + const selectedAccount = accounts.find( + (acc) => acc.name_acc_income === navigationData.account + ); + const accountId = selectedAccount ? String(selectedAccount.id_acc_income) : ""; + + setForm({ + account_id: accountId, + date: formattedDate, + amount: String(navigationData.amount || ""), + invoice: invoiceString || "", + categories: mappedCategories, + }); + + } catch (err) { + console.error("Error processing navigation data:", err); + setError(lang === "en" ? "Failed to load income data for editing." : "Error al cargar datos del ingreso para editar."); + } finally { + setLoadingData(false); + } + } else { + console.warn("No navigation data found, this shouldn't happen"); + setError(lang === "en" ? "No data available for editing." : "No hay datos disponibles para editar."); + setLoadingData(false); + } + }, [isEditMode, id, invoiceOptions, accounts, location.state, lang]); + + const isAccountCash = () => { + if (!form.account_id) return false; + const selectedAccount = accounts.find( + (acc) => String(acc.id_acc_income) === String(form.account_id) + ); + return selectedAccount?.name_acc_income === "CASH"; + }; + + const getCurrentAccountName = () => { + if (!form.account_id) return ""; + const selectedAccount = accounts.find( + (acc) => String(acc.id_acc_income) === String(form.account_id) + ); + return selectedAccount?.name_acc_income || ""; + }; + + const getFilteredAccounts = () => { + if (isEditMode) { + const currentAccountName = getCurrentAccountName(); + if (currentAccountName === "STRIPE") { + return accounts; + } + return accounts.filter((account) => account.name_acc_income !== "STRIPE"); + } else { + return accounts.filter((account) => account.name_acc_income !== "STRIPE"); + } + }; + + const handleChange = (e) => { + const { name, value } = e.target; + setForm((prev) => ({ + ...prev, + [name]: value, + })); + if (error) setError(""); + }; + + const handleInvoiceInputChange = (e) => { + const value = e.target.value; + setInvoiceSearchTerm(value); + setShowInvoiceDropdown(true); + + const matchedInvoice = invoiceOptions.find( + (inv) => String(inv.id_inv_income) === value || + inv.name_inv_income === value + ); + + if (matchedInvoice) { + setForm((prev) => ({ + ...prev, + invoice: String(matchedInvoice.name_inv_income) + })); + } else { + setForm((prev) => ({ + ...prev, + invoice: value, + ...(isEditMode ? {} : { amount: "" }) + })); + } + + if (error) setError(""); + }; + + const handleInvoiceSelect = (invoice) => { + setForm((prev) => ({ + ...prev, + invoice: String(invoice.name_inv_income) + })); + setInvoiceSearchTerm(invoice.name_inv_income); + setShowInvoiceDropdown(false); + if (error) setError(""); + }; + + const handleInvoiceFocus = () => { + setShowInvoiceDropdown(true); + }; + + const handleCategoryChange = (index, field, value) => { + const updatedCategories = [...form.categories]; + updatedCategories[index][field] = value; + + if (field === "amount" || field === "selectedTax") { + const amount = parseFloat(updatedCategories[index].amount) || 0; + const selectedTax = updatedCategories[index].selectedTax; + const taxPercentage = selectedTax ? selectedTax / 100 : 0; + const taxAmount = amount * taxPercentage; + const total = amount + taxAmount; + + updatedCategories[index].total = total.toFixed(2); + } + + if (!isEditMode) { + const newTotalIncome = updatedCategories.reduce((total, category) => { + return total + (parseFloat(category.total) || 0); + }, 0); + + setForm((prev) => ({ + ...prev, + categories: updatedCategories, + amount: newTotalIncome.toFixed(2), + })); + } else { + setForm((prev) => ({ + ...prev, + categories: updatedCategories, + })); + } + + if (error) setError(""); + }; + + const handleAddCategory = () => { + const newCategory = { + categoryType: "", + amount: "", + selectedTax: null, + total: "0.00", + }; + + setForm((prev) => { + const updatedCategories = [...prev.categories, newCategory]; + + if (!isEditMode) { + const newTotalIncome = updatedCategories.reduce((total, category) => { + return total + (parseFloat(category.total) || 0); + }, 0); + + return { + ...prev, + categories: updatedCategories, + amount: newTotalIncome.toFixed(2), + }; + } else { + return { + ...prev, + categories: updatedCategories, + }; + } + }); + }; + + const handleRemoveCategory = (index) => { + if (form.categories.length > 1) { + setForm((prev) => { + const updatedCategories = prev.categories.filter((_, i) => i !== index); + + if (!isEditMode) { + const newTotalIncome = updatedCategories.reduce((total, category) => { + return total + (parseFloat(category.total) || 0); + }, 0); + + return { + ...prev, + categories: updatedCategories, + amount: newTotalIncome.toFixed(2), + }; + } else { + return { + ...prev, + categories: updatedCategories, + }; + } + }); + } + }; + + const calculateTotalIncome = () => { + return form.categories + .reduce((total, category) => { + return total + (parseFloat(category.total) || 0); + }, 0) + .toFixed(2); + }; + + const isUpdateButtonEnabled = () => { + if (!isEditMode) return true; + + const totalIncome = parseFloat(calculateTotalIncome()); + const amountValue = parseFloat(form.amount) || 0; + const difference = Math.abs(totalIncome - amountValue); + + return difference <= 2; + }; + + useEffect(() => { + if (form.categories.length === 0) { + setForm((prev) => ({ + ...prev, + categories: [ + { + categoryType: "", + amount: "", + selectedTax: null, + total: "0.00", + }, + ], + amount: "0.00", + })); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const validateForm = () => { + if (!form.account_id) { + setError(lang === 'en' ? "Account is required" : "La cuenta es requerida"); + return false; + } + if (!form.date) { + setError(lang === 'en' ? "Date is required" : "La fecha es requerida"); + return false; + } + if (!isAccountCash() && (!form.amount || parseFloat(form.amount) <= 0)) { + setError(lang === 'en' ? "Amount must be a positive number" : "El monto debe ser un número positivo"); + return false; + } + if (!isAccountCash() && !form.invoice) { + setError(lang === 'en' ? "Invoice is required" : "La factura es requerida"); + return false; + } + + if (form.categories.length === 0) { + setError(lang === 'en' ? "At least one category is required" : "Se requiere al menos una categoría"); + return false; + } + + for (let i = 0; i < form.categories.length; i++) { + const category = form.categories[i]; + if (!category.categoryType) { + setError(lang === 'en' + ? `Category ${i + 1}: Category type is required` + : `Categoría ${i + 1}: El tipo de categoría es requerido`); + return false; + } + if (!category.amount || parseFloat(category.amount) <= 0) { + setError(lang === 'en' + ? `Category ${i + 1}: Amount must be a positive number` + : `Categoría ${i + 1}: El monto debe ser un número positivo`); + return false; + } + } + + if (!isAccountCash() && isEditMode) { + const totalIncome = parseFloat(calculateTotalIncome()); + const amountValue = parseFloat(form.amount) || 0; + const difference = Math.abs(totalIncome - amountValue); + + if (difference > 2) { + setError(lang === 'en' + ? "The total income is not the same as the Amount input value" + : "El ingreso total no es igual al valor del campo Monto"); + return false; + } + } + + return true; + }; + + const formatDateForAPI = (dateStr) => { + if (!dateStr) return ""; + return dateStr; + }; + + const formatDateForUpdate = (dateStr) => { + if (!dateStr) return ""; + return dateStr; + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + if (!validateForm()) { + return; + } + + setLoading(true); + setError(""); + + try { + const formattedCategories = form.categories.map((cat) => { + const amount = parseFloat(cat.amount) || 0; + const selectedTax = cat.selectedTax || 0; + const taxPercentage = selectedTax / 100; + const taxAmount = amount * taxPercentage; + const total = amount + taxAmount; + + return { + id_category: parseInt(cat.categoryType) || 0, + amount: amount, + tax: parseFloat(taxAmount.toFixed(2)), + total: parseFloat(total.toFixed(2)), + }; + }); + + let response; + + if (isEditMode) { + + const payload = { + account_id: parseInt(form.account_id), + amount: parseFloat(form.amount), + up_date: formatDateForUpdate(form.date), + up_invoice: form.invoice && form.invoice.trim() ? form.invoice : null, + categories: formattedCategories, + }; + + + + response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/incomeshrx/updateincome/${id}`, + { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + } + ); + } else { + + const payload = { + account_id: parseInt(form.account_id), + amount: parseFloat(form.amount), + new_date: formatDateForAPI(form.date), + newinvoice: form.invoice && form.invoice.trim() ? form.invoice : null, + categories: formattedCategories, + }; + + + response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/incomeshrx/newincome`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + } + ); + } + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `HTTP error! status: ${response.status}`); + } + + setSuccess(true); + + if (!isEditMode) { + setForm({ + account_id: "", + date: "", + amount: "", + invoice: "", + categories: [], + }); + setInvoiceSearchTerm(""); + } + } catch (err) { + console.error("Error submitting income:", err); + setError(err.message || (lang === "en" ? "Failed to submit income. Please try again." : "Error al enviar el ingreso. Por favor inténtelo de nuevo.")); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    +
    +

    {isEditMode ? (lang === "en" ? "Edit Income" : "Editar Ingreso") : (lang === "en" ? "New Income" : "Nuevo Ingreso")}

    + +
    + + {success && ( +
    + {isEditMode + ? (lang === "en" ? "Income updated successfully!" : "¡Ingreso actualizado exitosamente!") + : (lang === "en" ? "Income submitted successfully!" : "¡Ingreso enviado exitosamente!")} +
    + )} + + {error &&
    {error}
    } + + {loadingData ? ( +
    +
    + + {lang === "en" ? "Loading income data..." : "Cargando datos del ingreso..."} +
    + ) : ( +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + + + {showInvoiceDropdown && ( +
    + {filteredInvoices.length > 0 ? ( + filteredInvoices.map((invoice) => ( +
    handleInvoiceSelect(invoice)} + style={{ + padding: '10px 12px', + cursor: 'pointer', + borderBottom: '1px solid #f0f0f0', + transition: 'background-color 0.2s' + }} + onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#f5f5f5'} + onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'white'} + > + {invoice.name_inv_income} +
    + )) + ) : ( +
    + {lang === "en" ? "No invoices found" : "No se encontraron facturas"} +
    + )} +
    + )} +
    +
    + +
    +

    {lang === "en" ? "Income Categories" : "Categorías de Ingreso"}

    + +
    + {form.categories.map((category, index) => ( +
    +
    + + +
    + +
    + + + handleCategoryChange(index, "amount", e.target.value) + } + placeholder="0.00" + step="0.01" + min="0" + /> +
    + +
    + +
    + {taxOptions.map((tax) => ( + + ))} +
    +
    + +
    + + +
    + +
    + +
    +
    + ))} + + +
    + +
    + {lang === "en" ? "Total Income:" : "Ingreso Total:"} ${calculateTotalIncome()} +
    +
    + +
    + +
    + + )} +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/Adjustments.css b/frontend/Frontend-Hotel/src/pages/Inventory/Adjustments.css new file mode 100644 index 0000000..5214145 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/Adjustments.css @@ -0,0 +1,86 @@ +.adjustments-page-container { + padding: 20px; + color: #213547; +} + +.adjustments-page-container h2 { + color: #213547; +} + +.filters-section { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 12px; + margin-bottom: 20px; + min-width: fit-content; +} + +.filters-section select { + color: #213547; + background-color: white; + max-width: 250px; + min-width: 150px; + flex: 0 1 auto; +} + +.filters-section input[type="date"] { + color: #213547; + background-color: white; + max-width: 200px; + min-width: 150px; + flex: 0 1 auto; +} + +.filters-section .filter-search { + color: #213547; + background-color: white; + max-width: 300px; + min-width: 200px; + flex: 0 0 auto; + width: 250px; +} + +.filters-section .save-button { + width: 120px; + background: #F2C300; + color: #fff; + font-weight: bold; + font-size: 14px; + border-radius: 25px; + padding: 10px 20px; + border: none; + cursor: pointer; + white-space: nowrap; + flex: 0 0 auto; + margin-left: auto; +} + +.save-button:hover:not(:disabled) { + background: #ddb000; +} + +.save-button:disabled { + background: #ccc; + cursor: not-allowed; + opacity: 0.6; +} + +@media (max-width: 768px) { + .filters-section { + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .filters-section .filter-search { + min-width: 100%; + max-width: 100%; + } + + .filters-section .save-button { + font-size: 13px; + padding: 8px 16px; + align-self: flex-end; + } +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/Adjustments.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/Adjustments.jsx new file mode 100644 index 0000000..a34c344 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/Adjustments.jsx @@ -0,0 +1,269 @@ +import React, { useState, useContext } from "react"; +import "../../components/Filters/Filters.css"; +import "./Adjustments.css"; +import Table from "../../components/Table/HotelTable copy"; +import { redirect } from "react-router-dom"; +import { langContext } from "../../context/LenguageContext"; +import ExcelExportButton from "../../components/ExcelExportButton"; + +//**////** */ */ VERIFICAR POR QUE MANDA DISCARD Y NO AJUSTMENT solo el endpoint /products/stockadjusmentset +export default function Adjustments() { + const { lang } = useContext(langContext); + const [adjustments, setAdjustments] = useState([]); + const [productSearch, setProductSearch] = useState(''); + const [saving, setSaving] = useState(false); + + React.useEffect(() => { + fetch(import.meta.env.VITE_API_BASE_URL + "/products") + .then((res) => res.json()) + .then((data) => { + if (Array.isArray(data.data)) { + setAdjustments( + data.data.map((prod) => ({ + productId: prod.id_product, + product: prod.name_product, + currentStock: Number(prod.units), + realStock: prod.units, + adjustment: 0, + })) + ); + } else { + setAdjustments([]); + } + }); + }, []); + + const handleRealStockChange = (productId, value) => { + const numericValue = Number(value); + const realStock = + isNaN(numericValue) || numericValue < 0 ? 0 : numericValue; + + const currentDate = new Date(); + const newAdjustments = adjustments.map((item) => { + if (item.productId === productId) { + return { + ...item, + realStock, + adjustment: realStock - item.currentStock, + datediscard: `${currentDate.getDay}-${currentDate.getMonth}-${currentDate.getFullYear()}`, + }; + } + return item; + }); + setAdjustments(newAdjustments); + }; + + const columns = [ + { + header: lang === "es" ? "ID DEL PRODUCTO" : "PRODUCT ID", + key: "productId", + }, + { header: lang === "es" ? "PRODUCTO" : "PRODUCT", key: "product" }, + { + header: lang === "es" ? "STOCK ACTUAL" : "CURRENT STOCK", + key: "currentStock", + }, + { + header: lang === "es" ? "STOCK REAL" : "REAL STOCK", + key: "realStock", + render: (value, row) => { + const isDisabled = !row.currentStock || Number(row.currentStock) <= 0 || saving; + return ( + { + if ( + e.key === "-" || + e.key === "e" || + e.key === "E" || + e.key === "+" + ) { + e.preventDefault(); + } + }} + style={{ + width: "60px", + textAlign: "center", + backgroundColor: isDisabled ? "#f0f0f0" : "white", + color: "#000", + cursor: isDisabled ? "not-allowed" : "text", + opacity: isDisabled ? 0.6 : 1, + }} + onChange={(e) => { + const inputValue = e.target.value; + if ( + inputValue === "" || + (!isNaN(inputValue) && Number(inputValue) >= 0) + ) { + handleRealStockChange( + row.productId, + inputValue === "" ? 0 : Number(inputValue) + ); + } + }} + /> + ); + }, + }, + { + header: lang === "es" ? "AJUSTE" : "ADJUSTMENT", + key: "adjustment", + render: (value) => ( + + {value} + + ), + }, + ]; + + const filteredAdjustments = adjustments.filter(item => + item.product?.toLowerCase().includes(productSearch.toLowerCase()) + ); + + const exportColumns = [ + { + header: lang === "es" ? "ID DEL PRODUCTO" : "PRODUCT ID", + key: "productId", + }, + { header: lang === "es" ? "PRODUCTO" : "PRODUCT", key: "product" }, + { + header: lang === "es" ? "STOCK ACTUAL" : "CURRENT STOCK", + key: "currentStock", + }, + { header: lang === "es" ? "STOCK REAL" : "REAL STOCK", key: "realStock" }, + { header: lang === "es" ? "AJUSTE" : "ADJUSTMENT", key: "adjustment" }, + ]; + + const handleSave = async () => { + setSaving(true); + + try { + // Actualiza los ajustes antes de enviar + const updatedAdjustments = adjustments.map((item) => ({ + ...item, + adjustment: item.realStock - item.currentStock, + })); + setAdjustments(updatedAdjustments); + //console.log('Ajustes a guardar:', updatedAdjustments); + + ///***/// *//products/stockadjusmentset/${item.productId}`, + + // { + // "stockproductadjusment":[{"id_product":1,"stock_adjusment":2}] + // + // } valida positivo negativo + // { quantity: (item.adjustment)*(-1), reasons: 'ajuste' } + + // Petición a discardproduct + for (const item of updatedAdjustments) { + await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/stockadjusmentset`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + stockproductadjusment: [ + { + id_product: item.productId, + stock_adjusment: item.adjustment, + }, + ], + }), + } + ); + } + + alert(lang === "es" ? "Ajustes guardados correctamente" : "Adjustments saved successfully"); + redirect("/app/inventory"); + // Recarga la página para reflejar los cambios + window.location.reload(); + } catch (error) { + console.error('Error saving adjustments:', error); + alert(lang === "es" ? "Error al guardar los ajustes" : "Error saving adjustments"); + } finally { + setSaving(false); + } + }; + + return ( +
    +
    +

    {lang === "es" ? "Ajustes" : "Adjustments"}

    +
    + +
    + setProductSearch(e.target.value)} + disabled={saving} + className="filter-search" + style={{ + backgroundColor: saving ? '#f5f5f5' : undefined, + cursor: saving ? 'not-allowed' : undefined + }} + /> + +
    + +
    + + {saving && ( +
    + )} +
    + +
    +
    + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/AlterProduct.css b/frontend/Frontend-Hotel/src/pages/Inventory/AlterProduct.css new file mode 100644 index 0000000..25fe4d5 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/AlterProduct.css @@ -0,0 +1,149 @@ +.new-expense-container { + display: flex; + justify-content: flex-start; + align-items: flex-start; + min-height: 100vh; + background-color: #f0f2f5; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + padding: 20px; + box-sizing: border-box; +} + +.form-card { + background: white; + padding: 2rem; + border-radius: 12px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + width: 100%; +} + +.form-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 1px solid #e2e8f0; +} + +.form-id { + font-size: 1.75rem; + font-weight: bold; + margin-bottom: 0; + color: #1a202c; + border-bottom: none; + padding-bottom: 0; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; +} + +.form-grid > div, .image-upload-section { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-bottom: 1rem; +} + +label { + font-weight: 600; + color: #4a5568; + font-size: 0.9rem; +} + +input, select { + padding: 0.8rem; + border: 1px solid #cbd5e0; + border-radius: 8px; + font-size: 1rem; + width: 100%; + box-sizing: border-box; + transition: border-color 0.2s, box-shadow 0.2s; +} + +input:focus, select:focus { + outline: none; + border-color: #3182ce; + box-shadow: 0 0 0 2px rgba(66, 153, 225, 0.5); +} + +select[multiple] { + height: 120px; +} + +.save-button-wrapper { + text-align: right; + margin-top: 2rem; + padding-top: 1.5rem; + border-top: 1px solid #e2e8f0; +} + +.save-button { + background-color: #3182ce; + color: white; + border: none; + padding: 0.8rem 1.6rem; + border-radius: 8px; + font-size: 1rem; + font-weight: bold; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.1s ease; +} + +.save-button:hover { + background-color: #2b6cb0; +} + +.save-button:active { + transform: translateY(1px); +} + +.save-button:disabled { + background-color: #a0aec0; + cursor: not-allowed; +} + +.feedback-message { + margin-top: 1rem; + padding: 0.75rem; + border-radius: 6px; + text-align: center; +} + +.feedback-message.success { + background-color: #c6f6d5; + color: #22543d; +} + +.feedback-message.error { + background-color: #fed7d7; + color: #742a2a; +} + +.back-button { + background-color: #718096; + color: white; + border: none; + padding: 0.6rem 1.2rem; + border-radius: 8px; + font-size: 0.9rem; + font-weight: 600; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.1s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 1rem; +} + +.back-button:hover { + background-color: #4a5568; +} + +.back-button:active { + transform: translateY(1px); +} + diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/AlterProduct.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/AlterProduct.jsx new file mode 100644 index 0000000..973bc8a --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/AlterProduct.jsx @@ -0,0 +1,373 @@ +import React, { useEffect, useState } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; +import './AlterProduct.css'; + +const IMAGE_BASE_URL = import.meta.env.VITE_API_BASE_URL + '/products'; + +export default function NewProduct() { + const { lang } = useContext(langContext); + const { id } = useParams(); + const navigate = useNavigate(); + const [productTypes, setProductTypes] = useState([]); + const [categories, setCategories] = useState([]); + const [suppliers, setSuppliers] = useState([]); + const [currencies, setCurrencies] = useState([]); + const [units, setUnits] = useState([]); + const [imagePreview, setImagePreview] = useState(null); + const [form, setForm] = useState({ + up_name_product: '', + up_sku_product: '', + product_type: 1, + id_category: 0, + supplier_rfc: '', + unit: '', + new_stock: '', + up_price_product: '', + up_id_tax: '', + img_product: '', + currency: '', + }); + + // Estados para la retroalimentación al usuario + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(''); + + // Efecto para cargar los datos de los selects y del producto a editar + useEffect(() => { + // Si no hay un ID en la URL, no se hace nada. + if (!id) return; + + const fetchInitialData = async () => { + setLoading(true); // Mostrar indicador de carga mientras se obtienen los datos + setError(''); + try { + // Realizar todas las peticiones de red en paralelo para mayor eficiencia + const [ + productTypesRes, + categoriesRes, + suppliersRes, + currenciesRes, + unitsRes, + productRes + ] = await Promise.all([ + fetch(import.meta.env.VITE_API_BASE_URL + '/products/producttype', { method: 'GET' }), + fetch(import.meta.env.VITE_API_BASE_URL + '/products/productcategory', { method: 'GET' }), + fetch(import.meta.env.VITE_API_BASE_URL + '/products/suppliers', { method: 'GET' }), + fetch(import.meta.env.VITE_API_BASE_URL + '/settings/currency', { method: 'GET' }), + fetch(import.meta.env.VITE_API_BASE_URL + '/settings/units', { method: 'GET' }), + fetch(`${import.meta.env.VITE_API_BASE_URL}/products/product/${id}`, { method: 'PUT' }) + ]); + // Manejar errores si alguna de las respuestas de la API falla + if (!productTypesRes.ok || !categoriesRes.ok || !suppliersRes.ok || !currenciesRes.ok || !unitsRes.ok || !productRes.ok) { + throw new Error('Error al cargar los datos necesarios para el formulario.'); + } + + // Convertir todas las respuestas a formato JSON + const productTypesData = await productTypesRes.json(); + const categoriesData = await categoriesRes.json(); + const suppliersData = await suppliersRes.json(); + const currenciesData = await currenciesRes.json(); + const unitsData = await unitsRes.json(); + const productData = await productRes.json(); + + // Poblar los estados para las opciones de los selects + setProductTypes( + productTypesData.data.map(d => ({ + id: d.id_product_type, + name: d.name_product_type, + spanish_name: d.spanish_name + })) + ); + setCategories( + categoriesData.data + .filter(d => d.id_prod_category) + .map(d => ({ + id: d.id_prod_category, + name: d.name_prod_category, + spanish_name: d.spanish_name + })) + ); + setSuppliers(suppliersData.data); + if (currenciesData.currency) { + setCurrencies(currenciesData.currency.map(c => ({ id: c.id_currency, name: c.name_currency }))); + } + if (unitsData.units) { + setUnits(unitsData.units.map(u => ({ id: u.id_unit, name: u.name_unit }))); + } + + // Poblar el estado del formulario con los datos del producto existente + if (productData && productData.data && productData.data.length > 0) { + const prod = productData.data[0]; + setForm({ + up_name_product: prod.name_product || '', + up_sku_product: prod.sku_product || '', + product_type: prod.product_type || [], // Se espera que sea un array de IDs + id_category: prod.id_category_pro || '', + supplier_rfc: prod.supplier_product || '', + unit: prod.id_unit || '', + new_stock: prod.stock || '', + up_price_product: prod.price_product || '', + up_id_tax: prod.id_tax || '', + img_product: prod.image_product || '', + currency: prod.id_curreny || '', + }); + + if (prod.image_product) { + if (prod.image_product.startsWith('/')) { + setImagePreview(`data:image/jpeg;base64,${prod.image_product}`); + } else if (prod.image_product.length > 200) { + setImagePreview(`data:image/jpeg;base64,${prod.image_product}`); + } else { + setImagePreview(`${IMAGE_BASE_URL}/${prod.image_product}`); + } + } + } else { + throw new Error(`No se encontró un producto con el ID ${id}.`); + } + + } catch (err) { + console.error("Error al cargar datos iniciales:", err); + setError(err.message); + } finally { + setLoading(false); // Ocultar el indicador de carga + } + }; + + fetchInitialData(); + }, [id]); // El efecto se volverá a ejecutar si el `id` del producto cambia + + // Manejar cambios en los campos del formulario + const handleChange = e => { + const { name, value } = e.target; + // Manejo especial para el select múltiple de 'product_type' + if (name === 'product_type') { + const options = e.target.options; + const selected = []; + for (let i = 0; i < options.length; i++) { + if (options[i].selected) selected.push(Number(options[i].value)); + } + setForm(prev => ({ ...prev, product_type: selected })); + } else { + setForm(prev => ({ ...prev, [name]: value })); + } + }; + + // Redimensionar y convertir la imagen a base64 + const handleImage = e => { + const file = e.target.files[0]; + if (file) { + const img = new window.Image(); + const reader = new FileReader(); + reader.onload = ev => { + img.onload = () => { + const MAX_WIDTH = 800; + const scale = Math.min(1, MAX_WIDTH / img.width); + const width = img.width * scale; + const height = img.height * scale; + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, width, height); + const dataUrl = canvas.toDataURL('image/jpeg', 0.8); + const base64 = dataUrl.split(',')[1]; + setForm(prev => ({ ...prev, img_product: base64 })); + setImagePreview(dataUrl); + }; + img.src = ev.target.result; + }; + reader.readAsDataURL(file); + } + }; + + // Enviar el formulario para actualizar el producto + const handleSubmit = async e => { + e.preventDefault(); + setLoading(true); + setError(''); + setSuccess(false); + try { + const payload = { + up_name_product: form.up_name_product, + up_sku_product: form.up_sku_product, + product_type: form.product_type, + id_category: form.id_category ? Number(form.id_category) : undefined, + supplier_rfc: form.supplier_rfc, + unit: form.unit ? Number(form.unit) : undefined, + new_stock: form.new_stock ? Number(form.new_stock) : undefined, + up_price_product: form.up_price_product ? Number(form.up_price_product) : undefined, + up_id_tax: form.up_id_tax ? Number(form.up_id_tax) : undefined, + img_product: form.img_product, + currency: form.currency ? Number(form.currency) : undefined, + }; + + // Limpiar campos vacíos o indefinidos antes de enviar + Object.keys(payload).forEach(k => (payload[k] === '' || payload[k] === undefined) && delete payload[k]); + + const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/products/update_product/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + if (!res.ok) throw new Error('Error al actualizar el producto'); + setSuccess(true); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    +
    +
    {lang === "es" ? "Editar Producto" : "Edit Product"}
    + +
    +
    + {loading && !success &&

    {lang === "es" ? "Cargando datos del producto..." : "Loading product data..."}

    } + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + {imagePreview && ( +
    + Product preview +
    + )} + +
    +
    + +
    + {success &&
    {lang === "es" ? "¡Producto actualizado con éxito!" : "Product updated successfully!"}
    } + {error &&
    {error}
    } + +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/DiscardProduct.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/DiscardProduct.jsx new file mode 100644 index 0000000..06a28a8 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/DiscardProduct.jsx @@ -0,0 +1,304 @@ +import React, { useEffect, useState, useCallback } from "react"; +import "./NewProduct.css"; +import { useContext } from "react"; +import { langContext } from "../../context/LenguageContext"; +import DiscardConfirmModal from "../../components/Modals/DiscardConfirmModal"; + +export default function DiscardProduct() { + const { lang } = useContext(langContext); + const [products, setProducts] = useState([]); + console.log("PRODUCTS", products); + const [form, setForm] = useState({ + productId: "", + reasons: "", + quantity: "", + }); + const [loading, setLoading] = useState(false); + const [initialLoading, setInitialLoading] = useState(true); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(""); + const [selectedProduct, setSelectedProduct] = useState(null); + const [showConfirmModal, setShowConfirmModal] = useState(false); + + const loadProducts = useCallback(async () => { + try { + setError(""); + const response = await fetch( + import.meta.env.VITE_API_BASE_URL + "/products" + ); + if (!response.ok) { + throw new Error( + lang === "es" + ? "Error al cargar los productos" + : "Error loading products" + ); + } + const data = await response.json(); + setProducts(Array.isArray(data.data) ? data.data : []); + } catch (err) { + console.error("Error fetching products:", err); + setError( + err.message || + (lang === "es" + ? "Error al cargar los productos" + : "Error loading products") + ); + } + }, [lang]); + + useEffect(() => { + async function loadInitialProducts() { + try { + setInitialLoading(true); + await loadProducts(); + } finally { + setInitialLoading(false); + } + } + loadInitialProducts(); + }, [loadProducts]); + + const handleChange = (e) => { + const { name, value } = e.target; + setForm((prev) => { + const updated = { ...prev, [name]: value }; + if (name === "productId") { + const product = products.find((p) => p.id_product === parseInt(value)); + setSelectedProduct(product || null); + } + return updated; + }); + }; + + const validateForm = () => { + if (!form.productId) { + setError( + lang === "es" + ? "Por favor selecciona un producto" + : "Please select a product" + ); + return false; + } + const quantity = parseInt(form.quantity); + if (!quantity || quantity < 1) { + setError( + lang === "es" + ? "La cantidad debe ser mayor a 0" + : "Quantity must be greater than 0" + ); + return false; + } + if (selectedProduct && quantity > (parseInt(selectedProduct.units) || 0)) { + setError( + lang === "es" + ? `La cantidad no puede ser mayor al stock disponible (${selectedProduct.units})` + : `Quantity cannot exceed available stock (${selectedProduct.units})` + ); + return false; + } + if (!form.reasons || form.reasons.trim() === "") { + setError( + lang === "es" ? "Por favor ingresa una razón" : "Please enter a reason" + ); + return false; + } + return true; + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setError(""); + setSuccess(false); + + if (!validateForm()) { + return; + } + + setShowConfirmModal(true); + }; + + const handleConfirmDiscard = async () => { + setShowConfirmModal(false); + setLoading(true); + const currentDate = new Date(); + try { + const day = currentDate.getDate(); + const month = currentDate.getMonth() + 1; + const year = currentDate.getFullYear(); + const formattedDate = `${day}-${month}-${year}`; + + const payload = { + quantity: parseInt(form.quantity), + reasons: form.reasons.trim(), + datediscard: formattedDate, + }; + + const res = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/discardproduct/${form.productId}`, + { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + } + ); + + if (!res.ok) { + const errorData = await res.json().catch(() => ({})); + throw new Error( + errorData.message || + (lang === "es" + ? "Error al descartar el producto" + : "Error discarding product") + ); + } + + await loadProducts(); + + setSuccess(true); + setForm({ productId: "", reasons: "", quantity: "" }); + setSelectedProduct(null); + + setTimeout(() => { + setSuccess(false); + }, 2000); + } catch (err) { + setError( + err.message || + (lang === "es" + ? "Error al descartar el producto" + : "Error discarding product") + ); + } finally { + setLoading(false); + } + }; + + const handleCancelDiscard = () => { + setShowConfirmModal(false); + }; + + const confirmMessage = + lang === "es" + ? `¿Estás seguro de descartar ${form.quantity} unidad(es) de ${selectedProduct?.name_product || "este producto"}?` + : `Are you sure you want to discard ${form.quantity} unit(s) of ${selectedProduct?.name_product || "this product"}?`; + + return ( +
    +
    +
    + {lang === "es" ? "Descartar producto" : "Discard product"} +
    + + {initialLoading ? ( +

    + {lang === "es" ? "Cargando productos..." : "Loading products..."} +

    + ) : ( +
    +
    +
    + + +
    +
    + + +
    +
    + + + {selectedProduct && ( + + {lang === "es" ? "Stock disponible" : "Available stock"}:{" "} + {selectedProduct.units || 0} + + )} +
    +
    +
    + +
    + {success && ( +
    + {lang === "es" + ? "¡Producto descartado con éxito!" + : "Product discarded successfully!"} +
    + )} + {error &&
    {error}
    } + + )} +
    + + +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/HousekeeperOutcomes.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/HousekeeperOutcomes.jsx new file mode 100644 index 0000000..2370dbe --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/HousekeeperOutcomes.jsx @@ -0,0 +1,314 @@ +import React, { useState, useEffect, useContext } from 'react'; +import '../../components/Filters/Filters.css'; +import './Outcomes.css'; +import { langContext } from '../../context/LenguageContext'; +import ConfirmationOutcome from '../../components/Modals/ConfirmationOutcome'; +import axios from 'axios'; + +const IMAGE_BASE_URL = import.meta.env.VITE_API_BASE_URL + '/products'; + + +export default function HousekeeperOutcomes() { + const { lang } = useContext(langContext); + const [products, setProducts] = useState([]); + const [filteredProducts, setFilteredProducts] = useState([]); + const [categories, setCategories] = useState([]); + const [nameFilter, setNameFilter] = useState(''); + const [categoryFilter, setCategoryFilter] = useState(''); + const [stockFilter, setStockFilter] = useState(''); + const [formHousekepeer, setFormHousekepeer] = useState(null) + const [modalOpen, setModalOpen] = useState(false); + const [selectedId, setSelectedId] = useState(null); + const [selectedProdName, setSelectedProdName] = useState(null); + const [selectedProductStock, setSelectedProductStock] = useState(null); + + const handleOpenModal = (id, product, productStock) => { + setSelectedId(id); + setSelectedProdName(product); + setSelectedProductStock(productStock); + //setSelectedStatus(statusType); + //setSelectedStatusId(statusId); + setModalOpen(true); + }; + const handleConfirm = (PCO, UCO, HCO) => { + if (!PCO || !UCO || !HCO) return; + + const currentdate = new Date(); + axios.post(`${import.meta.env.VITE_API_BASE_URL}/products/newconsumptionstock`, { + "product_id": PCO, + "quantity_consumption": UCO, + "date_consumption": currentdate.getFullYear() + "-" + (currentdate.getMonth() + 1) + "-" + currentdate.getDate(), + "rfc_emp": HCO + }) + .then((res) => { + console.log(res || 'Outcome realizado correctamente'); + // Cerrar el modal y limpiar selección + setModalOpen(false); + setSelectedId(null); + setSelectedProdName(null); + setSelectedProductStock(null); + async function loadProducts() { + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/products'); + const data = await response.json(); + const productsList = Array.isArray(data.data) ? data.data : []; + + const productsWithDetails = await Promise.all( + productsList.map(async (prod) => { + try { + const detailResponse = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/product/${prod.id_product}`, + { method: "PUT" } + ); + const detailData = await detailResponse.json(); + if (detailData.data && detailData.data.length > 0) { + const detail = detailData.data[0]; + return { + ...prod, + category: detail.id_category_pro || null, + }; + } + return { + ...prod, + category: null, + }; + } catch (err) { + console.error(`Error fetching product ${prod.id_product}:`, err); + return { + ...prod, + category: null, + }; + } + }) + ); + + setProducts(productsWithDetails); + setFilteredProducts(productsWithDetails); + } catch (err) { + console.error('Error fetching products', err); + setProducts([]); + setFilteredProducts([]); + } + } + loadProducts(); + }) + .catch((err) => { + console.error(`Error al actualizar el outcome con el producto ${selectedId}:`, err); + alert('❌ Error al actualizar el outcome.'); + }); + }; + + const handleCancel = () => { + setModalOpen(false); + }; + + useEffect(() => { + async function loadProducts() { + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/products'); + const data = await response.json(); + const productsList = Array.isArray(data.data) ? data.data : []; + + const productsWithDetails = await Promise.all( + productsList.map(async (prod) => { + try { + const detailResponse = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/product/${prod.id_product}`, + { method: "PUT" } + ); + const detailData = await detailResponse.json(); + if (detailData.data && detailData.data.length > 0) { + const detail = detailData.data[0]; + return { + ...prod, + category: detail.id_category_pro || null, + }; + } + return { + ...prod, + category: null, + }; + } catch (err) { + console.error(`Error fetching product ${prod.id_product}:`, err); + return { + ...prod, + category: null, + }; + } + }) + ); + + setProducts(productsWithDetails); + setFilteredProducts(productsWithDetails); + } catch (err) { + console.error('Error fetching products', err); + setProducts([]); + setFilteredProducts([]); + } + } + async function fetchSelectData() { + try { + const res = await fetch(import.meta.env.VITE_API_BASE_URL + '/products/gethousekeeper', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) throw new Error(`Error fetching info: ${res.status}`); + const data = await res.json(); + setFormHousekepeer(data.houseKeeper || []); + } catch (err) { + console.error('Error cargando metadata (getinfo):', err); + } + } + fetchSelectData(); + loadProducts(); + }, []); + + useEffect(() => { + async function loadFilterOptions() { + try { + const categoriesRes = await fetch( + import.meta.env.VITE_API_BASE_URL + "/products/productcategory" + ); + + const categoriesData = await categoriesRes.json(); + + if (categoriesData.data) { + setCategories( + categoriesData.data + .filter((d) => d.id_prod_category) + .map((d) => ({ + id: d.id_prod_category, + name: d.name_prod_category, + spanish_name: d.spanish_name || d.name_prod_category, + })) + ); + } + } catch (err) { + console.error("Error loading filter options", err); + } + } + loadFilterOptions(); + }, []); + + useEffect(() => { + let filtered = [...products]; + + if (nameFilter) { + filtered = filtered.filter(prod => + prod.name_product?.toLowerCase().includes(nameFilter.toLowerCase()) + ); + } + + if (categoryFilter) { + filtered = filtered.filter( + (prod) => prod.category && prod.category.toString() === categoryFilter + ); + } + + if (stockFilter) { + switch (stockFilter) { + case 'out': + filtered = filtered.filter(prod => (parseInt(prod.units) || 0) === 0); + break; + case 'low': + filtered = filtered.filter(prod => { + const units = parseInt(prod.units) || 0; + return units > 0 && units < 10; + }); + break; + case 'in': + filtered = filtered.filter(prod => (parseInt(prod.units) || 0) >= 10); + break; + default: + break; + } + } + + setFilteredProducts(filtered); + }, [nameFilter, categoryFilter, stockFilter, products]); + + return ( +
    +
    +

    {lang === "es" ? "Productos" : "Products"}

    +
    + +
    + setNameFilter(e.target.value)} + /> + + + + +
    + +
    + {Array.isArray(filteredProducts) && + filteredProducts.map((prod, index) => ( +
    handleOpenModal(prod.id_product, prod.name_product, prod.units)}> + {prod.image_product && ( + 200 + ? `data:image/jpeg;base64,${prod.image_product}` + : `${IMAGE_BASE_URL}/${prod.image_product}` + } + alt={prod.name_product} + className="product-image" + /> + )} +
    +
    {prod.name_product}
    +
    {lang === "es" ? "Precio: $" : "Price: $"}{prod.price_product}
    +
    {lang === "es" ? "Unidades: " : "Units: "}{prod.units}
    +
    +
    + ))} +
    + +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/InventoryReport.css b/frontend/Frontend-Hotel/src/pages/Inventory/InventoryReport.css new file mode 100644 index 0000000..3fc0cd9 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/InventoryReport.css @@ -0,0 +1,161 @@ +.report-page { + padding: 20px; + color: #213547; +} + +.report-page h2 { + color: #213547; +} + +.page-filters { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 20px; + flex-wrap: wrap; +} + +.page-filters select { + color: #213547; + background-color: white; + max-width: 250px; + min-width: 150px; + flex: 0 1 auto; +} + +.page-filters input[type="date"] { + color: #213547; + background-color: white; + max-width: 200px; + min-width: 150px; + flex: 0 1 auto; +} + +.summary-container { + display: flex; + gap: 80px; + margin-bottom: 20px; +} + +.summary-card { + background-color: white; + border-radius: 12px; + padding: 15px 25px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + min-width: 180px; + text-align: center; + color: #213547; + align-items: center; + display: block; +} + +.summary-card strong { + color: #213547; + display: block; + margin-bottom: 8px; +} + +.summary-card div { + color: #213547; + font-size: 1.2em; + font-weight: bold; +} + +.inventory-filters { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.inventory-filters .filter-search { + flex: 1; + max-width: 280px; + min-width: 180px; +} + +.inventory-filters .date-input-group { + display: flex; + flex-direction: row; + align-items: center; + gap: 8px; + min-width: 180px; +} + +.inventory-filters .date-label { + font-size: 12px; + font-weight: 600; + white-space: nowrap; + flex-shrink: 0; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; +} + +.inventory-filters .date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.inventory-filters .date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.inventory-filters .date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +@media (max-width: 768px) { + .inventory-filters { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .inventory-filters .filter-search { + min-width: 100%; + max-width: 100%; + order: -1; + } + + .inventory-filters .filter-select { + min-width: 100%; + } + + .inventory-filters .date-input-group { + min-width: auto; + width: 100%; + flex-direction: column; + gap: 4px; + } + + .inventory-filters .date-input { + min-width: 100%; + } + + .inventory-filters .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/InventoryReport.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/InventoryReport.jsx new file mode 100644 index 0000000..5b5a756 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/InventoryReport.jsx @@ -0,0 +1,351 @@ +import React, { useEffect, useState, useContext } from 'react'; +import Table from '../../components/Table/HotelTable'; +import ConfirmationModal from '../../components/Modals/ConfirmationModal'; +import '../../components/Filters/Filters.css'; +import './InventoryReport.css'; +import { langContext } from '../../context/LenguageContext'; +import ExcelExportButton from '../../components/ExcelExportButton'; + + +export default function InventoryReport() { + const { lang } = useContext(langContext); + const [data, setData] = useState([]); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [productFilter, setProductFilter] = useState(''); + const [productSelectFilter, setProductSelectFilter] = useState(''); + const [movementFilter, setMovementFilter] = useState(''); + + useEffect(() => { + fetch(import.meta.env.VITE_API_BASE_URL + '/products/reportinventory') + .then(res => res.json()) + .then(report => { + if (report && report.new_product) { + const products = report.new_product.map(item => ({ + dateOriginal: item.date_movement ? new Date(item.date_movement) : null, + productId: item.id_product, + product: item.name_product, + movement: item.movement, + quantity: item.quantity, + beforeStock: Number(item.before_stock), + stock: Number(item.stock), + commentsDiscard: item.comments_discard, + housekeeperName: item.housekeeper_name + })); + setData(products); + } else { + setData([]); + } + }) + .catch(() => setData([])); + }, []); + + const uniqueProducts = [...new Set(data.map(item => item.product).filter(Boolean))].sort(); + const uniqueMovements = [...new Set(data.map(item => item.movement).filter(Boolean))].sort(); + + const filteredData = data.filter((item) => { + if (dateRange.from && dateRange.to) { + if (!item.dateOriginal) return false; + const movementDate = new Date(item.dateOriginal); + const from = new Date(dateRange.from); + const to = new Date(dateRange.to); + to.setHours(23, 59, 59, 999); + if (movementDate < from || movementDate > to) return false; + } + + if (productFilter && !item.product?.toLowerCase().includes(productFilter.toLowerCase())) { + return false; + } + + if (productSelectFilter && item.product !== productSelectFilter) { + return false; + } + + if (movementFilter && item.movement !== movementFilter) { + return false; + } + + return true; + }); + + const totalMovements = filteredData.length; + const stockSum = filteredData.reduce((acc, curr) => acc + (curr.stock || 0), 0); + + const clearFilters = () => { + setDateRange({ from: '', to: '' }); + setProductFilter(''); + setProductSelectFilter(''); + setMovementFilter(''); + }; + + const columns = [ + { header: lang === "es" ? 'ID Producto' : 'Product ID', key: 'productId' }, + { header: lang === "es" ? 'Producto' : 'Product', key: 'product' }, + { header: lang === "es" ? 'Movimiento' : 'Movement', key: 'movement' }, + { + header: lang === "es" ? 'Comentarios' : 'Comments', + key: 'commentsDiscard', + render: (text, row) => { + const movement = row.movement?.toLowerCase(); + if (movement === 'discard' && row.commentsDiscard) { + return row.commentsDiscard; + } + return '—'; + } + }, + { + header: lang === "es" ? 'Ama de Llaves' : 'Housekeeper', + key: 'housekeeperName', + render: (text, row) => { + const movement = row.movement?.toLowerCase(); + if (movement === 'consumption' && row.housekeeperName) { + return row.housekeeperName; + } + return '—'; + } + }, + { header: lang === "es" ? 'Cantidad' : 'Quantity', key: 'quantity' }, + { + header: lang === "es" ? 'Stock Anterior' : 'Before Stock', + key: 'beforeStock', + render: (value) => value !== undefined && value !== null ? value : '—' + }, + { header: lang === "es" ? 'Stock' : 'Stock', key: 'stock' }, + { + header: lang === "es" ? 'Fecha' : 'Date', + key: 'dateOriginal', + render: (text, row) => { + const date = row.dateOriginal; + return date && !isNaN(date.getTime()) + ? date.toLocaleDateString(lang === "es" ? "es-MX" : "en-US") + : '—'; + } + }, + ]; + + const exportColumns = [ + { header: lang === "es" ? 'ID Producto' : 'Product ID', key: 'productId' }, + { header: lang === "es" ? 'Producto' : 'Product', key: 'product' }, + { header: lang === "es" ? 'Movimiento' : 'Movement', key: 'movement' }, + { header: lang === "es" ? 'Comentarios' : 'Comments', key: 'commentsDiscard' }, + { header: lang === "es" ? 'Ama de Llaves' : 'Housekeeper', key: 'housekeeperName' }, + { header: lang === "es" ? 'Cantidad' : 'Quantity', key: 'quantity' }, + { header: lang === "es" ? 'Stock Anterior' : 'Before Stock', key: 'beforeStock' }, + { header: lang === "es" ? 'Stock' : 'Stock', key: 'stock' }, + { header: lang === "es" ? 'Fecha' : 'Date', key: 'dateOriginal' }, + ]; + + const transformDataForExport = (data) => { + return data.map(item => { + const movement = item.movement?.toLowerCase(); + return { + ...item, + dateOriginal: item.dateOriginal && !isNaN(item.dateOriginal.getTime()) + ? item.dateOriginal.toLocaleDateString(lang === "es" ? "es-MX" : "en-US") + : '—', + comments_discard: movement === 'discard' && item.comments_discard ? item.comments_discard : '—', + housekeeper_name: movement === 'consumption' && item.housekeeper_name ? item.housekeeper_name : '—' + }; + }); + }; + + return ( +
    +
    +

    {lang === "es" ? "Reporte de Inventario" : "Inventory Report"}

    +
    + +
    +
    + + setDateRange({ ...dateRange, from: e.target.value })} + className="date-input" + /> +
    + +
    + + setDateRange({ ...dateRange, to: e.target.value })} + className="date-input" + /> +
    + + setProductFilter(e.target.value)} + className="filter-search" + /> + + + + + + +
    + +
    +
    +
    + {lang === "es" ? "Total Movimientos" : "Total Movements"} +
    {totalMovements}
    +
    +
    + {lang === "es" ? "Stock Total" : "Total Stock"} +
    {stockSum}
    +
    +
    + +
    + +
    +
    + + + ); +} + + +// import React, { useEffect, useState } from 'react'; +// import Table from '../../components/Table/HotelTable'; +// import ConfirmationModal from '../../components/Modals/ConfirmationModal'; +// import '../../components/Filters/Filters.css'; + +// const fakeInventoryReport = [ +// { +// id: 1, +// date: '2025-09-10', +// productId: 'P-001', +// product: 'Coffee Beans', +// movement: 'Stock In', +// quantity: 100, +// stock: 350 +// }, +// { +// id: 2, +// date: '2025-09-12', +// productId: 'P-002', +// product: 'Sugar', +// movement: 'Stock Out', +// quantity: 20, +// stock: 80 +// }, +// { +// id: 3, +// date: '2025-09-13', +// productId: 'P-003', +// product: 'Milk', +// movement: 'Stock In', +// quantity: 50, +// stock: 150 +// }, +// ]; + +// export default function InventoryReport() { +// const [data, setData] = useState([]); +// const [dateRange, setDateRange] = useState({ from: '', to: '' }); + +// useEffect(() => { +// setData(fakeInventoryReport); +// // En el futuro: aquí llamas a tu API real con fetch/axios +// }, []); + +// const filteredData = data.filter((item) => { +// if (!dateRange.from || !dateRange.to) return true; +// const movementDate = new Date(item.date); +// const from = new Date(dateRange.from); +// const to = new Date(dateRange.to); +// return movementDate >= from && movementDate <= to; +// }); + +// const totalMovements = filteredData.length; + +// const stockSum = filteredData.reduce((acc, curr) => acc + curr.stock, 0); + +// const columns = [ +// { header: 'DATE', key: 'date' }, +// { header: 'PRODUCT ID', key: 'productId' }, +// { header: 'PRODUCT', key: 'product' }, +// { header: 'MOVEMENT', key: 'movement' }, +// { header: 'QUANTITY', key: 'quantity' }, +// { header: 'STOCK', key: 'stock' }, +// ]; + +// return ( +//
    +//

    REPORT

    + +// {/* Filtros por fecha */} +//
    +// setDateRange({ ...dateRange, from: e.target.value })} +// /> +// setDateRange({ ...dateRange, to: e.target.value })} +// /> +//
    + +// {/* Summary */} +//
    +//
    +// Total Movements +//
    {totalMovements}
    +//
    +//
    +// Total Stock +//
    {stockSum}
    +//
    +//
    + +//
    +// +// ); +// } diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/NewProduct.css b/frontend/Frontend-Hotel/src/pages/Inventory/NewProduct.css new file mode 100644 index 0000000..87b015d --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/NewProduct.css @@ -0,0 +1,259 @@ +/* .new-product-container { + padding: 20px; + max-width: 600px; + margin: 0 auto; +} + +.new-product-form { + display: flex; + flex-direction: column; + gap: 16px; +} + +.new-product-form label { + display: flex; + flex-direction: column; + font-weight: bold; +} + +.new-product-form input, +.new-product-form select { + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.new-product-form button { + background-color: #007bff; + color: white; + padding: 10px; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.new-product-form button:hover { + background-color: #0056b3; +} */ + + +.new-expense-container { + color: #213547; + padding: 20px; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + color: #213547; +} + +.form-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + padding-bottom: 1rem; + border-bottom: 1px solid #e2e8f0; +} + +.form-id { + font-weight: bold; + margin-bottom: 0; + font-size: 24px; + color: #213547; + border-bottom: none; + padding-bottom: 0; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 15px; + margin-bottom: 30px; +} + +.form-grid > div { + min-width: 0; +} + +.form-grid label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #213547; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; + color: #213547; + box-sizing: border-box; + height: 38px; + min-width: 0; /* Prevent inputs from overflowing grid cells */ +} + +.form-grid input[type="file"] { + padding: 6px 4px; + height: auto; + background-color: transparent; + cursor: pointer; +} + +.form-grid input:focus, +.form-grid select:focus { + outline: none; + border-color: #ffcb05; + background-color: #fff; +} + +form > div:not(.form-grid):not(.save-button-wrapper) { + min-width: 0; +} + +form > div:not(.form-grid):not(.save-button-wrapper) input { + width: 100%; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + background-color: #f9f9f9; + color: #213547; + box-sizing: border-box; + height: 38px; +} + +form > div:not(.form-grid):not(.save-button-wrapper) input[type="file"] { + padding: 6px 4px; + height: auto; + background-color: transparent; + width: 100%; + box-sizing: border-box; +} + +form > div:not(.form-grid):not(.save-button-wrapper) label { + font-weight: bold; + font-size: 14px; + margin-bottom: 5px; + display: block; + color: #213547; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 20px; +} + +.save-button { + background-color: #ffcb05; + color: #fff; + padding: 10px 30px; + font-weight: bold; + border: none; + border-radius: 25px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.save-button:hover { + background-color: #f4b400; +} + +.save-button:disabled { + background-color: #a0aec0; + cursor: not-allowed; + opacity: 0.6; +} + +.back-button { + background-color: #718096; + color: white; + border: none; + padding: 0.6rem 1.2rem; + border-radius: 8px; + font-size: 0.9rem; + font-weight: 600; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.1s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.back-button:hover { + background-color: #4a5568; +} + +.back-button:active { + transform: translateY(1px); +} + +.feedback-message { + margin-top: 1rem; + padding: 0.75rem; + border-radius: 6px; + text-align: center; +} + +.feedback-message.success { + background-color: #c6f6d5; + color: #22543d; +} + +.feedback-message.error { + background-color: #fed7d7; + color: #742a2a; +} + +.product-table-section { + margin-top: 25px; + overflow-x: auto; +} + +.product-table { + width: 100%; + border-collapse: collapse; +} + +.product-table th, .product-table td { + border: 1px solid #d4af37; /* dorado */ + padding: 8px; + text-align: center; +} + +.product-table th { + background-color: #800020; /* bordo/morado oscuro, según tus imágenes */ + color: white; + font-weight: bold; +} + +.add-product-row { + cursor: pointer; + color: #d4af37; /* dorado */ + text-align: center; + padding: 10px; + font-style: italic; +} + +.tax-pill { + background-color: white; + border: 1px solid #d4af37; + border-radius: 12px; + padding: 2px 6px; + color: #800020; +} + +.product-table tfoot td { + border-top: 2px solid #d4af37; + padding: 8px; +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/NewProduct.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/NewProduct.jsx new file mode 100644 index 0000000..104f998 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/NewProduct.jsx @@ -0,0 +1,415 @@ +import React, { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import './NewProduct.css'; +import { useContext } from 'react'; +import { langContext } from '../../context/LenguageContext'; + +export default function NewProduct() { + const { lang } = useContext(langContext); + const navigate = useNavigate(); + const [productTypes, setProductTypes] = useState([]); + const [categories, setCategories] = useState([]); + const [suppliers, setSuppliers] = useState([]); + const [form, setForm] = useState({ + new_name_product: '', + new_sku_product: '', + product_type: '', + new_category: '', + new_rfc_suppliers: '', + unit: '', + new_stock: '', + newprice_product: '', + new_tax: '', + currency: '', // aquí se guardará el id_currency + image_product: '', + }); + const [currencies, setCurrencies] = useState([]); + const [_imageFile, setImageFile] = useState(null); + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(''); + const [units, setUnits] = useState([]); + const [packageQuantity, setPackageQuantity] = useState(''); + const [piecesPerPackage, setPiecesPerPackage] = useState(''); + const [numberOfPairs, setNumberOfPairs] = useState(''); + const [numberOfDozens, setNumberOfDozens] = useState(''); + + useEffect(() => { + fetch(import.meta.env.VITE_API_BASE_URL + '/products/producttype') + .then(res => res.json()) + .then(data => { + setProductTypes( + data.data.map(d => ({ + id: d.id_product_type, + name: d.name_product_type, + spanish_name: d.spanish_name || d.name_product_type + })) + ); + }); + fetch(import.meta.env.VITE_API_BASE_URL + '/products/productcategory') + .then(res => res.json()) + .then(data => { + setCategories( + data.data + .filter(d => d.id_prod_category) + .map(d => ({ + id: d.id_prod_category, + name: d.name_prod_category, + spanish_name: d.spanish_name || d.name_prod_category + })) + ); + }); + fetch(import.meta.env.VITE_API_BASE_URL + '/products/suppliers') + .then(res => res.json()) + .then(data => setSuppliers(data.data)); + fetch(import.meta.env.VITE_API_BASE_URL + '/settings/currency') + .then(res => res.json()) + .then(data => { + if (data.currency) { + setCurrencies(data.currency.map(c => ({ id: c.id_currency, name: c.name_currency }))); + } + }); + fetch(import.meta.env.VITE_API_BASE_URL + '/settings/units') + .then(res => res.json()) + .then(data => { + if (data.units) { + setUnits(data.units.map(u => ({ + id: u.id_unit, + name: u.name_unit, + spanish_name: u.spanish_name || u.name_unit + }))); + } + }); + }, []); + + + const getSelectedUnitName = () => { + if (!form.unit) return ''; + const selectedUnit = units.find(u => u.id === Number(form.unit)); + return selectedUnit ? selectedUnit.name.toLowerCase() : ''; + }; + + const getUnitType = () => { + const unitName = getSelectedUnitName(); + if (unitName.includes('package') || unitName.includes('paquete')) { + return 'package'; + } + if (unitName.includes('pair') || unitName.includes('par')) { + return 'pair'; + } + if (unitName.includes('dozen') || unitName.includes('docena')) { + return 'dozen'; + } + return null; + }; + + useEffect(() => { + if (!form.unit) return; + + const selectedUnit = units.find(u => u.id === Number(form.unit)); + if (!selectedUnit) return; + + const unitName = selectedUnit.name.toLowerCase(); + let calculatedStock = ''; + + if (unitName.includes('package') || unitName.includes('paquete')) { + if (packageQuantity && piecesPerPackage) { + calculatedStock = (Number(packageQuantity) * Number(piecesPerPackage)).toString(); + } + } else if (unitName.includes('pair') || unitName.includes('par')) { + if (numberOfPairs) { + calculatedStock = (Number(numberOfPairs) * 2).toString(); + } + } else if (unitName.includes('dozen') || unitName.includes('docena')) { + if (numberOfDozens) { + calculatedStock = (Number(numberOfDozens) * 12).toString(); + } + } + + if (calculatedStock) { + setForm(prev => ({ ...prev, new_stock: calculatedStock })); + } + }, [packageQuantity, piecesPerPackage, numberOfPairs, numberOfDozens, form.unit, units]); + + // Manejar cambios en el formulario + const handleChange = e => { + const { name, value } = e.target; + + if (name === 'unit') { + const newUnitType = units.find(u => u.id === Number(value)); + const newUnitName = newUnitType ? newUnitType.name.toLowerCase() : ''; + + const isPackage = newUnitName.includes('package') || newUnitName.includes('paquete'); + const isPair = newUnitName.includes('pair') || newUnitName.includes('par'); + const isDozen = newUnitName.includes('dozen') || newUnitName.includes('docena'); + + if (!isPackage) { + setPackageQuantity(''); + setPiecesPerPackage(''); + } + if (!isPair) { + setNumberOfPairs(''); + } + if (!isDozen) { + setNumberOfDozens(''); + } + + if (!isPackage && !isPair && !isDozen) { + setForm(prev => ({ ...prev, [name]: value, new_stock: '' })); + } else { + setForm(prev => ({ ...prev, [name]: value })); + } + } else { + setForm(prev => ({ ...prev, [name]: value })); + } + }; + + // Manejar imagen + + // Redimensionar imagen antes de convertir a base64 + const handleImage = e => { + const file = e.target.files[0]; + setImageFile(file); + if (file) { + const img = new window.Image(); + const reader = new FileReader(); + reader.onload = ev => { + img.onload = () => { + // Redimensionar a 800px de ancho máximo + const MAX_WIDTH = 800; + const scale = Math.min(1, MAX_WIDTH / img.width); + const width = img.width * scale; + const height = img.height * scale; + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, width, height); + // Convertir a base64 (jpeg para mayor compresión) + const dataUrl = canvas.toDataURL('image/jpeg', 0.8); // calidad 80% + const base64 = dataUrl.split(',')[1]; + setForm(prev => ({ ...prev, image_product: base64 })); + }; + img.src = ev.target.result; + }; + reader.readAsDataURL(file); + } + }; + + // Enviar formulario + const handleSubmit = async e => { + e.preventDefault(); + setLoading(true); + setError(''); + setSuccess(false); + try { + // Construir payload + const payload = { + ...form, + product_type: form.product_type ? [Number(form.product_type)] : [], + new_category: form.new_category ? Number(form.new_category) : undefined, + new_rfc_suppliers: form.new_rfc_suppliers, + new_sku_product: form.new_sku_product ? Number(form.new_sku_product) : undefined, + unit: form.unit ? Number(form.unit) : undefined, + new_stock: form.new_stock ? Number(form.new_stock) : undefined, + newprice_product: form.newprice_product ? Number(form.newprice_product) : undefined, + new_tax: form.new_tax ? Number(form.new_tax) : undefined, + currency: form.currency ? Number(form.currency) : undefined, // id_currency como número + }; + // Eliminar campos vacíos + Object.keys(payload).forEach(k => (payload[k] === '' || payload[k] === undefined) && delete payload[k]); + const res = await fetch(import.meta.env.VITE_API_BASE_URL + '/products/newproduct', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + if (!res.ok) throw new Error('Error al guardar el producto'); + setSuccess(true); + setForm({ + new_name_product: '', new_sku_product: '', product_type: '', new_category: '', new_rfc_suppliers: '', unit: '', new_stock: '', newprice_product: '', new_tax: '', currency: '', image_product: '' + }); + setImageFile(null); + setPackageQuantity(''); + setPiecesPerPackage(''); + setNumberOfPairs(''); + setNumberOfDozens(''); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    +
    +
    {lang === "es" ? "Nuevo producto" : "New product"}
    + +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + {getUnitType() === 'package' && ( + <> +
    + + setPackageQuantity(e.target.value)} + required + min="1" + /> +
    +
    + + setPiecesPerPackage(e.target.value)} + required + min="1" + /> +
    + + )} + {getUnitType() === 'pair' && ( +
    + + setNumberOfPairs(e.target.value)} + required + min="1" + /> +
    + )} + {getUnitType() === 'dozen' && ( +
    + + setNumberOfDozens(e.target.value)} + required + min="1" + /> +
    + )} +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + +
    + {success && {lang === "es" ? '¡Producto guardado!' : 'Product saved!'}} + {error && {error}} + +
    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/Outcomes.css b/frontend/Frontend-Hotel/src/pages/Inventory/Outcomes.css new file mode 100644 index 0000000..03fd698 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/Outcomes.css @@ -0,0 +1,42 @@ +.outcomes-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + gap: 12px; + align-items: center; + flex-wrap: wrap; + justify-content: center; +} + +.outcomes-page .filters-section .filter-search { + flex: 1; + max-width: 280px; + min-width: 180px; +} + +.outcomes-page .filters-section .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +@media (max-width: 768px) { + .outcomes-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .outcomes-page .filters-section .filter-search { + min-width: 100%; + max-width: 100%; + order: -1; + } + + .outcomes-page .filters-section .filter-select { + min-width: 100%; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/Outcomes.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/Outcomes.jsx new file mode 100644 index 0000000..7c66659 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/Outcomes.jsx @@ -0,0 +1,314 @@ +import React, { useState, useEffect, useContext } from 'react'; +import '../../components/Filters/Filters.css'; +import './Outcomes.css'; +import { langContext } from '../../context/LenguageContext'; +import ConfirmationOutcome from '../../components/Modals/ConfirmationOutcome'; +import axios from 'axios'; + +const IMAGE_BASE_URL = import.meta.env.VITE_API_BASE_URL + '/products'; + + +export default function Outcomes() { + const { lang } = useContext(langContext); + const [products, setProducts] = useState([]); + const [filteredProducts, setFilteredProducts] = useState([]); + const [categories, setCategories] = useState([]); + const [nameFilter, setNameFilter] = useState(''); + const [categoryFilter, setCategoryFilter] = useState(''); + const [stockFilter, setStockFilter] = useState(''); + const [formHousekepeer, setFormHousekepeer] = useState(null) + const [modalOpen, setModalOpen] = useState(false); + const [selectedId, setSelectedId] = useState(null); + const [selectedProdName, setSelectedProdName] = useState(null); + const [selectedProductStock, setSelectedProductStock] = useState(null); + + const handleOpenModal = (id, product, productStock) => { + setSelectedId(id); + setSelectedProdName(product); + setSelectedProductStock(productStock); + //setSelectedStatus(statusType); + //setSelectedStatusId(statusId); + setModalOpen(true); + }; + const handleConfirm = (PCO, UCO, HCO) => { + if (!PCO || !UCO || !HCO) return; + + const currentdate = new Date(); + axios.post(`${import.meta.env.VITE_API_BASE_URL}/products/newconsumptionstock`, { + "product_id": PCO, + "quantity_consumption": UCO, + "date_consumption": currentdate.getFullYear() + "-" + (currentdate.getMonth() + 1) + "-" + currentdate.getDate(), + "rfc_emp": HCO + }) + .then((res) => { + console.log(res || 'Outcome realizado correctamente'); + // Cerrar el modal y limpiar selección + setModalOpen(false); + setSelectedId(null); + setSelectedProdName(null); + setSelectedProductStock(null); + async function loadProducts() { + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/products'); + const data = await response.json(); + const productsList = Array.isArray(data.data) ? data.data : []; + + const productsWithDetails = await Promise.all( + productsList.map(async (prod) => { + try { + const detailResponse = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/product/${prod.id_product}`, + { method: "PUT" } + ); + const detailData = await detailResponse.json(); + if (detailData.data && detailData.data.length > 0) { + const detail = detailData.data[0]; + return { + ...prod, + category: detail.id_category_pro || null, + }; + } + return { + ...prod, + category: null, + }; + } catch (err) { + console.error(`Error fetching product ${prod.id_product}:`, err); + return { + ...prod, + category: null, + }; + } + }) + ); + + setProducts(productsWithDetails); + setFilteredProducts(productsWithDetails); + } catch (err) { + console.error('Error fetching products', err); + setProducts([]); + setFilteredProducts([]); + } + } + loadProducts(); + }) + .catch((err) => { + console.error(`Error al actualizar el outcome con el producto ${selectedId}:`, err); + alert('❌ Error al actualizar el outcome.'); + }); + }; + + const handleCancel = () => { + setModalOpen(false); + }; + + useEffect(() => { + async function loadProducts() { + try { + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/products'); + const data = await response.json(); + const productsList = Array.isArray(data.data) ? data.data : []; + + const productsWithDetails = await Promise.all( + productsList.map(async (prod) => { + try { + const detailResponse = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/product/${prod.id_product}`, + { method: "PUT" } + ); + const detailData = await detailResponse.json(); + if (detailData.data && detailData.data.length > 0) { + const detail = detailData.data[0]; + return { + ...prod, + category: detail.id_category_pro || null, + }; + } + return { + ...prod, + category: null, + }; + } catch (err) { + console.error(`Error fetching product ${prod.id_product}:`, err); + return { + ...prod, + category: null, + }; + } + }) + ); + + setProducts(productsWithDetails); + setFilteredProducts(productsWithDetails); + } catch (err) { + console.error('Error fetching products', err); + setProducts([]); + setFilteredProducts([]); + } + } + async function fetchSelectData() { + try { + const res = await fetch(import.meta.env.VITE_API_BASE_URL + '/products/gethousekeeper', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) throw new Error(`Error fetching info: ${res.status}`); + const data = await res.json(); + setFormHousekepeer(data.houseKeeper || []); + } catch (err) { + console.error('Error cargando metadata (getinfo):', err); + } + } + fetchSelectData(); + loadProducts(); + }, []); + + useEffect(() => { + async function loadFilterOptions() { + try { + const categoriesRes = await fetch( + import.meta.env.VITE_API_BASE_URL + "/products/productcategory" + ); + + const categoriesData = await categoriesRes.json(); + + if (categoriesData.data) { + setCategories( + categoriesData.data + .filter((d) => d.id_prod_category) + .map((d) => ({ + id: d.id_prod_category, + name: d.name_prod_category, + spanish_name: d.spanish_name || d.name_prod_category, + })) + ); + } + } catch (err) { + console.error("Error loading filter options", err); + } + } + loadFilterOptions(); + }, []); + + useEffect(() => { + let filtered = [...products]; + + if (nameFilter) { + filtered = filtered.filter(prod => + prod.name_product?.toLowerCase().includes(nameFilter.toLowerCase()) + ); + } + + if (categoryFilter) { + filtered = filtered.filter( + (prod) => prod.category && prod.category.toString() === categoryFilter + ); + } + + if (stockFilter) { + switch (stockFilter) { + case 'out': + filtered = filtered.filter(prod => (parseInt(prod.units) || 0) === 0); + break; + case 'low': + filtered = filtered.filter(prod => { + const units = parseInt(prod.units) || 0; + return units > 0 && units < 10; + }); + break; + case 'in': + filtered = filtered.filter(prod => (parseInt(prod.units) || 0) >= 10); + break; + default: + break; + } + } + + setFilteredProducts(filtered); + }, [nameFilter, categoryFilter, stockFilter, products]); + + return ( +
    +
    +

    {lang === "es" ? "Productos" : "Products"}

    +
    + +
    + setNameFilter(e.target.value)} + /> + + + + +
    + +
    + {Array.isArray(filteredProducts) && + filteredProducts.map((prod, index) => ( +
    handleOpenModal(prod.id_product, prod.name_product, prod.units)}> + {prod.image_product && ( + 200 + ? `data:image/jpeg;base64,${prod.image_product}` + : `${IMAGE_BASE_URL}/${prod.image_product}` + } + alt={prod.name_product} + className="product-image" + /> + )} +
    +
    {prod.name_product}
    +
    {lang === "es" ? "Precio: $" : "Price: $"}{prod.price_product}
    +
    {lang === "es" ? "Unidades: " : "Units: "}{prod.units}
    +
    +
    + ))} +
    + +
    + ); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/Products.css b/frontend/Frontend-Hotel/src/pages/Inventory/Products.css new file mode 100644 index 0000000..a47c238 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/Products.css @@ -0,0 +1,155 @@ +/* src/pages/Inventory/Products.css */ + +.products-page-container { + padding: 20px; + color: #213547; +} + +.products-page-container h2 { + color: #213547; +} + +.products-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); + gap: 20px; + margin-top: 20px; +} + +.product-card { + background-color: white; + border: 1px solid #e2e2e2; + border-radius: 8px; + padding: 15px; + box-shadow: 0 2px 5px rgba(0,0,0,0.1); + cursor: pointer; + text-align: center; + transition: transform 0.2s; + color: #213547; +} + +.product-card:hover { + transform: translateY(-4px); +} + +.add-new-card { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #666; + font-size: 1.2em; + font-weight: bold; +} + +.add-icon { + font-size: 3em; + margin-bottom: 10px; +} + +.product-image { + max-width: 100%; + height: 120px; + object-fit: contain; +} + +.product-info { + margin-top: 10px; +} + +.product-name { + font-weight: bold; + margin-bottom: 5px; + color: #213547; +} + +.product-price, +.product-units { + font-size: 0.9em; + color: #444; +} + +.page-filters { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 20px; + flex-wrap: wrap; +} + +.page-filters select { + color: #213547; + background-color: white; + max-width: 250px; + min-width: 150px; + flex: 0 1 auto; +} + +.page-filters input[type="text"], +.page-filters .filter-search-input { + color: #213547; + background-color: white; + max-width: 300px; + min-width: 200px; + flex: 0 1 auto; + padding: 10px 16px; + border: none; + border-radius: 30px; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-weight: bold; + box-sizing: border-box; +} + +.page-filters p { + color: #213547; +} + +.products-page-container p { + color: #213547; +} + +.products-filters { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + gap: 12px; + align-items: center; + flex-wrap: wrap; + justify-content: center; +} + +.products-filters .filter-search { + flex: 1; + max-width: 280px; + min-width: 180px; +} + +@media (max-width: 768px) { + .products-filters { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .products-filters .filter-search { + min-width: 100%; + max-width: 100%; + order: -1; + } + + .products-filters .filter-select { + min-width: 100%; + } + + .products-filters .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} diff --git a/frontend/Frontend-Hotel/src/pages/Inventory/Products.jsx b/frontend/Frontend-Hotel/src/pages/Inventory/Products.jsx new file mode 100644 index 0000000..4d818f5 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Inventory/Products.jsx @@ -0,0 +1,386 @@ +// // // src/pages/Inventory/Products.jsx +// import React, { useState, useEffect } from 'react'; +// import { useNavigate } from 'react-router-dom'; +// import '../../components/Filters/Filters.css'; +// import './Products.css'; + +// const IMAGE_BASE_URL = import.meta.env.VITE_API_BASE_URL + '/products'; + +// export default function Products() { +// const [products, setProducts] = useState([]); +// const navigate = useNavigate(); + +// useEffect(() => { +// async function loadProducts() { +// try { +// const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/products'); +// const data = await response.json(); +// setProducts(Array.isArray(data.data) ? data.data : []); +// } catch (err) { +// console.error('Error fetching products', err); +// setProducts([]); +// } +// } +// loadProducts(); +// }, []); + +// const handleAddNew = () => { +// navigate('/app/new-product'); + +// }; + +// return ( +//
    +//

    Products

    +//
    +//
    +//
    +
    +//
    Add new product
    +//
    +// {Array.isArray(products) && +// products.map((prod, index) => ( +//
    +// {prod.image_product && ( +// 200 +// ? `data:image/jpeg;base64,${prod.image_product}` +// : `${IMAGE_BASE_URL}/${prod.image_product}` +// } +// alt={prod.name_product} +// className="product-image" +// /> +// )} +//
    +//
    {prod.name_product}
    +//
    Price: ${prod.price_product}
    +//
    Units: {prod.units}
    +//
    +//
    +// ))} +//
    +//
    +// ); +// } + +import React, { useState, useEffect, useContext } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import "../../components/Filters/Filters.css"; +import "./Products.css"; +import { langContext } from "../../context/LenguageContext"; + +const IMAGE_BASE_URL = import.meta.env.VITE_API_BASE_URL + "/products"; + +export default function Products() { + const { lang } = useContext(langContext); + const [products, setProducts] = useState([]); + const [filteredProducts, setFilteredProducts] = useState([]); + const [categories, setCategories] = useState([]); + const [productTypes, setProductTypes] = useState([]); + const [searchTerm, setSearchTerm] = useState(""); + const [categoryFilter, setCategoryFilter] = useState(""); + const [productTypeFilter, setProductTypeFilter] = useState(""); + const [stockFilter, setStockFilter] = useState(""); + const [loading, setLoading] = useState(true); + const navigate = useNavigate(); + + useEffect(() => { + async function loadProducts() { + try { + setLoading(true); + const response = await fetch( + import.meta.env.VITE_API_BASE_URL + "/products" + ); + const data = await response.json(); + const productsList = Array.isArray(data.data) ? data.data : []; + + const productsWithDetails = await Promise.all( + productsList.map(async (prod) => { + try { + const detailResponse = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/products/product/${prod.id_product}`, + { method: "PUT" } + ); + const detailData = await detailResponse.json(); + if (detailData.data && detailData.data.length > 0) { + const detail = detailData.data[0]; + return { + ...prod, + category: detail.id_category_pro || null, + product_type: detail.product_type || [], + units: detail.stock || prod.units || 0, + }; + } + return { + ...prod, + category: null, + product_type: [], + units: prod.units || 0, + }; + } catch (err) { + console.error(`Error fetching product ${prod.id_product}:`, err); + return { + ...prod, + category: null, + product_type: [], + units: prod.units || 0, + }; + } + }) + ); + + setProducts(productsWithDetails); + setFilteredProducts(productsWithDetails); + } catch (err) { + console.error("Error fetching products", err); + setProducts([]); + setFilteredProducts([]); + } finally { + setLoading(false); + } + } + loadProducts(); + }, []); + + useEffect(() => { + async function loadFilterOptions() { + try { + const [categoriesRes, typesRes] = await Promise.all([ + fetch( + import.meta.env.VITE_API_BASE_URL + "/products/productcategory" + ), + fetch(import.meta.env.VITE_API_BASE_URL + "/products/producttype"), + ]); + + const categoriesData = await categoriesRes.json(); + const typesData = await typesRes.json(); + + if (categoriesData.data) { + setCategories( + categoriesData.data + .filter((d) => d.id_prod_category) + .map((d) => ({ + id: d.id_prod_category, + name: d.name_prod_category, + spanish_name: d.spanish_name || d.name_prod_category, + })) + ); + } + + if (typesData.data) { + setProductTypes( + typesData.data.map((d) => ({ + id: d.id_product_type, + name: d.name_product_type, + spanish_name: d.spanish_name || d.name_product_type, + })) + ); + } + } catch (err) { + console.error("Error loading filter options", err); + } + } + loadFilterOptions(); + }, []); + + useEffect(() => { + let filtered = [...products]; + + if (searchTerm) { + filtered = filtered.filter((prod) => + prod.name_product?.toLowerCase().includes(searchTerm.toLowerCase()) + ); + } + + if (categoryFilter) { + filtered = filtered.filter( + (prod) => prod.category && prod.category.toString() === categoryFilter + ); + } + + if (productTypeFilter) { + filtered = filtered.filter((prod) => { + if (!prod.product_type || !Array.isArray(prod.product_type)) + return false; + return prod.product_type.some( + (type) => + type.toString() === productTypeFilter || + (typeof type === "object" && + type.id_product_type?.toString() === productTypeFilter) + ); + }); + } + + if (stockFilter) { + switch (stockFilter) { + case "out": + filtered = filtered.filter( + (prod) => (parseInt(prod.units) || 0) === 0 + ); + break; + case "low": + filtered = filtered.filter((prod) => { + const units = parseInt(prod.units) || 0; + return units > 0 && units < 10; + }); + break; + case "in": + filtered = filtered.filter( + (prod) => (parseInt(prod.units) || 0) >= 10 + ); + break; + default: + break; + } + } + + setFilteredProducts(filtered); + }, [searchTerm, categoryFilter, productTypeFilter, stockFilter, products]); + + const handleAddNew = () => { + navigate("/app/new-product"); + }; + + const clearFilters = () => { + setSearchTerm(""); + setCategoryFilter(""); + setProductTypeFilter(""); + setStockFilter(""); + }; + + return ( +
    +
    +

    + {lang === "es" ? "Productos" : "Products"} +

    +
    + +
    + setSearchTerm(e.target.value)} + className="filter-search" + /> + + + + + + + +
    + + {loading ? ( +

    {lang === "es" ? "Cargando productos..." : "Loading products..."}

    + ) : ( +
    +
    +
    +
    +
    + {lang === "es" ? "Agregar nuevo producto" : "Add new product"} +
    +
    + {Array.isArray(filteredProducts) && + filteredProducts.map((prod, index) => ( + +
    + {prod.image_product && ( + 200 + ? `data:image/jpeg;base64,${prod.image_product}` + : `${IMAGE_BASE_URL}/${prod.image_product}` + } + alt={prod.name_product} + className="product-image" + /> + )} +
    +
    {prod.name_product}
    +
    + {lang === "es" ? "Precio: $" : "Price: $"} + {prod.price_product} +
    +
    + {lang === "es" ? "Unidades: " : "Units: "} + {prod.units} +
    +
    +
    + + ))} +
    + )} +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Login.jsx b/frontend/Frontend-Hotel/src/pages/Login.jsx new file mode 100644 index 0000000..539c655 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Login.jsx @@ -0,0 +1,175 @@ +import { useContext, useState } from "react"; +import api from "../services/api"; +import { useNavigate } from "react-router-dom"; +import "../styles/Login.css"; +import { AuthContext } from "../context/AuthContext"; + +export default function Login() { + const { login } = useContext(AuthContext); + const [form, setForm] = useState({ user: "", password: "" }); + const [isModal, setShowModal] = useState(false); + const [recoverEmail, setRecoverEmail] = useState(""); + const [error, setError] = useState(""); + const navigate = useNavigate(); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + const response = await api.post("/auth/login", { + name_mail_user: form.user, + user_pass: form.password, + }); + if (response.data.rol != 0) { + login(response.data.rol, response.data); + navigate("/app"); + } else { + throw new Error(response.data.message || "Error al iniciar sesión"); + } + } catch (error) { + const errorMsg = error + ? "Usuario o contraseña incorrecto" + : "Error al iniciar sesión"; + setError(errorMsg); + } + + // try { + // const response = await api.post("/auth/login", { + // name_mail_user: form.user, + // user_pass: form.password, + // }); + + // console.log("✅ Login exitoso", response.data); + // setMensaje(response.data.message); + // setError(""); + // navigate("/app/income"); + + // } catch (err) { + // const errorMsg = err.response?.data?.error || "Error al iniciar sesión"; + // console.error("❌ Error:", errorMsg); + // setError(errorMsg); + // setMensaje(""); + // } + }; + + const handleRecoverPass = async () => { + try { + await api.post("/auth/recoverpass", { + user_mail: recoverEmail, + }); + alert(`Se envió un enlace de recuperación a: ${recoverEmail}`); + setShowModal(false); + setRecoverEmail(""); + } catch (err) { + const errorMsg = err.response?.data?.error || "Error al iniciar sesión"; + console.error("❌ Error:", errorMsg); + setError(errorMsg); + } + }; + + const handleRecover = (e) => { + e.preventDefault(); + handleRecoverPass(); + }; + + return ( +
    +
    +
    + {/* Logo a la izquierda */} +
    + Logo +
    +
    +
    +
    + { + setForm({ ...form, user: e.target.value }); + if (error) setError(""); + }} + className="custom-input" + required + /> + + { + setForm({ ...form, password: e.target.value }); + if (error) setError(""); + }} + className="custom-input" + required + /> + + {error && ( +
    + {error} +
    + )} + +
    + + +
    + +
    +
    + + {/* Modal */} + {isModal && ( +
    +
    +

    Recover Password

    +
    + setRecoverEmail(e.target.value)} + required + className="recover-input" + /> +
    + + +
    + +
    +
    + )} +
    +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/LoginPage.jsx b/frontend/Frontend-Hotel/src/pages/LoginPage.jsx new file mode 100644 index 0000000..64eec31 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/LoginPage.jsx @@ -0,0 +1,61 @@ +// src/pages/LoginPage.jsx + + +// import React, { useState } from "react"; +// import Input from "../components/Inputs/Input"; +// import Button from "../components/Buttons/Button"; + +// function LoginPage() { +// const [email, setEmail] = useState(""); +// const [password, setPassword] = useState(""); + +// const handleLogin = async (e) => { +// console.log("Email:", email, "Password:", password); +// console.log("Angel"); +// e.preventDefault(); + +// try { +// const response = await api.post("/auth/login", { +// name_user: form.user, +// password_use: form.password, +// }); + +// console.log("✅ Login exitoso", response.data); +// setMensaje(response.data.message); +// setError(""); + +// // Si el backend devuelve un token, guárdalo: +// // localStorage.setItem("token", response.data.token); + +// } catch (err) { +// const errorMsg = err.response?.data?.error || "Error al iniciar sesión"; +// console.error("❌ Error:", errorMsg); +// setError(errorMsg); +// setMensaje(""); +// } +// }; + +// return ( +//
    +//

    Log In

    + +// setEmail(e.target.value)} +// /> + +// setPassword(e.target.value)} +// /> + +//
    +// ); +// } + +// export default LoginPage; diff --git a/frontend/Frontend-Hotel/src/pages/NotFound.jsx b/frontend/Frontend-Hotel/src/pages/NotFound.jsx new file mode 100644 index 0000000..31634ba --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/NotFound.jsx @@ -0,0 +1,11 @@ +import { NavLink } from "react-router-dom"; + +export default function NotFound() { + return ( +
    +

    404 - No encontrado

    +

    La ruta que intentas abrir no existe.

    + Volver al inicio +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/ContractsDetail.css b/frontend/Frontend-Hotel/src/pages/Payroll/ContractsDetail.css new file mode 100644 index 0000000..798b154 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/ContractsDetail.css @@ -0,0 +1,165 @@ +.contract-detail-container { + background: #f9f9f9; + padding: 30px; + border-radius: 12px; + max-width: 1100px; + margin: auto; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; +} + +.form-grid label { + font-weight: 600; + margin-bottom: 5px; + display: block; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 8px; + border-radius: 6px; + border: 1px solid #ccc; +} + +.uniforms-section { + grid-column: span 3; +} + +.uniform-list { + display: flex; + gap: 15px; + flex-wrap: wrap; +} + +.save-button-container { + margin-top: 30px; + text-align: right; +} + +.save-button-container button { + background-color: #f0ad4e; + border: none; + color: white; + padding: 10px 20px; + border-radius: 8px; + font-size: 16px; + cursor: pointer; +} +.save-button-container button:hover { + background-color: #ec971f; +} + +/* .uniforms-container { + display: grid; + grid-template-columns: 1.2fr 0.8fr; + align-items: start; + gap: 24px; + margin-top: 10px; + width: 100%; + max-width: 900px; +} + +.uniform-checkbox-list { + display: flex; + flex-direction: column; + gap: 6px; + flex: 1; +} + +.uniform-chips { + display: flex; + flex-wrap: wrap; + gap: 8px; + flex: 1; + justify-content: flex-start; + align-content: flex-start; + padding-top: 4px; +} + +.uniforms-container label { + display: flex; + align-items: center; + gap: 8px; +} + +.checkbox-item { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; +} + +.checkbox-item input[type="checkbox"] { + width: 18px; + height: 18px; + cursor: pointer; +} + +.chip { + background-color: #e0e0e0; + border-radius: 16px; + padding: 4px 10px; + display: flex; + align-items: center; + font-size: 14px; +} + +.remove-chip { + background: transparent; + border: none; + font-size: 16px; + margin-left: 6px; + cursor: pointer; + color: #444; +} + +.remove-chip:hover { + color: #d00; +} + +.chip { + display: inline-flex; + align-items: center; + background-color: #f5f5f5; + border: 2px solid #ccc; + border-radius: 20px; + padding: 6px 12px; + font-size: 14px; + cursor: pointer; + transition: all 0.2s ease; + color: #333; +} + +.chip.selected { + background-color: #ffcb05; + border-color: #e0b400; + color: #000; + font-weight: bold; +} + +.chip button { + background: transparent; + border: none; + color: #555; + margin-left: 6px; + font-size: 14px; + cursor: pointer; +} + +.chip button:hover { + color: #b30000; +} + +.chip:hover { + background-color: #f0f0f0; + transform: translateY(-2px); +} +.chip.selected:hover { + background-color: #e6b800; + transform: translateY(-2px); +} */ diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/ContractsDetail.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/ContractsDetail.jsx new file mode 100644 index 0000000..c88a379 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/ContractsDetail.jsx @@ -0,0 +1,304 @@ +import React, { useEffect, useState, useRef, useContext } from "react"; +import { useParams } from "react-router-dom"; +import "./ContractsDetail.css"; +import { langContext } from "../../context/LenguageContext"; + +export default function ContractsDetail() { + const { id } = useParams(); + const { lang } = useContext(langContext); + + const [form, setForm] = useState({ + name_employee: "", + id_position_emp: "", + id_area_emp: "", + start_contract: "", + end_contract: "", + status_contract: "", + new_daily_pay: "", + uniforms: [], + }); + + const [positions, setPositions] = useState([]); + const [areas, setAreas] = useState([]); + const [uniforms, setUniforms] = useState([]); + const [selectedUniforms, setSelectedUniforms] = useState([]); + + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [successMsg, setSuccessMsg] = useState(""); + const initialFormRef = useRef(null); + + // 🧭 Formatear fecha a yyyy-MM-dd + const formatDate = (iso) => { + if (!iso) return ""; + const d = new Date(iso); + return d.toISOString().split("T")[0]; + }; + + //Cargar áreas, uniformes y positions + useEffect(() => { + const baseApiUrl = import.meta.env.VITE_API_BASE_URL; + + const fetchOptions = async () => { + try { + // Primer fetch (igual que antes) + const res = await fetch(`${baseApiUrl}/expenses/getinfo`); + const data = await res.json(); + + console.log("DEBUG: expenses/getinfo ->", data); + + setUniforms(data.uniforms || []); + setAreas(data.areas || []); + + // Segundo fetch para positions + const resPositions = await fetch(`${baseApiUrl}/contracts/positions`); + const dataPositions = await resPositions.json(); + console.log("DEBUG: contracts/positions ->", dataPositions); + + setPositions(dataPositions.data || []); + } catch (err) { + console.error("❌ Error loading options:", err); + } + }; + + fetchOptions(); + }, []); + + + //Cargar contrato específico + useEffect(() => { + const baseApiUrl = import.meta.env.VITE_API_BASE_URL; + + const fetchContract = async () => { + try { + const response = await fetch(`${baseApiUrl}/contracts/getinfocontract/${id}`); + const resData = await response.json(); + + if (!resData.data || resData.data.length === 0) { + setError("Contract not found"); + setLoading(false); + return; + } + + const c = resData.data[0]; + + // 🔍 Mapeo más flexible: busca coincidencias por nombre + const positionMatch = positions.find( + (p) => + p.name_position?.toLowerCase().trim() === + c.position_employee?.toLowerCase().trim() + ); + + const areaMatch = areas.find( + (a) => a.name?.toLowerCase().trim() === c.area_employee?.toLowerCase().trim() + ); + + const loaded = { + name_employee: c.name_employee || "", + id_position_emp: positionMatch?.id_position || "", + id_area_emp: areaMatch?.id_area || areaMatch?.id || "", + start_contract: formatDate(c.contract_start), + end_contract: formatDate(c.contract_end), + status_contract: c.status_contract, + new_daily_pay: c.daily_pay || "", + uniforms: [], + }; + + setForm(loaded); + initialFormRef.current = loaded; + setLoading(false); + } catch (err) { + console.error("❌ Error loading contract:", err); + setError("Contract could not be loaded"); + setLoading(false); + } + }; + + fetchContract(); + }, [id, positions, areas]); + + + + // 🔹 Manejadores de cambios + const handleChange = (e) => { + const { name, value } = e.target; + setForm((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const handleUniformChange = (idUniform) => { + setSelectedUniforms((prev) => + prev.includes(idUniform) + ? prev.filter((u) => u !== idUniform) + : [...prev, idUniform] + ); + }; + + // 🔹 Guardar cambios + const handleSave = async () => { + setError(null); + setSuccessMsg(""); + try { + const payload = { + name_employee: form.name_employee, + id_position_emp: Number(form.id_position_emp), + id_area_emp: Number(form.id_area_emp), + start_contract: form.start_contract, + end_contract: form.end_contract, + status_contract: + form.status_contract === "Active" + ? 1 + : form.status_contract === "Inactive" + ? 2 + : 3, + new_daily_pay: Number(form.new_daily_pay) || 0, + uniforms: selectedUniforms.map((id) => ({ id_uniform: id })), + }; + + console.log("📤 Payload enviado:", payload); + + const response = await fetch( + `${import.meta.env.VITE_API_BASE_URL}/contracts/updatecontract/${id}`, + { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + } + ); + + if (!response.ok) { + const errData = await response.json(); + throw new Error(errData.message || "Error updating contract"); + } + + setSuccessMsg("Contract updated successfully!"); + } catch (err) { + console.error("❌ Server error:", err); + setError(`Server error: ${err.message}`); + } + }; + + if (loading) + return
    Loading...
    ; + + return ( +
    +

    Edit Contract (ID: {id})

    + + {error &&

    {error}

    } + {successMsg &&

    {successMsg}

    } + +
    + {/* Name Empployee */} +
    + + + +
    + + {/* Position */} +
    + + + +
    + + {/* Area */} +
    + + +
    + + {/* Start & End Dates */} +
    + + +
    + +
    + + +
    + + {/* Status */} +
    + + +
    + + {/* Daily Pay */} +
    + + +
    + + {/* Uniforms */} +
    + +
    + {uniforms.map((u) => ( + + ))} +
    +
    +
    + + {/* Save Button */} +
    + +
    +
    + ); +} + diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/EditPayroll.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/EditPayroll.jsx new file mode 100644 index 0000000..3604108 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/EditPayroll.jsx @@ -0,0 +1,160 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; +import '../../components/Filters/Filters.css'; +import Table from '../../components/Table/HotelTable'; +import { Link, useParams } from 'react-router-dom'; +import FormInput from '../../components/FormInput'; + +export default function Plantillapayroll(){ + const { id: paramId } = useParams(); + function generateRandomId() { + return Math.floor(1000 + Math.random() * 9000); // 4 dígitos + } + let id = paramId; + const [contracts, setContracts] = useState([]); + const [contractId, setContractId] = useState(null); + const [formData, setFormData] = useState(null); + + // Consultar contratos al montar el componente + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/reportcontracts') + .then(res => { + if (Array.isArray(res.data?.data)) { + setContracts(res.data.data); + } + }) + .catch(() => setContracts([])); + }, []); + + // Determinar el contrato a mostrar/editar cuando cambian los contratos o el id + useEffect(() => { + let contractIdValue; + if (!id || isNaN(Number(id))) { + contractIdValue = contracts.length > 0 ? contracts.length + 1 : 1; + } else { + contractIdValue = Number(id); + } + setContractId(contractIdValue); + // Buscar el contrato por índice (ya que no hay id_contract en la API) + const contrato = contracts.find(c => c.id_contract === contractIdValue) || { + id_contract: contractIdValue, + name_employee: "", + position_employee: "", + area_employee: "", + contract_start: "", + contract_end: "", + status_contract: "" + }; + // Si el contrato tiene área, asegúrate de que el campo esté presente y no sea null/undefined + setFormData({ + ...contrato + }); + }, [contracts, id]); + // Estados para áreas y posiciones consultadas + const [areas, setAreas] = useState([]); + const [positions, setPositions] = useState([]); + + // Consultar áreas y posiciones al montar el componente + useEffect(() => { + // Consulta de áreas + axios.get(import.meta.env.VITE_API_BASE_URL + '/contracts') + .then(res => { + if (Array.isArray(res.data?.data) && res.data.data.length > 0) { + setAreas(res.data.data.map(a => a.name_area)); + } else { + // Si la consulta de áreas está vacía, usar los valores únicos de area_employee de los contratos + const uniqueAreas = Array.from(new Set(contracts.map(c => c.area_employee).filter(Boolean))); + setAreas(uniqueAreas); + } + }) + .catch(() => { + // Si falla la consulta, usar los valores únicos de area_employee de los contratos + const uniqueAreas = Array.from(new Set(contracts.map(c => c.area_employee).filter(Boolean))); + setAreas(uniqueAreas); + }); + // Consulta de posiciones + axios.get(import.meta.env.VITE_API_BASE_URL + '/contracts/positions') + .then(res => { + if (Array.isArray(res.data?.data)) { + setPositions(res.data.data.map(p => p.name_position)); + } + }) + .catch(() => setPositions([])); + }, [contracts]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + }; + + // ...existing code... + + return ( +
    +

    Insert/Update Contract

    +
    +
    ID #{contractId}
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    +); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/NewEmployee.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/NewEmployee.jsx new file mode 100644 index 0000000..ef7c6fb --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/NewEmployee.jsx @@ -0,0 +1,260 @@ +import React, { useEffect, useState, useContext } from 'react'; +import '../../components/Filters/Filters.css'; +import { useParams } from 'react-router-dom'; +import axios from 'axios'; +import { langContext } from '../../context/LenguageContext'; + +export default function NewEmployee(){ + const { lang } = useContext(langContext); + const { id: paramId } = useParams(); + + const isEditMode = !!paramId; + const nssParam = paramId; + + const [formState, setFormState] = useState({ + name_emp: "", + rfc_emp: "", + nss_emp: "", + addres_emp: "", + phone_emp: "", + email_emp: "", + birthday_emp: "", + curp_emp: "" + }); + + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [fetchingEmployee, setFetchingEmployee] = useState(false); + + useEffect(() => { + if (!isEditMode) { + setFormState({ + name_emp: "", + rfc_emp: "", + nss_emp: "", + addres_emp: "", + phone_emp: "", + email_emp: "", + birthday_emp: "", + curp_emp: "" + }); + setError(null); + } + }, [isEditMode]); + + useEffect(() => { + if (isEditMode && nssParam) { + setFetchingEmployee(true); + setError(null); + + axios.get(`${import.meta.env.VITE_API_BASE_URL}/employees?limit=1000&page=1`) + .then((res) => { + const employees = res.data?.data || []; + const employee = employees.find(emp => String(emp.nss_employe) === String(nssParam)); + + if (employee && employee.employee_rfc) { + return axios.post(`${import.meta.env.VITE_API_BASE_URL}/employees/employee`, { + rfcEmployee: employee.employee_rfc + }); + } else { + throw new Error("Employee not found or missing RFC"); + } + }) + .then((res) => { + const employeeData = res.data?.data; + + if (employeeData && Array.isArray(employeeData) && employeeData.length > 0) { + const emp = employeeData[0]; + + let formattedBirthday = ''; + if (emp.birthday) { + const date = new Date(emp.birthday); + if (!isNaN(date.getTime())) { + formattedBirthday = date.toISOString().split('T')[0]; + } + } + + const newFormState = { + name_emp: String(emp.name_emp || ""), + rfc_emp: String(emp.rfc_emp || ""), + nss_emp: String(emp.nss_emp || ""), + addres_emp: String(emp.addres_emp || ""), + phone_emp: String(emp.phone_emp || ""), + email_emp: String(emp.email_emp || ""), + birthday_emp: String(formattedBirthday || ""), + curp_emp: String(emp.curp || "") + }; + setFormState(newFormState); + } else if (employeeData === 0 || !employeeData) { + setError(lang === "es" ? "Empleado no encontrado" : "Employee not found"); + } + }) + .catch((err) => { + console.error("Error fetching employee:", err); + setError(lang === "es" ? "Error al cargar el empleado" : "Error loading employee"); + }) + .finally(() => { + setFetchingEmployee(false); + }); + } + }, [isEditMode, nssParam, lang]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormState((prev) => ({ ...prev, [name]: value })); + }; + + const handleSave = () => { + setLoading(true); + setError(null); + + const payload = { + ...formState + }; + + const endpoint = isEditMode + ? `${import.meta.env.VITE_API_BASE_URL}/employees/updateemployee` + : `${import.meta.env.VITE_API_BASE_URL}/employees/newemployee`; + + axios.post(endpoint, payload) + .then(() => { + const successMsg = isEditMode + ? (lang === "es" ? "Empleado actualizado correctamente" : "Employee updated successfully") + : (lang === "es" ? "Empleado guardado con éxito" : "Employee saved successfully"); + alert(successMsg); + }) + .catch((err) => { + console.error(err); + const errorMsg = isEditMode + ? (lang === "es" ? "Error al actualizar el empleado" : "Error updating employee") + : (lang === "es" ? "Error al guardar el empleado" : "Error saving employee"); + alert(errorMsg); + }) + .finally(() => { + setLoading(false); + }); + }; + if (fetchingEmployee) { + return ( +
    +
    {lang === "es" ? "Cargando empleado..." : "Loading employee..."}
    +
    + ); + } + + return ( +
    +

    {isEditMode ? (lang === "es" ? "Editar empleado" : "Edit Employee") : (lang === "es" ? "Insertar empleado" : "Insert Employee")}

    + {error && ( +
    + {error} +
    + )} +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + +
    +
    +
    + ); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/Payroll.css b/frontend/Frontend-Hotel/src/pages/Payroll/Payroll.css new file mode 100644 index 0000000..085df1d --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/Payroll.css @@ -0,0 +1,103 @@ +.payroll-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.payroll-page .filters-section .filter-search { + flex: 1; + max-width: 280px; + min-width: 180px; +} + +.payroll-page .filters-section .date-input-group { + display: flex; + flex-direction: row; + align-items: center; + gap: 8px; + min-width: 180px; +} + +.payroll-page .filters-section .date-label { + font-size: 12px; + font-weight: 600; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + white-space: nowrap; + flex-shrink: 0; +} + +.payroll-page .filters-section .date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.payroll-page .filters-section .date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.payroll-page .filters-section .date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.payroll-page .filters-section .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +.payroll-page .filters-section .clear-filters-btn { + flex-shrink: 0; +} + +@media (max-width: 768px) { + .payroll-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .payroll-page .filters-section .filter-search { + min-width: 100%; + max-width: 100%; + order: -1; + } + + .payroll-page .filters-section .date-input-group { + min-width: auto; + width: 100%; + flex-direction: column; + gap: 4px; + } + + .payroll-page .filters-section .filter-select { + min-width: 100%; + } + + .payroll-page .filters-section .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/Payroll.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/Payroll.jsx new file mode 100644 index 0000000..74e0c7e --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/Payroll.jsx @@ -0,0 +1,291 @@ +import React, { useEffect, useState, useContext } from "react"; +import "../../components/Filters/Filters.css"; +import "./Payroll.css"; +import Table from "../../components/Table/HotelTable copy"; +import { Link } from "react-router-dom"; +import { langContext } from "../../context/LenguageContext"; +import ExcelExportButton from "../../components/ExcelExportButton"; +// import axios from 'axios'; + +export default function Payroll() { + const { lang } = useContext(langContext); + const [income, setIncome] = useState({ data: [] }); + const [dateRange, setDateRange] = useState({ from: "", to: "" }); + const [positionFilter, setPositionFilter] = useState(""); + const [areaFilter, setAreaFilter] = useState(""); + const [searchName, setSearchName] = useState(""); + // eslint-disable-next-line no-unused-vars + const [activeEmployees, setActiveEmployees] = useState({ data: 0 }); + const [filteredContracts, setFilteredContracts] = useState([]); + + useEffect(() => { + fetch(import.meta.env.VITE_API_BASE_URL + "/contracts/disabledcontract") + .then((res) => { + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + return res.json(); + }) + .catch((err) => { + console.warn('Failed to fetch disabled contracts:', err.message); + }); + + // Obtener el número de empleados activos desde la API + fetch(import.meta.env.VITE_API_BASE_URL + "/employees/activeEmployees") + .then((res) => res.json()) + .then((data) => { + setActiveEmployees(data); + }) + .catch(() => setActiveEmployees({ data: 0 })); + // Obtener los contratos desde la API + fetch(import.meta.env.VITE_API_BASE_URL + "/contracts") + .then((res) => res.json()) + .then((data) => { + // Si la respuesta tiene la propiedad data como array + if (Array.isArray(data.data)) { + setIncome(data); + setFilteredContracts(data.data); + } else { + setIncome({ data: [] }); + setFilteredContracts([]); + } + }) + .catch(() => { + setIncome({ data: [] }); + setFilteredContracts([]); + }); + }, []); + + useEffect(() => { + let filtered = [...income.data]; + + filtered = filtered.filter((contract) => + contract.status_contract === 'Active' || + contract.status_contract === 'Activo' || + contract.status_contract === true + ); + + if (dateRange.from && dateRange.to) { + filtered = filtered.filter((contract) => { + const endDate = contract.contract_end?.slice(0, 10); + + if (!endDate) return false; + + // Compare date strings directly to avoid timezone issues + return endDate >= dateRange.from && endDate <= dateRange.to; + }); + } + + if (positionFilter) { + filtered = filtered.filter( + (contract) => contract.position_employee === positionFilter + ); + } + + if (areaFilter) { + filtered = filtered.filter( + (contract) => contract.area_employee === areaFilter + ); + } + + if (searchName) { + filtered = filtered.filter((contract) => + contract.name_employee?.toLowerCase().includes(searchName.toLowerCase()) + ); + } + + setFilteredContracts(filtered); + }, [dateRange, positionFilter, areaFilter, searchName, income]); + + const uniquePositions = [ + ...new Set( + income.data.map((contract) => contract.position_employee).filter(Boolean) + ), + ].sort(); + const uniqueAreas = [ + ...new Set( + income.data.map((contract) => contract.area_employee).filter(Boolean) + ), + ].sort(); + + const formatDate = (dateStr) => { + if (!dateStr) return ""; + + const dateOnly = dateStr.slice(0, 10); + const [year, month, day] = dateOnly.split("-"); + return `${day}/${month}/${year}`; + }; + + const clearFilters = () => { + setDateRange({ from: "", to: "" }); + setPositionFilter(""); + setAreaFilter(""); + setSearchName(""); + }; + + const exportColumns = [ + { header: lang === "es" ? "NOMBRE" : "NAME", key: "name_employee" }, + { + header: lang === "es" ? "POSICIÓN" : "POSITION", + key: "position_employee", + }, + { header: lang === "es" ? "ÁREA" : "AREA", key: "area_employee" }, + { + header: lang === "es" ? "FIN DE CONTRATO" : "END OF CONTRACT", + key: "contract_end", + }, + { header: lang === "es" ? "ESTADO" : "STATUS", key: "status_contract" }, + ]; + + const transformDataForExport = (data) => { + return data.map((contract) => ({ + ...contract, + contract_end: formatDate(contract.contract_end), + })); + }; + + const columns = [ + { + header: lang === "es" ? "NOMBRE" : "NAME", + key: "name_employee", + render: (value, row) => ( + + {value} + + ), + }, + { + header: lang === "es" ? "POSICIÓN" : "POSITION", + key: "position_employee", + }, + { header: lang === "es" ? "ÁREA" : "AREA", key: "area_employee" }, + { + header: lang === "es" ? "FIN DE CONTRATO" : "END OF CONTRACT", + key: "contract_end", + render: (value) => formatDate(value), + }, + { header: lang === "es" ? "ESTADO" : "STATUS", key: "status_contract" }, + ]; + + return ( +
    +
    +

    {lang === "es" ? "Informe" : "Report"}

    +
    + +
    + setSearchName(e.target.value)} + className="filter-search" + /> + +
    + + + setDateRange({ ...dateRange, from: e.target.value }) + } + className="date-input" + /> +
    + +
    + + setDateRange({ ...dateRange, to: e.target.value })} + className="date-input" + /> +
    + + + + + + +
    + +
    +
    +
    + + {lang === "es" + ? "Contratos por vencer" + : "Contracts due to expire"} + +
    {filteredContracts.length}
    +
    + {/*} +
    + Active employees +
    {Array.isArray(activeEmployees.data) ? activeEmployees.data.filter(e => e.status === 'Active').length : 0}
    +
    + */} +
    + +
    + +
    +
    + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/PayrollAttendance.css b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollAttendance.css new file mode 100644 index 0000000..48c1925 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollAttendance.css @@ -0,0 +1,126 @@ +.payroll-attendance-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + gap: 12px; + align-items: stretch; +} + +.payroll-attendance-page .filters-row { + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.payroll-attendance-page .filters-row.second-row { + justify-content: flex-end; + align-items: flex-start; +} + +.payroll-attendance-page .filters-row.second-row .filter-search { + flex: 0 0 auto; + min-width: 160px; + max-width: 200px; +} + +.payroll-attendance-page .filters-row.second-row .clear-filters-btn { + flex-shrink: 0; + margin-left: 8px; +} + +.payroll-attendance-page .filters-section .date-input-group { + display: flex; + flex-direction: row; + align-items: center; + gap: 8px; + min-width: 180px; +} + +.payroll-attendance-page .filters-section .date-label { + font-size: 12px; + font-weight: 600; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + white-space: nowrap; + flex-shrink: 0; +} + +.payroll-attendance-page .filters-section .date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.payroll-attendance-page .filters-section .date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.payroll-attendance-page .filters-section .date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.payroll-attendance-page .filters-section .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +@media (max-width: 768px) { + .payroll-attendance-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .payroll-attendance-page .filters-row { + flex-direction: column; + gap: 10px; + } + + .payroll-attendance-page .filters-row.second-row { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .payroll-attendance-page .filters-section .date-input-group { + min-width: auto; + width: 100%; + flex-direction: column; + gap: 4px; + } + + .payroll-attendance-page .filters-section .filter-select { + min-width: 100%; + } + + .payroll-attendance-page .filters-row.second-row .filter-search { + min-width: 100%; + max-width: 100%; + } + + .payroll-attendance-page .filters-row.second-row .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/PayrollAttendance.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollAttendance.jsx new file mode 100644 index 0000000..4dde861 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollAttendance.jsx @@ -0,0 +1,446 @@ +import React, { useEffect, useState, useContext } from 'react'; +import '../../components/Filters/Filters.css'; +import './PayrollAttendance.css'; +import Table from '../../components/Table/HotelTable'; +import { langContext } from '../../context/LenguageContext'; +import ExcelExportButton from '../../components/ExcelExportButton'; + +export default function PayrollEmployees(){ + const {lang} = useContext(langContext); + const [attendanceData, setAttendanceData] = useState([]); + const [filteredRooms, setFilteredRooms] = useState([]); + const [nameFilter, setNameFilter] = useState(''); + const [idFilter, setIdFilter] = useState(''); + const [positionFilter, setPositionFilter] = useState(''); + const [dayFilter, setDayFilter] = useState(''); + const [startDateFilter, setStartDateFilter] = useState(''); + const [endDateFilter, setEndDateFilter] = useState(''); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(50); + + useEffect(() => { + async function fetchAttendance() { + try { + setLoading(true); + const response = await fetch(import.meta.env.VITE_API_BASE_URL + '/employees/getattendance'); + + if (!response.ok) { + throw new Error('Failed to fetch attendance data'); + } + + const result = await response.json(); + + const dataArray = Array.isArray(result) ? result : (result.data || []); + + const mappedData = dataArray.map(item => ({ + name: item.aname_emp || '', + lastname: item.alast_name || '', + id: item.aid_attendance || '', + position: item.arol || '', + date: item.adate_atten ? formatApiDate(item.adate_atten) : '', + day: item.alaboral_day || '', + checkintime: item.atime_atten || '', + checkouttime: item.atime_out || '--', + observations: item.aobservations || '--', + })); + + setAttendanceData(mappedData); + setFilteredRooms(mappedData); + } catch (err) { + console.error('Error fetching attendance:', err); + setError(err.message); + setAttendanceData([]); + setFilteredRooms([]); + } finally { + setLoading(false); + } + } + + fetchAttendance(); + }, []); + + const formatApiDate = (isoDate) => { + const date = new Date(isoDate); + const day = String(date.getDate()).padStart(2, '0'); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const year = date.getFullYear(); + return `${day}/${month}/${year}`; + }; + + useEffect(() => { + let filtered = [...attendanceData]; + + if (nameFilter) { + filtered = filtered.filter(room => + room.name?.toLowerCase().includes(nameFilter.toLowerCase()) || + room.lastname?.toLowerCase().includes(nameFilter.toLowerCase()) + ); + } + + if (idFilter) { + filtered = filtered.filter(room => + room.id?.toString().includes(idFilter) + ); + } + + if (positionFilter) { + filtered = filtered.filter(room => + room.position === positionFilter + ); + } + + if (dayFilter) { + filtered = filtered.filter(room => + room.day === dayFilter + ); + } + + if (startDateFilter || endDateFilter) { + filtered = filtered.filter(room => { + const roomDateParts = room.date?.split('/'); + if (!roomDateParts || roomDateParts.length !== 3) return false; + + const roomDate = new Date(roomDateParts[2], roomDateParts[1] - 1, roomDateParts[0]); + + const startDate = startDateFilter ? new Date(startDateFilter) : null; + const endDate = endDateFilter ? new Date(endDateFilter) : null; + + if (startDate && endDate) { + return roomDate >= startDate && roomDate <= endDate; + } else if (startDate) { + return roomDate >= startDate; + } else if (endDate) { + return roomDate <= endDate; + } + + return true; + }); + } + + setFilteredRooms(filtered); + setCurrentPage(1); + }, [nameFilter, idFilter, positionFilter, dayFilter, startDateFilter, endDateFilter, attendanceData]); + + const totalItems = filteredRooms.length; + const totalPages = Math.ceil(totalItems / itemsPerPage); + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + const currentPageData = filteredRooms.slice(startIndex, endIndex); + + const goToPage = (page) => { + if (page >= 1 && page <= totalPages) { + setCurrentPage(page); + } + }; + + const goToFirstPage = () => setCurrentPage(1); + const goToLastPage = () => setCurrentPage(totalPages); + const goToPreviousPage = () => goToPage(currentPage - 1); + const goToNextPage = () => goToPage(currentPage + 1); + + const getPageNumbers = () => { + const pages = []; + const maxPagesToShow = 5; + + if (totalPages <= maxPagesToShow) { + for (let i = 1; i <= totalPages; i++) { + pages.push(i); + } + } else { + if (currentPage <= 3) { + pages.push(1, 2, 3, 4, '...', totalPages); + } else if (currentPage >= totalPages - 2) { + pages.push(1, '...', totalPages - 3, totalPages - 2, totalPages - 1, totalPages); + } else { + pages.push(1, '...', currentPage - 1, currentPage, currentPage + 1, '...', totalPages); + } + } + + return pages; + }; + + const columns = [ + { header: lang === 'es' ? 'ID' : 'ID', key: 'id'}, + { header: lang === 'es' ? 'NOMBRE' : 'NAME', key: 'name'}, + { header: lang === 'es' ? 'APELLIDO' : 'LAST NAME', key: 'lastname'}, + { header: lang === 'es' ? 'POSICIÓN' : 'POSITION', key: 'position' }, + { header: lang === 'es' ? 'FECHA' : 'DATE', key: 'date' }, + { header: lang === 'es' ? 'DÍA' : 'DAY', key: 'day' }, + { header: lang === 'es' ? 'HORA DE ENTRADA' : 'CHECK-IN TIME', key: 'checkintime' }, +]; + + const uniquePositions = [...new Set(attendanceData.map(room => room.position).filter(Boolean))].sort(); + const uniqueDays = [...new Set(attendanceData.map(room => room.day).filter(Boolean))].sort(); + + const clearFilters = () => { + setNameFilter(''); + setIdFilter(''); + setPositionFilter(''); + setDayFilter(''); + setStartDateFilter(''); + setEndDateFilter(''); + }; + + const exportColumns = [ + { header: lang === "es" ? "NOMBRE" : "NAME", key: 'name' }, + { header: lang === "es" ? "APELLIDO" : "LAST NAME", key: 'lastname' }, + { header: lang === "es" ? "ID" : "ID", key: 'id' }, + { header: lang === "es" ? "POSICIÓN" : "POSITION", key: 'position' }, + { header: lang === "es" ? "FECHA" : "DATE", key: 'date' }, + { header: lang === "es" ? "DÍA" : "DAY", key: 'day' }, + { header: lang === "es" ? "HORA DE ENTRADA" : "CHECK-IN TIME", key: 'checkintime' }, + { header: lang === "es" ? "HORA DE SALIDA" : "CHECK-OUT TIME", key: 'checkouttime' }, + ]; + + return ( +
    +
    +

    {lang === 'es' ? 'Asistencia' : 'Attendance'}

    +
    + + {loading && ( +
    + {lang === 'es' ? 'Cargando datos de asistencia...' : 'Loading attendance data...'} +
    + )} + + {error && ( +
    + {lang === 'es' ? 'Error al cargar los datos: ' : 'Error loading data: '}{error} +
    + )} + + {!loading && !error && ( + <> +
    +
    +
    + + setStartDateFilter(e.target.value)} + className="date-input" + /> +
    + +
    + + setEndDateFilter(e.target.value)} + className="date-input" + /> +
    + + + + +
    + +
    + setNameFilter(e.target.value)} + className="filter-search" + /> + + setIdFilter(e.target.value)} + className="filter-search" + /> + + +
    +
    + +
    + +
    + +
    +
    + + + {totalPages > 1 && ( +
    +
    + + + + {lang === 'es' + ? `Mostrando ${startIndex + 1} a ${Math.min(endIndex, totalItems)} de ${totalItems} registros` + : `Showing ${startIndex + 1} to ${Math.min(endIndex, totalItems)} of ${totalItems} records` + } + +
    + +
    + + + + + {getPageNumbers().map((page, index) => ( + page === '...' ? ( + ... + ) : ( + + ) + ))} + + + + +
    +
    + )} + + )} + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/PayrollContract.css b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollContract.css new file mode 100644 index 0000000..ff3c167 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollContract.css @@ -0,0 +1,91 @@ +.payroll-contract-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.payroll-contract-page .filters-section .date-input-group { + display: flex; + flex-direction: row; + align-items: center; + gap: 8px; + min-width: 180px; +} + +.payroll-contract-page .filters-section .date-label { + font-size: 12px; + font-weight: 600; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + white-space: nowrap; + flex-shrink: 0; +} + +.payroll-contract-page .filters-section .date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.payroll-contract-page .filters-section .date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.payroll-contract-page .filters-section .date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.payroll-contract-page .filters-section .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +.payroll-contract-page .filters-section .clear-filters-btn { + flex-shrink: 0; +} + +@media (max-width: 768px) { + .payroll-contract-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .payroll-contract-page .filters-section .date-input-group { + min-width: auto; + width: 100%; + flex-direction: column; + gap: 4px; + } + + .payroll-contract-page .filters-section .filter-select { + min-width: 100%; + } + + .payroll-contract-page .filters-section .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/PayrollContract.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollContract.jsx new file mode 100644 index 0000000..ccc8531 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollContract.jsx @@ -0,0 +1,229 @@ +import React, { useEffect, useState, useContext } from 'react'; +import '../../components/Filters/Filters.css'; +import './PayrollContract.css'; +import Table from '../../components/Table/HotelTable'; +import ExcelExportButton from '../../components/ExcelExportButton'; +import { Link } from 'react-router-dom'; +import { langContext } from '../../context/LenguageContext'; + +export default function PayrollContract(){ + const { lang } = useContext(langContext); + + const [contracts, setContracts] = useState([]); + const [filteredContracts, setFilteredContracts] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const [areaFilter, setAreaFilter] = useState('All'); + const [statusFilter, setStatusFilter] = useState('All'); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + + useEffect(() => { + setLoading(true); + fetch(import.meta.env.VITE_API_BASE_URL + "/contracts") + .then((res) => { + if (!res.ok) throw new Error('Failed to fetch contracts'); + return res.json(); + }) + .then((data) => { + if (Array.isArray(data.data)) { + setContracts(data.data); + setFilteredContracts(data.data); + } else { + setContracts([]); + setFilteredContracts([]); + } + setError(null); + }) + .catch((err) => { + console.error("Error fetching contracts:", err); + setError(err.message); + setContracts([]); + setFilteredContracts([]); + }) + .finally(() => { + setLoading(false); + }); + }, []); + + useEffect(() => { + let filtered = [...contracts]; + + if (areaFilter && areaFilter !== 'All') { + filtered = filtered.filter( + (contract) => contract.area_employee === areaFilter + ); + } + + if (statusFilter && statusFilter !== 'All') { + filtered = filtered.filter( + (contract) => contract.status_contract === statusFilter + ); + } + + if (dateRange.from && dateRange.to) { + filtered = filtered.filter((contract) => { + const endDate = contract.contract_end?.slice(0, 10); + if (!endDate) return false; + return endDate >= dateRange.from && endDate <= dateRange.to; + }); + } + + setFilteredContracts(filtered); + }, [areaFilter, statusFilter, dateRange, contracts]); + + const uniqueAreas = [ + ...new Set( + contracts.map((contract) => contract.area_employee).filter(Boolean) + ), + ].sort(); + + const uniqueStatuses = [ + ...new Set( + contracts.map((contract) => contract.status_contract).filter(Boolean) + ), + ].sort(); + + const clearFilters = () => { + setAreaFilter('All'); + setStatusFilter('All'); + setDateRange({ from: '', to: '' }); + }; + + const formatDate = (dateStr) => { + if (!dateStr) return '-'; + const dateOnly = dateStr.slice(0, 10); + const [year, month, day] = dateOnly.split("-"); + return `${day}/${month}/${year}`; + }; + + const columns = [ + { + header: lang === "en" ? 'ID' : 'ID', + key: 'id_contract', + render: (value, row) => ( + + {row.id_contract} + + ), + }, + { header: lang === "en" ? 'NAME' : 'NOMBRE', key: 'name_employee' }, + { header: lang === "en" ? 'POSITION' : 'POSICIÓN', key: 'position_employee' }, + { header: lang === "en" ? 'AREA' : 'ÁREA', key: 'area_employee' }, + { + header: lang === "en" ? 'START OF CONTRACT' : 'INICIO DE CONTRATO', + key: 'contract_start', + render: (value) => formatDate(value) + }, + { + header: lang === "en" ? 'END OF CONTRACT' : 'FIN DE CONTRATO', + key: 'contract_end', + render: (value) => formatDate(value) + }, + { header: lang === "en" ? 'STATUS' : 'ESTADO', key: 'status_contract' }, +]; + + const exportColumns = [ + { header: lang === "es" ? "ID" : "ID", key: "id_contract" }, + { header: lang === "es" ? "NOMBRE" : "NAME", key: "name_employee" }, + { header: lang === "es" ? "POSICIÓN" : "POSITION", key: "position_employee" }, + { header: lang === "es" ? "ÁREA" : "AREA", key: "area_employee" }, + { header: lang === "es" ? "INICIO DE CONTRATO" : "START OF CONTRACT", key: "contract_start" }, + { header: lang === "es" ? "FIN DE CONTRATO" : "END OF CONTRACT", key: "contract_end" }, + { header: lang === "es" ? "ESTADO" : "STATUS", key: "status_contract" }, + ]; + + const dataTransform = (data) => { + return data.map((row) => ({ + ...row, + contract_start: formatDate(row.contract_start), + contract_end: formatDate(row.contract_end), + })); + }; + + return ( +
    +
    +

    + {lang === "en" ? "Contracts" : "Contratos"} +

    +
    + + {loading &&

    {lang === "en" ? "Loading..." : "Cargando..."}

    } + {error &&

    {lang === "en" ? `Error: ${error}` : `Error: ${error}`}

    } + + {!loading && !error && ( + <> +
    +
    + + setDateRange({ ...dateRange, from: e.target.value })} + /> +
    + +
    + + setDateRange({ ...dateRange, to: e.target.value })} + /> +
    + + + + + + +
    + +
    + +
    + +
    +
    + + + )} + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/PayrollEmployees.css b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollEmployees.css new file mode 100644 index 0000000..0596b09 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollEmployees.css @@ -0,0 +1,126 @@ +.payroll-employees-page .filters-section { + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + border-radius: 16px; + padding: 20px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + gap: 12px; + align-items: stretch; +} + +.payroll-employees-page .filters-row { + display: flex; + gap: 12px; + align-items: flex-end; + flex-wrap: wrap; + justify-content: flex-end; +} + +.payroll-employees-page .filters-row.second-row { + justify-content: flex-end; + align-items: flex-start; +} + +.payroll-employees-page .filters-row.second-row .filter-search { + flex: 0 0 auto; + min-width: 160px; + max-width: 200px; +} + +.payroll-employees-page .filters-row.second-row .clear-filters-btn { + flex-shrink: 0; + margin-left: 8px; +} + +.payroll-employees-page .filters-section .date-input-group { + display: flex; + flex-direction: row; + align-items: center; + gap: 8px; + min-width: 180px; +} + +.payroll-employees-page .filters-section .date-label { + font-size: 12px; + font-weight: 600; + color: #666; + text-transform: uppercase; + letter-spacing: 0.5px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + white-space: nowrap; + flex-shrink: 0; +} + +.payroll-employees-page .filters-section .date-input { + padding: 10px 16px; + border: none; + border-radius: 30px; + background-color: white; + box-shadow: 0 0 0 2px #f4f4f4; + font-size: 14px; + color: #333; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + height: 42px; + box-sizing: border-box; +} + +.payroll-employees-page .filters-section .date-input:focus { + outline: none; + box-shadow: 0 0 0 2px #fcd200; +} + +.payroll-employees-page .filters-section .date-input:hover { + box-shadow: 0 0 0 2px #e6e6e6; +} + +.payroll-employees-page .filters-section .filter-select { + flex: 0 0 auto; + min-width: 160px; +} + +@media (max-width: 768px) { + .payroll-employees-page .filters-section { + padding: 12px; + border-radius: 12px; + gap: 10px; + } + + .payroll-employees-page .filters-row { + flex-direction: column; + gap: 10px; + } + + .payroll-employees-page .filters-row.second-row { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .payroll-employees-page .filters-section .date-input-group { + min-width: auto; + width: 100%; + flex-direction: column; + gap: 4px; + } + + .payroll-employees-page .filters-section .filter-select { + min-width: 100%; + } + + .payroll-employees-page .filters-row.second-row .filter-search { + min-width: 100%; + max-width: 100%; + } + + .payroll-employees-page .filters-row.second-row .clear-filters-btn { + width: 100%; + align-self: stretch; + margin-top: 8px; + } +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/PayrollEmployees.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollEmployees.jsx new file mode 100644 index 0000000..9980aa4 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/PayrollEmployees.jsx @@ -0,0 +1,299 @@ +import React, { useEffect, useState, useContext } from 'react'; +import axios from "axios"; +import '../../components/Filters/Filters.css'; +import './PayrollEmployees.css'; +import Table from '../../components/Table/HotelTable'; +import { Link } from 'react-router-dom'; +import { langContext } from '../../context/LenguageContext'; +import ExcelExportButton from '../../components/ExcelExportButton'; + +export default function PayrollEmployees() { + const { lang } = useContext(langContext); + + const [employees, setEmployees] = useState([]); + const [filteredEmployees, setFilteredEmployees] = useState([]); + const [loading, setLoading] = useState(true); + const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [areaFilter, setAreaFilter] = useState('All'); + const [statusFilter, setStatusFilter] = useState('All'); + const [positionFilter, setPositionFilter] = useState('All'); + const [nameSearch, setNameSearch] = useState(''); + const [nssSearch, setNssSearch] = useState(''); + + const areas = ['Hotel', 'Restaurant', 'Maintenance']; + const statuses = ['Active', 'Inactive']; + + const uniquePositions = [...new Set(employees.map(emp => emp.position_employee).filter(Boolean))].sort(); + + const clearFilters = () => { + setDateRange({ from: '', to: '' }); + setAreaFilter('All'); + setStatusFilter('All'); + setPositionFilter('All'); + setNameSearch(''); + setNssSearch(''); + }; + + + + useEffect(() => { + axios + .get(`${import.meta.env.VITE_API_BASE_URL}/employees`) + .then((res) => { + const fixedData = res.data.data.map(emp => { + // Only apply the "026" fix if the date is not in ISO format + if (emp.end_contract && typeof emp.end_contract === 'string' && + !emp.end_contract.includes('T') && emp.end_contract.startsWith("026")) { + emp.end_contract = "20" + emp.end_contract; + } + return emp; + }); + + const groupedByRfc = fixedData.reduce((acc, emp) => { + const rfc = emp.employee_rfc; + if (!acc[rfc]) { + acc[rfc] = []; + } + acc[rfc].push(emp); + return acc; + }, {}); + + const uniqueEmployees = Object.values(groupedByRfc).map(contracts => { + return contracts.sort((a, b) => { + const dateA = new Date(a.end_contract); + const dateB = new Date(b.end_contract); + if (isNaN(dateA.getTime()) && isNaN(dateB.getTime())) return 0; + if (isNaN(dateA.getTime())) return 1; + if (isNaN(dateB.getTime())) return -1; + return dateB - dateA; + })[0]; + }); + + setEmployees(uniqueEmployees); + setFilteredEmployees(uniqueEmployees); + }) + .catch((err) => console.error("Error al cargar empleados:", err)) + .finally(() => setLoading(false)); +}, []); + + + + const columns = [ + { + header: lang === 'es' ? 'NOMBRE' : 'NAME', + key: 'name_employee', + render: (text, row) => ( + + {row.name_employee} + + ), + }, + { header: 'NSS', key: 'nss_employe' }, + { header: lang === 'es' ? 'POSICIÓN' : 'POSITION', key: 'position_employee' }, + { header: lang === 'es' ? 'ÁREA' : 'AREA', key: 'area_employee' }, + { header: lang === 'es' ? 'TELÉFONO' : 'PHONE', key: 'phone_employee' }, + { + header: lang === 'es' ? 'FIN DE CONTRATO' : 'END OF CONTRACT', + key: 'end_contract', + render: (text, row) => { + if (!row.end_contract || row.end_contract === '' || row.end_contract === null) { + return '—'; + } + const date = new Date(row.end_contract); + return isNaN(date.getTime()) ? '—' : date.toLocaleDateString(lang === 'es' ? 'es-MX' : 'en-US'); + } +} +, + { header: lang === 'es' ? 'PAGO DIARIO' : 'DAILY PAY', key: 'daily_pay' }, + { header: lang === 'es' ? 'UNIFORMES' : 'UNIFORMS', key: 'uniforms' }, + { header: lang === 'es' ? 'ESTATUS' : 'STATUS', key: 'status' }, + ]; + + + useEffect(() => { + let filtered = [...employees]; + + if (areaFilter !== 'All') { + filtered = filtered.filter(emp => emp.area_employee === areaFilter); + } + + if (statusFilter !== 'All') { + filtered = filtered.filter(emp => emp.status === statusFilter); + } + + if (positionFilter !== 'All') { + filtered = filtered.filter(emp => emp.position_employee === positionFilter); + } + + if (nameSearch) { + filtered = filtered.filter(emp => + emp.name_employee?.toLowerCase().includes(nameSearch.toLowerCase()) + ); + } + + if (nssSearch) { + filtered = filtered.filter(emp => + emp.nss_employe?.toString().includes(nssSearch) + ); + } + + if (dateRange.from && dateRange.to) { + filtered = filtered.filter((emp) => { + const end = new Date(emp.end_contract); + return end >= new Date(dateRange.from) && end <= new Date(dateRange.to); + }); + } + + setFilteredEmployees(filtered); + }, [dateRange, areaFilter, statusFilter, positionFilter, nameSearch, nssSearch, employees]); + + const exportColumns = [ + { header: lang === 'es' ? 'NOMBRE' : 'NAME', key: 'name_employee' }, + { header: 'NSS', key: 'nss_employe' }, + { header: lang === 'es' ? 'POSICIÓN' : 'POSITION', key: 'position_employee' }, + { header: lang === 'es' ? 'ÁREA' : 'AREA', key: 'area_employee' }, + { header: lang === 'es' ? 'TELÉFONO' : 'PHONE', key: 'phone_employee' }, + { + header: lang === 'es' ? 'FIN DE CONTRATO' : 'END OF CONTRACT', + key: 'end_contract' + }, + { header: lang === 'es' ? 'PAGO DIARIO' : 'DAILY PAY', key: 'daily_pay' }, + { header: lang === 'es' ? 'UNIFORMES' : 'UNIFORMS', key: 'uniforms' }, + { header: lang === 'es' ? 'ESTATUS' : 'STATUS', key: 'status' }, + ]; + + const transformDataForExport = (data) => { + return data.map(emp => ({ + ...emp, + end_contract: (!emp.end_contract || emp.end_contract === '' || emp.end_contract === null) + ? '—' + : (() => { + const date = new Date(emp.end_contract); + return isNaN(date.getTime()) + ? '—' + : date.toLocaleDateString(lang === 'es' ? 'es-MX' : 'en-US'); + })() + })); + }; + + return ( +
    +
    +

    {lang === 'es' ? 'Empleados' : 'Employees'}

    +
    + +
    +
    +
    + + setDateRange({ ...dateRange, from: e.target.value })} + className="date-input" + /> +
    + +
    + + setDateRange({ ...dateRange, to: e.target.value })} + className="date-input" + /> +
    + + + + + + +
    + +
    + setNameSearch(e.target.value)} + className="filter-search" + /> + + setNssSearch(e.target.value)} + className="filter-search" + /> + + +
    +
    + +
    + +
    + + {loading ? ( +

    {lang === 'es' ? 'Cargando empleados...' : 'Loading employees...'}

    + ) : ( +
    +
    + + )} + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll copy.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll copy.jsx new file mode 100644 index 0000000..3604108 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll copy.jsx @@ -0,0 +1,160 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; +import '../../components/Filters/Filters.css'; +import Table from '../../components/Table/HotelTable'; +import { Link, useParams } from 'react-router-dom'; +import FormInput from '../../components/FormInput'; + +export default function Plantillapayroll(){ + const { id: paramId } = useParams(); + function generateRandomId() { + return Math.floor(1000 + Math.random() * 9000); // 4 dígitos + } + let id = paramId; + const [contracts, setContracts] = useState([]); + const [contractId, setContractId] = useState(null); + const [formData, setFormData] = useState(null); + + // Consultar contratos al montar el componente + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/reportcontracts') + .then(res => { + if (Array.isArray(res.data?.data)) { + setContracts(res.data.data); + } + }) + .catch(() => setContracts([])); + }, []); + + // Determinar el contrato a mostrar/editar cuando cambian los contratos o el id + useEffect(() => { + let contractIdValue; + if (!id || isNaN(Number(id))) { + contractIdValue = contracts.length > 0 ? contracts.length + 1 : 1; + } else { + contractIdValue = Number(id); + } + setContractId(contractIdValue); + // Buscar el contrato por índice (ya que no hay id_contract en la API) + const contrato = contracts.find(c => c.id_contract === contractIdValue) || { + id_contract: contractIdValue, + name_employee: "", + position_employee: "", + area_employee: "", + contract_start: "", + contract_end: "", + status_contract: "" + }; + // Si el contrato tiene área, asegúrate de que el campo esté presente y no sea null/undefined + setFormData({ + ...contrato + }); + }, [contracts, id]); + // Estados para áreas y posiciones consultadas + const [areas, setAreas] = useState([]); + const [positions, setPositions] = useState([]); + + // Consultar áreas y posiciones al montar el componente + useEffect(() => { + // Consulta de áreas + axios.get(import.meta.env.VITE_API_BASE_URL + '/contracts') + .then(res => { + if (Array.isArray(res.data?.data) && res.data.data.length > 0) { + setAreas(res.data.data.map(a => a.name_area)); + } else { + // Si la consulta de áreas está vacía, usar los valores únicos de area_employee de los contratos + const uniqueAreas = Array.from(new Set(contracts.map(c => c.area_employee).filter(Boolean))); + setAreas(uniqueAreas); + } + }) + .catch(() => { + // Si falla la consulta, usar los valores únicos de area_employee de los contratos + const uniqueAreas = Array.from(new Set(contracts.map(c => c.area_employee).filter(Boolean))); + setAreas(uniqueAreas); + }); + // Consulta de posiciones + axios.get(import.meta.env.VITE_API_BASE_URL + '/contracts/positions') + .then(res => { + if (Array.isArray(res.data?.data)) { + setPositions(res.data.data.map(p => p.name_position)); + } + }) + .catch(() => setPositions([])); + }, [contracts]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + }; + + // ...existing code... + + return ( +
    +

    Insert/Update Contract

    +
    +
    ID #{contractId}
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    +); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll.css b/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll.css new file mode 100644 index 0000000..57c5b5e --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll.css @@ -0,0 +1,177 @@ +.uniform-checkbox-list { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 8px; + margin-top: 8px; +} + +.checkbox-item { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + user-select: none; + padding: 6px 12px; + border-radius: 6px; + border: 1px solid #e0e0e0; + background-color: #fafafa; + transition: all 0.2s ease; + font-size: 14px; +} + +.checkbox-item:hover { + background-color: #f0f8ff; + border-color: #fcd200; +} + +.checkbox-item input[type="checkbox"] { + width: 16px; + height: 16px; + accent-color: #fcd200; + cursor: pointer; + margin: 0; +} + +.uniform-chips { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 12px; +} + +.chip { + background-color: #fcd200; + color: #333; + border-radius: 20px; + padding: 6px 12px; + display: flex; + align-items: center; + font-size: 13px; + font-weight: 500; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.chip:hover { + background-color: #f4b400; +} + +.remove-chip { + background: transparent; + border: none; + font-size: 18px; + margin-left: 8px; + cursor: pointer; + color: #333; + padding: 0; + line-height: 1; + transition: color 0.2s ease; +} + +.remove-chip:hover { + color: #d00; + transform: scale(1.1); +} + +.new-expense-container h2 { + color: #333; + font-size: 24px; + font-weight: bold; + text-align: center; +} + +.new-expense-container { + display: flex; + flex-direction: column; + width: 100%; + padding: 20px 0; + box-sizing: border-box; +} + +.form-card { + background-color: #fff; + border-radius: 10px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + box-sizing: border-box; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 20px; + margin-bottom: 24px; +} + +.form-grid label { + font-weight: 600; + font-size: 14px; + color: #333; + margin-bottom: 6px; + display: block; +} + +.form-grid input, +.form-grid select { + width: 100%; + padding: 10px 12px; + border: 2px solid #e0e0e0; + border-radius: 8px; + font-size: 14px; + background-color: #fff; + transition: all 0.2s ease; + box-sizing: border-box; +} + +.form-grid input:focus, +.form-grid select:focus { + outline: none; + border-color: #fcd200; + box-shadow: 0 0 0 3px rgba(252, 210, 0, 0.1); +} + +.form-grid input.readonly-input { + background-color: #f8f9fa; + cursor: not-allowed; + color: #6c757d; +} + +.uniform-section { + grid-column: 1 / -1; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 24px; + padding-top: 20px; + border-top: 1px solid #e0e0e0; +} + +.save-button { + background-color: #fcd200; + color: #333; + padding: 12px 24px; + font-weight: 600; + border: none; + border-radius: 8px; + font-size: 16px; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.save-button:hover { + background-color: #f4b400; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.save-button:active { + transform: translateY(0); +} + +.checkbox-item-content { + display: flex; + align-items: center; + gap: 8px; +} diff --git a/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll.jsx b/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll.jsx new file mode 100644 index 0000000..fc284d7 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Payroll/Plantillapayroll.jsx @@ -0,0 +1,414 @@ +import React, { useEffect, useState, useContext } from 'react'; +import '../../components/Filters/Filters.css'; +import { langContext } from '../../context/LenguageContext'; +import './Plantillapayroll.css'; +import { useParams } from 'react-router-dom'; + +export default function Plantillapayroll() { + const { lang } = useContext(langContext); + const { id } = useParams(); + + const isNumericId = id && !isNaN(Number(id)) && Number(id) > 0; + const contractId = isNumericId ? id : null; + + const [areas, setAreas] = useState([]); + const [positions, setPositions] = useState([]); + const [uniformsList, setUniformsList] = useState([]); + const [employees, setEmployees] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [formState, setFormState] = useState({ + rfc_emp: '', + selectedEmployee: '', + id_position_emp: '', + id_area_emp: '', + start_contract: '', + end_contract: '', + new_daily_pay: 600.0, + uniforms: [] + }); + + const formatDateForInput = (dateStr) => { + if (!dateStr) return ''; + if (dateStr.match(/^\d{4}-\d{2}-\d{2}$/)) return dateStr; + return dateStr.slice(0, 10); + }; + + useEffect(() => { + Promise.all([ + fetch(import.meta.env.VITE_API_BASE_URL + '/contracts/areas').then(res => res.json()), + fetch(import.meta.env.VITE_API_BASE_URL + '/contracts/positions').then(res => res.json()), + fetch(import.meta.env.VITE_API_BASE_URL + '/expenses/getinfo').then(res => res.json()), + fetch(import.meta.env.VITE_API_BASE_URL + '/employees').then(res => res.json()) + ]) + .then(([areasData, positionsData, getInfoData, activeEmployeesData]) => { + setAreas(areasData.data || []); + setPositions(positionsData.data || []); + setUniformsList(getInfoData.uniforms || []); + + const employeesData = activeEmployeesData.data || []; + const uniqueEmployees = employeesData.filter((emp, index, self) => + index === self.findIndex(e => + e.name_employee?.toLowerCase().trim() === emp.name_employee?.toLowerCase().trim() + ) + ); + setEmployees(uniqueEmployees); + }) + .catch(() => console.warn("Error cargando datos iniciales")); + }, []); + + useEffect(() => { + if (!isNumericId) { + setFormState({ + rfc_emp: '', + selectedEmployee: '', + id_position_emp: '', + id_area_emp: '', + start_contract: '', + end_contract: '', + new_daily_pay: 600.0, + uniforms: [] + }); + setError(null); + setLoading(false); + } + }, [isNumericId]); + + useEffect(() => { + if (!contractId || !areas.length || !positions.length || !employees.length || !uniformsList.length) { + return; + } + + const fetchContractInfo = async () => { + setLoading(true); + setError(null); + try { + const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/contracts/getinfocontract/${contractId}`); + const data = await response.json(); + + + if (!data.data || data.data.length === 0) { + setError(lang === 'es' ? 'Contrato no encontrado' : 'Contract not found'); + setLoading(false); + return; + } + + const contract = data.data[0]; + + const employeeMatch = employees.find( + (emp) => emp.name_employee?.toLowerCase().trim() === contract.name_employee?.toLowerCase().trim() + ); + + const employeeRfc = employeeMatch?.employee_rfc || employeeMatch?.rfc_emp || contract.rfc_emp || ''; + + const positionMatch = positions.find( + (p) => p.name_position?.toLowerCase().trim() === contract.position_employee?.toLowerCase().trim() + ); + + const areaMatch = areas.find( + (a) => a.name_area?.toLowerCase().trim() === contract.area_employee?.toLowerCase().trim() + ); + + let uniformIds = []; + if (contract.uniforms) { + if (Array.isArray(contract.uniforms)) { + uniformIds = contract.uniforms.map(u => { + if (typeof u === 'object' && u !== null) { + return String(u.id_uniform || u.id || u); + } + if (typeof u === 'string') { + const uniformMatch = uniformsList.find(uni => uni.name === u || uni.name_uniform === u); + return uniformMatch ? String(uniformMatch.id || uniformMatch.id_uniform) : ''; + } + return String(u); + }).filter(id => id); + } else if (typeof contract.uniforms === 'object') { + uniformIds = Object.values(contract.uniforms).map(u => { + if (typeof u === 'object' && u !== null) { + return String(u.id_uniform || u.id || u); + } + if (typeof u === 'string') { + const uniformMatch = uniformsList.find(uni => uni.name === u || uni.name_uniform === u); + return uniformMatch ? String(uniformMatch.id || uniformMatch.id_uniform) : ''; + } + return String(u); + }).filter(id => id); + } + } + + setFormState({ + rfc_emp: employeeRfc, + selectedEmployee: contract.name_employee || '', + id_position_emp: positionMatch?.id_position || '', + id_area_emp: areaMatch?.id_area || '', + start_contract: formatDateForInput(contract.contract_start), + end_contract: formatDateForInput(contract.contract_end), + new_daily_pay: contract.daily_pay || 600.0, + uniforms: uniformIds + }); + + setLoading(false); + } catch (err) { + console.error('Error fetching contract info:', err); + setError(lang === 'es' ? 'Error al cargar el contrato' : 'Error loading contract'); + setLoading(false); + } + }; + + fetchContractInfo(); + }, [contractId, areas, positions, employees, uniformsList, lang]); + + const handleEmployeeChange = (e) => { + const selectedName = e.target.value; + const selectedEmp = employees.find(emp => emp.name_employee === selectedName); + const employeeRfc = selectedEmp?.employee_rfc || selectedEmp?.rfc_emp || ''; + setFormState(prev => ({ + ...prev, + selectedEmployee: selectedName, + rfc_emp: employeeRfc + })); + }; + + const handleChange = (e) => { + const { name, value } = e.target; + setFormState(prev => ({ + ...prev, + [name]: value ?? '' + })); + }; + + const handleUniformToggle = (id) => { + setFormState(prev => { + const exists = prev.uniforms.includes(String(id)); + return { + ...prev, + uniforms: exists + ? prev.uniforms.filter(u => u !== String(id)) + : [...prev.uniforms, String(id)] + }; + }); + }; + + const removeUniform = (id) => { + setFormState(prev => ({ + ...prev, + uniforms: prev.uniforms.filter(u => String(u) !== String(id)) + })); + }; + + const handleSave = async () => { + const formatDate = (dateStr) => { + if (!dateStr) return ''; + const [year, month, day] = dateStr.split('-'); + return `${year}-${month}-${day}`; + }; + + const payload = { + rfc_emp: formState.rfc_emp, + id_position_emp: parseInt(formState.id_position_emp) || null, + id_area_emp: parseInt(formState.id_area_emp) || null, + start_contract: formatDate(formState.start_contract), + end_contract: formatDate(formState.end_contract), + new_daily_pay: parseFloat(formState.new_daily_pay) || 0, + uniforms: formState.uniforms.map(id => ({ id_uniform: parseInt(id) })) + }; + + if (contractId) { + payload.name_employee = formState.selectedEmployee; + } + + try { + const url = contractId + ? `${import.meta.env.VITE_API_BASE_URL}/contracts/updatecontract/${contractId}` + : `${import.meta.env.VITE_API_BASE_URL}/contracts/newcontract`; + + const method = contractId ? 'PUT' : 'POST'; + + const res = await fetch(url, { + method: method, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + + if (res.ok) { + const successMsg = contractId + ? (lang === 'es' ? 'Contrato actualizado correctamente' : 'Contract updated successfully') + : (lang === 'es' ? 'Contrato guardado correctamente' : 'Contract saved successfully'); + alert(successMsg); + } else { + const errorMsg = contractId + ? (lang === 'es' ? 'Error al actualizar el contrato' : 'Error updating contract') + : (lang === 'es' ? 'Error al guardar el contrato' : 'Error saving contract'); + alert(errorMsg); + } + } catch { + const errorMsg = contractId + ? (lang === 'es' ? 'Error de red al actualizar el contrato' : 'Network error updating contract') + : (lang === 'es' ? 'Error de red al guardar el contrato' : 'Network error saving contract'); + alert(errorMsg); + } + }; + + if (!areas.length || !positions.length) { + return
    {lang === "es" ? "Cargando datos..." : "Loading data..."}
    ; + } + + if (loading) { + return
    {lang === "es" ? "Cargando contrato..." : "Loading contract..."}
    ; + } + + return ( +
    +

    {contractId ? (lang === "es" ? "Editar Contrato" : "Edit Contract") : (lang === "es" ? "Nuevo Contrato" : "New Contract")}

    + {error && ( +
    + {error} +
    + )} +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    + {uniformsList.map(u => ( + + ))} +
    + +
    + {formState.uniforms.map(id => { + const uniform = uniformsList.find(u => String(u.id) === String(id)); + return ( + + {uniform ? uniform.name : `Uniforme ${id}`} + + + ); + })} +
    +
    +
    + +
    + +
    +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/PendingApproval.css b/frontend/Frontend-Hotel/src/pages/PendingApproval.css new file mode 100644 index 0000000..ea47700 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/PendingApproval.css @@ -0,0 +1,61 @@ +.pending-approval-page { + padding: 0; + max-width: 100%; +} + +.page-header { + margin-bottom: 24px; +} + +.page-title { + color: #1a1a1a; + font-size: 28px; + font-weight: 700; + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: -0.5px; +} + +.table-section { + background: white; + border-radius: 16px; + padding: 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + min-height: 400px; +} + +@media (max-width: 1024px) { + .page-title { + font-size: 24px; + } + + .table-section { + padding: 20px; + } +} + +@media (max-width: 768px) { + .pending-approval-page { + padding: 0; + } + + .page-title { + font-size: 22px; + } + + .table-section { + padding: 16px; + border-radius: 12px; + } +} + +@media (max-width: 480px) { + .page-title { + font-size: 20px; + } + + .table-section { + padding: 12px; + } +} + diff --git a/frontend/Frontend-Hotel/src/pages/PendingApproval.jsx b/frontend/Frontend-Hotel/src/pages/PendingApproval.jsx new file mode 100644 index 0000000..c6ef489 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/PendingApproval.jsx @@ -0,0 +1,133 @@ +import React, { useState, useEffect } from 'react'; +import Table from '../components/Table/HotelTable'; +import ConfirmationModal from '../components/Modals/ConfirmationModal'; +import { Link } from 'react-router-dom'; +import axios from 'axios'; +import '../components/Filters/Filters.css'; +import './PendingApproval.css'; +import { useContext } from 'react'; +import { langContext } from '../context/LenguageContext'; + +export default function PendingApproval() { + const { lang } = useContext(langContext); + const [data, setData] = useState([]); + const [modalOpen, setModalOpen] = useState(false); + const [selectedStatus, setSelectedStatus] = useState(null); + const [selectedId, setSelectedId] = useState(null); + const [selectedStatusId, setSelectedStatusId] = useState(null); + + //Cargar datos reales al montar el componente + useEffect(() => { + axios.get(import.meta.env.VITE_API_BASE_URL + '/expenses/pendingapproval') + .then((res) => { + //Mapeamos los datos para adaptarlos a las columnas + const formattedData = res.data.data.map(item => ({ + id: item.id_expense, + description: item.expense_description, + date: new Date(item.request_date).toISOString().split('T')[0], // yyyy-mm-dd + requestedBy: item.requested_by, + area: item.area, + amount: `$${parseFloat(item.amount).toLocaleString()}`, + })); + + setData(formattedData); + }) + .catch((err) => { + console.error("Error al obtener gastos pendientes:", err); + }); + }, []); + + const handleOpenModal = (id, statusType, statusId) => { + setSelectedId(id); + setSelectedStatus(statusType); + setSelectedStatusId(statusId); + setModalOpen(true); + }; + + const handleConfirm = () => { + if (!selectedId || !selectedStatus) return; + + const statusValue = selectedStatusId; + + axios.put(`${import.meta.env.VITE_API_BASE_URL}/status/approveupdate/${selectedId}`, { + status: statusValue + }) + .then((res) => { + console.log(res.data.message || 'Estado actualizado correctamente'); + + // Quitar el gasto aprobado/rechazado de la lista actual + setData(prevData => prevData.filter(item => item.id !== selectedId)); + + // Cerrar el modal y limpiar selección + setModalOpen(false); + setSelectedId(null); + setSelectedStatus(null); + }) + .catch((err) => { + console.error(`Error al actualizar el estado del gasto ${selectedId}:`, err); + alert('❌ Error al actualizar el estado. Intenta nuevamente.'); + }); + }; + + const handleCancel = () => { + setModalOpen(false); + }; + + const columns = [ + { + header: lang === "en" ? "EXPENSE DESCRIPTION" : "DESCRIPCIÓN DEL GASTO", + key: 'description', + render: (text, row) => ( + + {text} + + ), + }, + { header: lang === "en" ? "REQUEST DATE" : "FECHA DE SOLICITUD", key: 'date' }, + { header: lang === "en" ? "REQUESTED BY" : "SOLICITADO POR", key: 'requestedBy' }, + { header: lang === "en" ? "AREA" : "ÁREA", key: 'area' }, + { header: lang === "en" ? "AMOUNT" : "IMPORTE", key: 'amount' }, + { + header: lang === "en" ? "STATUS" : "ESTADO", + key: 'id', + headerStyle: { textAlign: 'center' }, + render: (id) => ( +
    + + +
    + ), + }, + ]; + + return ( +
    +
    +

    + {lang === "en" ? "Pending Approval" : "Aprobación Pendiente"} +

    +
    + +
    +
    + + + + + ); +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/pages/Reportes.jsx b/frontend/Frontend-Hotel/src/pages/Reportes.jsx new file mode 100644 index 0000000..e92ca9f --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Reportes.jsx @@ -0,0 +1,31 @@ +export default function Reportes() { + const cargas = [ + { id: 1, nombre: "Alta_08-2025.zip", estado: "Aceptado" }, + { id: 2, nombre: "Actualizacion_08-2025.zip", estado: "Pendiente" }, + { id: 3, nombre: "Alta_07-2025.zip", estado: "Rechazado" }, + ]; + + return ( +
    +

    Reportes de Cargas

    +
    + + + + + + + + + {cargas.map((c) => ( + + + + + + ))} + +
    IDArchivoEstado
    {c.id}{c.nombre}{c.estado}
    + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Settings/RoomManagement.css b/frontend/Frontend-Hotel/src/pages/Settings/RoomManagement.css new file mode 100644 index 0000000..0a0dc7b --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Settings/RoomManagement.css @@ -0,0 +1,31 @@ +.room-management h2 { + font-size: 1.5rem; + margin-bottom: 1rem; +} + +.room-table { + width: 100%; + border-collapse: collapse; + background-color: white; + font-size: 0.95rem; +} + +.room-table th { + background-color: #791313; + color: white; + padding: 0.75rem; + text-align: left; + font-weight: bold; + border: 1px solid #e3b600; +} + +.room-table td { + padding: 0.75rem; + border: 1px solid #e3b600; + text-align: left; +} + +.room-table td a { + color: #791313; + text-decoration: underline; +} diff --git a/frontend/Frontend-Hotel/src/pages/Settings/RoomsManagement.jsx b/frontend/Frontend-Hotel/src/pages/Settings/RoomsManagement.jsx new file mode 100644 index 0000000..80d2e88 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Settings/RoomsManagement.jsx @@ -0,0 +1,72 @@ +import React from "react"; +import { useNavigate } from 'react-router-dom'; +import Table from "../../components/Table/HotelTable"; +import { useContext } from "react"; +import { langContext } from "../../context/LenguageContext"; + +export default function RoomManagement() { + const navigate = useNavigate(); + const { lang } = useContext(langContext); + + const columns = [ + { + header: lang === "en" ? "ROOM ID" : "ID DE HABITACIÓN", + key: "id", + render: (value) => ( + navigate('/app/settings/settings-id')} + style={{ + color: '#b42a00ff', + cursor: 'pointer', + textDecoration: 'underline', + fontWeight: 'bold' + }} + > + {value} + + ), + }, + { header: lang === "en" ? "ROOM NAME" : "NOMBRE DE HABITACIÓN", key: "name" }, + { header: lang === "en" ? "GUEST" : "HUÉSPED", key: "guest" }, + { header: lang === "en" ? "BED TYPE" : "TIPO DE CAMA", key: "bedType" }, + { header: lang === "en" ? "QUANTITY" : "CANTIDAD", key: "quantity" }, + ]; + + const data = [ + { + id: "0000001", + name: "San Miguel Presidencial", + guest: "02", + bedType: "KING SIZE", + quantity: "01", + }, + { + id: "0000002", + name: "Angels View", + guest: "02", + bedType: "KING SIZE", + quantity: "01", + }, + { + id: "0000003", + name: "Angels Dome", + guest: "02", + bedType: "QUEEN SIZE", + quantity: "01", + }, + { + id: "0000004", + name: "Celestial", + guest: "04", + bedType: "QUEEN SIZE", + quantity: "01", + }, + ]; + + return ( +
    +

    {lang === "en" ? "Room management" : "Gestión de habitaciones"}

    + + + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Settings/Settings.jsx b/frontend/Frontend-Hotel/src/pages/Settings/Settings.jsx new file mode 100644 index 0000000..a758e85 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Settings/Settings.jsx @@ -0,0 +1,217 @@ +// // src/pages/General/Settings.jsx +import { FaUsers, FaArrowRight, FaCubes, FaThLarge } from "react-icons/fa"; +import { useNavigate } from "react-router-dom"; +import { FaBed } from "react-icons/fa"; +import { useContext } from "react"; +import { langContext } from "../../context/LenguageContext"; + +export default function Settings() { + const navigate = useNavigate(); + const { lang } = useContext(langContext); + + return ( +
    +
    +
    +
    +

    General

    + + {/* USERS */} +
    +

    {lang === "en" ? "Users" : "Usuarios"}

    +
    +
    + + 4 {lang === "en" ? "Active users" : "Usuarios activos"} +
    + +
    +
    + + {/* UNITS */} +
    +

    {lang === "en" ? "Units" : "Unidades"}

    +
    +
    + + {lang === "en" ? "Manage all unit data" : "Gestionar todos los datos de unidades"} +
    + +
    +
    + + {/* AREAS */} +
    +

    {lang === "en" ? "Areas" : "Áreas"}

    +
    +
    + + {lang === "en" ? "Customize working areas" : "Personalizar áreas de trabajo"} +
    + +
    +
    + + {/* Rooms card */} +
    +

    {lang === "en" ? "Rooms" : "Habitaciones"}

    +
    + +
    +
    15 {lang === "en" ? "active rooms" : "habitaciones activas"}
    +
    + +
    +
    +
    +
    +
    +
    + ); +} + +// import { FaUsers, FaArrowRight, FaCubes, FaThLarge } from 'react-icons/fa'; +// import { useNavigate } from 'react-router-dom'; + +// export default function Settings() { +// const navigate = useNavigate(); + +// return ( +//
    +// {/* Título principal */} +//

    General

    + +// {/* Sección: Users */} +//
    +//

    Users

    +//
    +//
    +// +// 4 Active users +//
    +// +//
    +//
    + +// {/* Sección: Units */} +//
    +//

    Units

    +//
    +//
    +// +// Manage all unit data +//
    +// +//
    +//
    + +// {/* Sección: Areas */} +//
    +//

    Areas

    +//
    +//
    +// +// Customize working areas +//
    +// +//
    +//
    +//
    +// ); +// } + + +// import { FaUsers, FaArrowRight, FaCubes, FaThLarge } from 'react-icons/fa'; +// import { useNavigate } from 'react-router-dom'; + +// const Settings = () => { +// const navigate = useNavigate(); + +// return ( +//
    +//

    General

    + +//
    +//

    Users

    +//
    +//
    +// +// 4 Active users +//
    +// +//
    +//
    + +//
    +//

    Units

    +// +//
    + +//
    +//

    Areas

    +// +//
    +//
    +// ); +// }; + +// export default Settings; diff --git a/frontend/Frontend-Hotel/src/pages/Settings/SettingsId.css b/frontend/Frontend-Hotel/src/pages/Settings/SettingsId.css new file mode 100644 index 0000000..28f7991 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Settings/SettingsId.css @@ -0,0 +1,75 @@ +.settings-id-container { + padding: 1rem; +} + +.page-title { + font-size: 1.8rem; + font-weight: bold; + margin-bottom: 1rem; +} + +.form-card { + background-color: #ffffff; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + font-family: Montserrat; +} + +.form-id { + font-size: 24px; + margin-bottom: 1rem; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1rem; + font-family: Montserrat; +} + +.form-grid input, +.form-grid select { + width: 80%; + padding: 8px; + border-radius: 6px; + border: 1px solid #ccc; + font-family: Montserrat; +} + +.amenities-section { + grid-column: span 2; +} + +.amenities-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; + margin-top: 0.2rem; +} + +.amenities-list label { + display: flex; + align-items: center; + gap: 0px; +} + +.save-button-wrapper { + display: flex; + justify-content: flex-end; + margin-top: 1.5rem; +} + +.save-button { + background-color: #e3b600; + color: white; + padding: 10px 20px; + border: none; + font-weight: bold; + border-radius: 25px; + cursor: pointer; +} + +.save-button:hover { + background-color: #c9a300; +} diff --git a/frontend/Frontend-Hotel/src/pages/Settings/SettingsId.jsx b/frontend/Frontend-Hotel/src/pages/Settings/SettingsId.jsx new file mode 100644 index 0000000..08c16a1 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Settings/SettingsId.jsx @@ -0,0 +1,150 @@ +import React, { useState } from 'react'; +import './SettingsId.css'; + +export default function SettingsId() { + const [formData, setFormData] = useState({ + name: 'San Miguel Presidencial', + guests: '2', + bedType: 'King size', + hotelierId: '000001', + amenities: { + jacuzzi: true, + airConditioning: true, + hairdryer: true, + telephone: false, + minibar: false, + } + }); + + const handleChange = (e) => { + const { name, value, type, checked } = e.target; + + if (name in formData.amenities) { + setFormData(prev => ({ + ...prev, + amenities: { + ...prev.amenities, + [name]: checked, + }, + })); + } else { + setFormData(prev => ({ + ...prev, + [name]: value, + })); + } + }; + + const handleSave = () => { + console.log('Saving room:', formData); + alert('Room data saved!'); + }; + + return ( +
    +

    {formData.name}

    + +
    +
    ID #{'0000001'}
    + +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    + + + + + +
    +
    +
    + +
    + +
    +
    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Sifen.jsx b/frontend/Frontend-Hotel/src/pages/Sifen.jsx new file mode 100644 index 0000000..2b68c50 --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Sifen.jsx @@ -0,0 +1,12 @@ +export default function Sifen() { + return ( +
    +

    Integración con SIFEN

    +

    + Aquí podrás enviar Documentos Electrónicos (DE/DTE) al SIFEN vía Web + Services. Próximamente conectaremos con los servicios definidos en el + Manual Técnico. +

    +
    + ); +} diff --git a/frontend/Frontend-Hotel/src/pages/Users.jsx b/frontend/Frontend-Hotel/src/pages/Users.jsx new file mode 100644 index 0000000..c230cfc --- /dev/null +++ b/frontend/Frontend-Hotel/src/pages/Users.jsx @@ -0,0 +1,85 @@ +import { useEffect, useState } from "react"; +import { getUsers } from "../services/userService"; + +export default function Users() { + const [users, setUsers] = useState([]); + + useEffect(() => { + async function loadData() { + const res = await getUsers(); + setUsers(res); + } + loadData(); + }, []); + + return ( +
    +

    Usuarios

    +
    + + + + + + + + + + + + {users.map((u) => ( + + + + + + + + + ))} + +
    IDNombreEmailRol IDPropiedad IDContraseña
    {u.id_users}{u.name_user}{u.mail}{u.id_roles}{u.id_properties}{u.password_user}
    +
    + ); +} + + + +// import { useEffect, useState } from "react"; +// import { getUsers } from "../services/userService"; + +// export default function Users() { +// const [users, setUsers] = useState([]); + +// useEffect(() => { +// async function loadData() { +// const res = await getUsers(); +// setUsers(res); +// } +// loadData(); +// }, []); + +// return ( +//
    +//

    Usuarios

    +// +// +// +// +// +// +// +// +// +// {users.map((u) => ( +// +// +// +// +// +// ))} +// +//
    NombreEmailRol
    {u.name}{u.mail}{u.role_name}
    +//
    +// ); +// } diff --git a/frontend/Frontend-Hotel/src/routes/ProtectedRoute.jsx b/frontend/Frontend-Hotel/src/routes/ProtectedRoute.jsx new file mode 100644 index 0000000..dbf4951 --- /dev/null +++ b/frontend/Frontend-Hotel/src/routes/ProtectedRoute.jsx @@ -0,0 +1,10 @@ +import { Navigate } from "react-router-dom"; +import { useAuth } from "../context/AuthContext.jsx"; + +export default function ProtectedRoute({ children }) { + const { isAuthenticated } = useAuth(); + if (!isAuthenticated) { + return ; + } + return children; +} diff --git a/frontend/Frontend-Hotel/src/services/api.js b/frontend/Frontend-Hotel/src/services/api.js new file mode 100644 index 0000000..0630f14 --- /dev/null +++ b/frontend/Frontend-Hotel/src/services/api.js @@ -0,0 +1,57 @@ +import axios from "axios"; + +const api = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL, + timeout: 15000, +}); + +export default api; + + +//Ejemplo con fetch +const API_BASE_URL = 'http://localhost:4000/api'; + +export async function createProduct(data) { + try { + const response = await fetch(`${API_BASE_URL}/products`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + throw new Error('Failed to save product'); + } + + return await response.json(); + } catch (error) { + console.error('API error:', error); + throw error; + } +} + +export async function fetchProducts() { + const res = await fetch(`${API_BASE_URL}/products`); + if (!res.ok) throw new Error('Error fetching products'); + return await res.json(); +} + +export async function fetchInventoryProducts() { + const res = await fetch(`${API_BASE_URL}/inventory-products`); + if (!res.ok) throw new Error('Error fetching inventory products'); + // forma esperada: objeto, ej: { "PILLOWS": { unitCost: 300, tax: "IVA 16%" }, ... } + return await res.json(); +} + +export async function createExpense(payload) { + const res = await fetch(`${API_BASE_URL}/expenses`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + if (!res.ok) throw new Error('Error creating expense'); + return await res.json(); +} + diff --git a/frontend/Frontend-Hotel/src/services/contractService.js b/frontend/Frontend-Hotel/src/services/contractService.js new file mode 100644 index 0000000..9e2ab52 --- /dev/null +++ b/frontend/Frontend-Hotel/src/services/contractService.js @@ -0,0 +1,11 @@ +import axios from 'axios'; + +export async function getContracts() { + try { + const response = await axios.get('http://localhost:3000/api/contracts'); + return response.data; + } catch (error) { + console.error('Error fetching contracts:', error); + return []; + } +} diff --git a/frontend/Frontend-Hotel/src/services/employeeService.js b/frontend/Frontend-Hotel/src/services/employeeService.js new file mode 100644 index 0000000..af4f7de --- /dev/null +++ b/frontend/Frontend-Hotel/src/services/employeeService.js @@ -0,0 +1,13 @@ +// services/employeeService.js +// import API from './api'; + +// export const getEmployees = () => API.get('/employees'); +export const getEmployees = async () => { + try { + const response = await axios.get(API_URL); + return response.data; + } catch (error) { + console.error('Error fetching employees:', error); + return []; + } +}; diff --git a/frontend/Frontend-Hotel/src/services/incomeService.js b/frontend/Frontend-Hotel/src/services/incomeService.js new file mode 100644 index 0000000..7f57ba9 --- /dev/null +++ b/frontend/Frontend-Hotel/src/services/incomeService.js @@ -0,0 +1,6 @@ +import axios from "axios"; + +export const getIncome = async () => { + const response = await axios.get("http://localhost:3000/api/income"); + return response.data; +}; diff --git a/frontend/Frontend-Hotel/src/services/userService.js b/frontend/Frontend-Hotel/src/services/userService.js new file mode 100644 index 0000000..ad04737 --- /dev/null +++ b/frontend/Frontend-Hotel/src/services/userService.js @@ -0,0 +1,8 @@ +import axios from 'axios'; + +const API = "http://localhost:4000/api"; + +export async function getUsers() { + const res = await axios.get(`${API}/users`); + return res.data; +} \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/styles/Dashboard.css b/frontend/Frontend-Hotel/src/styles/Dashboard.css new file mode 100644 index 0000000..e5239c5 --- /dev/null +++ b/frontend/Frontend-Hotel/src/styles/Dashboard.css @@ -0,0 +1,378 @@ + +/* Contenedor principal */ +.dashboard-layout { + display: flex; + font-family: sans-serif; + min-height: 100vh; + height: auto; +} + +.sidebar { + background: linear-gradient(to bottom, #961227, #680012); + color: white; + width: 200px; + display: flex; + flex-direction: column; + padding: 20px; + min-height: 100vh; + justify-content: flex-start; +} + +.sidebar nav a { + display: flex; + flex-direction: column; + color: #ffffff; + text-decoration: none; + padding: 8px; + border-radius: 6px; + font-size: x-large; + font-weight: 500; + transition: color 0.2s; + font-family: Georgia, 'Times New Roman', Times, serif; +} + +.sidebar nav a:hover { + background: #fc9b00; + color: rgb(14, 0, 0); +} + +.sidebar-header { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 1rem; +} + +.sidebar-toggle-button { + font-size: 1rem; + background: none; + border: none; + color: white; + cursor: pointer; + border-radius: 38px; +} + +.sidebar-toggle-button:focus { + outline: none; + background: #fc9b00; + box-shadow: 0 0 0 3px; + background-color: rgba(255, 207, 48, 0.733); +} + +.menu-btn { + background: none; + border: none; + font-size: 1.5rem; + color: white; + cursor: pointer; +} + +.sidebar-title { + font-size: 1.2rem; + font-weight: bold; +} + +/* Menú */ +.menu-items { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.menu-items a { + color: white; + text-decoration: none; + font-size: 1rem; + padding: 5px 10px; + border-radius: 5px; +} + +.menu-items a:hover { + background-color: #a0122b; +} + +/* Área principal */ +.main-content { + flex: 1; + display: flex; + flex-direction: column; + overflow: auto; + min-height: 100vh; +} + +.content { + padding: 2rem; + background-color: #f0eeee; + flex: 1; + overflow-y: auto; /* Permite scroll vertical si es necesario */ +} + +.topbar { + background-color: #e3b600; + display: flex; + flex-direction: column; + padding: 0.1rem 0.4rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.topbar-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0rem; +} + +.topbar-title { + font-size: 1.2rem; + font-weight: 600; + color: #ffffff; +} + +.topbar-submenu { + display: flex; + font-family:'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; + gap: 15px; + flex-wrap: wrap; + justify-content: center; + margin-top: 0; + padding: 0.2rem 0; +} + +.submenu-link { + font-size: 1.2rem; + padding: 3px 6px; + border-radius: 4px; + background-color: #791313; + color: white; + font-weight: 600; + text-decoration: none; + transition: background-color 0.5s ease; +} + +.submenu-link:hover { + background-color: #a0122b; +} + +.topbar-left { + display: flex; + align-items: center; + gap: 1rem; +} + +.topbar-icons { + display: flex; + align-items: center; + gap: 20px; +} + +.topbar-icon { + font-size: 1.6rem; + cursor: pointer; + color: #ffffff; + transition: color 0.2s ease; +} + +.topbar-icon:hover { + color: #791313; +} + +.submenu-link:hover { + background-color: #f5d600; +} + +.language-select { + padding: 6px 10px; + border-radius: 20px; + background-color: #ffffff; + border: none; + font-size: 0.9rem; + font-weight: bold; + color: #680012; + cursor: pointer; + transition: background-color 0.3s ease; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); +} + +.language-select:hover { + background-color: #f5d600; +} + +.language-select:focus { + outline: none; + box-shadow: 0 0 0 2px #680012; +} + +/* +.submenu-link { + font-size: 1.2rem; + padding: 3px 6px; + border-radius: 4px; + background-color: #f5d400cc; +} */ + + +/* .submenu-link.active { + background-color: #791313; + color: white; + font-weight: 600; +} */ + +/* +.topbar { + background-color: #e3b600; + display: flex; + flex-direction: column; + padding: 0.8rem 1.5rem; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.topbar-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.topbar-title { + font-size: 1.2rem; + font-weight: bold; + color: #ffffff; +} + +.topbar-submenu { + display: flex; + gap: 15px; + margin-top: 0.5rem; + flex-wrap: wrap; + justify-content: center; +} + +.submenu-link { + font-size: 1rem; + color: #ffffff; + text-decoration: none; + padding: 5px 10px; + border-radius: 4px; + background-color: #f5d400cc; + font-weight: 500; +} + +.submenu-link.active { + background-color: #791313; + color: white; + font-weight: bold; +} + */ + +/* .sidebar-toggle-button { + font-size: 1.5rem; + background: none; + border: none; + color: white; + cursor: pointer; + outline: none; +} + +.sidebar-toggle-button:focus { + outline: none; + box-shadow: 0 0 0 3px #ffcf30; + border-radius: 4px; +} + */ + +/* .sidebar-toggle-button:focus { + outline: 3px solid #ffcf30; + outline-offset: 2px; + border-radius: 4px; + background-color: rgba(255, 207, 48, 0.021); +} */ + + +/* .sidebar-toggle-button:focus { + outline: 20px solid #ffcf30; + outline-offset: 8px; +} */ + +/* .sidebar-toggle-button:focus { + outline: none; +} */ + +/* Header */ +/* .topbar { + background-color: #e3b600; + font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; + align-items: center; + justify-content: space-between; + padding-top: 0.8rem; + padding-right: 1.5rem; + padding-bottom: 0.8rem; + padding-left: 1.5rem; + flex-wrap: wrap; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.topbar-title { + font-size: 1.2rem; + font-weight: bold; + color: #ffffff; + justify-content: flex-start; +} + +.topbar-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.topbar-icons { + display: flex; + gap: 20px; + align-items:end; +} + +.topbar-icon { + font-size: 1.4rem; + cursor: pointer; + color: #ffffff; + transition: color 0.2s ease; +} + +.topbar-icon:hover { + color: #791313; +} + +.topbar-submenu { + flex: 2; + justify-content: center; + display: flex; + gap: 1.2rem; + flex-wrap: wrap; +} */ + +/* .submenu-link { + font-size: 1rem; + color: #ffffff; + text-decoration: none; + padding: 5px 10px; + border-radius: 4px; + transition: background 0.3s; + background-color: #f5d400cc; + font-weight: 500; +} + +.submenu-link:hover { + background-color: #f5d600; +} + +.submenu-link.active { + background-color: #791313; + color: white; + font-weight: bold; +} */ + +/* .topbar-center { + flex: 2; + justify-content: center; + display: flex; + gap: 15px; + flex-wrap: wrap; +} */ diff --git a/frontend/Frontend-Hotel/src/styles/Layout.css b/frontend/Frontend-Hotel/src/styles/Layout.css new file mode 100644 index 0000000..d53a268 --- /dev/null +++ b/frontend/Frontend-Hotel/src/styles/Layout.css @@ -0,0 +1,24 @@ +/* src/styles/Layout.css */ + +.app { + display: flex; + flex-direction: column; +} + +.main { + margin-left: 220px; /* espacio del sidebar */ + padding: 20px; + margin-top: 50px; /* espacio del navbar */ +} + +/* .topbar { + display: flex; + justify-content: flex-end; + margin-bottom: 20px; +} */ + +.content { + background-color: white; + padding: 20px; + border-radius: 8px; +} diff --git a/frontend/Frontend-Hotel/src/styles/Login.css b/frontend/Frontend-Hotel/src/styles/Login.css new file mode 100644 index 0000000..ae48c3e --- /dev/null +++ b/frontend/Frontend-Hotel/src/styles/Login.css @@ -0,0 +1,306 @@ +/* CONTENEDOR PRINCIPAL */ +.login-page { + background-color: #e4bd00; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; +} + +/* TARJETA BLANCA */ +.login-container { + background-color: white; + padding: 100px; + border-radius: 1px; + box-shadow: 0 0 30px rgba(0, 0, 0, 0.15); + display: flex; + gap: 20px; + align-items: center; + justify-content: center; + max-width: 1000px; + width: 100%; + overflow: hidden; +} + +/* LOGO */ +.logo-box { + flex: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.logo { + width: 250px; + height: auto; +} + +/* FORMULARIO */ +.login-form { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + width: 100%; +} + +.login-form input.custom-input { + width: 170%; + padding: 12px; + border: none; + border-radius: 20px; + background-color: #d1d5db; + /* color: #ed0404; */ + font-size: 15px; + font-weight: 500; +} + +.login-form input::placeholder { + color: ed0404; +} + +/* BOTONES */ +.login-buttons { + display: flex; + justify-content: space-between; + gap: 10px; + width: 180%; +} + +.login-buttons button { + flex: 1; + padding: 12px; + font-weight: 600; + border-radius: 20px; + border: none; + background-color: #6a0e0e; + color: white; + cursor: pointer; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.2); +} + +/* Opcional: efecto hover */ +.login-buttons button:hover { + background-color: #8b0e0e; +} + +.custom-input { + width: 100%; + padding: 16px 24px; + /*border: none;*/ + border-radius: 16px; + background-color: #ce0f0f; + box-shadow: 0 4px 6px rgba(255, 255, 255, 0.1); + font-family: 'Roboto', sans-serif; + /* font-size: 16px; */ + font-weight: bold; + font-size: 1.2rem; + color: #505050 !important; + /* Gris oscuro */ + text-align: center; + outline: none; + transition: box-shadow 0.3s ease; +} + +.custom-input::placeholder { + color: #888; + font-weight: bold; +} + +.custom-input:focus { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.custom2-input:focus { + background-color: #d5d8de; +} + +.login-button, +.recover-button { + background-color: #5b1410; + color: white; + border: none; + border-radius: 30px; + padding: 14px; + font-weight: bold; + cursor: pointer; + box-shadow: 2px 4px 6px rgba(0, 0, 0, 0.2); +} + +.recover-button { + background-color: #5b1410; +} + +.recover-input { + width: 200px; + padding: 10px; + margin: 0 auto 15px auto; /* Centrado + espacio debajo */ + border: none; + border-radius: 30px; + background-color: #d1d5db; + color: #111; + font-size: 14px; + display: block; + text-align: center; +} + + +.modal-title { + font-family: 'Roboto', sans-serif; + font-size: 20px; + font-weight: 600; + color: #5D1A2A; + text-align: center; + margin-bottom: 20px; +} + +.modal-form input.recover-input { + width: 100% !important; + padding: 12px 16px; + margin: 0 0 20px 0; + border: none; + border-radius: 25px; + background-color: #d1d5db; + color: #111; + font-size: 14px; + display: block; + text-align: center; + box-sizing: border-box; +} + +.modal-actions { + display: flex; + gap: 10px; + justify-content: center; + margin-top: 20px; +} + +.modal-actions .btn { + flex: 1; + padding: 12px 20px; + border: none; + border-radius: 25px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; +} + +.modal-actions .btn-primary { + background-color: #5D1A2A; + color: white; +} + +.modal-actions .btn-primary:hover { + background-color: #7a2336; +} + +.modal-actions .btn-secondary { + background-color: #6c757d; + color: white; +} + +.modal-actions .btn-secondary:hover { + background-color: #5a6268; +} + +/* +.modal-form input { + width: 100%; + padding: 12px; + margin-bottom: 15px; + border: none; + border-radius: 30px; + background-color: #d1d5db; + color: #111; + font-size: 14px; +} */ + + +/* +.btn { + flex: 1; + padding: 12px; + border: none; + border-radius: 20px; + font-weight: bold; + cursor: pointer; +} + +.btn--primary { + background-color: #8b0000; + color: white; +} */ + + +/*--------------------------------------*/ +/* .login-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-color: #fff; +} */ + +/* .login-form { + display: flex; + flex-direction: column; + gap: 16px; + width: 300px; +} */ +/* +.btn--primary:hover { + background-color: #a00000; +} +.btn--secondary { + background-color: #b22222; + color: white; +} +.btn--secondary:hover { + background-color: #cc0000; +} */ + + +/* +.login-page { + background-color: #e3b400; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; +} + +.login-container { + background-color: white; + padding: 40px; + border-radius: 10px; + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); + max-width: 900px; + width: 100%; + display: flex; + flex-direction: row; + gap: 40px; + align-items: center; + justify-content: center; +} + +.logo-box { + flex: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.logo { + max-width: 150px; + height: auto; +} + +.login-form { + flex: 1; + display: flex; + flex-direction: column; + gap: 20px; +} + */ \ No newline at end of file diff --git a/frontend/Frontend-Hotel/src/styles/LoginPage.css b/frontend/Frontend-Hotel/src/styles/LoginPage.css new file mode 100644 index 0000000..3805767 --- /dev/null +++ b/frontend/Frontend-Hotel/src/styles/LoginPage.css @@ -0,0 +1,22 @@ +/* Login Page */ +.login-page { + background: url('/path/to/background-image.jpg') no-repeat center center fixed; + background-size: cover; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; +} + +.login-box { + background: rgba(255, 255, 255, 0.85); /* Fondo blanco semi-transparente */ + padding: 40px; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + width: 320px; +} + +.btn--primary { + background-color: #8b0000; + color: white; +} diff --git a/frontend/Frontend-Hotel/src/styles/Sidebar.css b/frontend/Frontend-Hotel/src/styles/Sidebar.css new file mode 100644 index 0000000..f356c30 --- /dev/null +++ b/frontend/Frontend-Hotel/src/styles/Sidebar.css @@ -0,0 +1,141 @@ +/* .app { + display: flex; + height: 100vh; +} + +.sidebar nav a { + color: #d1d5db; + text-decoration: none; + padding: 8px; + border-radius: 6px; +} + +.sidebar nav a.active, +.sidebar nav a:hover { + background: #f0ff64; + color: rgb(14, 0, 0); +} + +.main { + flex: 1; + display: flex; + flex-direction: column; + margin-left: 220px; + padding: 20px; + background: #fff; +} + +.topbar { + padding: 12px; + background: #fdd700b2; + display: flex; + justify-content: flex-end; + z-index: 2; +} + +.content { + padding: 20px; + background: #fff; + margin-top: 20px; +} + +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.55); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +.modal-box { + background: white; + padding: 30px; + border-radius: 10px; + width: 350px; + max-width: 90%; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); + animation: fadeIn 0.2s ease-in-out; +} + +.modal-box h3 { + margin-top: 0; + margin-bottom: 15px; + color: #111; + text-align: center; +} + +.sidebar { + width: 220px; + background: #741111; + height: 100vh; + padding: 20px; + color: white; + font-family: sans-serifs; + display: flex; + flex-direction: column; + transition: width 0.3s ease; + align-items: flex-start; + min-height: 100vh; +} + +.sidebar.collapsed { + width: 60px; +} + +.sidebar-header { + display: flex; + align-items: center; + margin-bottom: 30px; +} + +.toggle-btn { + background: none; + border: none; + color: white; + font-size: 24px; + cursor: pointer; + margin-right: 10px; +} + +.title { + font-weight: bold; + font-size: 18px; + color: white; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 12px; +} + +.sidebar-nav a { + color: white; + text-decoration: none; + padding: 8px; + border-radius: 6px; + transition: background 0.2s ease; + font-size: 15px; +} + +.sidebar-nav a.active, +.sidebar-nav a:hover { + background: #f0ff64; + color: #111; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} */ diff --git a/frontend/Frontend-Hotel/src/styles/global.css b/frontend/Frontend-Hotel/src/styles/global.css new file mode 100644 index 0000000..d23d982 --- /dev/null +++ b/frontend/Frontend-Hotel/src/styles/global.css @@ -0,0 +1,157 @@ +.app { + background-color: rgba(255, 223, 0, 0.85); + display: flex; + min-height: 100vh; +} + +.main { + flex: 1; + display: flex; + flex-direction: column; +} + +/* .topbar { + padding: 12px; + background: #fdd700; + display: flex; + justify-content: flex-end; + align-items: center; + font-size: 1rem; + color: white; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} */ + +button:hover { + background-color: #ddbf16; +} + +/* +button { + background-color: #4a0d0d; + color: white; + padding: 10px; + border-radius: 6px; + border: none; + cursor: pointer; +} + */ +.content { + padding: 20px; +} + +/* Fondo del modal */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.55); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +/* Caja del modal */ +.modal-box { + background: white; + padding: 30px; + border-radius: 12px; + width: 350px; + max-width: 90%; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + animation: fadeIn 0.3s ease-in-out; +} + +/* Agregar un fondo semi-transparente al modal */ +.modal-overlay { + background: rgba(0, 0, 0, 0.7); + z-index: 100; +} + +.modal-box h3 { + margin-top: 0; + margin-bottom: 15px; + color: #111; + text-align: center; +} + +/* Formulario del modal */ +.modal-form input { + width: 100%; + padding: 10px; + margin-bottom: 15px; + border: none; + border-radius: 6px; + background: #d1d5db; + color: #111; + font-size: 14px; +} + +.modal-actions { + display: flex; + justify-content: space-between; + gap: 10px; +} + +/* Animación */ +@keyframes fadeIn { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} +/*Login.css*/ +/* Fondo amarillo opaco */ +/* +.login-page { + background-color: rgba(255, 223, 0, 0.85); + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; +} */ + + +/* Cuadro central blanco */ +.login-box { + background: white; + padding: 40px; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + width: 320px; +} + +/* Botones tintos */ +/* .btn { + width: 100%; + padding: 12px; + border: none; + border-radius: 6px; + font-weight: 600; + margin-bottom: 10px; + cursor: pointer; +} + +.btn--primary { + background-color: #8b0000; + color: white; +} + +.btn--primary:hover { + background-color: #a00000; +} + +.btn--secondary { + background-color: #b22222; + color: white; +} + +.btn--secondary:hover { + background-color: #cc0000; +} */ diff --git a/frontend/Frontend-Hotel/tailwind.config.cjs b/frontend/Frontend-Hotel/tailwind.config.cjs new file mode 100644 index 0000000..614c86b --- /dev/null +++ b/frontend/Frontend-Hotel/tailwind.config.cjs @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/frontend/Frontend-Hotel/vite.config.js b/frontend/Frontend-Hotel/vite.config.js new file mode 100644 index 0000000..d5fc092 --- /dev/null +++ b/frontend/Frontend-Hotel/vite.config.js @@ -0,0 +1,31 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + react({ + jsxRuntime: 'automatic', + }) + ], + server: { + host: true, + port: 5172, + allowedHosts: [ + 'hacienda.consultoria-as.com' + ], + hmr: { + overlay: true, + }, + // proxy:{ + // '/api':{ + // target: 'http://localhost:4000', + // changeOrigin : true, + // secure: false, + // } + // } + }, + optimizeDeps: { + include: ['react', 'react-dom', 'react-router-dom'], + }, +})