# Manual de uso completo — Lliria Properties Scraper

## 1) Objetivo de la aplicación

Aplicación web para:
- capturar anuncios inmobiliarios desde múltiples portales,
- separar datos por **operación**: `venta` y `alquiler`,
- visualizar en **listado** y **mapa**,
- gestionar zonas/poblaciones y portales,
- crear filtros y alertas por correo.

---

## 2) Acceso y arranque

1. Instalar dependencias:
   - `npm install`
2. Inicializar BD (primera vez):
   - `npm run init-db`
3. Arrancar en desarrollo:
   - `npm run dev`
4. Abrir:
   - `http://localhost:3000/login`

Credenciales por defecto:
- usuario: `George`
- contraseña: `4213`

---

## 3) Estructura funcional del dashboard

## 3.1 Listado (`/dashboard`)
- Modo por operación:
  - `Venta`: `/dashboard?op=sale`
  - `Alquiler`: `/dashboard?op=rent`
- Tabla con DataTables server-side.
- Filtros:
  - municipio, tipo, precio min/max, habitaciones, portal, zona Valencia.
- Botones:
  - filtrar, limpiar, guardar plantilla, exportar CSV/Excel.

## 3.2 Mapa (`/dashboard/map`)
- Modo por operación:
  - `Venta`: `/dashboard/map?op=sale`
  - `Alquiler`: `/dashboard/map?op=rent`
- Filtros:
  - precio, tipo, portal y zonas.
- UI adaptada móvil:
  - panel flotante tipo bottom-sheet en pantallas pequeñas.

## 3.3 Zonas (`/dashboard/zones`)
- Alta/edición/borrado de zonas.
- Slugs específicos por portal.
- Scraping por zona con selección de operación (`sale`/`rent`).

## 3.4 Portales (`/dashboard/portals`)
- Activar/desactivar portales.
- Controlar qué scrapers participan en cada ejecución.

## 3.5 Filtros (`/dashboard/filters`)
- Crear plantillas.
- Reutilizar búsquedas.
- Configurar alertas email.

## 3.6 Archivo (`/dashboard/archive`)
- Propiedades archivadas (soft-delete).
- Restauración o borrado definitivo.

---

## 4) Scraping manual

## 4.1 Scraping global por operación
- Venta:
  - `POST /api/scraper/scrape/sale`
- Alquiler:
  - `POST /api/scraper/scrape/rent`

## 4.2 Scraping por portal
- `POST /api/scraper/scrape/:slug?op=sale`
- `POST /api/scraper/scrape/:slug?op=rent`

## 4.3 Scraping por zona
- `POST /api/scraper/scrape-zone/:slug?op=sale`
- `POST /api/scraper/scrape-zone/:slug?op=rent`

## 4.4 Logs y estado
- Estado:
  - `GET /api/scraper/status`
- Logs SSE:
  - `GET /api/scraper/logs/stream`
- Logs JSON:
  - `GET /api/scraper/logs`

---

## 5) Segmentación de Valencia por distritos reales

Cuando la zona activa incluye `Valencia`, los scrapers principales expanden automáticamente a distritos reales (en venta y alquiler):
- Ciutat Vella
- Eixample
- Extramurs
- Campanar
- La Saïdia
- El Pla del Real
- L'Olivereta
- Patraix
- Jesús
- Quatre Carreres
- Poblats Maritims
- Camins al Grau
- Algirós
- Benimaclet
- Benicalap
- Rascanya
- Pobles del Nord
- Pobles de l'Oest
- Pobles del Sud

Portales con slugs distritales implementados:
- Idealista
- Fotocasa
- Pisos.com

Los slugs se leen de `valencia_district_slugs`. Si la tabla está vacía al
arrancar, se siembran los valores de `src/config/valenciaDistricts.ts`; una
zona marcada como inactiva no se sustituye por el fallback estático.

La cobertura metropolitana se sincroniza desde `municipalities_es` con un
radio Haversine de 40 km desde el centro de Valencia. `npm run
coverage:dry-run` muestra el plan y `npm run coverage:apply` lo aplica. Las
zonas quedan etiquetadas por banda (`metro`, `cercana`, `exterior`) y sector
cardinal. Valencia capital se procesa todos los días; los municipios se rotan
en lotes para no disparar bloqueos (`SCRAPER_MAX_ZONES_PER_PORTAL`, 12 por
defecto; `0` desactiva el límite).

---

## 6) Cómo comprobar alquileres (si “no aparecen”)

1. Ir a `/dashboard?op=rent`.
2. Ejecutar scraping de alquiler:
   - botón “Escanear ahora” en modo alquiler, o endpoint `/api/scraper/scrape/rent`.
3. Revisar logs en `/api/scraper/logs` y estado en `/api/scraper/status`.
4. Confirmar que hay portales activos en `/dashboard/portals`.
5. Quitar filtros restrictivos (portal, municipio, zona Valencia, precio).

Nota: si no hay datos de alquiler tras scrapeo, suele deberse a:
- bloqueo anti-bot temporal del portal,
- páginas sin resultados para una zona concreta,
- cambio de estructura HTML en un portal.

Sólo se ejecutan en alquiler los scrapers que tienen URL y clasificación de
operación específicas. La vista de salud muestra `Operación no soportada` para
los portales que únicamente implementan venta.

---

## 7) Modelo de datos clave

Tabla `properties` (campos relevantes):
- `title`, `price`, `location`, `municipality`, `property_type`
- `operation_type` (`sale` o `rent`)
- `source`, `url`, `lat`, `lng`
- `deleted_at` para archivo lógico

El archivado de anuncios obsoletos está aislado por `source` y
`operation_type`: un ciclo de venta no puede archivar alquileres. Si un anuncio
archivado vuelve a aparecer, el `upsert` lo reactiva (`deleted_at = NULL`).

---

## 8) Scheduler y mantenimiento

- Scheduler automático configurado en `schedulerService`.
- Una ejecución diaria a `SCRAPING_DAILY_TIME=01:00`, usando
  `SCRAPING_TIMEZONE=Europe/Madrid` y sin solapar ciclos.
- Por defecto ejecuta `rent,sale` (prioriza actualizar alquileres); se puede limitar con
  `SCRAPING_OPERATIONS=sale`, `SCRAPING_OPERATIONS=rent` o
  `SCRAPING_OPERATIONS=rent,sale`.
- Purga diaria de archivo (>30 días).
- Idealista, Fotocasa y Habitaclia reutilizan una única sesión por ciclo. Ante
  403/429 o challenge confirmado se detiene el portal y se aplica una
  cuarentena (`SCRAPER_CHALLENGE_COOLDOWN_MINUTES`, 360 por defecto); no se
  resuelven CAPTCHAs ni se falsifican cookies.
- Re-geocodificación disponible vía endpoint.

---

## 9) API de propiedades (resumen)

- `GET /api/properties/dt`
  - filtros soportados:
    - `f_op`, `f_muni`, `f_tipo`, `f_pmin`, `f_pmax`, `f_rooms`, `f_portal`, `f_valencia_zone`
- `GET /api/properties/:id`
- `DELETE /api/properties/:id` (archivar)
- `PATCH /api/properties/:id/restore`
- `DELETE /api/properties/:id/forcedelete`

---

## 10) Buenas prácticas operativas

- Ejecutar scrapeos por operación separada (`sale` y `rent`).
- Revisar periódicamente portales activos.
- Mantener zonas y slugs actualizados desde la vista de zonas.
- Usar filtros guardados para consultas frecuentes.
- Revisar logs tras cambios de scraper o bloqueo anti-bot.

