# 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.