diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..6e75e2b --- /dev/null +++ b/docs/API.md @@ -0,0 +1,1751 @@ +# CondoPay — Documentazione API completa + +Questa documentazione descrive tutti gli endpoint API disponibili nella soluzione CondoPay. + +--- + +## Indice + +1. [Configurazione base](#configurazione-base) +2. [Autenticazione](#autenticazione) +3. [Endpoint pubblici](#endpoint-pubblici) +4. [Autenticazione e profilo](#autenticazione-e-profilo) +5. [Impostazioni](#impostazioni) +6. [Condomini](#condomini) +7. [Famiglie](#famiglie) +8. [Pagamenti](#pagamenti) +9. [Utenti](#utenti) +10. [Avvisi](#avvisi) +11. [Comunicazioni](#comunicazioni) +12. [Ticket](#ticket) +13. [Spese straordinarie](#spese-straordinarie) +14. [Spese condominiali ordinarie](#spese-condominiali-ordinarie) +15. [Documenti](#documenti) + +--- + +## Configurazione base + +| Proprietà | Valore | +|-----------|--------| +| **Base URL** | `/api` (relativo all'host dell'applicazione) | +| **Content-Type** | `application/json` | +| **Formato risposta** | JSON | + +### Header di autenticazione + +Tutti gli endpoint protetti richiedono l'header: + +``` +Authorization: Bearer +``` + +Il token viene restituito dall'endpoint `POST /api/auth/login`. + +--- + +## Autenticazione + +### Token JWT + +- **Scadenza**: 24 ore +- **Contenuto**: `{ id, email, role, familyId }` +- **Ruoli**: `admin`, `poweruser`, `user` + +### Middleware + +- **authenticateToken**: richiede un token valido (restituisce 401 se mancante o non valido) +- **requireAdmin**: richiede ruolo `admin` o `poweruser` (restituisce 403 se insufficiente) + +--- + +## Endpoint pubblici + +### GET /api/public/branding + +Restituisce il branding dell'applicazione (senza autenticazione). + +**Autenticazione**: Non richiesta + +**Risposta** `200 OK`: +```json +{ + "appName": "CondoPay", + "primaryColor": "blue", + "logoUrl": "", + "loginBackgroundUrl": "" +} +``` + +--- + +## Autenticazione e profilo + +### POST /api/auth/login + +Effettua il login con email e password. + +**Autenticazione**: Non richiesta + +**Body**: +```json +{ + "email": "string", + "password": "string" +} +``` + +**Risposta** `200 OK`: +```json +{ + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": "string", + "email": "string", + "name": "string", + "role": "admin | poweruser | user", + "familyId": "string | null", + "receiveAlerts": true + } +} +``` + +**Errori**: +- `401`: Credenziali non valide +- `500`: Errore server + +--- + +### PUT /api/profile + +Aggiorna il profilo dell'utente autenticato. + +**Autenticazione**: Richiesta + +**Body**: +```json +{ + "name": "string", + "phone": "string", + "password": "string (opzionale - solo se si cambia password)", + "receiveAlerts": true +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true, + "user": { + "id": "string", + "email": "string", + "name": "string", + "role": "string", + "phone": "string", + "family_id": "string", + "receiveAlerts": true + } +} +``` + +--- + +## Impostazioni + +### GET /api/settings + +Restituisce le impostazioni generali dell'applicazione. + +**Autenticazione**: Richiesta + +**Risposta** `200 OK`: +```json +{ + "currentYear": 2025, + "smtpConfig": { + "host": "string", + "port": 587, + "user": "string", + "pass": "string", + "secure": false, + "fromEmail": "string" + }, + "storageConfig": { + "provider": "local_db | s3 | google_drive | dropbox | onedrive", + "apiKey": "string", + "apiSecret": "string", + "bucket": "string", + "region": "string" + }, + "features": { + "multiCondo": true, + "tickets": true, + "payPal": true, + "notices": true, + "reports": true, + "extraordinaryExpenses": true, + "condoFinancialsView": false, + "documents": true + }, + "branding": { + "appName": "CondoPay", + "primaryColor": "blue", + "logoUrl": "", + "loginBackgroundUrl": "" + } +} +``` + +**Errori**: +- `404`: Settings non trovati +- `500`: Errore server + +--- + +### PUT /api/settings + +Aggiorna le impostazioni generali. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "currentYear": 2025, + "smtpConfig": { }, + "features": { }, + "storageConfig": { }, + "branding": { } +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +**Errori**: +- `403`: Accesso negato +- `500`: Errore server + +--- + +### POST /api/settings/smtp-test + +Invia un'email di test per verificare la configurazione SMTP. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "host": "smtp.example.com", + "port": 587, + "user": "string", + "pass": "string", + "secure": false, + "fromEmail": "string" +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +**Errori**: +- `400`: Parametri SMTP incompleti o errore invio +- `403`: Accesso negato + +--- + +### GET /api/years + +Restituisce gli anni disponibili per i pagamenti (anni con almeno un pagamento o anno corrente dalle impostazioni). + +**Autenticazione**: Richiesta + +**Risposta** `200 OK`: +```json +[2025, 2024, 2023] +``` + +--- + +## Condomini + +### GET /api/condos + +Elenco di tutti i condomini. + +**Autenticazione**: Richiesta + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "name": "string", + "address": "string", + "streetNumber": "string", + "city": "string", + "province": "string", + "zipCode": "string", + "notes": "string", + "iban": "string", + "paypalClientId": "string", + "defaultMonthlyQuota": 100.00, + "image": "string", + "dueDay": 10 + } +] +``` + +--- + +### POST /api/condos + +Crea un nuovo condominio. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "name": "string", + "address": "string", + "streetNumber": "string", + "city": "string", + "province": "string", + "zipCode": "string", + "notes": "string", + "defaultMonthlyQuota": 100.00, + "paypalClientId": "string", + "dueDay": 10 +} +``` + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "name": "string", + "address": "string", + "streetNumber": "string", + "city": "string", + "province": "string", + "zipCode": "string", + "notes": "string", + "defaultMonthlyQuota": 100.00, + "paypalClientId": "string", + "dueDay": 10 +} +``` + +--- + +### PUT /api/condos/:id + +Aggiorna un condominio esistente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID del condominio + +**Body**: +```json +{ + "name": "string", + "address": "string", + "streetNumber": "string", + "city": "string", + "province": "string", + "zipCode": "string", + "notes": "string", + "defaultMonthlyQuota": 100.00, + "paypalClientId": "string", + "dueDay": 10 +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### DELETE /api/condos/:id + +Elimina un condominio. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID del condominio + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Famiglie + +### GET /api/families + +Elenco delle famiglie. Per admin/poweruser può essere filtrato per condominio; per utenti normali restituisce solo la propria famiglia. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio (opzionale, per admin/poweruser) | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "condoId": "uuid", + "name": "string", + "unitNumber": "string", + "stair": "string", + "floor": "string", + "notes": "string", + "contactEmail": "string", + "customMonthlyQuota": 120.00, + "balance": 0 + } +] +``` + +--- + +### POST /api/families + +Crea una nuova famiglia. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "condoId": "uuid", + "name": "string", + "unitNumber": "string", + "stair": "string", + "floor": "string", + "notes": "string", + "contactEmail": "string", + "customMonthlyQuota": 120.00 +} +``` + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "condoId": "uuid", + "name": "string", + "unitNumber": "string", + "stair": "string", + "floor": "string", + "notes": "string", + "contactEmail": "string", + "customMonthlyQuota": 120.00 +} +``` + +--- + +### PUT /api/families/:id + +Aggiorna una famiglia esistente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della famiglia + +**Body**: +```json +{ + "name": "string", + "unitNumber": "string", + "stair": "string", + "floor": "string", + "notes": "string", + "contactEmail": "string", + "customMonthlyQuota": 120.00 +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### DELETE /api/families/:id + +Elimina una famiglia. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della famiglia + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Pagamenti + +### GET /api/payments + +Elenco dei pagamenti (quota condominiale ordinaria). + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| familyId | string | Filtra per famiglia | +| condoId | string | Filtra per condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "familyId": "uuid", + "amount": 100.00, + "datePaid": "2025-01-15T00:00:00.000Z", + "forMonth": 1, + "forYear": 2025, + "notes": "string" + } +] +``` + +--- + +### POST /api/payments + +Registra un nuovo pagamento di quota ordinaria. + +**Autenticazione**: Richiesta + +**Body**: +```json +{ + "familyId": "uuid", + "amount": 100.00, + "datePaid": "2025-01-15", + "forMonth": 1, + "forYear": 2025, + "notes": "string" +} +``` + +**Restrizioni**: Gli utenti non admin possono registrare pagamenti solo per la propria famiglia (`familyId` deve coincidere con `req.user.familyId`). + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "familyId": "uuid", + "amount": 100.00, + "datePaid": "2025-01-15", + "forMonth": 1, + "forYear": 2025, + "notes": "string" +} +``` + +**Errori**: +- `403`: Unauthorized (utente che tenta di registrare per un'altra famiglia) + +--- + +## Utenti + +### GET /api/users + +Elenco degli utenti. Può essere filtrato per condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | Restituisce utenti del condominio + admin/poweruser | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "email": "string", + "name": "string", + "role": "admin | poweruser | user", + "phone": "string", + "familyId": "uuid | null", + "receiveAlerts": true + } +] +``` + +--- + +### POST /api/users + +Crea un nuovo utente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "email": "string", + "password": "string", + "name": "string", + "role": "admin | poweruser | user", + "phone": "string", + "familyId": "uuid | null", + "receiveAlerts": true +} +``` + +**Nota**: Se `password` non viene fornita, viene usata `"password"`. + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +--- + +### PUT /api/users/:id + +Aggiorna un utente esistente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID dell'utente + +**Body**: +```json +{ + "email": "string", + "name": "string", + "role": "admin | poweruser | user", + "phone": "string", + "familyId": "uuid | null", + "receiveAlerts": true, + "password": "string (opzionale - solo se si cambia password)" +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### DELETE /api/users/:id + +Elimina un utente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID dell'utente + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Avvisi + +Gli avvisi sono definizioni di email automatiche (es. promemoria scadenza quote). + +### GET /api/alerts + +Elenco degli avvisi configurati per un condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "subject": "string", + "body": "string", + "daysOffset": 1, + "offsetType": "before_next_month", + "sendHour": 9, + "active": true, + "lastSent": "2025-01-01T09:00:00.000Z" + } +] +``` + +--- + +### POST /api/alerts + +Crea un nuovo avviso. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "condoId": "uuid", + "subject": "string", + "body": "string", + "daysOffset": 1, + "offsetType": "before_next_month", + "sendHour": 9, + "active": true +} +``` + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "subject": "string", + "body": "string", + "daysOffset": 1, + "offsetType": "string", + "sendHour": 9, + "active": true +} +``` + +--- + +### PUT /api/alerts/:id + +Aggiorna un avviso esistente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID dell'avviso + +**Body**: +```json +{ + "subject": "string", + "body": "string", + "daysOffset": 1, + "offsetType": "string", + "sendHour": 9, + "active": true +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +--- + +### DELETE /api/alerts/:id + +Elimina un avviso. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID dell'avviso + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Comunicazioni (Notices) + +### GET /api/notices + +Elenco delle comunicazioni/avvisi per un condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "condoId": "uuid", + "title": "string", + "content": "string", + "type": "info | warning | maintenance | event", + "link": "string", + "date": "2025-01-15T00:00:00.000Z", + "active": true, + "targetFamilyIds": [] + } +] +``` + +--- + +### GET /api/notices/unread + +Elenco delle comunicazioni non lette per un utente in un condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| userId | string | ID dell'utente | +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "title": "string", + "content": "string", + "type": "info", + "date": "2025-01-15T00:00:00.000Z", + ... + } +] +``` + +--- + +### GET /api/notices/:id/read-status + +Stato di lettura di una comunicazione (chi l'ha letta). + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della comunicazione + +**Risposta** `200 OK`: +```json +[ + { + "userId": "uuid", + "readAt": "2025-01-15T10:00:00.000Z" + } +] +``` + +--- + +### POST /api/notices + +Crea una nuova comunicazione. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "condoId": "uuid", + "title": "string", + "content": "string", + "type": "info | warning | maintenance | event", + "link": "string", + "active": true, + "targetFamilyIds": ["uuid1", "uuid2"] +} +``` + +**Nota**: `targetFamilyIds` vuoto = comunicazione visibile a tutte le famiglie. + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +--- + +### PUT /api/notices/:id + +Aggiorna una comunicazione esistente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della comunicazione + +**Body**: +```json +{ + "title": "string", + "content": "string", + "type": "info | warning | maintenance | event", + "link": "string", + "active": true, + "targetFamilyIds": [] +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### DELETE /api/notices/:id + +Elimina una comunicazione. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della comunicazione + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### POST /api/notices/:id/read + +Segna una comunicazione come letta per un utente. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID della comunicazione + +**Body**: +```json +{ + "userId": "uuid" +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Ticket + +### GET /api/tickets + +Elenco dei ticket. Gli utenti non admin vedono solo i propri ticket. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "condoId": "uuid", + "userId": "uuid", + "title": "string", + "description": "string", + "status": "OPEN | IN_PROGRESS | SUSPENDED | RESOLVED | CLOSED", + "priority": "LOW | MEDIUM | HIGH | URGENT", + "category": "MAINTENANCE | ADMINISTRATIVE | NOISE | CLEANING | OTHER", + "createdAt": "2025-01-15T00:00:00.000Z", + "updatedAt": "2025-01-15T00:00:00.000Z", + "userName": "string", + "userEmail": "string", + "attachments": [ + { + "id": "uuid", + "fileName": "string", + "fileType": "string" + } + ] + } +] +``` + +--- + +### POST /api/tickets + +Crea un nuovo ticket. + +**Autenticazione**: Richiesta + +**Body**: +```json +{ + "condoId": "uuid", + "title": "string", + "description": "string", + "priority": "LOW | MEDIUM | HIGH | URGENT", + "category": "MAINTENANCE | ADMINISTRATIVE | NOISE | CLEANING | OTHER", + "attachments": [ + { + "fileName": "string", + "fileType": "string", + "data": "base64-string" + } + ] +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +--- + +### PUT /api/tickets/:id + +Aggiorna stato e priorità di un ticket. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID del ticket + +**Body**: +```json +{ + "status": "OPEN | IN_PROGRESS | SUSPENDED | RESOLVED | CLOSED", + "priority": "LOW | MEDIUM | HIGH | URGENT" +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### DELETE /api/tickets/:id + +Elimina un ticket. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID del ticket + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### GET /api/tickets/:id/attachments/:attId + +Scarica un allegato di un ticket. + +**Autenticazione**: Richiesta + +**Parametri percorso**: +- `id` — ID del ticket +- `attId` — ID dell'allegato + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "fileName": "string", + "fileType": "string", + "data": "base64-string" +} +``` + +**Errori**: `404` — Allegato non trovato + +--- + +### GET /api/tickets/:id/comments + +Elenco dei commenti di un ticket. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID del ticket + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "ticketId": "uuid", + "userId": "uuid", + "userName": "string", + "text": "string", + "createdAt": "2025-01-15T00:00:00.000Z" + } +] +``` + +--- + +### POST /api/tickets/:id/comments + +Aggiunge un commento a un ticket. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID del ticket + +**Body**: +```json +{ + "text": "string" +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Spese straordinarie + +### GET /api/expenses + +Elenco delle spese straordinarie di un condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "condoId": "uuid", + "title": "string", + "description": "string", + "startDate": "2025-01-01", + "endDate": "2025-06-30", + "contractorName": "string", + "totalAmount": 5000.00 + } +] +``` + +--- + +### GET /api/expenses/:id + +Dettaglio di una spesa straordinaria (con voci, quote per famiglia, allegati). + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID della spesa + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "condoId": "uuid", + "title": "string", + "description": "string", + "startDate": "2025-01-01", + "endDate": "2025-06-30", + "contractorName": "string", + "totalAmount": 5000.00, + "items": [ + { + "description": "string", + "amount": 2500.00 + } + ], + "shares": [ + { + "id": "uuid", + "familyId": "uuid", + "familyName": "string", + "percentage": 10.00, + "amountDue": 500.00, + "amountPaid": 0, + "status": "UNPAID | PARTIAL | PAID" + } + ], + "attachments": [ + { + "id": "uuid", + "fileName": "string", + "fileType": "string" + } + ] +} +``` + +**Errori**: `404` — Spesa non trovata + +--- + +### POST /api/expenses + +Crea una nuova spesa straordinaria. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "condoId": "uuid", + "title": "string", + "description": "string", + "startDate": "2025-01-01", + "endDate": "2025-06-30", + "contractorName": "string", + "items": [ + { + "description": "string", + "amount": 2500.00 + } + ], + "shares": [ + { + "familyId": "uuid", + "percentage": 10.00, + "amountDue": 500.00 + } + ], + "attachments": [ + { + "fileName": "string", + "fileType": "string", + "data": "base64-string" + } + ] +} +``` + +**Nota**: `totalAmount` è calcolato automaticamente dalla somma di `items`. + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +--- + +### DELETE /api/expenses/:id + +Elimina una spesa straordinaria. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della spesa + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### GET /api/expenses/:id/attachments/:attId + +Scarica un allegato di una spesa straordinaria. + +**Autenticazione**: Richiesta + +**Parametri percorso**: +- `id` — ID della spesa +- `attId` — ID dell'allegato + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "fileName": "string", + "fileType": "string", + "data": "base64-string" +} +``` + +**Errori**: `404` — File non trovato + +--- + +### GET /api/my-expenses + +Elenco delle quote straordinarie assegnate alla famiglia dell'utente loggato. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "title": "string", + "startDate": "2025-01-01", + "totalAmount": 5000.00, + "contractorName": "string", + "myShare": { + "percentage": 10.00, + "amountDue": 500.00, + "amountPaid": 0, + "status": "UNPAID" + } + } +] +``` + +--- + +### POST /api/expenses/:id/pay + +Registra un pagamento per una quota straordinaria. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID della spesa straordinaria + +**Body**: +```json +{ + "amount": 250.00, + "notes": "string", + "familyId": "uuid (opzionale - solo admin/poweruser)" +} +``` + +**Nota**: Gli utenti normali pagano per la propria famiglia; admin/poweruser possono specificare `familyId`. + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +**Errori**: +- `400`: Famiglia non trovata +- `500`: Share non trovata o errore + +--- + +### GET /api/expenses/:id/shares/:familyId/payments + +Elenco dei pagamenti effettuati per una quota straordinaria di una famiglia. + +**Autenticazione**: Richiesta + +**Parametri percorso**: +- `id` — ID della spesa +- `familyId` — ID della famiglia + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "amount": 250.00, + "datePaid": "2025-01-15T00:00:00.000Z", + "notes": "string" + } +] +``` + +--- + +### DELETE /api/expenses/payments/:paymentId + +Elimina un pagamento straordinario (annulla il pagamento e aggiorna lo stato della quota). + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `paymentId` — ID del pagamento + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +**Errori**: +- `400`: Pagamento non trovato o non è un pagamento straordinario + +--- + +## Spese condominiali ordinarie + +Gestione delle uscite ordinarie del condominio (utenze, fornitori, ecc.). + +### GET /api/condo-expenses + +Elenco delle spese ordinarie del condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | +| year | number | Anno (opzionale) | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "condoId": "uuid", + "description": "string", + "supplierName": "string", + "amount": 500.00, + "paymentDate": "2025-01-15", + "status": "PAID | UNPAID | SUSPENDED", + "paymentMethod": "string", + "invoiceNumber": "string", + "notes": "string", + "createdAt": "2025-01-15T00:00:00.000Z", + "attachments": [ + { + "id": "uuid", + "fileName": "string", + "fileType": "string" + } + ] + } +] +``` + +--- + +### POST /api/condo-expenses + +Crea una nuova spesa ordinaria. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "condoId": "uuid", + "description": "string", + "supplierName": "string", + "amount": 500.00, + "paymentDate": "2025-01-15", + "status": "PAID | UNPAID | SUSPENDED", + "paymentMethod": "string", + "invoiceNumber": "string", + "notes": "string", + "attachments": [ + { + "fileName": "string", + "fileType": "string", + "data": "base64-string" + } + ] +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +--- + +### PUT /api/condo-expenses/:id + +Aggiorna una spesa ordinaria esistente. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della spesa + +**Body**: +```json +{ + "description": "string", + "supplierName": "string", + "amount": 500.00, + "paymentDate": "2025-01-15", + "status": "PAID | UNPAID | SUSPENDED", + "paymentMethod": "string", + "invoiceNumber": "string", + "notes": "string" +} +``` + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### DELETE /api/condo-expenses/:id + +Elimina una spesa ordinaria. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID della spesa + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +### GET /api/condo-expenses/:id/attachments/:attId + +Scarica un allegato di una spesa ordinaria. + +**Autenticazione**: Richiesta + +**Parametri percorso**: +- `id` — ID della spesa +- `attId` — ID dell'allegato + +**Risposta** `200 OK`: +```json +{ + "id": "uuid", + "fileName": "string", + "fileType": "string", + "data": "base64-string" +} +``` + +**Errori**: `404` — File non trovato + +--- + +## Documenti + +Gestione documenti del condominio con supporto per storage locale (DB) e cloud (S3, Google Drive, Dropbox, OneDrive). + +### GET /api/documents + +Elenco dei documenti di un condominio. + +**Autenticazione**: Richiesta + +**Query parameters**: +| Parametro | Tipo | Descrizione | +|-----------|------|-------------| +| condoId | string | ID del condominio | + +**Risposta** `200 OK`: +```json +[ + { + "id": "uuid", + "condoId": "uuid", + "title": "string", + "description": "string", + "fileName": "string", + "fileType": "string", + "fileSize": 1024, + "tags": ["tag1", "tag2"], + "storageProvider": "local_db | s3 | google_drive | dropbox | onedrive", + "uploadDate": "2025-01-15T00:00:00.000Z" + } +] +``` + +--- + +### POST /api/documents + +Carica un nuovo document. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Body**: +```json +{ + "condoId": "uuid", + "title": "string", + "description": "string", + "fileName": "string", + "fileType": "string", + "fileSize": 1024, + "tags": ["tag1", "tag2"], + "fileData": "base64-string o data:...;base64,...", + "storageConfig": { + "provider": "local_db | s3 | google_drive | dropbox | onedrive", + "apiKey": "string", + "apiSecret": "string", + "bucket": "string", + "region": "string" + } +} +``` + +**Nota**: `storageConfig` viene solitamente passato dalle impostazioni correnti (`/api/settings`). Per `local_db` il file viene salvato nel database; per cloud viene caricato sul provider configurato. + +**Risposta** `200 OK`: +```json +{ + "success": true, + "id": "uuid" +} +``` + +**Errori**: +- `500`: Errore caricamento cloud + +--- + +### GET /api/documents/:id/download + +Scarica un document. + +**Autenticazione**: Richiesta + +**Parametri percorso**: `id` — ID del document + +**Risposta** `200 OK`: +```json +{ + "fileName": "string", + "fileType": "string", + "data": "base64-string o URL firmato (se isUrl: true)", + "isUrl": false +} +``` + +**Nota**: Per storage cloud, `data` può essere una URL firmata (es. S3) con `isUrl: true`, oppure base64 per altri provider. + +**Errori**: +- `404`: Document non trovato +- `500`: Errore download da storage cloud + +--- + +### DELETE /api/documents/:id + +Elimina un document. + +**Autenticazione**: Richiesta (admin/poweruser) + +**Parametri percorso**: `id` — ID del document + +**Risposta** `200 OK`: +```json +{ + "success": true +} +``` + +--- + +## Codici di errore HTTP + +| Codice | Descrizione | +|--------|-------------| +| 400 | Bad Request — Parametri mancanti o non validi | +| 401 | Unauthorized — Token mancante o non valido | +| 403 | Forbidden — Accesso negato (ruolo insufficiente o risorsa non accessibile) | +| 404 | Not Found — Risorsa non trovata | +| 500 | Internal Server Error — Errore lato server | + +--- + +## Note finali + +- **Limite body**: La richiesta supporta fino a 50MB per gestire upload di file in base64 (ticket, spese, documenti). +- **Database**: L'applicazione supporta MySQL e PostgreSQL; lo schema è compatibile con entrambi. +- **ID**: Gli ID delle entità sono UUID v4. +- **Date**: Le date sono in formato ISO 8601.