# Backoffice Preventivi — Architettura, ambienti e deploy Questo documento descrive il sistema di preventivi collegato al configuratore: come sono collegati i componenti, come vengono serviti e cosa serve per portarlo in produzione. Per il modello dati, l'API e il flusso applicativo dettagliato vedi [`backoffice/README.md`](../backoffice/README.md). Per il contratto dei parametri URL del configuratore vedi [`URL_PARAMS.md`](./URL_PARAMS.md). ## Architettura: un solo server ``` Backend Laravel (backoffice/) — unica origine ┌──────────────────────────────────────────────────────────────────────────────────┐ │ /configuratore/ build statica del configuratore 3D (root repo, Vite+Three.js) │ │ /preventivo/ build statica dell'app cliente (backoffice/cliente, Vue 3) │ │ /api/... API catalogo, prezzi, carrello, auth │ │ /admin pannello Filament │ └──────────────────────────────────────────────────────────────────────────────────┘ ``` | Componente | Sorgenti | Build in | URL | |---|---|---|---| | Configuratore 3D | `/` (root repo, `src/`) | `backoffice/public/configuratore/` | `/configuratore/?sistema=…&type=…` | | App cliente (preventivo) | `backoffice/cliente/` | `backoffice/public/preventivo/` | `/preventivo/?token=…` | | Backend (API + admin) | `backoffice/` | — | `/api`, `/admin` | I due frontend restano progetti Vite separati, ma vengono compilati dentro `backoffice/public` e serviti da Laravel: un solo dominio, un solo processo, nessun CORS tra frontend e API. Il configuratore e l'app cliente non si parlano direttamente: il configuratore scrive nel carrello via API, l'app cliente lo legge via API; il collegamento tra i due è il `token` passato in query string nel link "Vai al preventivo". ### Come vengono serviti - I file statici (`/configuratore/assets/…`, `/preventivo/assets/…`) li serve direttamente il web server (o `php artisan serve`), come qualsiasi file in `public/`. - L'`index.html` di ciascun frontend è servito dalle route `configuratore` e `preventivo` in [`backoffice/routes/web.php`](../backoffice/routes/web.php) (`Cache-Control: no-cache`, così una nuova build è visibile subito; gli asset hanno nomi con hash). Se la build manca rispondono 404. - La home `/` reindirizza a `/configuratore/`, conservando eventuali parametri (`/?sistema=pvc` → `/configuratore/?sistema=pvc`). Senza parametri il configuratore apre il primo sistema e modello attivi. - Il configuratore usa path runtime relativi (`./assets/…`), quindi l'URL deve finire con `/`: Apache/nginx reindirizzano `/configuratore` → `/configuratore/`, e uno script inline in `src/index.html` aggiunge lo slash anche quando il server non lo fa (es. `php artisan serve`). ### URL dell'API e dell'app cliente - **Configuratore → API**: di default `${location.origin}/api` ([`src/js/api_base.js`](../src/js/api_base.js)). Override possibili: `VITE_PREVENTIVI_API_BASE` a build time (`.env*` nella root del repo) o `window.PREVENTIVI_API_BASE` a runtime — servono solo se l'API sta su un altro dominio. - **App cliente → API**: di default `${location.origin}/api` ([`backoffice/cliente/src/api.js`](../backoffice/cliente/src/api.js)), override con `VITE_API_BASE`. - **Configuratore → app cliente**: il link "Vai al preventivo" usa `frontend_cliente_url` restituito da `GET /api/config` ([`backoffice/config/preventivi.php`](../backoffice/config/preventivi.php)), che di default vale `APP_URL/preventivo`. Fallback se l'API non risponde: `${location.origin}/preventivo`. ## Sviluppo `./dev.sh` dalla root avvia `php artisan serve --port=8000` e i due `vite build --watch`: ogni modifica ai sorgenti ricompila il frontend in `backoffice/public/…`; basta ricaricare la pagina (non c'è HMR). Dettagli in [AVVIO_LOCALE.md](AVVIO_LOCALE.md). ## Variabili d'ambiente ### Backend Laravel (`backoffice/.env`) | Variabile | Descrizione | Default | |---|---|---| | `APP_URL` | URL pubblico del backend: base per link nelle email, `/preventivo` e `/configuratore/` | — | | `APP_FRONTEND_CLIENTE_URL` | Solo se l'app cliente **non** è servita dal backend | `APP_URL/preventivo` | | `APP_CONFIGURATORE_URL` | Link "Configuratore" nel menu admin, solo se servito altrove | `APP_URL/configuratore/` | | `ADMIN_NOTIFY_EMAIL` | Email che riceve la notifica di nuovo preventivo | — | | `CORS_ALLOWED_ORIGINS` | Origini autorizzate all'API da domini **esterni** (i frontend serviti dal backend non ne hanno bisogno) | `*` | | `DB_*`, `MAIL_*` | Database e posta | — | ### Frontend Nessuna variabile necessaria. `VITE_PREVENTIVI_API_BASE` (root) e `VITE_API_BASE` (`backoffice/cliente`) restano disponibili solo per puntare a un'API su un dominio diverso. ## Deploy in produzione (Plesk + Git) Il deploy avviene con l'estensione Git di Plesk, che scarica l'intero repository. Le build dei frontend non sono in git: le genera `./build.sh` sul server dopo ogni pull. ### Configurazione una tantum in Plesk 1. **Git**: repository collegato al dominio, cartella di deploy es. `kreios/`. 2. **Hosting**: Document root = `kreios/backoffice/public`, PHP 8.3+. 3. **Node.js**: estensione Node.js di Plesk (versione 22) e accesso SSH dell'utente della subscription con shell `/bin/bash` (non chroot, altrimenti `/opt/plesk/node` non è visibile). pnpm non va installato: `build.sh` usa `npx pnpm@10.34.7`, la versione dei lockfile (`lockfileVersion: '9.0'`), qualunque pnpm sia presente sulla macchina. 4. **`.env`** creato a mano in `kreios/backoffice/.env` (`APP_ENV=production`, `APP_DEBUG=false`, `APP_URL`, `DB_*`, `MAIL_*`, `ADMIN_NOTIFY_EMAIL`), poi una volta sola: `php artisan key:generate`, `php artisan storage:link`, `php artisan db:seed --force` (admin, catalogo e immagini del configuratore). 5. **Azioni di deploy aggiuntive** (Git → impostazioni del repository). Esempio, da adattare ai percorsi di PHP/Node del server: ```bash export PATH=/opt/plesk/node/22/bin:$PATH PHP=/opt/plesk/php/8.3/bin/php (cd backoffice && composer install --no-dev --optimize-autoloader --no-interaction) # svuota tutte le cache di Laravel (config, route, view, eventi, cache applicativa, compilati) (cd backoffice && $PHP artisan optimize:clear) # esegue solo le migrazioni non ancora applicate (--force: richiesto in produzione) (cd backoffice && $PHP artisan migrate --force) (cd backoffice && $PHP artisan optimize && $PHP artisan queue:restart) ./build.sh ``` `build.sh` installa le dipendenze con `pnpm install --frozen-lockfile`: se `package.json` cambia, va committato anche il `pnpm-lock.yaml` aggiornato (generato con pnpm 10), altrimenti il deploy fallisce. Durante la build le cartelle `public/configuratore` e `public/preventivo` vengono svuotate e riscritte: per qualche secondo le due pagine non sono disponibili. ### Dopo ogni deploy - Nel sito `kreiosinfissi.it` l'iframe punta a `https:///configuratore/?sistema=…&type=…`. - Restringere `CORS_ALLOWED_ORIGINS` (o lasciarlo vuoto) se nessun dominio esterno usa l'API. - Verifica end-to-end: configurare un prodotto → "Aggiungi al preventivo" → "Vai al preventivo" apre `/preventivo/` sullo stesso dominio → completare il checkout → il preventivo compare in Filament e le email (cliente + admin) sono inviate. ## Riferimenti file - [`backoffice/routes/web.php`](../backoffice/routes/web.php) — route `/configuratore/` e `/preventivo/`. - [`vite.config.js`](../vite.config.js), [`backoffice/cliente/vite.config.js`](../backoffice/cliente/vite.config.js) — `base` e `outDir` dentro `backoffice/public`. - [`src/js/api_base.js`](../src/js/api_base.js), [`backoffice/cliente/src/api.js`](../backoffice/cliente/src/api.js) — base URL dell'API. - [`src/js/starter.js`](../src/js/starter.js) — integrazione configuratore↔backend, link all'app cliente. - [`backoffice/config/preventivi.php`](../backoffice/config/preventivi.php) — `frontend_cliente_url`, `configuratore_url`. - [`build.sh`](../build.sh), [`dev.sh`](../dev.sh) — build dei frontend (anche su Plesk) e ambiente di sviluppo.