/** * Creates an order from the given items. Note that the suggested price for each item must be * equal to or exceed the current article price. Also, note that orders which exhaust the * available article capacity are rejected. * * @param alias the customer alias * @param passwordHash the customer password-hash * @param items the items * @return the order identity * @throws NullPointerException if one of the given values is {@code null} * @throws IllegalArgumentException if items is empty, or if any of the given items is priced too * low * @throws IllegalStateException if the login data is invalid, or the order creation fails * @throws SQLException if there is a problem with the underlying JDBC connection */ public long insertOrder( final String alias, final byte[] passwordHash, final double taxRate, final Collection<OrderItem> items) throws SQLException { final long purchaseIdentity; final Customer customer = this.queryCustomer(alias, passwordHash); synchronized (this.connection) { try (PreparedStatement statement = this.connection.prepareStatement(SQL_INSERT_PURCHASE, Statement.RETURN_GENERATED_KEYS)) { statement.setLong(1, customer.getIdentity()); statement.setLong(2, System.currentTimeMillis()); statement.setDouble(3, taxRate); if (statement.executeUpdate() != 1) throw new IllegalStateException("purchase creation failed."); try (ResultSet resultSet = statement.getGeneratedKeys()) { if (!resultSet.next()) throw new IllegalStateException("purchase key generation failed."); purchaseIdentity = resultSet.getLong(1); } } } if (items.isEmpty()) throw new IllegalArgumentException("missing items."); for (final OrderItem item : items) { if (item.getCount() <= 0) throw new IllegalArgumentException("item count too low."); final Article article = this.queryArticle(item.getArticleIdentity()); if (article.getPrice() > item.getArticleGrossPrice()) throw new IllegalArgumentException("price offer too low."); synchronized (this.connection) { try (PreparedStatement statement = this.connection.prepareStatement(SQL_RESERVE_ARTICLE_UNITS)) { statement.setLong(1, item.getCount()); statement.setLong(2, article.getIdentity()); statement.setLong(3, item.getCount()); if (statement.executeUpdate() != 1) throw new IllegalStateException("too few article units on stock."); } } synchronized (this.connection) { try (PreparedStatement statement = this.connection.prepareStatement(SQL_INSERT_PURCHASE_ITEM)) { statement.setLong(1, purchaseIdentity); statement.setLong(2, item.getArticleIdentity()); statement.setLong(3, item.getArticleGrossPrice()); statement.setInt(4, item.getCount()); if (statement.executeUpdate() != 1) throw new IllegalStateException("purchase item creation failed."); } } } return purchaseIdentity; }
/** * Cancels an order. Note that cancel requests for orders will be rejected if they are older than * one hour, or don't target the given customer. * * @param alias the customer alias * @param passwordHash the customer password-hash * @param orderIdentity the order identity * @throws IllegalStateException if the login data is invalid, if the order is too old, or if it * is not targeting the given customer * @throws SQLException if there is a problem with the underlying JDBC connection */ public void deleteOrder(final String alias, final byte[] passwordHash, final long orderIdentity) throws SQLException { final Customer customer = this.queryCustomer(alias, passwordHash); final Order order = this.queryOrder(alias, passwordHash, orderIdentity); if (order.getCustomerIdentity() != customer.getIdentity()) throw new IllegalStateException("purchase not created by given customer."); if (System.currentTimeMillis() > order.getCreationTimestamp() + TimeUnit.HOURS.toMillis(1)) throw new IllegalStateException("purchase too old."); synchronized (this.connection) { try (PreparedStatement statement = this.connection.prepareStatement(SQL_DELETE_PURCHASE)) { statement.setLong(1, orderIdentity); statement.executeUpdate(); } } for (final OrderItem item : order.getItems()) { synchronized (this.connection) { try (PreparedStatement statement = this.connection.prepareStatement(SQL_RELEASE_ARTICLE_UNITS)) { statement.setLong(1, item.getCount()); statement.setLong(2, item.getArticleIdentity()); statement.executeUpdate(); } } } }