Files
Condopay/docs/API.md
2026-02-16 09:15:18 +01:00

1752 lines
28 KiB
Markdown

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