# Cofradía

Aplicación de gestión para hermandades y cofradías: hermanos, cuotas y remesas SEPA,
tesorería e inventario, calendario con avisos push/email, salidas y papeletas de sitio
con QR, cuadrillas y banda, comunicaciones, portal del hermano y panel de superadmin
multi-hermandad. Ver `especificacion_app_cofradias.md` para el detalle funcional completo.

**Stack:** PHP 8.2+ · Laravel 12 · Livewire 3 + Alpine.js · Tailwind CSS · MySQL/MariaDB ·
cola de base de datos · PWA con Web Push (VAPID).

---

## 1. Desarrollo local

Requisitos: PHP 8.2+, Composer, Node 18+, MySQL/MariaDB 10.6+ (o el que traiga XAMPP).

```bash
composer install
npm install
cp .env.example .env
php artisan key:generate
```

Configura `DB_*` en `.env` contra una base de datos vacía, y genera las claves VAPID
para las notificaciones push:

```bash
php artisan webpush:vapid
```

Copia `VAPID_PUBLIC_KEY` y `VAPID_PRIVATE_KEY` al `.env` (si el comando falla en Windows/XAMPP
por no encontrar `openssl.cnf`, define `OPENSSL_CONF` apuntando al `openssl.cnf` de PHP antes
de ejecutarlo).

```bash
php artisan migrate --seed   # crea superadmin + hermandad de demostración
php artisan storage:link
npm run build                # o `npm run dev` en una terminal aparte durante desarrollo
php artisan serve
```

Usuarios de la hermandad de demostración (contraseña `password` salvo el superadmin,
ver más abajo): `admin@humildadyesperanza.example`, `secretaria@...`, `tesoreria@...`,
`capataz@...`, `banda@...`, `hermano@...`. Superadmin: `superadmin@cofradia.app`.

Para que los avisos automáticos (recordatorios de eventos) y las colas funcionen en
local, deja corriendo en dos terminales:

```bash
php artisan queue:work
php artisan schedule:work
```

Ejecuta la batería de tests con `php artisan test` y el formateador con `./vendor/bin/pint`.

---

## 2. Despliegue en VPS (Ubuntu 22.04/24.04 + Nginx + PHP-FPM + MySQL)

### 2.1 Paquetes del sistema

```bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx mysql-server git unzip supervisor cron \
    php8.3-fpm php8.3-cli php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl \
    php8.3-zip php8.3-gd php8.3-bcmath php8.3-intl php8.3-common
```

(PHP 8.3 vía el PPA `ppa:ondrej/php` si no viene en los repos por defecto de tu Ubuntu.)

Composer y Node:

```bash
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
```

### 2.2 Base de datos

```bash
sudo mysql -e "CREATE DATABASE cofradia CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mysql -e "CREATE USER 'cofradia'@'localhost' IDENTIFIED BY 'CAMBIA_ESTA_CONTRASENA';"
sudo mysql -e "GRANT ALL PRIVILEGES ON cofradia.* TO 'cofradia'@'localhost'; FLUSH PRIVILEGES;"
```

### 2.3 Código de la aplicación

```bash
sudo mkdir -p /var/www/cofradia
sudo chown $USER:$USER /var/www/cofradia
git clone <url-del-repositorio> /var/www/cofradia
cd /var/www/cofradia

composer install --no-dev --optimize-autoloader
npm ci
npm run build

cp .env.example .env
php artisan key:generate
```

Edita `.env`:

```
APP_ENV=production
APP_DEBUG=false
APP_URL=https://tu-dominio.example

DB_DATABASE=cofradia
DB_USERNAME=cofradia
DB_PASSWORD=CAMBIA_ESTA_CONTRASENA

SESSION_DRIVER=database
QUEUE_CONNECTION=database
CACHE_STORE=database
FILESYSTEM_DISK=local

MAIL_MAILER=smtp
MAIL_HOST=...
MAIL_PORT=587
MAIL_USERNAME=...
MAIL_PASSWORD=...
MAIL_FROM_ADDRESS="..."
MAIL_FROM_NAME="${APP_NAME}"

VAPID_SUBJECT="mailto:soporte@tu-dominio.example"
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=

BACKUP_ARCHIVE_PASSWORD=OTRA_CONTRASENA_LARGA
BACKUP_NOTIFICATION_EMAIL=soporte@tu-dominio.example
```

Genera las claves VAPID (`php artisan webpush:vapid`) y complétalas en el `.env`.

Migraciones y permisos de storage:

```bash
php artisan migrate --force
php artisan db:seed --class=RolesAndPermissionsSeeder --force
php artisan storage:link

sudo chown -R www-data:www-data /var/www/cofradia/storage /var/www/cofradia/bootstrap/cache
sudo chmod -R 775 /var/www/cofradia/storage /var/www/cofradia/bootstrap/cache
```

**No ejecutes `DemoHermandadSeeder` en producción.** Crea el superadmin real a mano:

```bash
php artisan tinker
>>> $u = App\Models\User::create(['hermandad_id' => null, 'name' => 'Soporte', 'email' => 'tu-email@example.com', 'password' => Str::random(32), 'email_verified_at' => now()]);
>>> $u->assignRole('superadmin');
>>> Illuminate\Support\Facades\Password::sendResetLink(['email' => 'tu-email@example.com']);
```

(requiere `MAIL_MAILER` ya configurado para recibir el email de "establecer contraseña";
si no, define la contraseña directamente con `$u->update(['password' => 'algo-temporal'])`
y cámbiala nada más entrar).

Cachea configuración y rutas para producción:

```bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
```

### 2.4 PHP-FPM

Crea un pool dedicado en `/etc/php/8.3/fpm/pool.d/cofradia.conf` (o reutiliza el `www`
por defecto) apuntando su socket a algo como `/run/php/php8.3-fpm-cofradia.sock`, y
reinicia: `sudo systemctl restart php8.3-fpm`.

### 2.5 Nginx

`/etc/nginx/sites-available/cofradia`:

```nginx
server {
    listen 80;
    server_name tu-dominio.example;
    root /var/www/cofradia/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;
    charset utf-8;

    client_max_body_size 20M;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

```bash
sudo ln -s /etc/nginx/sites-available/cofradia /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```

### 2.6 HTTPS (Let's Encrypt)

```bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d tu-dominio.example
```

Certbot reescribe el `server {}` para forzar HTTPS y programa la renovación automática.
La PWA (manifest, Service Worker, Web Push) requiere HTTPS para funcionar salvo en `localhost`.

### 2.7 Cola de trabajos (avisos push/email, exportaciones, remesas)

La app usa la cola `database` (rule 9: los envíos nunca bloquean la interfaz). Necesita
un *worker* corriendo de forma persistente — usa Supervisor:

`/etc/supervisor/conf.d/cofradia-worker.conf`:

```ini
[program:cofradia-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/cofradia/artisan queue:work --sleep=3 --tries=3 --max-time=3600
directory=/var/www/cofradia
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/cofradia/storage/logs/worker.log
stopwaitsecs=3600
```

```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start cofradia-worker:*
```

### 2.8 Tareas programadas (cron)

El scheduler de Laravel (`routes/console.php`) dispara los recordatorios automáticos de
eventos cada 15 minutos y las copias de seguridad diarias. Solo necesitas una entrada
de cron que llame a `schedule:run` cada minuto:

```bash
sudo crontab -u www-data -e
```

```
* * * * * cd /var/www/cofradia && php artisan schedule:run >> /dev/null 2>&1
```

### 2.9 Copias de seguridad

`spatie/laravel-backup` está configurado (`config/backup.php`) para volcar la base de
datos y `storage/app` (excluyendo el propio directorio de backups) a diario, cifradas
con `BACKUP_ARCHIVE_PASSWORD`, en el disco `local` (`storage/app/private`, fuera del
document root — no descargable por HTTP). Cópialas además fuera del servidor (rsync a
otra máquina, o añade un disco S3/similar en `config/filesystems.php` y súmalo a
`backup.backup.destination.disks`). Verifica periódicamente:

```bash
php artisan backup:list
```

### 2.10 Despliegue de nuevas versiones

```bash
cd /var/www/cofradia
git pull
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan config:cache && php artisan route:cache && php artisan view:cache
sudo supervisorctl restart cofradia-worker:*
```

---

## 3. Notas de seguridad y RGPD

- El IBAN de cada persona se guarda cifrado (`encrypted` cast) y se muestra
  enmascarado en la interfaz.
- Los intentos de login fallidos están limitados (5 intentos, backoff progresivo).
- Personas, cuotas, movimientos y papeletas quedan auditados (tabla `auditoria`,
  visible en Configuración → Auditoría para el rol admin).
- Cada ficha de persona tiene una acción "Anonimizar (RGPD)" que borra los datos
  identificativos conservando el histórico contable.
- La política de privacidad y el texto del encargado del tratamiento se editan desde
  el panel de superadmin (`/superadmin/legal`) y se publican en `/privacidad`.
- Configura `APP_KEY`, `BACKUP_ARCHIVE_PASSWORD` y las credenciales de base de datos
  como secretos reales en producción — nunca reutilices los valores de ejemplo.
