{ "openapi": "3.0.3", "info": { "title": "API Gestione Rimborsi Spese Aziendali", "version": "1.0.0", "description": "Backend prova pratica S5 – Gestione rimborsi spese aziendali" }, "servers": [ { "url": "http://localhost:3003", "description": "Sviluppo locale" } ], "tags": [ { "name": "Sistema", "description": "Health check" }, { "name": "Autenticazione", "description": "Login e sessione Auth.js" }, { "name": "Utenti", "description": "Registrazione e profilo" }, { "name": "Categorie", "description": "Categorie di spesa" }, { "name": "Rimborsi", "description": "Richieste di rimborso" }, { "name": "Statistiche", "description": "Report amministrativi" } ], "components": { "securitySchemes": { "cookieAuth": { "type": "apiKey", "in": "cookie", "name": "authjs.session-token", "description": "Cookie di sessione impostato dopo il login. In produzione il nome può essere __Secure-authjs.session-token." } }, "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string" } }, "required": ["error"] }, "Message": { "type": "object", "properties": { "message": { "type": "string" } }, "required": ["message"] }, "Ruolo": { "type": "string", "enum": ["DIPENDENTE", "RESPONSABILE_AMMINISTRATIVO"] }, "StatoRichiesta": { "type": "string", "enum": ["IN_ATTESA", "APPROVATA", "RIFIUTATA", "LIQUIDATA"] }, "Utente": { "type": "object", "properties": { "id": { "type": "integer" }, "nome": { "type": "string" }, "cognome": { "type": "string" }, "email": { "type": "string", "format": "email" }, "ruolo": { "$ref": "#/components/schemas/Ruolo" } }, "required": ["id", "nome", "cognome", "email", "ruolo"] }, "UtenteSintetico": { "type": "object", "properties": { "id": { "type": "integer" }, "nome": { "type": "string" }, "cognome": { "type": "string" } }, "required": ["id", "nome", "cognome"] }, "RegistrazioneInput": { "type": "object", "required": ["nome", "cognome", "email", "password", "confermaPassword"], "properties": { "nome": { "type": "string", "example": "Mario" }, "cognome": { "type": "string", "example": "Rossi" }, "email": { "type": "string", "format": "email", "example": "mario.rossi@azienda.it" }, "password": { "type": "string", "format": "password" }, "confermaPassword": { "type": "string", "format": "password" }, "ruolo": { "$ref": "#/components/schemas/Ruolo" } } }, "RegistrazioneResponse": { "type": "object", "properties": { "message": { "type": "string" }, "utente": { "$ref": "#/components/schemas/Utente" } }, "required": ["message", "utente"] }, "CategoriaSpesa": { "type": "object", "properties": { "id": { "type": "integer" }, "descrizione": { "type": "string" } }, "required": ["id", "descrizione"] }, "Rimborso": { "type": "object", "properties": { "id": { "type": "integer" }, "dataInserimento": { "type": "string", "format": "date-time" }, "dataSpesa": { "type": "string", "format": "date" }, "categoriaId": { "type": "integer" }, "categoria": { "type": "string" }, "importo": { "type": "number" }, "descrizione": { "type": "string" }, "riferimentoGiustificativo": { "type": "string", "nullable": true }, "stato": { "$ref": "#/components/schemas/StatoRichiesta" }, "dipendenteId": { "type": "integer" }, "dipendenteNome": { "type": "string" }, "dataValutazione": { "type": "string", "format": "date-time", "nullable": true }, "responsabileValutazioneId": { "type": "integer", "nullable": true }, "responsabileNome": { "type": "string", "nullable": true }, "motivazioneRifiuto": { "type": "string", "nullable": true }, "dataLiquidazione": { "type": "string", "format": "date-time", "nullable": true } }, "required": [ "id", "dataInserimento", "dataSpesa", "categoriaId", "categoria", "importo", "descrizione", "stato", "dipendenteId", "dipendenteNome" ] }, "RimborsoInput": { "type": "object", "required": ["dataSpesa", "categoriaId", "importo", "descrizione"], "properties": { "dataSpesa": { "type": "string", "format": "date", "example": "2025-06-01" }, "categoriaId": { "type": "integer", "example": 1 }, "importo": { "type": "number", "minimum": 0.01, "example": 45.5 }, "descrizione": { "type": "string", "example": "Pranzo di lavoro con cliente" }, "riferimentoGiustificativo": { "type": "string", "nullable": true, "example": "FATT-2025-001" } } }, "RifiutaInput": { "type": "object", "properties": { "motivazione": { "type": "string", "nullable": true, "example": "Manca il giustificativo" } } }, "StatisticaRimborso": { "type": "object", "properties": { "mese": { "type": "string", "example": "2025-06" }, "categoria": { "type": "string" }, "numeroRichieste": { "type": "integer" }, "totaleRichiesto": { "type": "number" }, "totaleApprovato": { "type": "number" }, "totaleLiquidato": { "type": "number" } }, "required": [ "mese", "categoria", "numeroRichieste", "totaleRichiesto", "totaleApprovato", "totaleLiquidato" ] }, "CsrfResponse": { "type": "object", "properties": { "csrfToken": { "type": "string" } }, "required": ["csrfToken"] } }, "responses": { "Unauthorized": { "description": "Autenticazione richiesta", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "Operazione non consentita per il ruolo corrente", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "NotFound": { "description": "Risorsa non trovata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Richiesta non valida", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "paths": { "/api/health": { "get": { "tags": ["Sistema"], "summary": "Health check", "responses": { "200": { "description": "Servizio attivo", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "ok" } } } } } } } } }, "/api/auth/csrf": { "get": { "tags": ["Autenticazione"], "summary": "Ottieni token CSRF per login/logout", "responses": { "200": { "description": "Token CSRF", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CsrfResponse" } } } } } } }, "/api/auth/callback/credentials": { "post": { "tags": ["Autenticazione"], "summary": "Login con email e password", "description": "Invia i dati come application/x-www-form-urlencoded. Imposta il cookie di sessione in caso di successo.", "requestBody": { "required": true, "content": { "application/x-www-form-urlencoded": { "schema": { "type": "object", "required": ["csrfToken", "email", "password"], "properties": { "csrfToken": { "type": "string" }, "email": { "type": "string", "format": "email" }, "password": { "type": "string", "format": "password" }, "redirect": { "type": "string", "example": "false" } } } } } }, "responses": { "200": { "description": "Login riuscito" }, "401": { "description": "Credenziali non valide" } } } }, "/api/auth/signout": { "post": { "tags": ["Autenticazione"], "summary": "Logout", "requestBody": { "required": true, "content": { "application/x-www-form-urlencoded": { "schema": { "type": "object", "required": ["csrfToken"], "properties": { "csrfToken": { "type": "string" } } } } } }, "responses": { "200": { "description": "Logout effettuato" } } } }, "/api/utenti/register": { "post": { "tags": ["Utenti"], "summary": "Registrazione nuovo utente", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegistrazioneInput" } } } }, "responses": { "201": { "description": "Utente registrato", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegistrazioneResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "409": { "description": "Email già registrata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/api/utenti/me": { "get": { "tags": ["Utenti"], "summary": "Profilo utente corrente", "responses": { "200": { "description": "Profilo utente", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Utente" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } } } }, "/api/utenti/dipendenti": { "get": { "tags": ["Utenti"], "summary": "Elenco dipendenti", "description": "Solo per RESPONSABILE_AMMINISTRATIVO", "security": [{ "cookieAuth": [] }], "responses": { "200": { "description": "Lista dipendenti", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/UtenteSintetico" } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } } } }, "/api/categorie-spesa": { "get": { "tags": ["Categorie"], "summary": "Elenco categorie di spesa", "security": [{ "cookieAuth": [] }], "responses": { "200": { "description": "Lista categorie", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CategoriaSpesa" } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } } } }, "/api/rimborsi": { "get": { "tags": ["Rimborsi"], "summary": "Elenco richieste di rimborso", "security": [{ "cookieAuth": [] }], "parameters": [ { "name": "stato", "in": "query", "schema": { "$ref": "#/components/schemas/StatoRichiesta" } }, { "name": "categoriaId", "in": "query", "schema": { "type": "integer" } }, { "name": "mese", "in": "query", "description": "Formato YYYY-MM", "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}$", "example": "2025-06" } }, { "name": "dipendenteId", "in": "query", "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Lista rimborsi", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Rimborso" } } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" } } }, "post": { "tags": ["Rimborsi"], "summary": "Crea nuova richiesta di rimborso", "description": "Solo per DIPENDENTE", "security": [{ "cookieAuth": [] }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RimborsoInput" } } } }, "responses": { "201": { "description": "Richiesta creata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Rimborso" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } } } }, "/api/rimborsi/{id}": { "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "get": { "tags": ["Rimborsi"], "summary": "Dettaglio richiesta di rimborso", "security": [{ "cookieAuth": [] }], "responses": { "200": { "description": "Dettaglio rimborso", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Rimborso" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "put": { "tags": ["Rimborsi"], "summary": "Modifica richiesta (solo stato IN_ATTESA)", "security": [{ "cookieAuth": [] }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RimborsoInput" } } } }, "responses": { "200": { "description": "Richiesta aggiornata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Rimborso" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "delete": { "tags": ["Rimborsi"], "summary": "Elimina richiesta (solo stato IN_ATTESA)", "security": [{ "cookieAuth": [] }], "responses": { "200": { "description": "Richiesta eliminata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Message" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/api/rimborsi/{id}/approva": { "put": { "tags": ["Rimborsi"], "summary": "Approva richiesta", "description": "Solo RESPONSABILE_AMMINISTRATIVO. La richiesta deve essere IN_ATTESA.", "security": [{ "cookieAuth": [] }], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Richiesta approvata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Rimborso" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } } } }, "/api/rimborsi/{id}/rifiuta": { "put": { "tags": ["Rimborsi"], "summary": "Rifiuta richiesta", "description": "Solo RESPONSABILE_AMMINISTRATIVO. La richiesta deve essere IN_ATTESA.", "security": [{ "cookieAuth": [] }], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RifiutaInput" } } } }, "responses": { "200": { "description": "Richiesta rifiutata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Rimborso" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } } } }, "/api/rimborsi/{id}/liquida": { "put": { "tags": ["Rimborsi"], "summary": "Liquida richiesta approvata", "description": "Solo RESPONSABILE_AMMINISTRATIVO. La richiesta deve essere APPROVATA.", "security": [{ "cookieAuth": [] }], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Richiesta liquidata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Rimborso" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } } } }, "/api/statistiche/rimborsi": { "get": { "tags": ["Statistiche"], "summary": "Statistiche rimborsi aggregate", "description": "Solo RESPONSABILE_AMMINISTRATIVO", "security": [{ "cookieAuth": [] }], "parameters": [ { "name": "mese", "in": "query", "description": "Formato YYYY-MM", "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}$", "example": "2025-06" } }, { "name": "categoriaId", "in": "query", "schema": { "type": "integer" } }, { "name": "dipendenteId", "in": "query", "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Statistiche aggregate", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/StatisticaRimborso" } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } } } } } }