diff --git a/src/main/java/fr/unistra/sil/erp/back/DatabaseSystem.java b/src/main/java/fr/unistra/sil/erp/back/DatabaseSystem.java index 4cdb1f35f2e5c5e21acc56429545d2c7a4388238..e32e6a8aa5a5410eea224ef2db3cc13d14f34904 100644 --- a/src/main/java/fr/unistra/sil/erp/back/DatabaseSystem.java +++ b/src/main/java/fr/unistra/sil/erp/back/DatabaseSystem.java @@ -33,7 +33,7 @@ public class DatabaseSystem { DatabaseSystem.instance = new DatabaseSQLiteImpl(); if(DatabaseSystem.instance == null) - throw new DatabaseConnectionException(); + throw new DatabaseConnectionException("Failed to create DB."); return DatabaseSystem.instance; } diff --git a/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiErrorHandler.java b/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiErrorHandler.java index fbd17bf756a01709ade1816535a86f93c9e6ac7f..e3114b405da4c041301edc87e19bb9a5ab73b958 100644 --- a/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiErrorHandler.java +++ b/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiErrorHandler.java @@ -53,4 +53,19 @@ public class ApiErrorHandler { HttpStatus.BAD_REQUEST); } + /** + * Handler for HTTP 404 Not Found. + * @param ex the thrown Exception. + * @param request the HTTP Servlet request. + * @param response the HTTP Servlet response. + * @return the response to the client. + */ + @ExceptionHandler(ApiResourceNotFoundException.class) + public ResponseEntity<Object> handleResourceNotFound(Exception ex, + HttpServletRequest request, HttpServletResponse response) + { + return new ResponseEntity<>(new ErrorMessage(ex.getMessage()), + HttpStatus.NOT_FOUND); + } + } diff --git a/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiResourceNotFoundException.java b/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiResourceNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..0676ceff96fb6638645f806e561af0875cb133a7 --- /dev/null +++ b/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiResourceNotFoundException.java @@ -0,0 +1,28 @@ +/* + * CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B + * https://cecill.info/licences/Licence_CeCILL-B_V1-fr.html + */ +package fr.unistra.sil.erp.back.controller.api; + +/** + * API Exception for HTTP 404 Not Found. + * + * If a resource requested by the user does not exist, this exception + * is thrown and handled through ApiErrorHandler.class. + * + * @see ApiErrorHandler + * + * @author BEAUVAIS ANTOINE + */ +public class ApiResourceNotFoundException extends Exception { + + /** + * Class constructor. + * @param errMsg the error message. + */ + public ApiResourceNotFoundException(String errMsg) + { + super(errMsg); + } + +} diff --git a/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiSubmitTransactionController.java b/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiSubmitTransactionController.java index 33f6b5c7ff342d2c894671f32e694fbf3f2aebec..b39c3031d09cf32350521eb95e9bf2188969e7a1 100644 --- a/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiSubmitTransactionController.java +++ b/src/main/java/fr/unistra/sil/erp/back/controller/api/ApiSubmitTransactionController.java @@ -1,13 +1,19 @@ /* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + * CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B + * https://cecill.info/licences/Licence_CeCILL-B_V1-fr.html */ package fr.unistra.sil.erp.back.controller.api; import com.google.gson.Gson; import com.google.gson.JsonParseException; import static fr.unistra.sil.erp.back.Config.MAPPING_SUBTRANSAC; +import fr.unistra.sil.erp.back.DatabaseSystem; import fr.unistra.sil.erp.back.controller.ISubmitTransactionController; +import fr.unistra.sil.erp.back.db.DatabaseConnectionException; +import fr.unistra.sil.erp.back.db.DatabaseInterface; +import fr.unistra.sil.erp.back.db.DatabaseResourceNotFoundException; +import fr.unistra.sil.erp.back.db.DatabaseUpdateException; +import fr.unistra.sil.erp.back.model.Stock; import fr.unistra.sil.erp.back.model.Transaction; import java.io.IOException; import java.util.logging.Level; @@ -35,11 +41,15 @@ public class ApiSubmitTransactionController * @param response the HTTP Servlet Response provided by Spring. * @return the response for the user. * @throws ApiBadRequestException if the query failed. + * @throws ApiServerErrorException Server error. + * @throws ApiResourceNotFoundException Stock not found. */ @RequestMapping(value=MAPPING_SUBTRANSAC, method = RequestMethod.POST) @Override public ResponseEntity<Object> submitTransaction(HttpServletRequest request, - HttpServletResponse response) throws ApiBadRequestException + HttpServletResponse response) + throws ApiBadRequestException, ApiServerErrorException, + ApiResourceNotFoundException { Gson gson = new Gson(); String body; @@ -70,9 +80,34 @@ public class ApiSubmitTransactionController if(!t.checkIfValid()) throw new ApiBadRequestException("Invalid JSON schema."); - System.out.println("Transaction : " + t.getItem() + - t.getType() + " " + t.getAmount()); - + DatabaseInterface db; + Stock s; + try { + db = DatabaseSystem.getInstance(); + s = db.getStockForItem(t.getItem()); + if(s == null) + throw new ApiServerErrorException("Database failure."); + + int newQuantity = s.getQuantity() + t.getQuantity(); + if(newQuantity < 0) + newQuantity = 0; + + db.updateStock(s.getId(), newQuantity); + } catch (DatabaseConnectionException ex) { + Logger.getLogger(ApiSubmitTransactionController.class.getName()) + .log(Level.SEVERE, ex.getMessage(), ex); + throw new ApiServerErrorException("Database failure."); + } catch (DatabaseResourceNotFoundException ex) { + //Logger.getLogger(ApiSubmitTransactionController.class.getName()) + // .log(Level.SEVERE, null, ex); + throw new ApiResourceNotFoundException("No stock found for item " + + t.getItem()); + } catch (DatabaseUpdateException ex) { + Logger.getLogger(ApiSubmitTransactionController.class.getName()) + .log(Level.SEVERE, ex.getMessage(), ex); + throw new ApiServerErrorException("Database update failure."); + } + return new ResponseEntity<>(t, HttpStatus.CREATED); } diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseConnectionException.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseConnectionException.java index fcff9c1cf58a937d3a5714023b1aeefc3d0cbe4d..0ace8fd2c553a69ee9647ba0a2913a7d35441173 100644 --- a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseConnectionException.java +++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseConnectionException.java @@ -16,4 +16,13 @@ package fr.unistra.sil.erp.back.db; */ public class DatabaseConnectionException extends Exception { + /** + * Class constructor. + * @param errMsg the error message. + */ + public DatabaseConnectionException(String errMsg) + { + super(errMsg); + } + } diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java index 988daf0d507df0d7f8471b5ff48ac47866c1b3aa..c71e0835beece9982d04d1291e4c075041593048 100644 --- a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java +++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java @@ -46,4 +46,22 @@ public interface DatabaseInterface { */ public List<Stock> getStocks(); + /** + * Returns the stock entry of an item. + * @param id the item's ID. + * @return the stock line. + * @throws DatabaseResourceNotFoundException when the query fails. + */ + public Stock getStockForItem(int itemId) + throws DatabaseResourceNotFoundException; + + /** + * Updates the specified stock's quantity. + * @param id the stock entry's ID. + * @param quantity the new quantity. + * @throws DatabaseUpdateException when the query fails. + */ + public void updateStock(int id, int quantity) + throws DatabaseConnectionException, DatabaseUpdateException; + } diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseResourceNotFoundException.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseResourceNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..9a349196b20f067ac88dd802f66fc06a9aafe41b --- /dev/null +++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseResourceNotFoundException.java @@ -0,0 +1,26 @@ +/* + * CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B + * https://cecill.info/licences/Licence_CeCILL-B_V1-fr.html + */ +package fr.unistra.sil.erp.back.db; + +/** + * Exception for non-existent database resources. + * + * If the information requested in a database doesn't exist, this Exception + * is thrown. + * + * @author BEAUVAIS ANTOINE + */ +public class DatabaseResourceNotFoundException extends Exception { + + /** + * Class constructor. + * @param errMsg the error message. + */ + public DatabaseResourceNotFoundException(String errMsg) + { + super(errMsg); + } + +} diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java index dd162f3ad82e5fc2ec6427d46246f4c3200efac1..5d94b89488c5f04e67685fe8761fbb1fe2ea8f72 100644 --- a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java +++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java @@ -60,6 +60,12 @@ public class DatabaseSQLiteImpl implements DatabaseInterface { "i.name AS name, s.quantity AS quantity FROM stocks s " + "INNER JOIN items i ON s.item = i.ref"; + private static final String SQL_GETSTOCKFORITEM = SQL_GETSTOCKS + + " WHERE item = ?"; + + private static final String SQL_UPDATESTOCK = + "UPDATE stocks SET quantity = ? WHERE item = ?"; + /** * SQL Connection object. */ @@ -177,6 +183,7 @@ public class DatabaseSQLiteImpl implements DatabaseInterface { } catch (SQLException ex) { Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( Level.SEVERE, "Failed to parse results.", ex); + return null; } return res; @@ -235,5 +242,96 @@ public class DatabaseSQLiteImpl implements DatabaseInterface { return res; } + + /** + * Returns the stock entry for the specified item. + * @param itemId the item's ID. + * @return the Stock entry. + * @throws DatabaseResourceNotFoundException if the stock doesn't exist. + */ + @Override + public Stock getStockForItem(int itemId) + throws DatabaseResourceNotFoundException { + PreparedStatement ps; + try { + ps = this.conn.prepareStatement(SQL_GETSTOCKFORITEM); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( + Level.SEVERE, "Failed to connect to database.", ex); + return null; + } + + try { + ps.setInt(1, itemId); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( + Level.SEVERE, "Failed to set query parameter.", ex); + return null; + } + + ResultSet rs; + try { + rs = ps.executeQuery(); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( + Level.SEVERE, "Failed to fetch stock for item " + + itemId, ex); + return null; + } + + Stock s; + try { + if(rs.next()) + s = new Stock(rs.getInt("id"), rs.getInt("item"), + rs.getString("name"), + rs.getInt("quantity")); + else + throw new DatabaseResourceNotFoundException("Stock not found."); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( + Level.SEVERE, "Failed to parse results.", ex); + return null; + } + + return s; + } + + /** + * Updates the specified stock entry with the new quantity. + * @param id the stock's ID. + * @param quantity the associated quantity. + * @throws DatabaseConnectionException when the connection to the DB fails. + * @throws DatabaseUpdateException when the update fails. + */ + @Override + public void updateStock(int id, int quantity) + throws DatabaseConnectionException, DatabaseUpdateException { + + PreparedStatement ps; + try { + ps = this.conn.prepareStatement(SQL_UPDATESTOCK); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( + Level.SEVERE, "Failed to connect to database.", ex); + throw new DatabaseConnectionException("Failed to connect to DB."); + } + + try { + ps.setInt(1, quantity); + ps.setInt(2, id); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log( + Level.SEVERE, "Failed to set query parameter.", ex); + throw new DatabaseUpdateException("Failed to set query params."); + } + + try { + ps.execute(); + } catch (SQLException ex) { + Logger.getLogger(DatabaseSQLiteImpl.class.getName()) + .log(Level.SEVERE, "Failed to execute query.", ex); + throw new DatabaseUpdateException("Failed to execute query."); + } + } } diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseUpdateException.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseUpdateException.java new file mode 100644 index 0000000000000000000000000000000000000000..465912e1464ab18a3b3a8aa00149e101ccc0d310 --- /dev/null +++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseUpdateException.java @@ -0,0 +1,27 @@ +/* + * CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B + * https://cecill.info/licences/Licence_CeCILL-B_V1-fr.html + */ +package fr.unistra.sil.erp.back.db; + +/** + * Exception for database update failures. + * + * When a database system fails to update specific rows + * from the database, then it throws this Exception so + * the application can handle it. + * + * @author BEAUVAIS ANTOINE + */ +public class DatabaseUpdateException extends Exception { + + /** + * Class constructor. + * @param errMsg the error message. + */ + public DatabaseUpdateException(String errMsg) + { + super(errMsg); + } + +}